Exemple #1
0
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
Exemple #2
0
    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")
Exemple #3
0
    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()
Exemple #6
0
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
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
    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)
Exemple #10
0
 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()
Exemple #11
0
    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)
Exemple #12
0
    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)
Exemple #13
0
    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()
Exemple #15
0
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
Exemple #16
0
    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 __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
Exemple #18
0
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
Exemple #19
0
    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)
Exemple #20
0
    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()
Exemple #21
0
    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)
Exemple #22
0
    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)
Exemple #23
0
    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)
Exemple #24
0
    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)
Exemple #25
0
    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)
Exemple #26
0
    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()
Exemple #27
0
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)
Exemple #29
0
    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())
Exemple #30
0
 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()
Exemple #31
0
    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())
Exemple #32
0
    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())
Exemple #33
0
    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())
Exemple #34
0
    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
Exemple #35
0
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()
Exemple #36
0
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()
Exemple #37
0
 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
Exemple #38
0
 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
Exemple #39
0
 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()
Exemple #40
0
 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()
Exemple #41
0
    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
Exemple #42
0
    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
Exemple #43
0
 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()
Exemple #44
0
    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)
Exemple #45
0
    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)
Exemple #46
0
    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)
Exemple #47
0
 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()
Exemple #48
0
    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)
Exemple #49
0
    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]
Exemple #50
0
    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)
Exemple #51
0
    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]
Exemple #52
0
    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
Exemple #53
0
    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
Exemple #54
0
    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)
Exemple #55
0
    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
Exemple #56
0
    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
Exemple #57
0
    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
Exemple #58
0
    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
Exemple #59
0
 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()
Exemple #60
0
 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()