Adding support for other stream handlers in hopes to support Maemo 4.1
authorEd Page <eopage@byu.net>
Tue, 28 Sep 2010 02:29:28 +0000 (21:29 -0500)
committerEd Page <eopage@byu.net>
Tue, 28 Sep 2010 02:29:28 +0000 (21:29 -0500)
src/player.py
src/stream.py [deleted file]
src/stream_gst.py [new file with mode: 0644]
src/stream_osso.py [new file with mode: 0644]

index 1b1494e..b1871cd 100644 (file)
@@ -3,7 +3,11 @@ import logging
 import gobject
 
 import util.misc as misc_utils
 import gobject
 
 import util.misc as misc_utils
-import stream
+try:
+       import stream as _stream
+       stream = _stream # Silence PyFlakes
+except ImportError:
+       import stream_gst as stream
 import stream_index
 import call_monitor
 
 import stream_index
 import call_monitor
 
diff --git a/src/stream.py b/src/stream.py
deleted file mode 100644 (file)
index d584b65..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-import logging
-
-import gobject
-import gst
-
-import util.misc as misc_utils
-
-
-_moduleLogger = logging.getLogger(__name__)
-
-
-class GSTStream(gobject.GObject):
-
-       STATE_PLAY = "play"
-       STATE_PAUSE = "pause"
-       STATE_STOP = "stop"
-
-       __gsignals__ = {
-               'state-change' : (
-                       gobject.SIGNAL_RUN_LAST,
-                       gobject.TYPE_NONE,
-                       (gobject.TYPE_STRING, ),
-               ),
-               'eof' : (
-                       gobject.SIGNAL_RUN_LAST,
-                       gobject.TYPE_NONE,
-                       (gobject.TYPE_STRING, ),
-               ),
-               'error' : (
-                       gobject.SIGNAL_RUN_LAST,
-                       gobject.TYPE_NONE,
-                       (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT),
-               ),
-       }
-
-
-       def __init__(self):
-               gobject.GObject.__init__(self)
-               #Fields
-               self._state = self.STATE_STOP
-               self._uri = ""
-               self._elapsed = 0
-               self._duration = 0
-
-               #Set up GStreamer
-               self._player = gst.element_factory_make("playbin2", "player")
-               bus = self._player.get_bus()
-               bus.add_signal_watch()
-               bus.connect("message", self._on_message)
-
-               #Constants
-               self._timeFormat = gst.Format(gst.FORMAT_TIME)
-               self._seekFlag = gst.SEEK_FLAG_FLUSH
-
-       @property
-       def playing(self):
-               return self.state == self.STATE_PLAY
-
-       @property
-       def has_file(self):
-               return 0 < len(self._uri)
-
-       @property
-       def state(self):
-               state = self._player.get_state()[1]
-               return self._translate_state(state)
-
-       def set_file(self, uri):
-               if self._uri != file:
-                       self._invalidate_cache()
-               if self.state != self.STATE_STOP:
-                       self.stop()
-
-               self._uri = uri
-               self._player.set_property("uri", uri)
-
-       def play(self):
-               if self.state == self.STATE_PLAY:
-                       _moduleLogger.info("Already play")
-                       return
-               _moduleLogger.info("Play")
-               self._player.set_state(gst.STATE_PLAYING)
-               self.emit("state-change", self.STATE_PLAY)
-
-       def pause(self):
-               if self.state == self.STATE_PAUSE:
-                       _moduleLogger.info("Already pause")
-                       return
-               _moduleLogger.info("Pause")
-               self._player.set_state(gst.STATE_PAUSED)
-               self.emit("state-change", self.STATE_PAUSE)
-
-       def stop(self):
-               if self.state == self.STATE_STOP:
-                       _moduleLogger.info("Already stop")
-                       return
-               self._player.set_state(gst.STATE_NULL)
-               _moduleLogger.info("Stopped")
-               self.emit("state-change", self.STATE_STOP)
-
-       @property
-       def elapsed(self):
-               try:
-                       self._elapsed = self._player.query_position(self._timeFormat, None)[0]
-               except:
-                       pass
-               return self._elapsed
-
-       @property
-       def duration(self):
-               try:
-                       self._duration = self._player.query_duration(self._timeFormat, None)[0]
-               except:
-                       _moduleLogger.exception("Query failed")
-               return self._duration
-
-       def seek_time(self, ns):
-               self._elapsed = ns
-               self._player.seek_simple(self._timeFormat, self._seekFlag, ns)
-
-       def _invalidate_cache(self):
-               self._elapsed = 0
-               self._duration = 0
-
-       def _translate_state(self, gstState):
-               return {
-                       gst.STATE_NULL: self.STATE_STOP,
-                       gst.STATE_PAUSED: self.STATE_PAUSE,
-                       gst.STATE_PLAYING: self.STATE_PLAY,
-               }.get(gstState, self.STATE_STOP)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_message(self, bus, message):
-               t = message.type
-               if t == gst.MESSAGE_EOS:
-                       self._player.set_state(gst.STATE_NULL)
-                       self.emit("eof", self._uri)
-               elif t == gst.MESSAGE_ERROR:
-                       self._player.set_state(gst.STATE_NULL)
-                       err, debug = message.parse_error()
-                       _moduleLogger.error("Error: %s, (%s)" % (err, debug))
-                       self.emit("error", err, debug)
-
-
-gobject.type_register(GSTStream)
diff --git a/src/stream_gst.py b/src/stream_gst.py
new file mode 100644 (file)
index 0000000..0b6d959
--- /dev/null
@@ -0,0 +1,146 @@
+import logging
+
+import gobject
+import gst
+
+import util.misc as misc_utils
+
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+class GSTStream(gobject.GObject):
+
+       # @bug Advertising state changes a bit early, should watch for GStreamer state change
+
+       STATE_PLAY = "play"
+       STATE_PAUSE = "pause"
+       STATE_STOP = "stop"
+
+       __gsignals__ = {
+               'state-change' : (
+                       gobject.SIGNAL_RUN_LAST,
+                       gobject.TYPE_NONE,
+                       (gobject.TYPE_STRING, ),
+               ),
+               'eof' : (
+                       gobject.SIGNAL_RUN_LAST,
+                       gobject.TYPE_NONE,
+                       (gobject.TYPE_STRING, ),
+               ),
+               'error' : (
+                       gobject.SIGNAL_RUN_LAST,
+                       gobject.TYPE_NONE,
+                       (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT),
+               ),
+       }
+
+
+       def __init__(self):
+               gobject.GObject.__init__(self)
+               #Fields
+               self._uri = ""
+               self._elapsed = 0
+               self._duration = 0
+
+               #Set up GStreamer
+               self._player = gst.element_factory_make("playbin2", "player")
+               bus = self._player.get_bus()
+               bus.add_signal_watch()
+               bus.connect("message", self._on_message)
+
+               #Constants
+               self._timeFormat = gst.Format(gst.FORMAT_TIME)
+               self._seekFlag = gst.SEEK_FLAG_FLUSH
+
+       @property
+       def playing(self):
+               return self.state == self.STATE_PLAY
+
+       @property
+       def has_file(self):
+               return 0 < len(self._uri)
+
+       @property
+       def state(self):
+               state = self._player.get_state()[1]
+               return self._translate_state(state)
+
+       def set_file(self, uri):
+               if self._uri != uri:
+                       self._invalidate_cache()
+               if self.state != self.STATE_STOP:
+                       self.stop()
+
+               self._uri = uri
+               self._player.set_property("uri", uri)
+
+       def play(self):
+               if self.state == self.STATE_PLAY:
+                       _moduleLogger.info("Already play")
+                       return
+               _moduleLogger.info("Play")
+               self._player.set_state(gst.STATE_PLAYING)
+               self.emit("state-change", self.STATE_PLAY)
+
+       def pause(self):
+               if self.state == self.STATE_PAUSE:
+                       _moduleLogger.info("Already pause")
+                       return
+               _moduleLogger.info("Pause")
+               self._player.set_state(gst.STATE_PAUSED)
+               self.emit("state-change", self.STATE_PAUSE)
+
+       def stop(self):
+               if self.state == self.STATE_STOP:
+                       _moduleLogger.info("Already stop")
+                       return
+               self._player.set_state(gst.STATE_NULL)
+               _moduleLogger.info("Stopped")
+               self.emit("state-change", self.STATE_STOP)
+
+       @property
+       def elapsed(self):
+               try:
+                       self._elapsed = self._player.query_position(self._timeFormat, None)[0]
+               except:
+                       pass
+               return self._elapsed
+
+       @property
+       def duration(self):
+               try:
+                       self._duration = self._player.query_duration(self._timeFormat, None)[0]
+               except:
+                       _moduleLogger.exception("Query failed")
+               return self._duration
+
+       def seek_time(self, ns):
+               self._elapsed = ns
+               self._player.seek_simple(self._timeFormat, self._seekFlag, ns)
+
+       def _invalidate_cache(self):
+               self._elapsed = 0
+               self._duration = 0
+
+       def _translate_state(self, gstState):
+               return {
+                       gst.STATE_NULL: self.STATE_STOP,
+                       gst.STATE_PAUSED: self.STATE_PAUSE,
+                       gst.STATE_PLAYING: self.STATE_PLAY,
+               }.get(gstState, self.STATE_STOP)
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_message(self, bus, message):
+               t = message.type
+               if t == gst.MESSAGE_EOS:
+                       self._player.set_state(gst.STATE_NULL)
+                       self.emit("eof", self._uri)
+               elif t == gst.MESSAGE_ERROR:
+                       self._player.set_state(gst.STATE_NULL)
+                       err, debug = message.parse_error()
+                       _moduleLogger.error("Error: %s, (%s)" % (err, debug))
+                       self.emit("error", err, debug)
+
+
+gobject.type_register(GSTStream)
diff --git a/src/stream_osso.py b/src/stream_osso.py
new file mode 100644 (file)
index 0000000..92e0ede
--- /dev/null
@@ -0,0 +1,172 @@
+import logging
+
+import gobject
+import dbus
+
+import util.misc as misc_utils
+
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+class SimplePlayer(gobject.GObject):
+
+       STATE_PLAY = "play"
+       STATE_PAUSE = "pause"
+       STATE_STOP = "stop"
+
+       __gsignals__ = {
+               'state-change' : (
+                       gobject.SIGNAL_RUN_LAST,
+                       gobject.TYPE_NONE,
+                       (gobject.TYPE_STRING, ),
+               ),
+               'eof' : (
+                       gobject.SIGNAL_RUN_LAST,
+                       gobject.TYPE_NONE,
+                       (gobject.TYPE_STRING, ),
+               ),
+               'error' : (
+                       gobject.SIGNAL_RUN_LAST,
+                       gobject.TYPE_NONE,
+                       (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT),
+               ),
+       }
+
+       _SERVICE_NAME = "com.nokia.osso_media_server"
+       _OBJECT_PATH = "/com/nokia/osso_media_server"
+       _AUDIO_INTERFACE_NAME = "com.nokia.osso_media_server.music"
+
+       def __init__(self):
+               gobject.GObject.__init__(self)
+               #Fields
+               self._state = self.STATE_STOP
+               self._uri = ""
+               self._elapsed = 0
+               self._duration = 0
+
+               #Event callbacks
+               self.on_playing_done = on_playing_done
+
+               session_bus = dbus.SessionBus()
+
+               # Get the osso-media-player proxy object
+               oms_object = session_bus.get_object(
+                       self._SERVICE_NAME,
+                       self._OBJECT_PATH,
+                       introspect=False,
+                       follow_name_owner_changes=True,
+               )
+               # Use the audio interface
+               oms_audio_interface = dbus.Interface(
+                       oms_object,
+                       self._AUDIO_INTERFACE_NAME,
+               )
+               self._audioProxy = oms_audio_interface
+
+               self._audioProxy.connect_to_signal("state_changed", self._on_state_changed)
+               self._audioProxy.connect_to_signal("end_of_stream", self._on_end_of_stream)
+
+               error_signals = [
+                       "no_media_selected",
+                       "file_not_found",
+                       "type_not_found",
+                       "unsupported_type",
+                       "gstreamer",
+                       "dsp",
+                       "device_unavailable",
+                       "corrupted_file",
+                       "out_of_memory",
+                       "audio_codec_not_supported",
+               ]
+               for error in error_signals:
+                       self._audioProxy.connect_to_signal(error, self._on_error)
+
+       @property
+       def playing(self):
+               return self.state == self.STATE_PLAY
+
+       @property
+       def has_file(self):
+               return 0 < len(self._uri)
+
+       @property
+       def state(self):
+               return self._state
+
+       def set_file(self, uri):
+               if self._uri != uri:
+                       self._invalidate_cache()
+               if self.state != self.STATE_STOP:
+                       self.stop()
+
+               self._uri = uri
+               self._audioProxy.set_media_location(self._uri)
+
+       def play(self):
+               if self.state == self.STATE_PLAY:
+                       _moduleLogger.info("Already play")
+                       return
+               _moduleLogger.info("Play")
+               self._audioProxy.play()
+               self._state = self.STATE_PLAY
+               self.emit("state-change", self.STATE_PLAY)
+
+       def pause(self):
+               if self.state == self.STATE_PAUSE:
+                       _moduleLogger.info("Already pause")
+                       return
+               _moduleLogger.info("Pause")
+               self._audioProxy.pause()
+               self._state = self.STATE_PAUSE
+               self.emit("state-change", self.STATE_PLAY)
+
+       def stop(self):
+               if self.state == self.STATE_STOP:
+                       _moduleLogger.info("Already stop")
+                       return
+               self._audioProxy.stop()
+               _moduleLogger.info("Stopped")
+               self._state = self.STATE_STOP
+               self.emit("state-change", self.STATE_STOP)
+
+       @property
+       def elapsed(self):
+               pos_info = self._audioProxy.get_position()
+               if isinstance(pos_info, tuple):
+                       self._elapsed, self._duration = pos_info
+               return self._elapsed
+
+       @property
+       def duration(self):
+               pos_info = self._audioProxy.get_position()
+               if isinstance(pos_info, tuple):
+                       self._elapsed, self._duration = pos_info
+               return self._duration
+
+       def seek_time(self, ns):
+               _moduleLogger.debug("Seeking to: %s", ns)
+               self._audioProxy.seek( dbus.Int32(1), dbus.Int32(ns) )
+
+       def _invalidate_cache(self):
+               self._elapsed = 0
+               self._duration = 0
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_error(self, *args):
+               err, debug = "", repr(args)
+               _moduleLogger.error("Error: %s, (%s)" % (err, debug))
+               self.emit("error", err, debug)
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_end_of_stream(self, *args):
+               self._state = self.STATE_STOP
+               self.emit("eof", self._uri)
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_state_changed(self, state):
+               # @todo Switch to updating/emitting state based on this
+               _moduleLogger.info("State: %s", state)
+
+
+gobject.type_register(GSTStream)