Adding some consistency and fixing some bugs
[gc-dialer] / dialcentral / stream_osso.py
1 import logging
2
3 import gobject
4 import dbus
5
6 import util.misc as misc_utils
7
8
9 _moduleLogger = logging.getLogger(__name__)
10
11
12 class Stream(gobject.GObject):
13
14         STATE_PLAY = "play"
15         STATE_PAUSE = "pause"
16         STATE_STOP = "stop"
17
18         __gsignals__ = {
19                 'state-change' : (
20                         gobject.SIGNAL_RUN_LAST,
21                         gobject.TYPE_NONE,
22                         (gobject.TYPE_STRING, ),
23                 ),
24                 'eof' : (
25                         gobject.SIGNAL_RUN_LAST,
26                         gobject.TYPE_NONE,
27                         (gobject.TYPE_STRING, ),
28                 ),
29                 'error' : (
30                         gobject.SIGNAL_RUN_LAST,
31                         gobject.TYPE_NONE,
32                         (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT),
33                 ),
34         }
35
36         _SERVICE_NAME = "com.nokia.osso_media_server"
37         _OBJECT_PATH = "/com/nokia/osso_media_server"
38         _AUDIO_INTERFACE_NAME = "com.nokia.osso_media_server.music"
39
40         def __init__(self):
41                 gobject.GObject.__init__(self)
42                 #Fields
43                 self._state = self.STATE_STOP
44                 self._nextState = self.STATE_STOP
45                 self._uri = ""
46                 self._elapsed = 0
47                 self._duration = 0
48
49                 session_bus = dbus.SessionBus()
50
51                 # Get the osso-media-player proxy object
52                 oms_object = session_bus.get_object(
53                         self._SERVICE_NAME,
54                         self._OBJECT_PATH,
55                         introspect=False,
56                         follow_name_owner_changes=True,
57                 )
58                 # Use the audio interface
59                 oms_audio_interface = dbus.Interface(
60                         oms_object,
61                         self._AUDIO_INTERFACE_NAME,
62                 )
63                 self._audioProxy = oms_audio_interface
64
65                 self._audioProxy.connect_to_signal("state_changed", self._on_state_changed)
66                 self._audioProxy.connect_to_signal("end_of_stream", self._on_end_of_stream)
67
68                 error_signals = [
69                         "no_media_selected",
70                         "file_not_found",
71                         "type_not_found",
72                         "unsupported_type",
73                         "gstreamer",
74                         "dsp",
75                         "device_unavailable",
76                         "corrupted_file",
77                         "out_of_memory",
78                         "audio_codec_not_supported",
79                 ]
80                 for error in error_signals:
81                         self._audioProxy.connect_to_signal(error, self._on_error)
82
83         @property
84         def playing(self):
85                 return self.state == self.STATE_PLAY
86
87         @property
88         def has_file(self):
89                 return 0 < len(self._uri)
90
91         @property
92         def state(self):
93                 return self._state
94
95         def set_file(self, uri):
96                 if self._uri != uri:
97                         self._invalidate_cache()
98                 if self.state != self.STATE_STOP:
99                         self.stop()
100
101                 self._uri = uri
102                 self._audioProxy.set_media_location(self._uri)
103
104         def play(self):
105                 if self._nextState == self.STATE_PLAY:
106                         _moduleLogger.info("Already play")
107                         return
108                 _moduleLogger.info("Play")
109                 self._audioProxy.play()
110                 self._nextState = self.STATE_PLAY
111                 #self.emit("state-change", self.STATE_PLAY)
112
113         def pause(self):
114                 if self._nextState == self.STATE_PAUSE:
115                         _moduleLogger.info("Already pause")
116                         return
117                 _moduleLogger.info("Pause")
118                 self._audioProxy.pause()
119                 self._nextState = self.STATE_PAUSE
120                 #self.emit("state-change", self.STATE_PLAY)
121
122         def stop(self):
123                 if self._nextState == self.STATE_STOP:
124                         _moduleLogger.info("Already stop")
125                         return
126                 self._audioProxy.stop()
127                 _moduleLogger.info("Stopped")
128                 self._nextState = self.STATE_STOP
129                 #self.emit("state-change", self.STATE_STOP)
130
131         @property
132         def elapsed(self):
133                 pos_info = self._audioProxy.get_position()
134                 if isinstance(pos_info, tuple):
135                         self._elapsed, self._duration = pos_info
136                 return self._elapsed
137
138         @property
139         def duration(self):
140                 pos_info = self._audioProxy.get_position()
141                 if isinstance(pos_info, tuple):
142                         self._elapsed, self._duration = pos_info
143                 return self._duration
144
145         def seek_time(self, ns):
146                 _moduleLogger.debug("Seeking to: %s", ns)
147                 self._audioProxy.seek( dbus.Int32(1), dbus.Int32(ns) )
148
149         def _invalidate_cache(self):
150                 self._elapsed = 0
151                 self._duration = 0
152
153         @misc_utils.log_exception(_moduleLogger)
154         def _on_error(self, *args):
155                 err, debug = "", repr(args)
156                 _moduleLogger.error("Error: %s, (%s)" % (err, debug))
157                 self.emit("error", err, debug)
158
159         @misc_utils.log_exception(_moduleLogger)
160         def _on_end_of_stream(self, *args):
161                 self._state = self.STATE_STOP
162                 self._nextState = self.STATE_STOP
163                 self.emit("eof", self._uri)
164
165         @misc_utils.log_exception(_moduleLogger)
166         def _on_state_changed(self, state):
167                 _moduleLogger.info("State: %s", state)
168                 state = {
169                         "playing": self.STATE_PLAY,
170                         "paused": self.STATE_PAUSE,
171                         "stopped": self.STATE_STOP,
172                 }[state]
173                 if self._state == self.STATE_STOP and self._nextState == self.STATE_PLAY and state == self.STATE_STOP:
174                         # They seem to want to advertise stop right as the stream is starting, breaking the owner of this
175                         return
176                 self._state = state
177                 self._nextState = state
178                 self.emit("state-change", state)
179
180
181 gobject.type_register(Stream)