def get_url(url, post=None, get=None): post_params = urlencode(post or {}) get_params = urlencode(get or {}) if get: get_params = '?' + get_params # add post, get data and headers url = '%s%s' % (url, get_params) if post_params: request = Request(url, post_params) else: request = Request(url) # for discogs request.add_header('Accept-Encoding', 'gzip') request.add_header('User-Agent', USER_AGENT) url_sock = urlopen(request) enc = get_encoding_from_socket(url_sock) # unzip the response if needed data = url_sock.read() if url_sock.headers.get("content-encoding", "") == "gzip": data = gzip.GzipFile(fileobj=cBytesIO(data)).read() url_sock.close() content_type = url_sock.headers.get('Content-Type', '').split(';', 1)[0] domain = re.compile('\w+://([^/]+)/').search(url).groups(0)[0] print_d("Got %s data from %s" % (content_type, domain)) return (data if content_type.startswith('image') else data.decode(enc))
def _set_status(self, text): print_d("Setting status to \"%s\"..." % text) result, mid = self.client.publish(self.topic, text) if result != mqtt.MQTT_ERR_SUCCESS: print_w("Couldn't publish to %s at %s:%d (%s)" % (self.topic, self.host, self.port, result)) self.status = text
def changed(self, items): """Alert other users that these items have changed. This causes a 'changed' signal. If a librarian is available this function will call its changed method instead, and all libraries that librarian manages may fire a 'changed' signal. The item list may be filtered to those items actually in the library. If a librarian is available, it will handle the filtering instead. That means if this method is delegated to the librarian, this library's changed signal may not fire, but another's might. """ if not items: return if self.librarian and self in self.librarian.libraries.itervalues(): print_d("Changing %d items via librarian." % len(items), self) self.librarian.changed(items) else: items = set(item for item in items if item in self) if not items: return print_d("Changing %d items directly." % len(items), self) self._changed(items)
def search_complete(self, res): self.disconnect(sci) if res: print_d(res) self.download(Soup.Message.new('GET', res[0])) else: return self.fail('No cover was found')
def check_wrapper_changed(library, parent, songs): needs_write = filter(lambda s: s._needs_write, songs) if needs_write: win = WritingWindow(parent, len(needs_write)) win.show() for song in needs_write: try: song._song.write() except AudioFileError as e: qltk.ErrorMessage( None, _("Unable to edit song"), _("Saving <b>%s</b> failed. The file " "may be read-only, corrupted, or you " "do not have permission to edit it.") % util.escape(song('~basename'))).run() print_d("Couldn't save song %s (%s)" % (song("~filename"), e)) if win.step(): break win.destroy() changed = [] for song in songs: if song._was_updated(): changed.append(song._song) elif not song.valid() and song.exists(): library.reload(song._song) library.changed(changed)
def run(self, songs): """ Runs this command on `songs`, splitting into multiple calls if necessary """ args = [] if self.parameter: value = GetStringDialog(None, _("Input value"), _("Value for %s?") % self.parameter).run() self.command = self.command.format(**{self.parameter: value}) print_d("Actual command=%s" % self.command) for song in songs: arg = str(self.__pat.format(song)) if not arg: print_w("Couldn't build shell command using \"%s\"." "Check your pattern?" % self.pattern) break if not self.unique: args.append(arg) elif arg not in args: args.append(arg) max = int((self.max_args or 10000)) com_words = self.command.split(" ") while args: print_d("Running %s with %d substituted arg(s) (of %d%s total)..." % (self.command, min(max, len(args)), len(args), " unique" if self.unique else "")) util.spawn(com_words + args[:max]) args = args[max:]
def _load_item(self, item): """Load (add) an item into this library""" # Subclasses should override this if they want to check # item validity; see `FileLibrary`. print_d("Loading %r." % item.key, self) self.dirty = True self._contents[item.key] = item
def __request(self, line, raw=False, want_reply=True): """ Send a request to the server, if connected, and return its response """ line = line.strip() if not (self.is_connected or line.split()[0] == 'login'): print_d("Can't do '%s' - not connected" % line.split()[0], self) return None if self._debug: print_(">>>> \"%s\"" % line) try: self.telnet.write(line + "\n") if not want_reply: return None raw_response = self.telnet.read_until("\n").strip() except socket.error as e: print_w("Couldn't communicate with squeezebox (%s)" % e) self.failures += 1 if self.failures >= self._MAX_FAILURES: print_w("Too many Squeezebox failures. Disconnecting") self.is_connected = False return None response = raw_response if raw else urllib.unquote(raw_response) if self._debug: print_("<<<< \"%s\"" % (response,)) return response[len(line) - 1:] if line.endswith("?")\ else response[len(line) + 1:]
def get_data(self, key): """Gets the pattern for a given key""" try: return self.commands[key] except (KeyError, TypeError): print_d("Invalid key %s" % key) return None
def data(self): """A list of tuples of the persisted key:values in this class""" if self.FIELDS: return [(k, self.__getattribute__(k) if hasattr(self, k) else None) for k in self.FIELDS] else: print_d("No order specified for class %s" % type(self).__name__) return dict([(k, v) for k, v in self.__dict__.items() if self._should_store(k)])
def get_players(self): """ Returns (and caches) a list of the Squeezebox players available""" if self.players: return self.players pairs = self.__request("players 0 99", True).split(" ") def demunge(string): s = urllib.unquote(string) cpos = s.index(":") return (s[0:cpos], s[cpos + 1:]) # Do a meaningful URL-unescaping and tuplification for all values pairs = map(demunge, pairs) # First element is always count count = int(pairs.pop(0)[1]) self.players = [] for pair in pairs: if pair[0] == "playerindex": playerindex = int(pair[1]) self.players.append(SqueezeboxPlayerSettings()) else: # Don't worry playerindex is always the first entry... self.players[playerindex][pair[0]] = pair[1] if self._debug: print_d("Found %d player(s): %s" % (len(self.players), self.players)) assert (count == len(self.players)) return self.players
def rescan(self): """Scan for plugin changes or to initially load all plugins""" print_d("Rescanning..") removed, added = self.__scanner.rescan() # remember IDs of enabled plugin that get reloaded, so we can enable # them again reload_ids = [] for name in removed: if name not in added: continue mod = self.__modules[name] for plugin in mod.plugins: if self.enabled(plugin): reload_ids.append(plugin.id) for name in removed: # share the namespace with ModuleScanner for now self.__remove_module(name) # restore enabled state self.__enabled.update(reload_ids) for name in added: new_module = self.__scanner.modules[name] self.__add_module(name, new_module.module) print_d("Rescanning done.")
def enable(self, plugin, status, force=False): """Enable or disable a plugin.""" if not force and self.enabled(plugin) == bool(status): return if not status: print_d("Disable %r" % plugin.id) for handler in plugin.handlers: handler.plugin_disable(plugin) self.__enabled.discard(plugin.id) instance = plugin.instance if instance and hasattr(instance, "disabled"): try: instance.disabled() except Exception: util.print_exc() else: print_d("Enable %r" % plugin.id) obj = plugin.get_instance() if obj and hasattr(obj, "enabled"): try: obj.enabled() except Exception: util.print_exc() for handler in plugin.handlers: handler.plugin_enable(plugin) self.__enabled.add(plugin.id)
def rename(self, song, newname, changed=None): """Rename the song in all libraries it belongs to. The 'changed' signal will fire for any library the song is in except if a set() is passed as changed. """ # This needs to poke around inside the library directly. If # it uses add/remove to handle the songs it fires incorrect # signals. If it uses the library's rename method, it breaks # the call for future libraries because the item's key has # changed. So, it needs to reimplement the method. re_add = [] print_d("Renaming %r to %r" % (song.key, newname), self) for library in self.libraries.itervalues(): try: del library._contents[song.key] except KeyError: pass else: re_add.append(library) song.rename(newname) for library in re_add: library._contents[song.key] = song if changed is None: library._changed({song}) else: print_d("Delaying changed signal for %r." % library, self) changed.add(song)
def remove_songs(self, songs, library, leave_dupes=False): """ Removes `songs` from this playlist if they are there, removing only the first reference if `leave_dupes` is True """ changed = False for song in songs: # TODO: document the "library.masked" business if library.masked(song("~filename")): while True: try: self[self.index(song)] = song("~filename") except ValueError: break else: changed = True else: while song in self.songs: print_d("Removing \"%s\" from playlist \"%s\"..." % (song["~filename"], self.name)) self.songs.remove(song) if leave_dupes: changed = True break else: changed = True # Evict song from cache entirely try: del self._song_map_cache[song] print_d("Removed playlist cache for \"%s\"" % song["~filename"]) except KeyError: pass return changed
def remove_songs(self, songs, leave_dupes=False): """Removes `songs` from this playlist if they are there, removing only the first reference if `leave_dupes` is True """ print_d("Remove %d song(s) from %s?" % (len(songs), self.name)) changed = False for song in songs: # TODO: document the "library.masked" business if self.library is not None and self.library.masked(song): while True: try: self._list[self.index(song)] = song("~filename") except ValueError: break else: changed = True else: while song in self._list: self._list.remove(song) changed = True if leave_dupes: break def songs_gone(): return set(songs) - set(self._list) if changed: self.finalize() # Short-circuit logic will avoid the calculation if not leave_dupes or songs_gone(): self._emit_changed(songs, "remove_songs") return changed
def __changed_and_signal_library(self, entry, section, name): config.set(section, name, str(entry.get_value())) print_d("Signalling \"changed\" to entire library. Hold tight...") # Cache over clicks self._songs = self._songs or app.library.values() copool.add(emit_signal, self._songs, funcid="library changed", name=_("Updating for new ratings"))
def fetch_opml(url): try: outline = opml.parse(url) except IOError: print_d("Failed opening OPML %s" % url) return [] GObject.idle_add(lambda: update_feeds([x.xmlUrl for x in outline]))
def __remove(self, iters, smodel): def song_at(itr): return smodel[smodel.get_path(itr)][0] def remove_from_model(iters, smodel): for it in iters: smodel.remove(it) model, iter = self.__selected_playlists() if iter: playlist = model[iter][0] # A {iter: song} dict, exhausting `iters` once. removals = {iter_remove: song_at(iter_remove) for iter_remove in iters} if not removals: print_w("No songs selected to remove") return if self._query is None or not self.get_filter_text(): # Calling playlist.remove_songs(songs) won't remove the # right ones if there are duplicates remove_from_model(removals.keys(), smodel) self.__rebuild_playlist_from_songs_model(playlist, smodel) # Emit manually self.library.emit('changed', removals.values()) else: playlist.remove_songs(removals.values(), True) remove_from_model(iters, smodel) print_d("Removed %d song(s) from %s" % (len(removals), playlist)) self.changed(playlist) self.activate()
def init(icon=None, proc_title=None, name=None): global quodlibet print_d("Entering quodlibet.init") _gtk_init() _gtk_icons_init(get_image_dir(), icon) _gst_init() _dbus_init() _init_debug() from gi.repository import GLib if proc_title: GLib.set_prgname(proc_title) set_process_title(proc_title) # Issue 736 - set after main loop has started (gtk seems to reset it) GLib.idle_add(set_process_title, proc_title) if name: GLib.set_application_name(name) mkdir(get_user_dir(), 0750) print_d("Finished initialization.")
def quit_gtk(window): if before_quit is not None: before_quit() # disable plugins import quodlibet.plugins quodlibet.plugins.quit() # for debug: this will list active copools from quodlibet.util import copool copool.pause_all() # See which browser windows are open and save their names # so we can restore them on start from quodlibet.qltk.browser import LibraryBrowser LibraryBrowser.save() # destroy all open windows so they hide immediately on close: # destroying all top level windows doesn't work (weird errors), # so we hide them all and only destroy our tracked instances # (browser windows, tag editors, pref window etc.) from quodlibet.qltk import Window for toplevel in Gtk.Window.list_toplevels(): toplevel.hide() for window in Window.windows: window.destroy() Gtk.main_quit() print_d("Quit GTK: done.")
def _try_build_device(self, object_path, block, fs): """Returns a Device instance or None. None if it wasn't a media player etc.. """ drive = self._drives.get(block["Drive"]) if not drive: # I think this shouldn't happen, but check anyway return dev_path = dbus_barray_to_str(block["Device"]) print_d("Found device: %r" % dev_path) media_player_id = get_media_player_id(self._udev, dev_path) if not media_player_id: print_d("%r not a media player" % dev_path) return protocols = get_media_player_protocols(media_player_id) device_id = drive["Id"] dev = self.create_device(object_path, unicode(device_id), protocols) icon_name = block["HintIconName"] if icon_name: dev.icon = icon_name return dev
def __init__(self, library): print_d("Creating Soundcloud Browser") super(SoundcloudBrowser, self).__init__(spacing=12) self.set_orientation(Gtk.Orientation.VERTICAL) if not self.instances(): self._init(library) self._register_instance() self.connect('destroy', self.__destroy) self.connect('uri-received', self.__handle_incoming_uri) self.__auth_sig = self.api_client.connect('authenticated', self.__on_authenticated) connect_destroy(self.library, 'changed', self.__changed) self.login_state = (State.LOGGED_IN if self.online else State.LOGGED_OUT) self._create_searchbar(self.library) vbox = Gtk.VBox() vbox.pack_start(self._create_footer(), False, False, 6) vbox.pack_start(self._create_category_widget(), True, True, 0) vbox.pack_start(self.create_login_button(), False, False, 6) vbox.show() pane = qltk.ConfigRHPaned("browsers", "soundcloud_pos", 0.4) pane.show() pane.pack1(vbox, resize=False, shrink=False) self._songs_box = songs_box = Gtk.VBox(spacing=6) songs_box.pack_start(self._searchbox, False, True, 0) songs_box.show() pane.pack2(songs_box, resize=True, shrink=False) self.pack_start(pane, True, True, 0) self.show()
def send_nowplaying(self): data = {"s": self.session_id} for key, val in self.nowplaying_song.items(): data[key] = val.encode("utf-8") print_d("Now playing song: %s - %s" % (self.nowplaying_song["a"], self.nowplaying_song["t"])) return self._check_submit(self.nowplaying_url, data)
def add_station(uri): """Fetches the URI content and extracts IRFiles Returns None in error, else a possibly filled list of stations""" irfs = [] if uri.lower().endswith(".pls") or uri.lower().endswith(".m3u"): try: sock = urlopen(uri) except EnvironmentError as err: err = text_type(err) print_d("Got %s from %s" % (uri, err)) ErrorMessage(None, _("Unable to add station"), escape(err)).run() return None if uri.lower().endswith(".pls"): irfs = ParsePLS(sock) elif uri.lower().endswith(".m3u"): irfs = ParseM3U(sock) sock.close() else: try: irfs = [IRFile(uri)] except ValueError as err: ErrorMessage(None, _("Unable to add station"), err).run() return irfs
def add_station(uri): """Fetches the URI content and extracts IRFiles Returns None in error, else a possibly filled list of stations""" irfs = [] if uri.lower().endswith(".pls") or uri.lower().endswith(".m3u"): if not re.match('^([^/:]+)://', uri): # Assume HTTP if no protocol given. See #2731 uri = 'http://' + uri print_d("Assuming http: %s" % uri) try: sock = urlopen(uri) except EnvironmentError as err: err = "%s\n\nURL: %s" % (text_type(err), uri) print_d("Got %s from %s" % (err, uri)) ErrorMessage(None, _("Unable to add station"), escape(err)).run() return None if uri.lower().endswith(".pls"): irfs = ParsePLS(sock) elif uri.lower().endswith(".m3u"): irfs = ParseM3U(sock) sock.close() else: try: irfs = [IRFile(uri)] except ValueError as err: ErrorMessage(None, _("Unable to add station"), err).run() return irfs
def register_translation(domain, localedir=None): """Register a translation domain Args: domain (str): the gettext domain localedir (pathlike): A directory used for translations, if None the system one will be used. Returns: GlibTranslations """ global _debug_text, _translations, _initialized assert _initialized if localedir is None: iterdirs = iter_locale_dirs else: iterdirs = lambda: iter([localedir]) for dir_ in iterdirs(): try: t = gettext.translation(domain, dir_, class_=GlibTranslations) except OSError: continue else: print_d("Translations loaded: %r" % unexpand(t.path)) break else: print_d("No translation found for the domain %r" % domain) t = GlibTranslations() t.set_debug_text(_debug_text) _translations[domain] = t return t
def __save(self, *data): """Save the cover and spawn the program to edit it if selected""" save_format = self.name_combo.get_active_text() # Allow use of patterns in creating cover filenames pattern = ArbitraryExtensionFileFromPattern( save_format.decode("utf-8")) filename = pattern.format(self.song) print_d("Using '%s' as filename based on %s" % (filename, save_format)) file_path = os.path.join(self.dirname, filename) if os.path.exists(file_path): resp = ConfirmFileReplace(self, file_path).run() if resp != ConfirmFileReplace.RESPONSE_REPLACE: return try: f = open(file_path, 'wb') f.write(self.current_data) f.close() except IOError: qltk.ErrorMessage(None, _('Saving failed'), _('Unable to save "%s".') % file_path).run() else: if self.open_check.get_active(): try: util.spawn([self.cmd.get_text(), file_path]) except: pass app.cover_manager.cover_changed([self.song]) self.main_win.destroy()
def init(): global device_manager if not dbus: return device_manager = None print_d(_("Initializing device backend.")) try_text = _("Trying '%s'") #DKD maintainers will change the naming of dbus, app stuff #in january 2010 or so (already changed in trunk), so try both if device_manager is None: print_d(try_text % "DeviceKit Disks") try: device_manager = DKD(("DeviceKit", "Disks")) except (LookupError, dbus.DBusException): pass if device_manager is None: print_d(try_text % "UDisks") try: device_manager = DKD(("UDisks",)) except (LookupError, dbus.DBusException): pass if device_manager is None: print_d(try_text % "HAL") try: device_manager = HAL() except (LookupError, dbus.DBusException): pass if device_manager is None: print_w(_("Couldn't connect to a device backend.")) else: print_d(_("Device backend initialized.")) return device_manager
def plugin_songs(self, songs): songs = [s for s in songs if s.is_file] print_d("Trying to browse folders...") if not self._handle(songs): ErrorMessage(self.plugin_window, _("Unable to open folders"), _("No program available to open folders.")).run()
def restart_counting(self): self.play_count = START_COUNT print_d("Resetting play count")
def config_set(cls, name, value): """Saves a config string value for this plugin""" try: config.set(PM.CONFIG_SECTION, cls._config_key(name), value) except config.Error: print_d("Couldn't set config item '%s' to %r" % (name, value))
def save(self): print_d("Saving plugins: %d active" % len(self.__enabled)) config.set(self.CONFIG_SECTION, self.CONFIG_OPTION, "\n".join(self.__enabled))
def _moveart(self, art_sets, pathfile_old, pathfile_new, song): path_old = os.path.dirname(os.path.realpath(pathfile_old)) path_new = os.path.dirname(os.path.realpath(pathfile_new)) if os.path.realpath(path_old) == os.path.realpath(path_new): return if (path_old in art_sets.keys() and not art_sets[path_old]): return # get art set for path images = [] if path_old in art_sets.keys(): images = art_sets[path_old] else: def glob_escape(s): for c in '[*?': s = s.replace(c, '[' + c + ']') return s # generate art set for path art_sets[path_old] = images path_old_escaped = glob_escape(path_old) for suffix in self.IMAGE_EXTENSIONS: images.extend(glob.glob(os.path.join(path_old_escaped, "*." + suffix))) if images: # set not empty yet, (re)process filenames = config.getstringlist("albumart", "search_filenames") moves = [] for fn in filenames: fn = os.path.join(path_old, fn) if "<" in fn: # resolve path fnres = ArbitraryExtensionFileFromPattern(fn).format(song) if fnres in images and fnres not in moves: moves.append(fnres) elif "*" in fn: moves.extend(f for f in glob.glob(fn) if f in images and f not in moves) elif fn in images and fn not in moves: moves.append(fn) if len(moves) > 0: overwrite = config.getboolean("rename", "move_art_overwrite") for fnmove in moves: try: # existing files safeguarded until move successful, # then deleted if overwrite set fnmoveto = os.path.join(path_new, os.path.split(fnmove)[1]) fnmoveto_orig = "" if os.path.exists(fnmoveto): fnmoveto_orig = fnmoveto + ".orig" if not os.path.exists(fnmoveto_orig): os.rename(fnmoveto, fnmoveto_orig) else: suffix = 1 while os.path.exists(fnmoveto_orig + "." + str(suffix)): suffix += 1 fnmoveto_orig = (fnmoveto_orig + "." + str(suffix)) os.rename(fnmoveto, fnmoveto_orig) print_d("Renaming image %r to %r" % (fnmove, fnmoveto), self) shutil.move(fnmove, fnmoveto) if overwrite and fnmoveto_orig: os.remove(fnmoveto_orig) images.remove(fnmove) except Exception: util.print_exc()
def _rename(self, library): model = self.view.get_model() win = WritingWindow(self, len(model)) win.show() was_changed = set() skip_all = self.__skip_interactive self.view.freeze_child_notify() should_move_art = config.getboolean("rename", "move_art") moveart_sets = {} remove_empty_dirs = config.getboolean("rename", "remove_empty_dirs") for entry in itervalues(model): if entry.new_name is None: continue song = entry.song old_name = entry.name old_pathfile = song['~filename'] new_name = entry.new_name new_pathfile = "" # ensure target is a full path if os.path.abspath(new_name) != \ os.path.abspath(os.path.join(os.getcwd(), new_name)): new_pathfile = new_name else: # must be a relative pattern, so prefix the path new_pathfile = \ os.path.join(os.path.dirname(old_pathfile), new_name) try: library.rename(song, text2fsn(new_name), changed=was_changed) except Exception: util.print_exc() if skip_all: continue RESPONSE_SKIP_ALL = 1 msg = qltk.Message( Gtk.MessageType.ERROR, win, _("Unable to rename file"), _("Renaming <b>%(old-name)s</b> to <b>%(new-name)s</b> " "failed. Possibly the target file already exists, " "or you do not have permission to make the " "new file or remove the old one.") % { "old-name": util.escape(old_name), "new-name": util.escape(new_name), }, buttons=Gtk.ButtonsType.NONE) msg.add_button(_("Ignore _All Errors"), RESPONSE_SKIP_ALL) msg.add_icon_button(_("_Stop"), Icons.PROCESS_STOP, Gtk.ResponseType.CANCEL) msg.add_button(_("_Continue"), Gtk.ResponseType.OK) msg.set_default_response(Gtk.ResponseType.OK) resp = msg.run() skip_all |= (resp == RESPONSE_SKIP_ALL) # Preserve old behavior: shift-click is Ignore All mods = Gdk.Display.get_default().get_pointer()[3] skip_all |= mods & Gdk.ModifierType.SHIFT_MASK library.reload(song, changed=was_changed) if resp != Gtk.ResponseType.OK and resp != RESPONSE_SKIP_ALL: break if should_move_art: self._moveart(moveart_sets, old_pathfile, new_pathfile, song) if remove_empty_dirs: path_old = os.path.dirname(old_pathfile) if not os.listdir(path_old): try: os.rmdir(path_old) print_d("Removed empty directory: %r" % path_old, self) except Exception: util.print_exc() if win.step(): break self.view.thaw_child_notify() win.destroy() library.changed(was_changed) self.save.set_sensitive(False)
def __shuffle_updated(self, widget, shuffle_cls): if self.__inhibit: return print_d("New shuffle mode: %s" % shuffle_cls.name) config.set("memory", "shuffle_mode", shuffle_cls.name) self.__compose_order()
def __repeat_updated(self, widget, repeat_cls): if self.__inhibit: return print_d("New repeat mode: %s" % repeat_cls.name) config.set("memory", "repeat_mode", repeat_cls.name) self.__compose_order()
def _on_songs_received(self, client, songs): new = len(self.add(songs)) print_d("Got %d songs (%d new)." % (len(songs), new)) self.emit('changed', songs)
def applicationShouldTerminate_(self, sender): print_d("osx: block termination") # FIXME: figure out why idle_add is needed here from gi.repository import GLib GLib.idle_add(app.quit) return False
def __song_started(self, player, song): if isinstance(song, SoundcloudFile): print_d("Getting comments for %s (%s)" % (song("title"), song.key)) self.client.get_comments(song.track_id)
def _override_exceptions(): print_d("Enabling custom exception handler.") sys.excepthook = ExceptionDialog.excepthook
def _emit_changed(self, songs, msg=""): if self.library and not self.inhibit and songs: print_d("Emitting changed (%s) for %d song(s) from playlist %s " % (msg, len(songs), self)) self.library.emit('changed', songs)
def plugin_playlist(self, playlist): print_d("Running playlist plugin for %s" % playlist) return self._handle_songs(playlist.songs, playlist)
def applicationShouldHandleReopen_hasVisibleWindows_( self, ns_app, flag): print_d("osx: handle reopen") app.present() return True
def enabled(self): self.__enabled = True print_d("Plugin enabled - accepting new songs.")
def init_backend(backend, librarian): import quodlibet.player print_d("Initializing audio backend (%s)" % backend) backend = quodlibet.player.init(backend) device = backend.init(librarian) return device
def __destroy(self, *args): print_d(f"Destroying Soundcloud Browser {self}") if not self.instances(): self._destroy()
def disabled(self): self.__enabled = False print_d("Plugin disabled - not accepting any new songs.") QLSubmitQueue.dump_queue()
def __changed(self, library, songs): print_d("Updating view") self.activate()
def song_excluded(self, song): if self.exclude and Query(self.exclude).search(song): print_d("%s is excluded by %s" % (song("~artist~title"), self.exclude)) return True return False
def process_default(self, event): print_d('Uncaught event for %s' % (event.maskname if event else "??"))
def activate(self): print_d("Refreshing browser for query \"%r\"" % self.__filter) songs = self.library.query(self.get_filter_text()) self.songs_selected(songs)
def main(argv): import quodlibet quodlibet.init_cli() try: # we want basic commands not to import gtk (doubles process time) assert "gi.repository.Gtk" not in sys.modules sys.modules["gi.repository.Gtk"] = None startup_actions, cmds_todo = process_arguments(argv) finally: sys.modules.pop("gi.repository.Gtk", None) quodlibet.init() from quodlibet import app from quodlibet.qltk import add_signal_watch, Icons add_signal_watch(app.quit) import quodlibet.player import quodlibet.library from quodlibet import config from quodlibet import browsers from quodlibet import util app.name = "Quod Libet" app.id = "quodlibet" quodlibet.set_application_info(Icons.QUODLIBET, app.id, app.name) config.init(os.path.join(quodlibet.get_user_dir(), "config")) library_path = os.path.join(quodlibet.get_user_dir(), "songs") print_d("Initializing main library (%s)" % (quodlibet.util.path.unexpand(library_path))) library = quodlibet.library.init(library_path) app.library = library # this assumes that nullbe will always succeed from quodlibet.player import PlayerError wanted_backend = os.environ.get("QUODLIBET_BACKEND", config.get("player", "backend")) backend_traceback = None for backend in [wanted_backend, "nullbe"]: try: player = quodlibet.player.init_player(backend, app.librarian) except PlayerError: backend_traceback = format_exc() else: break app.player = player os.environ["PULSE_PROP_media.role"] = "music" os.environ["PULSE_PROP_application.icon_name"] = "quodlibet" browsers.init() from quodlibet.qltk.songlist import SongList, get_columns headers = get_columns() SongList.set_all_column_headers(headers) for opt in config.options("header_maps"): val = config.get("header_maps", opt) util.tags.add(opt, val) in_all = ("~filename ~uri ~#lastplayed ~#rating ~#playcount ~#skipcount " "~#added ~#bitrate ~current ~#laststarted ~basename " "~dirname").split() for Kind in browsers.browsers: if Kind.headers is not None: Kind.headers.extend(in_all) Kind.init(library) pm = quodlibet.init_plugins("no-plugins" in startup_actions) if hasattr(player, "init_plugins"): player.init_plugins() from quodlibet.qltk import unity unity.init("quodlibet.desktop", player) from quodlibet.qltk.songsmenu import SongsMenu SongsMenu.init_plugins() from quodlibet.util.cover import CoverManager app.cover_manager = CoverManager() app.cover_manager.init_plugins() from quodlibet.plugins.playlist import PLAYLIST_HANDLER PLAYLIST_HANDLER.init_plugins() from quodlibet.plugins.query import QUERY_HANDLER QUERY_HANDLER.init_plugins() from gi.repository import GLib def exec_commands(*args): for cmd in cmds_todo: try: resp = cmd_registry.run(app, *cmd) except CommandError: pass else: if resp is not None: print_(resp, end="") from quodlibet.qltk.quodlibetwindow import QuodLibetWindow, PlayerOptions # Call exec_commands after the window is restored, but make sure # it's after the mainloop has started so everything is set up. app.window = window = QuodLibetWindow( library, player, restore_cb=lambda: GLib.idle_add(exec_commands, priority=GLib.PRIORITY_HIGH)) app.player_options = PlayerOptions(window) from quodlibet.qltk.debugwindow import MinExceptionDialog from quodlibet.qltk.window import on_first_map if backend_traceback is not None: def show_backend_error(window): d = MinExceptionDialog( window, _("Audio Backend Failed to Load"), _("Loading the audio backend '%(name)s' failed. " "Audio playback will be disabled.") % {"name": wanted_backend}, backend_traceback) d.run() # so we show the main window first on_first_map(app.window, show_backend_error, app.window) from quodlibet.plugins.events import EventPluginHandler pm.register_handler(EventPluginHandler(library.librarian, player)) from quodlibet.mmkeys import MMKeysHandler from quodlibet.remote import Remote, RemoteError from quodlibet.commands import registry as cmd_registry, CommandError from quodlibet.qltk.tracker import SongTracker, FSInterface try: from quodlibet.qltk.dbus_ import DBusHandler except ImportError: DBusHandler = lambda player, library: None mmkeys_handler = MMKeysHandler(app) mmkeys_handler.start() current_path = os.path.join(quodlibet.get_user_dir(), "current") fsiface = FSInterface(current_path, player) remote = Remote(app, cmd_registry) try: remote.start() except RemoteError: exit_(1, True) DBusHandler(player, library) tracker = SongTracker(library.librarian, player, window.playlist) from quodlibet.qltk import session session.init("quodlibet") quodlibet.enable_periodic_save(save_library=True) if "start-playing" in startup_actions: player.paused = False # restore browser windows from quodlibet.qltk.browser import LibraryBrowser GLib.idle_add(LibraryBrowser.restore, library, player, priority=GLib.PRIORITY_HIGH) def before_quit(): print_d("Saving active browser state") try: app.browser.save() except NotImplementedError: pass print_d("Shutting down player device %r." % player.version_info) player.destroy() quodlibet.main(window, before_quit=before_quit) app.player_options.destroy() quodlibet.finish_first_session(app.id) mmkeys_handler.quit() remote.stop() fsiface.destroy() tracker.destroy() quodlibet.library.save() config.save() print_d("Finished shutdown.")
def _log(self, event): print_d('%s for "%s" on %s' % (event.maskname, event.name, event.path))
def get_winner(self, albums): print_d("Weights: %s " % self.plugin.weights) scores = self.plugin._score(albums) print_d("Scores: %s" % scores) return max(scores)[1]
def disabled(self): if self.running: self.running = False if self.notifier: print_d("Stopping inotify watch...") self.notifier.stop()
def __init__(self, name=None): print_d("Initializing SongFileLibrary \"%s\"." % name) super(SongFileLibrary, self).__init__(name)
def _show(self, line): self.text_buffer.set_text(line) self._start_clearing_from += 1 print_d("♪ %s ♪" % line.strip()) return False
def unmask(self, point): print_d("Unmasking %r." % point, self) items = self._masked.pop(point, {}) if items: self.add(items.values())
def filter_text(self, text): self.__searchbar.set_text(text) if SoundcloudQuery(text).is_parsable: self.activate() else: print_d("Not parsable: %s" % text)