そろそろ Y901x の GTK+ 3 化の準備。
gi.repository に Gst があるからコチラを使えばいいのかな。
GStreamer Application Development Manual (0.10.35.1)
0.10 だから別に変わっていないんだが PyGtk と同じには書けないし。
前回 Drag & Drop をやったので DnD されたファイルを再生できるのみを。
#!/usr/bin/env python #-*- coding:utf-8 -*- import sys import gi try: gi.require_version("Gtk", "3.0") except: print "This Program is GTK+ 3.0 or later." sys.exit() from gi.repository import Gst, Gtk, Gio, Gdk class Win(Gtk.Window): def __init__(self): Gtk.Window.__init__(self) # DnD dnd_list = Gtk.TargetEntry.new("text/uri-list", 0, 0) self.drag_dest_set( Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP, [dnd_list], Gdk.DragAction.MOVE ) self.drag_dest_add_uri_targets() self.connect("drag-data-received", self.on_drag_data_received) # Gst Gst.init(sys.argv) self.player = Gst.ElementFactory.make("playbin2", "player") # self self.set_title("movie player") self.show_all() def on_drag_data_received(self, widget, drag_context, x, y, data, info, time): uris = data.get_uris() self.player.set_property("uri", uris[0]) self.player.set_state(Gst.State.PLAYING) class App(Gtk.Application): def __init__(self): Gtk.Application.__init__( self, application_id="apps.test.gst", flags=Gio.ApplicationFlags.FLAGS_NONE) self.connect("activate", self.on_activate) def on_activate(self, application, user_data=None): Gdk.threads_init() w = Win() w.set_application(self) if __name__ == "__main__": app = App() app.run(sys.argv)
これで動画なら別ウインドウが出て再生できるだけのアプリ完成。
ほとんど変わっていなかった、けどやはり Gst.init() で初期化が必要になる。
PyGtk が親切すぎただけなんですけど。
しかし肝心なシグナルのハンドラで困った。
bus.add_watch なんてアトリビュートは無いんだが…
しかたがないから一番下の書き方をしてもエラーだし…
#bus.connect("message::state-changed", self.gst_on_message) # Error bus.connect("message", self.gst_on_message) ##### def gst_on_message(self, bus, message): print message # all messages are None
以前の手段では全部 None になってしまう…
python – GStreamer bus sends None message – Stack Overflow
わーい、同じことで詰まっている人を見つけた。
ってどうすりゃいいんだ…
ヤケクソだ、PyGI じゃない以前の gst を使ってやる。
#!/usr/bin/env python #-*- coding:utf-8 -*- import sys import gi try: gi.require_version("Gtk", "3.0") except: print "This Program is GTK+ 3.0 or later." sys.exit() from gi.repository import Gtk, Gio, Gdk import gst class Win(Gtk.Window): def __init__(self): Gtk.Window.__init__(self) # DnD dnd_list = Gtk.TargetEntry.new("text/uri-list", 0, 0) self.drag_dest_set( Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT | Gtk.DestDefaults.DROP, [dnd_list], Gdk.DragAction.MOVE ) self.drag_dest_add_uri_targets() self.connect("drag-data-received", self.on_drag_data_received) # old Gst self.player = gst.element_factory_make("playbin2", "player") bus = self.player.get_bus() bus.add_signal_watch() bus.enable_sync_message_emission() bus.connect("message", self.gst_on_message) # self self.set_title("movie player") self.show_all() def on_drag_data_received(self, widget, drag_context, x, y, data, info, time): uris = data.get_uris() self.player.set_property("uri", uris[0]) self.player.set_state(gst.STATE_PLAYING) def gst_on_message(self, bus, message, user_data=None): print message # OK class App(Gtk.Application): def __init__(self): Gtk.Application.__init__( self, application_id="apps.test.gst", flags=Gio.ApplicationFlags.FLAGS_NONE) self.connect("activate", self.on_activate) def on_activate(self, application, user_data=None): Gdk.threads_init() w = Win() w.set_application(self) if __name__ == "__main__": app = App() app.run(sys.argv)
よし、コレなら問題ない。
しかしこの GStreamer バインディングを今後も残してくれるのだろうか?
やはり PyGI を使ったほうがいいよな…
もう少し勉強します。