diff --git a/mediaserver/mediaclient.py b/mediaserver/mediaclient.py new file mode 100644 index 0000000..95a1890 --- /dev/null +++ b/mediaserver/mediaclient.py @@ -0,0 +1,356 @@ +import dbus +import dbus.service +import dbus.mainloop.glib + +from . import dbus_smartobject +from . import event + +import os + +import gi +from gi.repository import GLib +from gi.repository import GObject + +class MediaClient(dbus_smartobject.DBusSmartObject): + def __init__(self,quickfolder=None): + + if not quickfolder is None: + self._quickfolder = quickfolder + else: + self._quickfolder = os.path.dirname(os.getcwd()) + + self.Playing = False + self.Paused = False + self.Stopped = True + self.Buffering = False + + self.status_url = None + self.status_position = 0 + self.status_reloading = False + + # initialize the events + self.OnLoading = event.Event() + self.OnReady = event.Event() + self.OnPlaying = event.Event() + self.OnPaused = event.Event() + + self.OnReconnectReady = event.Event() + self.OnReconnectPlaying = event.Event() + self.OnReconnectPaused = event.Event() + + self.OnStopped = event.Event() + self.OnFinished = event.Event() + self.OnFinishing = event.Event() + + self.OnLoadFail = event.Event() + self.OnRunFail = event.Event() + + self.OnConnect = event.Event() + self.OnReconnect = event.Event() + self.OnDisconnect = event.Event() + + self.OnBuffering = event.Event() + + # init base object + dbus_smartobject.DBusSmartObject.__init__( self, + service='nl.miqra.MediaCore.Media', + path='/nl/miqra/MediaCore/Media', + interface='nl.miqra.MediaCore.Media', + systembus=True) + + self.statusticker() + + def init_busobject(self,busobject): + # this is what gives us the multi media keys. + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnLoading', self._onLoading) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnReady', self._onReady) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnPlaying', self._onPlaying) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnPaused', self._onPaused) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnStopped', self._onStopped) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnFinished', self._onFinished) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnFinishing', self._onFinishing) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnLoadFail', self._onLoadFail) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnRunFail', self._onRunFail) + + # connect_to_signal registers our callback function. + busobject.connect_to_signal('OnBuffering', self._onBuffering) + + def on_connection_lost(self): + self.OnDisconnect() + + def on_connection_made(self): + self.OnConnect() + + def on_connection_regained(self): + if self.status_url is not None: + self.status_reloading = True + self.LoadUrl(self.status_url) + + def statusticker(self): + if self.connected(): + if not self.status_reloading and (self.Playing or self.Paused): + self.status_position = self.Position() + #print "backed up position: {0}".format(self.status_position) + + GObject.timeout_add(1000, self.statusticker) + + #callback function + def _onLoading(self,url): + """ gets called when a source has been requested for playback + """ + self.OnLoading(url) + + def _onBuffering(self,pct): + """ gets called when a source has been requested for playback + """ + if pct < 100: + self.Buffering = True + else: + self.Buffering = False + self.OnBuffering(pct) + + def _onReady(self,url,tags): + """ gets called when a source is ready for playback + """ + if not self.status_reloading: + self.Playing = False + self.Paused = False + self.Stopped = True + self.status_url = url + self.OnReady(url,tags) + else: + if self.Playing or self.Paused: + self.Play() + else: + self.status_reloading = False + self.OnReconnectReady() + + def _onPlaying(self): + """ gets called when a playback has started + """ + if not self.status_reloading: + self.Playing = True + self.Paused = False + self.Stopped = False + self.OnPlaying() + else: + self.Seek(self.status_position) + if self.Paused: + self.Pause() + else: + self.status_reloading = False + self.OnReconnectPlaying() + pass + + def _onPaused(self): + """ gets called when a playback is paused + """ + if not self.status_reloading: + self.Playing = False + self.Paused = True + self.Stopped = False + self.OnPaused() + else: + self.status_reloading = False + self.OnReconnectPaused() + + + def _onStopped(self): + """ gets called when playback has stopped + """ + self.Playing = False + self.Paused = False + self.Stopped = True + self.status_position = 0 + self.OnStopped() + + def _onFinished(self): + """ gets called when playback has completed + """ + self.Playing = False + self.Paused = False + self.Stopped = True + self.status_position = 0 + self.OnFinished() + + def _onFinishing(self): + self.OnFinishing() + + def _onLoadFail(self,reason): + """ gets called when loading a source for playback fails + """ + self.OnLoadFail(reason) + + def _onRunFail(self,reason): + """ gets called when playback fails + """ + self.OnRunFail(reason) + + def QuickPlay(self, file, duration = None): + """ Directly play back a local file + """ + path = file + # check if the file exists, if not, try to find it in the base folder for quickplay or else as a subfolder of the __main__ folder + if not os.path.isfile(path): + path = os.path.join(self._quickfolder,file) + + if not os.path.isfile(path): + path = os.path.join(os.getcwd(),file) + + try: + if duration is None or duration <= 0: + self.call("QuickPlay",file) + else: + self.call("QuickPlayFor",file,duration) + except dbus_smartobject.NoConnectionError: + print("Could not call QuickPlay function because of no connection") + pass + + def QuickPlayUrl(self, url, duration = None): + """ Directly play back a URL + """ + try: + if duration is None or duration <= 0: + self.call("QuickPlayUrl",url) + else: + self.call("QuickPlayUrlFor",url,duration) + except dbus_smartobject.NoConnectionError: + print("Could not call QuickPlayUrl function because of no connection") + pass + + def QuickLoop(self, file): + """ Directly play back a local file + """ + path = file + # check if the file exists, if not, try to find it in the base folder for quickplay or else as a subfolder of the __main__ folder + if not os.path.isfile(path): + path = os.path.join(self._quickfolder,file) + + if not os.path.isfile(path): + path = os.path.join(os.getcwd(),file) + + try: + self.call("QuickLoop",file) + except dbus_smartobject.NoConnectionError: + print("Could not call QuickPlay function because of no connection") + pass + + def QuickLoopUrl(self, url): + """ Directly play back a URL + """ + try: + self.call("QuickLoopUrl",url) + except dbus_smartobject.NoConnectionError: + print("Could not call QuickPlayUrl function because of no connection") + pass + + def LoadFile(self, file): + """ Load a local file for playback + """ + try: + self.call("LoadFile",file) + except dbus_smartobject.NoConnectionError: + print("Could not call LoadFile because of no connection") + pass + + def LoadUrl(self, url): + """ Load an url for playback + """ + try: + self.call("LoadUrl",url) + except dbus_smartobject.NoConnectionError: + print("Could not call LoadUrl because of no connection") + pass + + def PlayFor(self, duration): + """ Starts playback for [duration] seconds + """ + try: + self.call("PlayFor",duration) + except dbus_smartobject.NoConnectionError: + print("Could not call PlayFor because of no connection") + pass + + def Play(self): + """ Starts/resumes playback + """ + try: + self.call("Play") + except dbus_smartobject.NoConnectionError: + print("Could not call Play because of no connection") + pass + + def Loop(self): + """ Starts/resumes playback + """ + try: + self.call("Loop") + except dbus_smartobject.NoConnectionError: + print("Could not call Loop because of no connection") + pass + + def Pause(self): + """ Pauses playback + """ + try: + self.call("Pause") + except dbus_smartobject.NoConnectionError: + print("Could not call Pause because of no connection") + pass + + def Stop(self): + """ Stops playback + """ + try: + self.call("Stop") + except dbus_smartobject.NoConnectionError: + print("Could not call Stop because of no connection") + pass + + def Length(self): + """ returns length of currently loaded source + """ + try: + return self.call("Length") + except dbus_smartobject.NoConnectionError: + print("Could not call Length because of no connection") + return 0 + + def Position(self): + """ returns current position in the source + """ + try: + return self.call("Position") + except dbus_smartobject.NoConnectionError: + print("Could not call Position because of no connection") + return 0 + + def Seek(self,position): + """ jump to new position in the source + """ + try: + self.call("Seek",position) + self.status_position = position + + except dbus_smartobject.NoConnectionError: + print("Could not call because of no connection") + pass +