def __on_owner_change(self, name, old, new): log.debug("dbus name owner changed: '%s' -> '%s'" % (old, new)) _stop_pa(self.__pa) if new: _start_pa(self.__pa)
def __get_position(self): sp = self.__shell.get_player() db = self.__shell.props.db position = 0 id_now = self.__item_id if id_now is not None: if sp.props.playing_from_queue: qmodel = self.__queue_sc.props.query_model elif self.__playlist_sc is not None: qmodel = self.__playlist_sc.get_entry_view().props.model else: qmodel = None if qmodel is not None: for row in qmodel: id = db.entry_get(row[0], rhythmdb.PROP_LOCATION) if id_now == id: break position += 1 log.debug("position: %i" % position) return position
def __notify_file_opened(self, totem, file): # XXX: does not get called for podcasts from BBC plugin log.debug("file opened: %s" % file) self.__update_item = True
def __init__(self, sock, addr, clients, pinfo_msg, msg_handler_fn, c_type): self.__sock = sock self.__addr = addr self.__clients = clients self.__pinfo_msg = pinfo_msg self.__msg_handler_fn = msg_handler_fn self.__conn_type = c_type # client info self.info = ClientInfo() self.__psave = False # the following fields are used for iterative receiving on message data # see io_recv() and io_recv_buff() self.__rcv_buff_header = ReceiveBuffer() self.__rcv_buff_data = ReceiveBuffer() self.__rcv_msg_id = message.IGNORE self.__rcv_msg_size = 0 self.__snd_buff = "" # buffer for outgoing data # source IDs for various events self.__sids = [ gobject.io_add_watch(self.__sock, gobject.IO_IN, self.__io_recv), gobject.io_add_watch(self.__sock, gobject.IO_ERR, self.__io_error), gobject.io_add_watch(self.__sock, gobject.IO_HUP, self.__io_hup) ] self.__sid_out = 0 log.debug("send 'hello' to %s" % self) self.send(ClientConnection.IO_HELLO)
def start(self, shell): if self.__shell is not None: log.warning("already started") return remuco.PlayerAdapter.start(self) self.__shell = shell sp = self.__shell.get_player() # gconf is used to adjust repeat and shuffle self.__gconf = gconf.client_get_default() # shortcuts to RB data self.__item_id = None self.__item_entry = None self.__playlist_sc = sp.get_playing_source() self.__queue_sc = self.__shell.props.queue_source # connect to shell player signals self.__signal_ids = ( sp.connect("playing_changed", self.__notify_playing_changed), sp.connect("playing_uri_changed", self.__notify_playing_uri_changed), sp.connect("playing-source-changed", self.__notify_source_changed) ) # state sync will happen by timeout # trigger item sync: self.__notify_playing_uri_changed(sp, sp.get_playing_path()) # item sync log.debug("start done")
def __notify_playing_uri_changed(self, sp, uri): """Shell player signal callback to handle an item change.""" log.debug("playing uri changed: %s" % uri) db = self.__shell.props.db entry = sp.get_playing_entry() if entry is None: id = None else: id = db.entry_get(entry, rhythmdb.PROP_LOCATION) self.__item_id = id self.__item_entry = entry if entry is not None and id is not None: info = self.__get_item_from_entry(entry) img_data = db.entry_request_extra_metadata(entry, "rb:coverArt") if img_data is None: img_file = self.find_image(id) else: try: img_file = "%s/art.png" % self.config.cache_dir img_data.save(img_file, "png") except IOError, e: log.warning("failed to save cover art (%s)" % e) img_file = None
def send(self, msg): """Send a message to the client. @param msg: complete message (incl. ID and length) in binary format (net.build_message() is your friend here) @see: net.build_message() """ if msg is None: log.error("** BUG ** msg is None") return if self.__sock is None: log.debug("cannot send message to %s, already disconnected" % self) return if self.__psave: log.debug("%s is in sleep mode, send nothing" % self) return self.__snd_buff = "%s%s" % (self.__snd_buff, msg) # if not already trying to send data .. if self.__sid_out == 0: # .. do it when it is possible: self.__sid_out = gobject.io_add_watch(self.__sock, gobject.IO_OUT, self.__io_send)
def __io_send(self, fd, cond): """ GObject callback function (when data can be written). """ if not self.__snd_buff: self.__sid_out = 0 return False log.debug("try to send %d bytes to %s" % (len(self.__snd_buff), self)) try: sent = self.__sock.send(self.__snd_buff) except socket.error as e: log.warning("failed to send data to %s (%s)" % (self, e)) self.disconnect() return False log.debug("sent %d bytes" % sent) if sent == 0: log.warning("failed to send data to %s" % self) self.disconnect() return False self.__snd_buff = self.__snd_buff[sent:] if not self.__snd_buff: self.__sid_out = 0 return False else: return True
def update_item(self, id, info, img): """Set currently played item. @param id: item ID (str) @param info: meta information (dict) @param img: image / cover art (either a file name or URI or an instance of Image.Image) @note: Call to synchronize player state with remote clients. @see: find_image() for finding image files for an item. @see: remuco.INFO_... for keys to use for 'info' """ log.debug("new item: (%s, %s %s)" % (id, info, img)) change = self.__item_id != id change |= self.__item_info != info change |= self.__item_img != img if change: self.__item_id = id self.__item_info = info self.__item_img = img self.__sync_trigger(self.__sync_item)
def __init__(self, sock, addr, clients, pinfo_msg, msg_handler_fn, c_type): self.__sock = sock self.__addr = addr self.__clients = clients self.__pinfo_msg = pinfo_msg self.__msg_handler_fn = msg_handler_fn self.__conn_type = c_type # client info self.info = ClientInfo() self.__psave = False # the following fields are used for iterative receiving on message data # see io_recv() and io_recv_buff() self.__rcv_buff_header = ReceiveBuffer() self.__rcv_buff_data = ReceiveBuffer() self.__rcv_msg_id = message.IGNORE self.__rcv_msg_size = 0 self.__snd_buff = "" # buffer for outgoing data # source IDs for various events self.__sids = [ gobject.io_add_watch(self.__sock, gobject.IO_IN, self.__io_recv), gobject.io_add_watch(self.__sock, gobject.IO_ERR, self.__io_error), gobject.io_add_watch(self.__sock, gobject.IO_HUP, self.__io_hup) ] self.__sid_out = 0 log.debug("send 'hello' to %s" % self) self.send(ClientConnection.IO_HELLO)
def __notify_playing_uri_changed(self, sp, uri): """Shell player signal callback to handle an item change.""" log.debug("playing uri changed: %s" % uri) db = self.__shell.props.db entry = sp.get_playing_entry() if entry is None: id = None else: id = db.entry_get(entry, rhythmdb.PROP_LOCATION) self.__item_id = id self.__item_entry = entry if entry is not None and id is not None: info = self.__get_item_from_entry(entry) img_data = db.entry_request_extra_metadata(entry, "rb:coverArt") if img_data is None: img_file = self.find_image(id) else: try: img_file = "%s/rhythmbox.cover" % self.config.cache img_data.save(img_file, "png") except IOError, e: log.warning("failed to save cover art (%s)" % e) img_file = None
def __get_position(self): sp = self.__shell.get_player() db = self.__shell.props.db position = 0 id_now = self.__item_id if id_now is not None: if sp.props.playing_from_queue: qmodel = self.__queue_sc.props.query_model elif self.__playlist_sc is not None: qmodel = self.__playlist_sc.get_entry_view().props.model else: qmodel = None if qmodel is not None: for row in qmodel: id = db.entry_get(row[0], rhythmdb.PROP_LOCATION) if id_now == id: break position += 1 log.debug("position: %i" % position) return position
def __notify_file_opened(self, totem, file): # XXX: does not get called for podcasts from BBC plugin log.debug("file opened: %s" % file) self.__update_item = True
def send(self, msg): """Send a message to the client. @param msg: complete message (incl. ID and length) in binary format (net.build_message() is your friend here) @see: net.build_message() """ if msg is None: log.error("** BUG ** msg is None") return if self.__sock is None: log.debug("cannot send message to %s, already disconnected" % self) return if self.__psave: log.debug("%s is in sleep mode, send nothing" % self) return self.__snd_buff = "%s%s" % (self.__snd_buff, msg) # if not already trying to send data .. if self.__sid_out == 0: # .. do it when it is possible: self.__sid_out = gobject.io_add_watch(self.__sock, gobject.IO_OUT, self.__io_send)
def get_art(resource, prefer_thumbnail=False): if resource is None: return None uri = __resource_to_file_uri(resource) if uri is None: log.debug("resource '%s' is not local, ignore" % resource) return None if prefer_thumbnail: file = __get_art_from_thumbnails(uri) if file is not None: return file file = __get_art_in_folder(uri) if file is not None: return file if not prefer_thumbnail: file = __get_art_from_thumbnails(uri) if file is not None: return file return None
def __on_owner_change(self, name, old, new): log.debug("dbus name owner changed: '%s' -> '%s'" % (old, new)) _stop_pa(self.__pa) if new: _start_pa(self.__pa)
def __recv_buff(self, rcv_buff): """ Receive some data and put it into the given ReceiveBuffer. @param rcv_buff: the receive buffer to put received data into @return: true if some data has been received, false if an error occurred """ try: log.debug("try to receive %d bytes" % rcv_buff.rest) data = self.__sock.recv(rcv_buff.rest) except socket.timeout as e: # TODO: needed? log.warning("connection to %s broken (%s)" % (self, e)) self.disconnect() return False except socket.error as e: log.warning("connection to %s broken (%s)" % (self, e)) self.disconnect() return False received = len(data) log.debug("received %d bytes" % received) if received == 0: log.warning("connection to %s broken (no data)" % self) self.disconnect() return False rcv_buff.data = rcv_buff.data + data rcv_buff.rest -= received return True
def write_string(self, s): """ Write a string. If the string is a unicode string, it will be encoded as a normal string in Bin.NET_ENCODING. If it already is a normal string it will be converted from Bin.HOST_ENCODING to Bin.NET_ENCODING. """ if s is None: self.__write_string(s) return if Bin.HOST_ENCODING not in Bin.NET_ENCODING_ALT: log.debug("convert '%s' from %s to %s" % (s, Bin.HOST_ENCODING, Bin.NET_ENCODING)) try: s = unicode(s, Bin.HOST_ENCODING).encode(Bin.NET_ENCODING) except UnicodeDecodeError as e: log.warning("could not decode '%s' with codec %s (%s)" % (s, Bin.HOST_ENCODING, e)) except UnicodeEncodeError as e: log.warning("could not encode '%s' with codec %s (%s)" % (s, Bin.NET_ENCODING, e)) self.__write_string(s)
def _notify_tracklist_change(self, new_len): log.debug("tracklist change") try: self._mp_t.GetCurrentTrack(reply_handler=self._notify_position, error_handler=self._dbus_error) except DBusException as e: log.warning("dbus error: %s" % e)
def __get_position(self): sp = self.__shell.props.shell_player db = self.__shell.props.db position = 0 id_now = self.__item_id if id_now is not None: if sp.props.playing_from_queue: qmodel = self.__queue_sc.props.query_model elif self.__playlist_sc is not None: qmodel = self.__playlist_sc.get_entry_view().props.model else: qmodel = None if qmodel is not None: for row in qmodel: id = row[0].get_string(RB.RhythmDBPropType.LOCATION) if id_now == id: break position += 1 log.debug("position: %i" % position) return position
def __get_art_in_folder(uri): """Try to find art images in the given URI's folder. @param uri: a file URI ('file://...') @return: path to an image file or None if there is no matching image file in the URI's folder """ elems = urlparse.urlparse(uri) path = urllib.url2pathname(elems[2]) path = os.path.dirname(path) log.debug("looking for art image in %s" % path) files = glob.glob(os.path.join(path, "*")) files = [os.path.basename(f) for f in files if os.path.isfile(f)] for rx in RE_FILE: for file in files: if rx.match(file): return os.path.join(path, file) return None
def __init__( self, name, display_name=None, poll=2.5, mime_types=None, rating=False, extra_file_actions=None, extra_playlist_actions=None, ): display_name = display_name or name if rating: max_rating = 5 else: max_rating = 0 all_file_actions = FILE_ACTIONS + tuple(extra_file_actions or ()) PlayerAdapter.__init__( self, display_name, max_rating=max_rating, playback_known=True, volume_known=True, repeat_known=True, shuffle_known=True, progress_known=True, file_actions=all_file_actions, mime_types=mime_types, ) self.__playlist_actions = PLAYLIST_ACTIONS if self.config.getx("playlist-jump-enabled", "0", int): self.__playlist_actions.append(IA_JUMP) if extra_playlist_actions: self.__playlist_actions.extend(extra_playlist_actions) self.__name = name self.__dbus_signal_handler = () self._mp_p = None self._mp_t = None self._repeat = False self._shuffle = False self._playing = PLAYBACK_STOP self.__volume = 0 self.__progress_now = 0 self.__progress_max = 0 self.__can_pause = False self.__can_play = False self.__can_seek = False self.__can_next = False self.__can_prev = False self.__can_tracklist = False log.debug("init done")
def stop(self): remuco.PlayerAdapter.stop(self) xl.event.remove_callback(self.__notify_track_change) xl.event.remove_callback(self.__notify_playback_change) log.debug("remuco exaile adapter stopped")
def _notify_tracklist_change(self, new_len): log.debug("tracklist change") try: self._mp_t.GetCurrentTrack(reply_handler=self._notify_position, error_handler=self._dbus_error) except DBusException, e: log.warning("dbus error: %s" % e)
def ctrl_next(self): sp = self.__shell.get_player() try: sp.do_next() except gobject.GError, e: log.debug("do next failed: %s" % str(e))
def stop(self): remuco.PlayerAdapter.stop(self) xl.event.remove_callback(self.__notify_track_change) xl.event.remove_callback(self.__notify_playback_change) log.debug("remuco exaile adapter stopped")
def ctrl_next(self): sp = self.__shell.props.shell_player try: sp.do_next() except GObject.GError as e: log.debug("do next failed: %s" % str(e))
def ctrl_rate(self, rating): if self.__item_entry is not None: db = self.__shell.props.db try: db.set(self.__item_entry, rhythmdb.PROP_RATING, rating) except gobject.GError, e: log.debug("rating failed: %s" % str(e))
def action_queue_item(self, action_id, positions, ids): if action_id == IA_JUMP.id: try: self.__jump_in_plq(self.__queue_sc, positions[0]) except gobject.GError, e: log.debug("queue jump failed: %s" % e)
def ctrl_toggle_playing(self): sp = self.__shell.get_player() try: sp.playpause() except gobject.GError, e: log.debug("toggle play pause failed: %s" % str(e))
def ctrl_seek(self, direction): sp = self.__shell.get_player() try: sp.seek(direction * 5) except gobject.GError, e: log.debug("seek failed: %s" % str(e))
def ctrl_toggle_playing(self): sp = self.__shell.get_player() try: sp.playpause() except gobject.GError, e: log.debug("toggle play pause failed: %s" % str(e))
def ctrl_rate(self, rating): if self.__item_entry is not None: db = self.__shell.props.db try: db.set(self.__item_entry, rhythmdb.PROP_RATING, rating) except gobject.GError, e: log.debug("rating failed: %s" % str(e))
def ctrl_seek(self, direction): sp = self.__shell.get_player() try: sp.seek(direction * 5) except gobject.GError, e: log.debug("seek failed: %s" % str(e))
def ctrl_rate(self, rating): if self.__item_entry is not None: db = self.__shell.props.db try: db.entry_set(self.__item_entry, RB.RhythmDBPropType.RATING, rating) except GObject.GError as e: log.debug("rating failed: %s" % str(e))
def action_queue_item(self, action_id, positions, ids): if action_id == IA_JUMP.id: try: self.__jump_in_plq(self.__queue_sc, positions[0]) except gobject.GError, e: log.debug("queue jump failed: %s" % e)
def ctrl_next(self): sp = self.__shell.get_player() try: sp.do_next() except gobject.GError, e: log.debug("do next failed: %s" % str(e))
def ctrl_toggle_playing(self): sp = self.__shell.props.shell_player try: sp.playpause(True) except GObject.GError as e: log.debug("toggle play pause failed: %s" % str(e))
def __load(self): log.debug("try to load config from %s" % self.__file_config) try: self.__cp.read(self.__file_config) except ConfigParser.Error, e: log.warning("failed to read config from %s (%s) -> %s" % (self.__file_config, e, "using defaults"))
def __notify_playing_changed(self, sp, b): """Shell player signal callback to handle a change in playback.""" log.debug("playing changed: %s" % str(b)) if b: self.update_playback(remuco.PLAYBACK_PLAY) else: self.update_playback(remuco.PLAYBACK_PAUSE)
def __notify_playing_changed(self, sp, b): """Shell player signal callback to handle a change in playback.""" log.debug("playing changed: %s" % str(b)) if b: self.update_playback(remuco.PLAYBACK_PLAY) else: self.update_playback(remuco.PLAYBACK_PAUSE)
def ctrl_previous(self): sp = self.__shell.get_player() try: sp.set_playing_time(0) time.sleep(0.1) sp.do_previous() except gobject.GError, e: log.debug("do previous failed: %s" % str(e))
def ctrl_previous(self): sp = self.__shell.get_player() try: sp.set_playing_time(0) time.sleep(0.1) sp.do_previous() except gobject.GError, e: log.debug("do previous failed: %s" % str(e))
def ctrl_previous(self): if not self.__can_prev: log.debug("go to previous is currently not possible") return try: self._mp_p.Prev(reply_handler=self._dbus_ignore, error_handler=self._dbus_error) except DBusException as e: log.warning("dbus error: %s" % e)
def __sync_trigger(self, sync_fn): if self.stopped: return if sync_fn in self.__sync_triggers: log.debug("trigger for %s already active" % sync_fn.func_name) return self.__sync_triggers[sync_fn] = gobject.idle_add(sync_fn, priority=gobject.PRIORITY_LOW)
def __init__(self, name, display_name=None, poll=2.5, mime_types=None, rating=False, extra_file_actions=None, extra_playlist_actions=None): display_name = display_name or name if rating: max_rating = 5 else: max_rating = 0 all_file_actions = FILE_ACTIONS + tuple(extra_file_actions or ()) PlayerAdapter.__init__(self, display_name, max_rating=max_rating, playback_known=True, volume_known=True, repeat_known=True, shuffle_known=True, progress_known=True, file_actions=all_file_actions, mime_types=mime_types) self.__playlist_actions = PLAYLIST_ACTIONS if self.config.getx("playlist-jump-enabled", "0", int): self.__playlist_actions.append(IA_JUMP) if extra_playlist_actions: self.__playlist_actions.extend(extra_playlist_actions) self.__name = name self.__dbus_signal_handler = () self._mp_p = None self._mp_t = None self._repeat = False self._shuffle = False self._playing = PLAYBACK_STOP self.__volume = 0 self.__progress_now = 0 self.__progress_max = 0 self.__can_pause = False self.__can_play = False self.__can_seek = False self.__can_next = False self.__can_prev = False self.__can_tracklist = False log.debug("init done")
def ctrl_volume(self, direction): sp = self.__shell.get_player() if direction == 0: sp.set_volume(0) else: try: sp.set_volume_relative(direction * 0.05) except gobject.GError, e: log.debug("set volume failed: %s" % str(e))
def ctrl_previous(self): if not self.__can_prev: log.debug("go to previous is currently not possible") return try: self._mp_p.Prev(reply_handler=self._dbus_ignore, error_handler=self._dbus_error) except DBusException, e: log.warning("dbus error: %s" % e)
def ctrl_next(self): if not self.__can_next: log.debug("go to next item is currently not possible") return try: self._mp_p.Next(reply_handler=self._dbus_ignore, error_handler=self._dbus_error) except DBusException, e: log.warning("dbus error: %s" % e)
def __notify_metadata_updated(self, totem, artist, title, album, track=0): # 'track' has been added in Totem 2.26 log.debug("metadata updated: %s, %s, %s" % (artist, title, album)) # in Totem < 2.26 meta data is always None self.__md_artist = artist self.__md_title = title self.__md_album = album self.__update_item = True
def down(self): """ Shut down the server. """ if self.__sid is not None: gobject.source_remove(self.__sid) if self._sock is not None: log.debug("closing %s server socket" % self._get_type()) try: self._sock.shutdown(socket.SHUT_RDWR) except socket.error: pass self._sock.close() self._sock = None
def __recv_buff(self, rcv_buff): """ Receive some data and put it into the given ReceiveBuffer. @param rcv_buff: the receive buffer to put received data into @return: true if some data has been received, false if an error occurred """ try: log.debug("try to receive %d bytes" % rcv_buff.rest) data = self.__sock.recv(rcv_buff.rest) except socket.timeout, e: # TODO: needed? log.warning("connection to %s broken (%s)" % (self, e)) self.disconnect() return False
def __io_send(self, fd, cond): """ GObject callback function (when data can be written). """ if not self.__snd_buff: self.__sid_out = 0 return False log.debug("try to send %d bytes to %s" % (len(self.__snd_buff), self)) try: sent = self.__sock.send(self.__snd_buff) except socket.error, e: log.warning("failed to send data to %s (%s)" % (self, e)) self.disconnect() return False
def request_mlib(self, reply, path): slm = self.__shell.props.sourcelist_model ### root ? ### if not path: for group in slm: group_name = group[2] reply.nested.append(group_name) reply.send() return ### group ? ### Library, Playlists if len(path) == 1: for group in slm: group_name = group[2] if path[0] == group_name: for sc in group.iterchildren(): source_name = sc[2] # FIXME: how to be l10n independent here? if source_name.startswith("Play Queue"): continue if source_name.startswith("Import Error"): continue log.debug("append %s" % source_name) reply.nested.append(source_name) break reply.list_actions = MLIB_LIST_ACTIONS reply.send() return ### regular playlist (source) ! ### Library/???, Playlists/??? sc = self.__mlib_path_to_source(path) if sc is None: reply.send() return qm = sc.get_entry_view().props.model try: reply.ids, reply.names = self.__get_item_list_from_qmodel(qm) except gobject.GError, e: log.warning("failed to list items: %s" % e)
def start(self): remuco.PlayerAdapter.start(self) for event in ("playback_track_start", "playback_track_end"): xl.event.add_callback(self.__notify_track_change, event) for event in ("playback_player_end", "playback_player_start", "playback_toggle_pause"): xl.event.add_callback(self.__notify_playback_change, event) self.__update_track(self.__ex.player.current) self.__update_position() self.__update_playback() # other updates via poll() log.debug("remuco exaile adapter started")
def __poll_item(self): try: mrl = self.__to.get_current_mrl() except AttributeError: # totem < 2.24 mrl = self.__to.get_main_window().get_title() # <- fake mrl if not self.__update_item and mrl == self.__last_mrl: return # reset seek step len = self.__to.get_property("stream-length") if len < 10000: self.__seek_step_initial = 0 else: self.__seek_step_initial = max(5000, len // 200) self.__seek_step = self.__seek_step_initial log.debug("reset seek step to %d" % self.__seek_step) # update meta information log.debug("update item") self.__update_item = False self.__last_mrl = mrl info = {} if ((self.__md_artist, self.__md_title, self.__md_album) == (None, None, None)): info[remuco.INFO_TITLE] = self.__get_title_from_window() else: info[remuco.INFO_ARTIST] = self.__md_artist info[remuco.INFO_TITLE] = self.__md_title info[remuco.INFO_ALBUM] = self.__md_album info[remuco.INFO_LENGTH] = int(len / 1000) img = self.find_image(mrl) self.update_item(mrl, info, img)
def __check_seek_step(self, progress_before, exp_min_diff, new_step): """Check if a seek had some effect and adjust seek step if not. @param progress_before: playback progress before seeking @param new_step: new seek step to set if progress did not change significantly """ progress_now = self.__to.get_current_time() log.debug("seek diff: %d" % abs(progress_now - progress_before)) if abs(progress_now - progress_before) < exp_min_diff: log.debug("adjust seek step to %d" % new_step) self.__seek_step = new_step self.__css_sid = 0
def ctrl_seek(self, direction): if not self.__can_seek: log.debug("seeking is currently not possible") return self.__progress_now += 5 * direction self.__progress_now = min(self.__progress_now, self.__progress_max) self.__progress_now = max(self.__progress_now, 0) log.debug("new progress: %d" % self.__progress_now) try: self._mp_p.PositionSet(self.__progress_now * 1000, reply_handler=self._dbus_ignore, error_handler=self._dbus_error) except DBusException, e: log.warning("dbus error: %s" % e)
def zc_publish(player, port): """Publish a service for the given player at the given port.""" zc_unpublish() log.debug("publishing zeroconf service") try: bus = dbus.SystemBus() obj = bus.get_object(_DBA_NAME, _DBA_PATH_SERVER) server = dbus.Interface(obj, _DBA_INTERFACE_SERVER) obj = bus.get_object(_DBA_NAME, server.EntryGroupNew()) group = dbus.Interface(obj, _DBA_INTERFACE_ENTRY_GROUP) group.AddService(-1, -1, 0, "Remuco %s" % player, _ZC_TYPE, "local", "", port, "") group.Commit() except dbus.DBusException, e: log.warning("failed to publish zeroconf service (%s)" % e) group = None
def action_mlib_list(self, action_id, path): if action_id == LA_PLAY.id: sc = self.__mlib_path_to_source(path) if sc is None: log.warning("no source for path %s" % path) return sp = self.__shell.get_player() if sc != self.__playlist_sc: try: sp.set_selected_source(sc) sp.set_playing_source(sc) self.__jump_in_plq(sc, 0) except gobject.GError, e: log.debug("switching source failed: %s" % str(e))