def load_dir_modules(path, package, load_compiled=False): """Load all modules and packages in path (recursive). Load pyc files if load_compiled is True. In case the module is already loaded, doesn't reload it. """ # needed for pickle etc. assert package in sys.modules try: modules = [e[0] for e in get_importables(path, load_compiled)] except OSError: util.print_w("%r not found" % path) return [] # get_importables can yield py and pyc for the same module # and we want to load it only once modules = set(modules) loaded = [] for name in modules: try: mod = load_module(name, package, path) except Exception: util.print_exc() continue if mod: loaded.append(mod) return loaded
def __about_to_finish(self, playbin): print_d("About to finish (async)") try: uri = self._runner.call(self.__about_to_finish_sync, priority=GLib.PRIORITY_HIGH, timeout=0.5) except MainRunnerTimeoutError as e: # Due to some locks being held during this signal we can get # into a deadlock when a seek or state change event happens # in the mainloop before our function gets scheduled. # In this case abort and do nothing, which results # in a non-gapless transition. print_d("About to finish (async): %s" % e) return except MainRunnerAbortedError as e: print_d("About to finish (async): %s" % e) return except MainRunnerError: util.print_exc() return if uri is not None: print_d("About to finish (async): setting uri") playbin.set_property('uri', uri) print_d("About to finish (async): done")
def __update_icon(self): if self.__size <= 0: return if not self.__pixbuf: flags = 0 if sys.platform == "win32": flags = Gtk.IconLookupFlags.FORCE_SIZE try: self.__pixbuf = self.__icon_theme.load_icon( Icons.QUODLIBET, self.__size, flags) except GLib.GError: util.print_exc() return # We need to fill the whole height that is given to us, or # the KDE panel will emit size-changed until we reach 0 w, h = self.__pixbuf.get_width(), self.__pixbuf.get_height() if h < self.__size: bg = GdkPixbuf.Pixbuf.new( GdkPixbuf.Colorspace.RGB, True, 8, w, self.__size) bg.fill(0) self.__pixbuf.copy_area(0, 0, w, h, bg, 0, (self.__size - h) / 2) self.__pixbuf = bg if app.player.paused and not self.__pixbuf_paused: self.__pixbuf_paused = new_with_paused_emblem(self.__pixbuf)[1] if app.player.paused: new_pixbuf = self.__pixbuf_paused else: new_pixbuf = self.__pixbuf self._icon.set_from_pixbuf(new_pixbuf)
def load_dir_modules(path, package, load_compiled=False): """Load all modules in path (non-recursive). Load pyc files if load_compiled is True. In case the module is already loaded, doesn't reload it. """ try: entries = os.listdir(path) except OSError: print_w("%r not found" % path) return [] modules = set() for entry in entries: if entry[:1] == "_": continue if entry.endswith(".py"): modules.add(entry[:-3]) elif load_compiled and entry.endswith(".pyc"): modules.add(entry[:-4]) loaded = [] for name in modules: try: mod = load_module(name, package, path) except Exception: util.print_exc() continue if mod: loaded.append(mod) return loaded
def _remove_empty_dirs(self): """ Delete all empty sub-directories from the given path. """ for root, dirs, __ in os.walk(self.expanded_destination, topdown=False): for dirname in dirs: dir_path = os.path.realpath(os.path.join(root, dirname)) if not os.listdir(dir_path): entry = Entry(None) entry.filename = dir_path entry.tag = Entry.Tags.IN_PROGRESS_DELETE iter_ = self.model.append(row=self._make_model_row(entry)) print_d(_('Removing "{}"').format(entry.filename)) self.c_songs_delete += 1 try: os.rmdir(dir_path) except Exception as ex: entry.tag = Entry.Tags.RESULT_FAILURE + ': ' + str(ex) self._update_model_value(iter_, 'tag', entry.tag) print_exc() self.c_files_failed += 1 else: entry.tag = Entry.Tags.RESULT_SUCCESS self._update_model_value(iter_, 'tag', entry.tag) self.c_files_delete += 1 self._update_sync_summary()
def _load_items(filename) -> Iterable[V]: """Load items from disk. In case of an error returns default or an empty list. """ try: with open(filename, "rb") as fp: data = fp.read() except EnvironmentError: print_w("Couldn't load library file from: %r" % filename) return [] try: items = load_audio_files(data) except SerializationError: # there are too many ways this could fail util.print_exc() # move the broken file out of the way try: shutil.copy(filename, filename + ".not-valid") except EnvironmentError: util.print_exc() return [] return items
def __save(self, save, song, buffer, delete): start, end = buffer.get_bounds() text = buffer.get_text(start, end, True) # First, write back to the tags. song["lyrics"] = text.decode("utf-8") try: song.write() except AudioFileError: util.print_exc() # Then, write to file. # TODO: write to file only if could not write to tags, otherwise delete # the file. lyricname = song.lyric_filename try: os.makedirs(os.path.dirname(lyricname)) except EnvironmentError as err: pass try: with open(lyricname, "w") as f: f.write(text) except EnvironmentError as err: encoding = util.get_locale_encoding() print_w(err.strerror.decode(encoding, "replace")) delete.set_sensitive(True) save.set_sensitive(False)
def __update_icon(self): if self.__size <= 0: return if not self.__pixbuf: flags = 0 if sys.platform == "win32": flags = Gtk.IconLookupFlags.FORCE_SIZE try: self.__pixbuf = self.__icon_theme.load_icon( Icons.QUODLIBET, self.__size, flags) except GLib.GError: util.print_exc() return # We need to fill the whole height that is given to us, or # the KDE panel will emit size-changed until we reach 0 w, h = self.__pixbuf.get_width(), self.__pixbuf.get_height() if h < self.__size: bg = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, w, self.__size) bg.fill(0) self.__pixbuf.copy_area(0, 0, w, h, bg, 0, (self.__size - h) / 2) self.__pixbuf = bg if app.player.paused and not self.__pixbuf_paused: self.__pixbuf_paused = new_with_paused_emblem(self.__pixbuf)[1] if app.player.paused: new_pixbuf = self.__pixbuf_paused else: new_pixbuf = self.__pixbuf self._icon.set_from_pixbuf(new_pixbuf)
def __save_files(self, parent, model, library): win = WritingWindow(parent, len(model)) was_changed = set() all_done = False for entry in itervalues(model): song, track = entry.song, entry.tracknumber if song.get("tracknumber") == track: win.step() continue if not song.valid(): win.hide() dialog = OverwriteWarning(self, song) resp = dialog.run() win.show() if resp != OverwriteWarning.RESPONSE_SAVE: break song["tracknumber"] = track try: song.write() except AudioFileError: util.print_exc() WriteFailedError(self, song).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break else: all_done = True library.changed(was_changed) win.destroy() self.save.set_sensitive(not all_done) self.revert.set_sensitive(not all_done)
def __save_files(self, parent, model, library): win = WritingWindow(parent, len(model)) was_changed = [] for row in model: song = row[0] track = row[2] if song.get("tracknumber") == track: win.step() continue if not song.valid() and not qltk.ConfirmAction( win, _("Tag may not be accurate"), _("<b>%s</b> changed while the program was running. " "Saving without refreshing your library may " "overwrite other changes to the song.\n\n" "Save this song anyway?") %( util.escape(util.fsdecode(song("~basename")))) ).run(): break song["tracknumber"] = track try: song.write() except: util.print_exc() qltk.ErrorMessage( win, _("Unable to save song"), _("Saving <b>%s</b> failed. The file may be " "read-only, corrupted, or you do not have " "permission to edit it.")%( util.escape(util.fsdecode(song('~basename'))))).run() library.reload(song, changed=was_changed) break was_changed.append(song) if win.step(): break library.changed(was_changed) win.destroy()
def __invoke(self, librarian, event, *args): args = list(args) if args and args[0]: if isinstance(args[0], dict): args[0] = SongWrapper(args[0]) elif isinstance(args[0], (set, list)): args[0] = ListWrapper(args[0]) for plugin in itervalues(self.__plugins): method_name = 'plugin_on_' + event.replace('-', '_') handler = getattr(plugin, method_name, None) def overridden(obj, name): return name in type(obj).__dict__ if overridden(plugin, method_name): try: handler(*args) except Exception: print_e("Error during %s on %s" % (method_name, type(plugin))) util.print_exc() if event not in ["removed", "changed"] and args: from quodlibet import app songs = args[0] if not isinstance(songs, (set, list)): songs = [songs] songs = filter(None, songs) check_wrapper_changed(librarian, app.window, songs)
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 plugin_songs(self, songs): for song in songs: song = song._song if not isinstance(song, ID3File): continue filename = song["~filename"] try: tag = ID3(filename) except Exception: util.print_exc() continue if not tag.getall("TLEN"): continue tag.delall("TLEN") try: tag.save() except Exception: util.print_exc() continue app.librarian.reload(song)
def __save_files(self, parent, model, library): win = WritingWindow(parent, len(model)) was_changed = set() for song, track in [(r[0], r[2]) for r in model]: if song.get("tracknumber") == track: win.step() continue if not song.valid() and not qltk.ConfirmAction( win, _("Tag may not be accurate"), _("<b>%s</b> changed while the program was running. " "Saving without refreshing your library may " "overwrite other changes to the song.\n\n" "Save this song anyway?") % util.escape(fsdecode(song("~basename")))).run(): break song["tracknumber"] = track try: song.write() except: util.print_exc() qltk.ErrorMessage( win, _("Unable to save song"), _("Saving <b>%s</b> failed. The file may be " "read-only, corrupted, or you do not have " "permission to edit it.") % util.escape(fsdecode(song('~basename')))).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break library.changed(was_changed) win.destroy()
def __process(self, source, condition, *args): if condition in (GLib.IO_ERR, GLib.IO_HUP): self.__open(*args) return False while True: try: data = source.read() except (IOError, OSError) as e: if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN): return True elif e.errno == errno.EINTR: continue else: self.__open(*args) return False break if not data: self.__open(*args) return False try: self.handle_data(data) except: util.print_exc() return True
def _load_items(filename): """Load items from disk. In case of an error returns default or an empty list. """ try: with open(filename, "rb") as fp: data = fp.read() except EnvironmentError: print_w("Couldn't load library file from: %r" % filename) return [] try: items = load_audio_files(data) except SerializationError: # there are too many ways this could fail util.print_exc() # move the broken file out of the way try: shutil.copy(filename, filename + ".not-valid") except EnvironmentError: util.print_exc() return [] return items
def plugin_songs(self, songs): for song in songs: song = song._song if not isinstance(song, ID3File): continue filename = song["~filename"] try: tag = ID3hack(filename) except Exception: util.print_exc() continue if not tag.getall("TLEN"): continue tag.delall("TLEN") try: tag.save() except Exception: util.print_exc() continue app.librarian.reload(song)
def handle_line(self, app, line): """Parses a command line and executes the command. Can not fail. Args: app (Application) line (fsnative) Returns: fsnative or None """ assert isinstance(line, fsnative) # only one arg supported atm parts = line.split(" ", 1) command = parts[0] args = parts[1:] print_d("command: %r(*%r)" % (command, args)) try: return self.run(app, command, *args) except CommandError as e: print_e(e) except: util.print_exc()
def load(self, filename, skip=False): """Load a library from a file, containing a picked list. Loading does not cause added, changed, or removed signals. """ self.filename = filename print_d("Loading contents of %r." % filename, self) try: if os.path.exists(filename): # pickle makes 1000 read syscalls for 6000 songs # read the file into memory so that there are less # context switches. saves 40% here.. fileobj = file(filename, "rb") try: items = pickle.loads(fileobj.read()) except (pickle.PickleError, EnvironmentError, ImportError, EOFError): util.print_exc() try: shutil.copy(filename, filename + ".not-valid") except EnvironmentError: util.print_exc() items = [] fileobj.close() else: return except EnvironmentError: return if skip: for item in filter(skip, items): self._contents[item.key] = item else: map(self._load, items) print_d("Done loading contents of %r." % filename, self)
def enable(self, plugin, status, force=False): """Enable or disable a plugin. Also takes an instance.""" if type(plugin) in self.__handlers: plugin = type(plugin) if not force and self.enabled(plugin) == bool(status): return if not status: print_d("Disable %r" % plugin.PLUGIN_ID) for handler in self.__handlers[plugin]: handler.plugin_disable(plugin) self.__enabled.discard(plugin.PLUGIN_ID) instance = self.__instance.get(plugin) if instance and hasattr(instance, "disabled"): try: instance.disabled() except Exception: util.print_exc() else: print_d("Enable %r" % plugin.PLUGIN_ID) obj = self.get_instance(plugin) if obj and hasattr(obj, "enabled"): try: obj.enabled() except Exception: util.print_exc() for handler in self.__handlers[plugin]: handler.plugin_enable(plugin, obj) self.__enabled.add(plugin.PLUGIN_ID)
def do_import(parent, library): db_path = expanduser(BansheeImport.USR_PATH) importer = BansheeDBImporter(library) try: db = sqlite3.connect(db_path) importer.read(db) db.close() except sqlite3.OperationalError: msg = _("Specified Banshee database is malformed or missing") WarningMessage(parent, BansheeImport.PLUGIN_NAME, msg).run() except Exception: util.print_exc() importer.finish() msg = _("Import Failed") # FIXME: don't depend on the plugin class here ErrorMessage(parent, BansheeImport.PLUGIN_NAME, msg).run() else: count = importer.finish() msg = ngettext( "Successfully imported ratings and statistics for %d song", "Successfully imported ratings and statistics for %d songs", count) % count Message(Gtk.MessageType.INFO, parent, BansheeImport.PLUGIN_NAME, msg).run()
def __save_files(self, parent, model, library): win = WritingWindow(parent, len(model)) was_changed = set() all_done = False for entry in model.itervalues(): song, track = entry.song, entry.tracknumber if song.get("tracknumber") == track: win.step() continue if not song.valid(): win.hide() dialog = OverwriteWarning(self, song) resp = dialog.run() win.show() if resp != OverwriteWarning.RESPONSE_SAVE: break song["tracknumber"] = track try: song.write() except AudioFileError: util.print_exc() WriteFailedError(self, song).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break else: all_done = True library.changed(was_changed) win.destroy() self.save.set_sensitive(not all_done) self.revert.set_sensitive(not all_done)
def __popup_menu(self, view, parent): menu = gtk.Menu() view.ensure_popup_selection() model, rows = view.get_selection().get_selected_rows() can_change = min([model[path][CANEDIT] for path in rows]) items = [ SplitDisc, SplitTitle, SplitPerformer, SplitArranger, SplitValues, SplitPerformerFromTitle, SplitOriginalArtistFromTitle, ] items.extend(self.handler.plugins) items.sort(key=lambda item: (item._order, item.__name__)) if len(rows) == 1: row = model[rows[0]] value = row[VALUE].decode("utf-8") text = util.unescape(value) multi = value.split("<")[0] != value for Item in items: if Item.tags and row[TAG] not in Item.tags: continue try: b = Item(row[TAG], text) except: util.print_exc() else: b.connect("activate", self.__menu_activate, view) if not min(map(self.__songinfo.can_change, b.needs) + [1]) or multi: b.set_sensitive(False) menu.append(b) if menu.get_children(): menu.append(gtk.SeparatorMenuItem()) b = gtk.ImageMenuItem(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU) b.connect("activate", self.__remove_tag, view) keyval, mod = gtk.accelerator_parse("Delete") menu.__accels = gtk.AccelGroup() b.add_accelerator("activate", menu.__accels, keyval, mod, gtk.ACCEL_VISIBLE) menu.append(b) menu.show_all() # Setting the menu itself to be insensitive causes it to not # be dismissed; see #473. for c in menu.get_children(): c.set_sensitive(can_change and c.get_property("sensitive")) menu.connect("selection-done", lambda m: m.destroy()) return view.popup_menu(menu, 3, gtk.get_current_event_time())
def _rewrite_json(self, obj, path): try: with path.open('w+', encoding='utf-8') as f: json.dump(obj, f, indent=self._get_json_indent()) except (ValueError, OSError): self._error_msg(_("Couldn't write '%s'") % path) print_e(f"Couldn't write {path} due to:") print_exc()
def __popup_menu(self, view, parent): menu = Gtk.Menu() view.ensure_popup_selection() model, rows = view.get_selection().get_selected_rows() can_change = min([model[path][0].canedit for path in rows]) items = [ SplitDisc, SplitTitle, SplitPerformer, SplitArranger, SplitValues, SplitPerformerFromTitle, SplitOriginalArtistFromTitle ] items.extend(self.handler.plugins) items.sort(key=lambda item: (item._order, item.__name__)) if len(rows) == 1: row = model[rows[0]] entry = row[0] comment = entry.value text = comment.text for Item in items: if Item.tags and entry.tag not in Item.tags: continue try: b = Item(entry.tag, text) except: util.print_exc() else: b.connect('activate', self.__menu_activate, view) if (not min( map(self.__songinfo.can_change, b.needs) + [1]) or comment.is_special()): b.set_sensitive(False) menu.append(b) if menu.get_children(): menu.append(SeparatorMenuItem()) b = MenuItem(_("_Remove"), Icons.LIST_REMOVE) b.connect('activate', self.__remove_tag, view) qltk.add_fake_accel(b, "Delete") menu.append(b) menu.show_all() # Setting the menu itself to be insensitive causes it to not # be dismissed; see #473. for c in menu.get_children(): c.set_sensitive(can_change and c.get_property('sensitive')) b.set_sensitive(True) menu.connect('selection-done', lambda m: m.destroy()) # XXX: Keep reference self.__menu = menu return view.popup_menu(menu, 3, Gtk.get_current_event_time())
def __popup_menu(self, view, parent): menu = Gtk.Menu() view.ensure_popup_selection() model, rows = view.get_selection().get_selected_rows() can_change = min([model[path][CANEDIT] for path in rows]) items = [SplitDisc, SplitTitle, SplitPerformer, SplitArranger, SplitValues, SplitPerformerFromTitle, SplitOriginalArtistFromTitle] items.extend(self.handler.plugins) items.sort(key=lambda item: (item._order, item.__name__)) if len(rows) == 1: row = model[rows[0]] value = row[VALUE].decode('utf-8') text = util.unescape(value) multi = (value.split("<")[0] != value) for Item in items: if Item.tags and row[TAG] not in Item.tags: continue try: b = Item(row[TAG], text) except: util.print_exc() else: b.connect('activate', self.__menu_activate, view) if (not min(map(self.__songinfo.can_change, b.needs) + [1]) or multi): b.set_sensitive(False) menu.append(b) if menu.get_children(): menu.append(SeparatorMenuItem()) b = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_REMOVE, None) b.connect('activate', self.__remove_tag, view) keyval, mod = Gtk.accelerator_parse("Delete") menu.__accels = Gtk.AccelGroup() b.add_accelerator( 'activate', menu.__accels, keyval, mod, Gtk.AccelFlags.VISIBLE) menu.append(b) menu.show_all() # Setting the menu itself to be insensitive causes it to not # be dismissed; see #473. for c in menu.get_children(): c.set_sensitive(can_change and c.get_property('sensitive')) menu.connect('selection-done', lambda m: m.destroy()) # XXX: Keep reference self.__menu = menu return view.popup_menu(menu, 3, Gtk.get_current_event_time())
def __popup_menu(self, view, parent): menu = Gtk.Menu() view.ensure_popup_selection() model, rows = view.get_selection().get_selected_rows() can_change = min([model[path][0].canedit for path in rows]) items = [SplitDisc, SplitTitle, SplitPerformer, SplitArranger, SplitValues, SplitPerformerFromTitle, SplitOriginalArtistFromTitle] items.extend(self.handler.plugins) items.sort(key=lambda item: (item._order, item.__name__)) if len(rows) == 1: row = model[rows[0]] entry = row[0] comment = entry.value text = comment.text for Item in items: if Item.tags and entry.tag not in Item.tags: continue try: b = Item(entry.tag, text) except: util.print_exc() else: b.connect('activate', self.__menu_activate, view) if (not min(listmap(self.__songinfo.can_change, b.needs) + [1]) or comment.is_special()): b.set_sensitive(False) menu.append(b) if menu.get_children(): menu.append(SeparatorMenuItem()) b = MenuItem(_("_Remove"), Icons.LIST_REMOVE) b.connect('activate', self.__remove_tag, view) qltk.add_fake_accel(b, "Delete") menu.append(b) menu.show_all() # Setting the menu itself to be insensitive causes it to not # be dismissed; see #473. for c in menu.get_children(): c.set_sensitive(can_change and c.get_property('sensitive')) b.set_sensitive(True) menu.connect('selection-done', lambda m: m.destroy()) # XXX: Keep reference self.__menu = menu return view.popup_menu(menu, 3, Gtk.get_current_event_time())
def Menu(self, library, songs): songs = ListWrapper(songs) attrs = [ 'plugin_song', 'plugin_songs', 'plugin_album', 'plugin_albums' ] if len(songs) == 1: attrs.append('plugin_single_song') last = (songs and songs[-1]) or None for song in songs: if song.album_key != last.album_key: break last = song else: attrs.append('plugin_single_album') items = [] kinds = self.__plugins kinds.sort(key=lambda plugin: plugin.PLUGIN_ID) for Kind in kinds: usable = max([callable(getattr(Kind, s)) for s in attrs]) if usable: try: items.append(Kind(songs, library)) except: print_e( "Couldn't initialise song plugin %s. Stack trace:" % Kind) print_exc() items = filter(lambda i: i.initialized, items) if items: menu = Gtk.Menu() for item in items: try: menu.append(item) args = (library, songs) if item.get_submenu(): for subitem in item.get_submenu().get_children(): subitem.connect('activate', self.__on_activate, item, *args) else: item.connect('activate', self.__on_activate, item, *args) except: print_exc() item.destroy() menu.append(SeparatorMenuItem()) prefs = Gtk.MenuItem(label=_("Configure Plugins…")) prefs.connect("activate", lambda _: PluginWindow().show()) menu.append(prefs) else: menu = None return menu
def MusicFile(filename): """Returns a AudioFile instance or None""" loader = get_loader(filename) if loader is not None: try: return loader(filename) except AudioFileError: print_w("Error loading %r" % filename) util.print_exc()
def wrap(): # check once we are scheduled if not cancellable.is_cancelled(): try: return function(*args, **kwargs) except: # ThreadPool catches the exception for the async result # which we don't use. Print instead as if it was not catched. util.print_exc() raise
def _set_status(self, text): print_d("Setting status to \"%s\"..." % text) self.status = text try: accounts = get_active_account_paths() # TODO: account filtering set_accounts_requested_presence(accounts, text) except dbus.DBusException: print_d("...but setting failed") util.print_exc()
def _set_status(self, text): print_d("Setting status to \"%s\"..." % text) self.status = text try: accounts = get_active_account_paths() # TODO: account filtering set_accounts_requested_presence(accounts, text) except GLib.Error: print_d("...but setting failed") util.print_exc()
def plugin_handle(self, plugin): try: ok = issubclass(plugin, GStreamerPlugin) and plugin.setup_element() except Exception: util.print_exc() ok = False if ok: plugin._handler = self return ok
def Menu(self, library, songs): songs = ListWrapper(songs) attrs = ['plugin_song', 'plugin_songs', 'plugin_album', 'plugin_albums'] if len(songs) == 1: attrs.append('plugin_single_song') last = (songs and songs[-1]) or None for song in songs: if song.album_key != last.album_key: break last = song else: attrs.append('plugin_single_album') items = [] kinds = self.__plugins kinds.sort(key=lambda plugin: plugin.PLUGIN_ID) for Kind in kinds: usable = max([callable(getattr(Kind, s)) for s in attrs]) if usable: try: items.append(Kind(songs, library)) except: print_e("Couldn't initialise song plugin %s. Stack trace:" % Kind) print_exc() items = filter(lambda i: i.initialized, items) if items: menu = Gtk.Menu() for item in items: try: menu.append(item) args = (library, songs) if item.get_submenu(): for subitem in item.get_submenu().get_children(): subitem.connect( 'activate', self.__on_activate, item, *args) else: item.connect( 'activate', self.__on_activate, item, *args) except: print_exc() item.destroy() menu.append(SeparatorMenuItem()) prefs = Gtk.MenuItem(label=_("Configure Plugins…")) prefs.connect("activate", lambda _: PluginWindow().show()) menu.append(prefs) else: menu = None return menu
def plugin_song(self, song): try: apesong = APEv2File(song["~filename"]) except: return # File doesn't have an APEv2 tag song.update(apesong) mutagen.apev2.delete(song["~filename"]) try: song._song.write() except AudioFileError: print_exc()
def __rename(self, library): model = self.view.get_model() win = WritingWindow(self, len(model)) win.show() was_changed = set() skip_all = False self.view.freeze_child_notify() for entry in model.itervalues(): song = entry.song new_name = entry.new_name old_name = entry.name if new_name is None: continue try: library.rename(song, fsnative(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 win.step(): break self.view.thaw_child_notify() win.destroy() library.changed(was_changed) self.save.set_sensitive(False)
def __delete(self, delete, song, save): # First, delete from the tags. song.remove("lyrics") try: song.write() except AudioFileError: util.print_exc() self._delete_file(song.lyric_filename) delete.set_sensitive(False) save.set_sensitive(True)
def __save(self, addreplace, library): pattern_text = self.combo.get_child().get_text().decode('utf-8') pattern = TagsFromPattern(pattern_text) model = self.view.get_model() add = bool(addreplace.get_active()) win = WritingWindow(self, len(model)) win.show() was_changed = set() all_done = False for entry in ((model and model.itervalues()) or []): song = entry.song changed = False if not song.valid(): win.hide() dialog = OverwriteWarning(self, song) resp = dialog.run() win.show() if resp != OverwriteWarning.RESPONSE_SAVE: break for i, h in enumerate(pattern.headers): text = entry.get_match(h) if text: can_multiple = song.can_multiple_values(h) if not add or h not in song or not can_multiple: song[h] = text changed = True else: for val in text.split("\n"): if val not in song.list(h): song.add(h, val) changed = True if changed: try: song.write() except: util.print_exc() WriteFailedError(self, song).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break else: all_done = True win.destroy() library.changed(was_changed) self.save.set_sensitive(not all_done)
def _on_comments_received(self, client, track_id, comments): def bookmark_for(com): text = "\"%s\" --%s" % (com['body'], com['user']['username']) return max(0, int((com.get('timestamp') or 0) / 1000.0)), text try: song = self.song_by_track_id(track_id) except KeyError: # https://github.com/quodlibet/quodlibet/issues/2410 print_exc() return song.bookmarks = [bookmark_for(c) for c in comments]
def __save(self, addreplace, library): pattern_text = gdecode(self.combo.get_child().get_text()) pattern = TagsFromPattern(pattern_text) model = self.view.get_model() add = bool(addreplace.get_active()) win = WritingWindow(self, len(model)) win.show() was_changed = set() all_done = False for entry in ((model and model.itervalues()) or []): song = entry.song changed = False if not song.valid(): win.hide() dialog = OverwriteWarning(self, song) resp = dialog.run() win.show() if resp != OverwriteWarning.RESPONSE_SAVE: break for i, h in enumerate(pattern.headers): text = entry.get_match(h) if text: can_multiple = song.can_multiple_values(h) if not add or h not in song or not can_multiple: song[h] = text changed = True else: for val in text.split("\n"): if val not in song.list(h): song.add(h, val) changed = True if changed: try: song.write() except AudioFileError: util.print_exc() WriteFailedError(self, song).run() library.reload(song, changed=was_changed) break was_changed.add(song) if win.step(): break else: all_done = True win.destroy() library.changed(was_changed) self.save.set_sensitive(not all_done)
def handle(self, plugin_id, library, parent, playlists): """Start a plugin directly without a menu""" for plugin in self.__plugins: if plugin.PLUGIN_ID == plugin_id: try: plugin = plugin(playlists, library, parent) except Exception: print_exc() else: self.__handle(plugin, library, parent, playlists) return
def Menu(self, library, parent, songs): songs = ListWrapper(songs) parent = qltk.get_top_parent(parent) attrs = [ 'plugin_song', 'plugin_songs', 'plugin_album', 'plugin_albums' ] if len(songs) == 1: attrs.append('plugin_single_song') last = (songs and songs[-1]) or None for song in songs: if song.album_key != last.album_key: break last = song else: attrs.append('plugin_single_album') items = [] kinds = self.__plugins kinds.sort(key=lambda plugin: plugin.PLUGIN_ID) for Kind in kinds: usable = max([callable(getattr(Kind, s)) for s in attrs]) if usable: try: items.append(Kind(songs, library, parent)) except: print_e( "Couldn't initialise song plugin %s. Stack trace:" % Kind) print_exc() items = filter(lambda i: i.initialized, items) if items: menu = Gtk.Menu() for item in items: try: menu.append(item) args = (library, parent, songs) if item.get_submenu(): for subitem in item.get_submenu().get_children(): subitem.connect_object('activate', self.__handle, item, *args) else: item.connect('activate', self.__handle, *args) except: print_exc() item.destroy() else: menu = None return menu
def handle(self, plugin_id, library, parent, songs): """Start a song menu plugin directly without a menu""" for plugin in self.__plugins: if plugin.PLUGIN_ID == plugin_id: songs = ListWrapper(songs) try: plugin = plugin(songs, library, parent) except Exception: print_exc() else: self.__handle(plugin, library, parent, songs) return
def __get_media_player_id(self, devpath): """DKD is for high-level device stuff. The info if the device is a media player and what protocol/formats it supports can only be retrieved through libudev""" try: dev = get_device_from_path(self.__udev, devpath) except Exception: print_w("Failed to retrieve udev properties for %r" % devpath) util.print_exc() return try: return dev["ID_MEDIA_PLAYER"] except KeyError: return None
def handle(self, plugin_id, library, browser, playlists): """Start a plugin directly without a menu""" for plugin in self.__plugins: if plugin.PLUGIN_ID == plugin_id: try: plugin = plugin(playlists, library) except Exception: print_exc() else: parent = get_top_parent(browser) self.__handle(plugin, library, browser, playlists, parent) return
def __write(self, widget, model): filenames = [row[0]["~filename"] for row in model] try: with open(QUEUE, "wb") as f: for filename in filenames: try: line = fsn2bytes(filename, "utf-8") except ValueError: print_exc() continue f.write(line + b"\n") except EnvironmentError: print_exc()