Exemple #1
0
def get_sort_tag(tag):
    """Returns a tag that can be used for sorting for the given column tag.

    Returns '' if the default sort key should be used.
    """

    replace_order = {"~#track": "", "~#disc": "", "~length": "~#length"}

    if tag == "~title~version":
        tag = "title"
    elif tag == "~album~discsubtitle":
        tag = "album"

    if "<" in tag:
        for key, value in iteritems(replace_order):
            tag = tag.replace("<%s>" % key, "<%s>" % value)
        for key, value in iteritems(TAG_TO_SORT):
            tag = tag.replace("<%s>" % key,
                              "<{1}|<{1}>|<{0}>>".format(key, value))
        tag = Pattern(tag).format
    else:
        tags = util.tagsplit(tag)
        sort_tags = []
        for tag in tags:
            tag = replace_order.get(tag, tag)
            tag = TAG_TO_SORT.get(tag, tag)
            if tag not in sort_tags:
                sort_tags.append(tag)
        if len(sort_tags) > 1:
            tag = "~" + "~".join(sort_tags)

    return tag
Exemple #2
0
def init_defaults():
    """Fills in the defaults, so they are guaranteed to be available"""

    _config.defaults.clear()
    for section, values in iteritems(INITIAL):
        _config.defaults.add_section(section)
        for key, value in iteritems(values):
            _config.defaults.set(section, key, value)
Exemple #3
0
def init_defaults():
    """Fills in the defaults, so they are guaranteed to be available"""

    _config.defaults.clear()
    for section, values in iteritems(INITIAL):
        _config.defaults.add_section(section)
        for key, value in iteritems(values):
            _config.defaults.set(section, key, value)
Exemple #4
0
    def _fill_stream(self, tags, librarian):
        # get a new remote file
        new_info = self.__info_buffer
        if not new_info:
            new_info = type(self.song)(self.song["~filename"])
            new_info.multisong = False
            new_info.streamsong = True

            # copy from the old songs
            # we should probably listen to the library for self.song changes
            new_info.update(self.song)
            new_info.update(self.info)

        changed = False
        info_changed = False

        tags = TagListWrapper(tags, merge=True)
        tags = parse_gstreamer_taglist(tags)

        for key, value in iteritems(sanitize_tags(tags, stream=False)):
            if self.song.get(key) != value:
                changed = True
                self.song[key] = value

        for key, value in iteritems(sanitize_tags(tags, stream=True)):
            if new_info.get(key) != value:
                info_changed = True
                new_info[key] = value

        if info_changed:
            # in case the title changed, make self.info a new instance
            # and emit ended/started for the the old/new one
            if self.info.get("title") != new_info.get("title"):
                if self.info is not self.song:
                    self.emit('song-ended', self.info, False)
                self.info = new_info
                self.__info_buffer = None
                self.emit('song-started', self.info)
            else:
                # in case title didn't changed, update the values of the
                # old instance if there is one and tell the library.
                if self.info is not self.song:
                    self.info.update(new_info)
                    librarian.changed([self.info])
                else:
                    # So we don't loose all tags before the first title
                    # save it for later
                    self.__info_buffer = new_info

        if changed:
            librarian.changed([self.song])
Exemple #5
0
    def _fill_stream(self, tags, librarian):
        # get a new remote file
        new_info = self.__info_buffer
        if not new_info:
            new_info = type(self.song)(self.song["~filename"])
            new_info.multisong = False
            new_info.streamsong = True

            # copy from the old songs
            # we should probably listen to the library for self.song changes
            new_info.update(self.song)
            new_info.update(self.info)

        changed = False
        info_changed = False

        tags = TagListWrapper(tags, merge=True)
        tags = parse_gstreamer_taglist(tags)

        for key, value in iteritems(sanitize_tags(tags, stream=False)):
            if self.song.get(key) != value:
                changed = True
                self.song[key] = value

        for key, value in iteritems(sanitize_tags(tags, stream=True)):
            if new_info.get(key) != value:
                info_changed = True
                new_info[key] = value

        if info_changed:
            # in case the title changed, make self.info a new instance
            # and emit ended/started for the the old/new one
            if self.info.get("title") != new_info.get("title"):
                if self.info is not self.song:
                    self.emit('song-ended', self.info, False)
                self.info = new_info
                self.__info_buffer = None
                self.emit('song-started', self.info)
            else:
                # in case title didn't changed, update the values of the
                # old instance if there is one and tell the library.
                if self.info is not self.song:
                    self.info.update(new_info)
                    librarian.changed([self.info])
                else:
                    # So we don't loose all tags before the first title
                    # save it for later
                    self.__info_buffer = new_info

        if changed:
            librarian.changed([self.song])
 def __load_tags(self, tags, expected):
     m = OggVorbis(self.filename)
     for key, value in iteritems(tags):
         m.tags[key] = value
     m.save()
     song = OggFile(self.filename)
     for key, value in iteritems(expected):
         self.failUnlessEqual(song(key), value)
     if self.MAIN not in expected:
         self.failIf(self.MAIN in song)
     if self.SINGLE not in expected:
         self.failIf(self.SINGLE in song)
     if self.FALLBACK not in expected:
         self.failIf(self.FALLBACK in song)
Exemple #7
0
 def __load_tags(self, tags, expected):
     m = OggVorbis(self.filename)
     for key, value in iteritems(tags):
         m.tags[key] = value
     m.save()
     song = OggFile(self.filename)
     for key, value in iteritems(expected):
         self.failUnlessEqual(song(key), value)
     if self.MAIN not in expected:
         self.failIf(self.MAIN in song)
     if self.SINGLE not in expected:
         self.failIf(self.SINGLE in song)
     if self.FALLBACK not in expected:
         self.failIf(self.FALLBACK in song)
Exemple #8
0
    def emit_properties_changed(self, interface, properties, path="/"):
        """Emits PropertiesChanged for the specified properties"""

        combos = {}
        for prop in properties:
            iface = self.get_interface(interface, prop)
            if iface is None:
                raise ValueError("Property %s not registered" % prop)
            combos.setdefault(iface, []).append(prop)

        for iface, props in iteritems(combos):
            values = {}
            inval = []
            for prop in props:
                emit = self.__props[iface][prop]["emit"]
                if emit == "false":
                    raise ValueError("Can't emit changed signal for %s" % prop)
                elif emit == "true":
                    values[prop] = self.get_value(iface, prop, path)
                elif emit == "invalidates":
                    inval.append(prop)

            if self.SUPPORTS_MULTIPLE_OBJECT_PATHS:
                self.PropertiesChanged(iface, values, inval, rel=path)
            else:
                self.PropertiesChanged(iface, values, inval)
Exemple #9
0
    def _text_to_song(self, text, song):
        assert isinstance(text, text_type)

        # parse
        tags = {}
        for line in text.splitlines():
            if not line.strip() or line.startswith(u"#"):
                continue
            try:
                key, value = line.split(u"=", 1)
            except ValueError:
                continue

            tags.setdefault(key, []).append(value)

        # apply changes, sort to always have the same output
        for key in sorted(song.realkeys(), key=sortkey):
            new = tags.pop(key, [])
            old = song.list(key)
            for value in old:
                if value not in new:
                    self.log("Remove %s=%s" % (key, value))
                    song.remove(key, value)
            for value in new:
                if value not in old:
                    self.log("Add %s=%s" % (key, value))
                    song.add(key, value)

        for key, values in iteritems(tags):
            if not song.can_change(key):
                raise CommandError(
                    "Can't change key '%(key-name)s'." % {"key-name": key})
            for value in values:
                self.log("Add %s=%s" % (key, value))
                song.add(key, value)
Exemple #10
0
def enum(cls):
    """Class decorator for enum types::

        @enum
        class SomeEnum(int):
            FOO = 0
            BAR = 1

    Result is an int subclass and all attributes are instances of it.
    """

    type_ = cls.__bases__[0]

    d = dict(cls.__dict__)
    new_type = type(cls.__name__, (type_, ), d)
    new_type.__module__ = cls.__module__

    map_ = {}
    for key, value in iteritems(d):
        if key.upper() == key and isinstance(value, type_):
            value_instance = new_type(value)
            setattr(new_type, key, value_instance)
            map_[value] = key

    def repr_(self):
        if self in map_:
            return "%s.%s" % (type(self).__name__, map_[self])
        else:
            return "%s(%s)" % (type(self).__name__, self)

    setattr(new_type, "__repr__", repr_)

    return new_type
Exemple #11
0
    def __init__(self, parent, library):
        DBusIntrospectable.__init__(self)
        DBusPropertyFilter.__init__(self)
        MediaObject.__init__(self, parent)
        MediaContainer.__init__(self)

        bus = dbus.SessionBus()
        self.ref = dbus.service.BusName(BUS_NAME, bus)
        dbus.service.FallbackObject.__init__(self, bus, self.PATH)

        parent.register_child(self)

        self.__library = library.albums
        self.__library.load()

        self.__map = dict((id(v), v) for v in itervalues(self.__library))
        self.__reverse = dict((v, k) for k, v in iteritems(self.__map))

        signals = [
            ("changed", self.__albums_changed),
            ("removed", self.__albums_removed),
            ("added", self.__albums_added),
        ]
        self.__sigs = map(
            lambda x: self.__library.connect(x[0], x[1]), signals)

        self.__dummy = DummyAlbumObject(self)
Exemple #12
0
    def __init__(self, library, users):
        DBusIntrospectable.__init__(self)
        DBusProperty.__init__(self)
        MediaObject.__init__(self, None)
        MediaItem.__init__(self, optional=SUPPORTED_SONG_PROPERTIES)

        bus = dbus.SessionBus()
        self.ref = dbus.service.BusName(BUS_NAME, bus)
        dbus.service.FallbackObject.__init__(self, bus, self.PATH)

        self.__library = library
        self.__map = dict((id(v), v) for v in itervalues(self.__library))
        self.__reverse = dict((v, k) for k, v in iteritems(self.__map))

        self.__song = DummySongObject(self)

        self.__users = users

        signals = [
            ("changed", self.__songs_changed),
            ("removed", self.__songs_removed),
            ("added", self.__songs_added),
        ]
        self.__sigs = map(
            lambda x: self.__library.connect(x[0], x[1]), signals)
Exemple #13
0
 def test_handles_albums(self):
     for id_, plugin in iteritems(self.plugins):
         if isinstance(plugin, SongsMenuPlugin):
             ha = plugin.handles_albums
             self.failIf(hasattr(plugin, "plugin_single_album") and not ha)
             self.failIf(hasattr(plugin, "plugin_plugin_album") and not ha)
             self.failIf(hasattr(plugin, "plugin_albums") and not ha)
Exemple #14
0
 def test_handles_albums(self):
     for id_, plugin in iteritems(self.plugins):
         if isinstance(plugin, SongsMenuPlugin):
             ha = plugin.handles_albums
             self.failIf(hasattr(plugin, "plugin_single_album") and not ha)
             self.failIf(hasattr(plugin, "plugin_plugin_album") and not ha)
             self.failIf(hasattr(plugin, "plugin_albums") and not ha)
Exemple #15
0
    def test_main(self):
        args = {"reply_handler": self._reply, "error_handler": self._error}
        piface = "org.mpris.MediaPlayer2"

        app.window.hide()
        self.failIf(app.window.get_visible())
        self._main_iface().Raise(**args)
        self.failIf(self._wait())
        self.failUnless(app.window.get_visible())
        app.window.hide()

        props = {
            "CanQuit": dbus.Boolean(True),
            "CanRaise": dbus.Boolean(True),
            "CanSetFullscreen": dbus.Boolean(False),
            "HasTrackList": dbus.Boolean(False),
            "Identity": dbus.String("Quod Libet"),
            "DesktopEntry": dbus.String("quodlibet"),
            "SupportedUriSchemes": dbus.Array(),
        }

        for key, value in iteritems(props):
            self._prop().Get(piface, key, **args)
            resp = self._wait()[0]
            self.failUnlessEqual(resp, value)
            self.failUnless(isinstance(resp, type(value)))

        self._prop().Get(piface, "SupportedMimeTypes", **args)
        self.failUnless("audio/vorbis" in self._wait()[0])

        self._introspect_iface().Introspect(**args)
        assert self._wait()
Exemple #16
0
    def test_player(self):
        args = {"reply_handler": self._reply, "error_handler": self._error}
        piface = "org.mpris.MediaPlayer2.Player"

        props = {
            "PlaybackStatus": dbus.String("Stopped"),
            "LoopStatus": dbus.String("None"),
            "Rate": dbus.Double(1.0),
            "Shuffle": dbus.Boolean(False),
            "Volume": dbus.Double(1.0),
            "Position": dbus.Int64(0),
            "MinimumRate": dbus.Double(1.0),
            "MaximumRate": dbus.Double(1.0),
            "CanGoNext": dbus.Boolean(True),
            "CanGoPrevious": dbus.Boolean(True),
            "CanPlay": dbus.Boolean(True),
            "CanPause": dbus.Boolean(True),
            "CanSeek": dbus.Boolean(True),
            "CanControl": dbus.Boolean(True),
        }

        for key, value in iteritems(props):
            self._prop().Get(piface, key, **args)
            resp = self._wait(msg="for key '%s'" % key)[0]
            self.failUnlessEqual(resp, value)
            self.failUnless(isinstance(resp, type(value)))
Exemple #17
0
def enum(cls):
    """Class decorator for enum types::

        @enum
        class SomeEnum(int):
            FOO = 0
            BAR = 1

    Result is an int subclass and all attributes are instances of it.
    """

    type_ = cls.__bases__[0]

    d = dict(cls.__dict__)
    new_type = type(cls.__name__, (type_,), d)
    new_type.__module__ = cls.__module__

    map_ = {}
    for key, value in iteritems(d):
        if key.upper() == key:
            value_instance = new_type(value)
            setattr(new_type, key, value_instance)
            map_[value] = key

    def repr_(self):
        if self in map_:
            return "%s.%s" % (type(self).__name__, map_[self])
        else:
            return "%s(%s)" % (type(self).__name__, self)

    setattr(new_type, "__repr__", repr_)

    return new_type
Exemple #18
0
    def __init__(self, parent, library):
        DBusIntrospectable.__init__(self)
        DBusPropertyFilter.__init__(self)
        MediaObject.__init__(self, parent)
        MediaContainer.__init__(self)

        bus = dbus.SessionBus()
        self.ref = dbus.service.BusName(BUS_NAME, bus)
        dbus.service.FallbackObject.__init__(self, bus, self.PATH)

        parent.register_child(self)

        self.__library = library.albums
        self.__library.load()

        self.__map = dict((id(v), v) for v in itervalues(self.__library))
        self.__reverse = dict((v, k) for k, v in iteritems(self.__map))

        signals = [
            ("changed", self.__albums_changed),
            ("removed", self.__albums_removed),
            ("added", self.__albums_added),
        ]
        self.__sigs = map(lambda x: self.__library.connect(x[0], x[1]),
                          signals)

        self.__dummy = DummyAlbumObject(self)
Exemple #19
0
    def __init__(self, library, users):
        DBusIntrospectable.__init__(self)
        DBusProperty.__init__(self)
        MediaObject.__init__(self, None)
        MediaItem.__init__(self, optional=SUPPORTED_SONG_PROPERTIES)

        bus = dbus.SessionBus()
        self.ref = dbus.service.BusName(BUS_NAME, bus)
        dbus.service.FallbackObject.__init__(self, bus, self.PATH)

        self.__library = library
        self.__map = dict((id(v), v) for v in itervalues(self.__library))
        self.__reverse = dict((v, k) for k, v in iteritems(self.__map))

        self.__song = DummySongObject(self)

        self.__users = users

        signals = [
            ("changed", self.__songs_changed),
            ("removed", self.__songs_removed),
            ("added", self.__songs_added),
        ]
        self.__sigs = map(lambda x: self.__library.connect(x[0], x[1]),
                          signals)
Exemple #20
0
    def emit_properties_changed(self, interface, properties, path="/"):
        """Emits PropertiesChanged for the specified properties"""

        combos = {}
        for prop in properties:
            iface = self.get_interface(interface, prop)
            if iface is None:
                raise ValueError("Property %s not registered" % prop)
            combos.setdefault(iface, []).append(prop)

        for iface, props in iteritems(combos):
            values = {}
            inval = []
            for prop in props:
                emit = self.__props[iface][prop]["emit"]
                if emit == "false":
                    raise ValueError("Can't emit changed signal for %s" % prop)
                elif emit == "true":
                    values[prop] = self.get_value(iface, prop, path)
                elif emit == "invalidates":
                    inval.append(prop)

            if self.SUPPORTS_MULTIPLE_OBJECT_PATHS:
                self.PropertiesChanged(iface, values, inval, rel=path)
            else:
                self.PropertiesChanged(iface, values, inval)
Exemple #21
0
    def _text_to_song(self, text, song):
        assert isinstance(text, text_type)

        # parse
        tags = {}
        for line in text.splitlines():
            if not line.strip() or line.startswith(u"#"):
                continue
            try:
                key, value = line.split(u"=", 1)
            except ValueError:
                continue

            tags.setdefault(key, []).append(value)

        # apply changes, sort to always have the same output
        for key in sorted(song.realkeys(), key=sortkey):
            new = tags.pop(key, [])
            old = song.list(key)
            for value in old:
                if value not in new:
                    self.log("Remove %s=%s" % (key, value))
                    song.remove(key, value)
            for value in new:
                if value not in old:
                    self.log("Add %s=%s" % (key, value))
                    song.add(key, value)

        for key, values in iteritems(tags):
            if not song.can_change(key):
                raise CommandError(
                    "Can't change key '%(key-name)s'." % {"key-name": key})
            for value in values:
                self.log("Add %s=%s" % (key, value))
                song.add(key, value)
Exemple #22
0
    def test_main(self):
        args = {"reply_handler": self._reply, "error_handler": self._error}
        piface = "org.mpris.MediaPlayer2"

        app.window.hide()
        self.failIf(app.window.get_visible())
        self._main_iface().Raise(**args)
        self.failIf(self._wait())
        self.failUnless(app.window.get_visible())
        app.window.hide()

        props = {
            "CanQuit": dbus.Boolean(True),
            "CanRaise": dbus.Boolean(True),
            "CanSetFullscreen": dbus.Boolean(False),
            "HasTrackList": dbus.Boolean(False),
            "Identity": dbus.String("Quod Libet"),
            "DesktopEntry": dbus.String("quodlibet"),
            "SupportedUriSchemes": dbus.Array(),
        }

        for key, value in iteritems(props):
            self._prop().Get(piface, key, **args)
            resp = self._wait()[0]
            self.failUnlessEqual(resp, value)
            self.failUnless(isinstance(resp, type(value)))

        self._prop().Get(piface, "SupportedMimeTypes", **args)
        self.failUnless("audio/vorbis" in self._wait()[0])
Exemple #23
0
    def test_player(self):
        args = {"reply_handler": self._reply, "error_handler": self._error}
        piface = "org.mpris.MediaPlayer2.Player"

        props = {
            "PlaybackStatus": dbus.String("Stopped"),
            "LoopStatus": dbus.String("None"),
            "Rate": dbus.Double(1.0),
            "Shuffle": dbus.Boolean(False),
            "Volume": dbus.Double(1.0),
            "Position": dbus.Int64(0),
            "MinimumRate": dbus.Double(1.0),
            "MaximumRate": dbus.Double(1.0),
            "CanGoNext": dbus.Boolean(True),
            "CanGoPrevious": dbus.Boolean(True),
            "CanPlay": dbus.Boolean(True),
            "CanPause": dbus.Boolean(True),
            "CanSeek": dbus.Boolean(True),
            "CanControl": dbus.Boolean(True),
        }

        for key, value in iteritems(props):
            self._prop().Get(piface, key, **args)
            resp = self._wait(msg="for key '%s'" % key)[0]
            self.failUnlessEqual(resp, value)
            self.failUnless(isinstance(resp, type(value)))
Exemple #24
0
    def plugin_album(self, songs):

        songs.sort(key=sort_key_for)

        chooser = filechooser(save=False, title=songs[0]('album'))
        box = Gtk.HBox()
        rename = Gtk.CheckButton("Rename Files")
        rename.set_active(False)
        box.pack_start(rename, True, True, 0)
        append = Gtk.CheckButton("Append Metadata")
        append.set_active(True)
        box.pack_start(append, True, True, 0)
        box.show_all()
        chooser.set_extra_widget(box)

        resp = chooser.run()
        append = append.get_active()
        rename = rename.get_active()
        fn = chooser.get_filename()
        chooser.destroy()
        if resp != Gtk.ResponseType.ACCEPT:
            return

        global lastfolder
        lastfolder = dirname(fn)

        metadata = []
        names = []
        index = 0
        for line in open(fn, 'rU'):
            if index == len(metadata):
                names.append(line[:line.rfind('.')])
                metadata.append({})
            elif line == '\n':
                index = len(metadata)
            else:
                key, value = line[:-1].split('=', 1)
                value = value.decode('utf-8')
                try:
                    metadata[index][key].append(value)
                except KeyError:
                    metadata[index][key] = [value]

        if not (len(songs) == len(metadata) == len(names)):
            ErrorMessage(None, "Songs mismatch",
                         "There are %(select)d songs selected, but %(meta)d "
                         "songs in the file. Aborting." %
                         dict(select=len(songs), meta=len(metadata))).run()
            return

        for song, meta, name in zip(songs, metadata, names):
            for key, values in iteritems(meta):
                if append and key in song:
                    values = song.list(key) + values
                song[key] = '\n'.join(values)
            if rename:
                origname = song['~filename']
                newname = name + origname[origname.rfind('.'):]
                app.library.rename(origname, newname)
Exemple #25
0
def _get_role_map(tags):
    roles = {}
    for (name, tag) in iteritems(tags):
        if tag.role:
            roles[name] = tag.role
            if tag.has_sort:
                roles[name + "sort"] = tag.role
    return roles
Exemple #26
0
def _get_standard_tags(tags, machine=False):
    stags = []
    for name, tag in iteritems(tags):
        if tag.user and tag.machine == machine:
            stags.append(name)
            if tag.has_sort:
                stags.append("%ssort" % name)
    return stags
Exemple #27
0
def _get_role_map(tags):
    roles = {}
    for (name, tag) in iteritems(tags):
        if tag.role:
            roles[name] = tag.role
            if tag.has_sort:
                roles[name + "sort"] = tag.role
    return roles
Exemple #28
0
def _get_standard_tags(tags, machine=False):
    stags = []
    for name, tag in iteritems(tags):
        if tag.user and tag.machine == machine:
            stags.append(name)
            if tag.has_sort:
                stags.append("%ssort" % name)
    return stags
Exemple #29
0
    def plugin_album(self, songs):

        songs.sort(key=sort_key_for)

        chooser = filechooser(save=False, title=songs[0]('album'))
        box = Gtk.HBox()
        rename = Gtk.CheckButton("Rename Files")
        rename.set_active(False)
        box.pack_start(rename, True, True, 0)
        append = Gtk.CheckButton("Append Metadata")
        append.set_active(True)
        box.pack_start(append, True, True, 0)
        box.show_all()
        chooser.set_extra_widget(box)

        resp = chooser.run()
        append = append.get_active()
        rename = rename.get_active()
        fn = chooser.get_filename()
        chooser.destroy()
        if resp != Gtk.ResponseType.ACCEPT:
            return

        global lastfolder
        lastfolder = dirname(fn)

        metadata = []
        names = []
        index = 0
        for line in open(fn, 'r', encoding="utf-8"):
            if index == len(metadata):
                names.append(line[:line.rfind('.')])
                metadata.append({})
            elif line == '\n':
                index = len(metadata)
            else:
                key, value = line[:-1].split('=', 1)
                try:
                    metadata[index][key].append(value)
                except KeyError:
                    metadata[index][key] = [value]

        if not (len(songs) == len(metadata) == len(names)):
            ErrorMessage(None, "Songs mismatch",
                         "There are %(select)d songs selected, but %(meta)d "
                         "songs in the file. Aborting." %
                         dict(select=len(songs), meta=len(metadata))).run()
            return

        for song, meta, name in zip(songs, metadata, names):
            for key, values in iteritems(meta):
                if append and key in song:
                    values = song.list(key) + values
                song[key] = '\n'.join(values)
            if rename:
                origname = song['~filename']
                newname = name + origname[origname.rfind('.'):]
                app.library.rename(origname, newname)
Exemple #30
0
    def has_changed(self, dep_paths):
        if set(self.deps.keys()) != set(dep_paths):
            return True

        for path, old_mtime in iteritems(self.deps):
            if mtime(path) != old_mtime:
                return True

        return False
Exemple #31
0
 def headers(self, new_headers):
     for button, headers in iteritems(self.__headers):
         if headers == new_headers:
             button.set_active(True)
             button.emit("toggled")
             break
     else:
         self.__headers[self.__custom] = new_headers
         self.__custom.set_active(True)
Exemple #32
0
 def Introspect(self):
     parts = []
     parts.append("<node>")
     for iface, intros in iteritems(self.__ispec):
         parts.append("<interface name=\"%s\">" % iface)
         parts.extend(intros)
         parts.append("</interface>")
     parts.append("</node>")
     return ("\n".join(parts)).encode("utf-8")
    def has_changed(self, dep_paths):
        if set(self.deps.keys()) != set(dep_paths):
            return True

        for path, old_mtime in iteritems(self.deps):
            if mtime(path) != old_mtime:
                return True

        return False
Exemple #34
0
 def Introspect(self):
     parts = []
     parts.append("<node>")
     for iface, intros in iteritems(self.__ispec):
         parts.append("<interface name=\"%s\">" % iface)
         parts.extend(intros)
         parts.append("</interface>")
     parts.append("</node>")
     return ("\n".join(parts)).encode("utf-8")
 def test_items(self):
     items = []
     for i in range(20):
         items.append(self.Fake(i))
         items[-1].key = i + 100
     self.library.add(items)
     expected = list(zip(range(100, 120), range(20)))
     self.failUnlessEqual(sorted(self.library.items()), expected)
     self.failUnlessEqual(sorted(iteritems(self.library)), expected)
Exemple #36
0
 def headers(self, new_headers):
     for button, headers in iteritems(self.__headers):
         if headers == new_headers:
             button.set_active(True)
             button.emit("toggled")
             break
     else:
         self.__headers[self.__custom] = new_headers
         self.__custom.set_active(True)
Exemple #37
0
def apply_to_song(meta, song):
    """Applies the tags to a AudioFile instance"""

    for key, value in iteritems(meta):
        if not value:
            song.remove(key)
        else:
            assert isinstance(value, text_type)
            song[key] = value
Exemple #38
0
def apply_to_song(meta, song):
    """Applies the tags to a AudioFile instance"""

    for key, value in iteritems(meta):
        if not value:
            song.remove(key)
        else:
            assert isinstance(value, text_type)
            song[key] = value
    def __save_tags(self, tags, expected):
        #return
        song = OggFile(self.filename)
        for key, value in iteritems(tags):
            song[key] = value
        song.write()
        m = OggVorbis(self.filename)
        # test if all values ended up where we wanted
        for key, value in iteritems(expected):
            self.failUnless(key in m.tags)
            self.failUnlessEqual(m.tags[key], [value])

        # test if not specified are not there
        if self.MAIN not in expected:
            self.failIf(self.MAIN in m.tags)
        if self.FALLBACK not in expected:
            self.failIf(self.FALLBACK in m.tags)
        if self.SINGLE not in expected:
            self.failIf(self.SINGLE in m.tags)
Exemple #40
0
    def __save_tags(self, tags, expected):
        #return
        song = OggFile(self.filename)
        for key, value in iteritems(tags):
            song[key] = value
        song.write()
        m = OggVorbis(self.filename)
        # test if all values ended up where we wanted
        for key, value in iteritems(expected):
            self.failUnless(key in m.tags)
            self.failUnlessEqual(m.tags[key], [value])

        # test if not specified are not there
        if self.MAIN not in expected:
            self.failIf(self.MAIN in m.tags)
        if self.FALLBACK not in expected:
            self.failIf(self.FALLBACK in m.tags)
        if self.SINGLE not in expected:
            self.failIf(self.SINGLE in m.tags)
Exemple #41
0
 def test_handle_single(self):
     self.skipTest("Pops up windows and needs user input.. so disabled."
                   "Still worth keeping whilst we don't have unit tests "
                   "for all plugins.")
     # Ignored...
     for id_, plugin in iteritems(self.plugins):
         if self.h.plugin_handle(plugin):
             self.h.plugin_enable(plugin, None)
             self.h.handle(id_, self.lib, self.parent, SONGS)
             self.h.plugin_disable(plugin)
Exemple #42
0
 def test_handle_single(self):
     self.skipTest("Pops up windows and needs user input.. so disabled."
                   "Still worth keeping whilst we don't have unit tests "
                   "for all plugins.")
     # Ignored...
     for id_, plugin in iteritems(self.plugins):
         if self.h.plugin_handle(plugin):
             self.h.plugin_enable(plugin, None)
             self.h.handle(id_, self.lib, self.parent, SONGS)
             self.h.plugin_disable(plugin)
Exemple #43
0
def build_song_data(release, track):
    """Returns a dict of tags to apply to a song. All the values are unicode.
    If the value is empty it means the tag should be deleted.
    """

    meta = {}

    join = lambda l: "\n".join(l)

    # track/disc data
    meta["tracknumber"] = "%s/%d" % (track.tracknumber, track.track_count)
    if release.disc_count > 1:
        meta["discnumber"] = "%s/%d" % (track.discnumber, release.disc_count)
    else:
        meta["discnumber"] = ""
    meta["title"] = track.title
    meta["musicbrainz_releasetrackid"] = track.id
    meta["musicbrainz_trackid"] = u""  # we used to write those, so delete

    # disc data
    meta["discsubtitle"] = track.disctitle

    # release data
    meta["album"] = release.title
    meta["date"] = release.date
    meta["musicbrainz_albumid"] = release.id
    meta["labelid"] = release.labelid

    if not release.is_single_artist and not release.is_various_artists:
        artists = release.artists
        meta["albumartist"] = join([a.name for a in artists])
        meta["albumartistsort"] = join([a.sort_name for a in artists])
        meta["musicbrainz_albumartistid"] = join([a.id for a in artists])
    else:
        meta["albumartist"] = ""
        meta["albumartistsort"] = ""
        meta["musicbrainz_albumartistid"] = ""

    meta["artist"] = join([a.name for a in track.artists])
    meta["artistsort"] = join([a.sort_name for a in track.artists])
    meta["musicbrainz_artistid"] = join([a.id for a in track.artists])
    meta["musicbrainz_releasetrackid"] = track.id

    # clean up "redundant" data
    if meta["albumartist"] == meta["albumartistsort"]:
        meta["albumartistsort"] = ""
    if meta["artist"] == meta["artistsort"]:
        meta["artistsort"] = ""

    # finally, as musicbrainzngs returns str values if it's ascii, we force
    # everything to unicode now
    for key, value in iteritems(meta):
        meta[key] = text_type(value)

    return meta
Exemple #44
0
def build_song_data(release, track):
    """Returns a dict of tags to apply to a song. All the values are unicode.
    If the value is empty it means the tag should be deleted.
    """

    meta = {}

    join = lambda l: "\n".join(l)

    # track/disc data
    meta["tracknumber"] = "%s/%d" % (track.tracknumber, track.track_count)
    if release.disc_count > 1:
        meta["discnumber"] = "%s/%d" % (track.discnumber, release.disc_count)
    else:
        meta["discnumber"] = ""
    meta["title"] = track.title
    meta["musicbrainz_releasetrackid"] = track.id
    meta["musicbrainz_trackid"] = u""  # we used to write those, so delete

    # disc data
    meta["discsubtitle"] = track.disctitle

    # release data
    meta["album"] = release.title
    meta["date"] = release.date
    meta["musicbrainz_albumid"] = release.id
    meta["labelid"] = release.labelid

    if not release.is_single_artist and not release.is_various_artists:
        artists = release.artists
        meta["albumartist"] = join([a.name for a in artists])
        meta["albumartistsort"] = join([a.sort_name for a in artists])
        meta["musicbrainz_albumartistid"] = join([a.id for a in artists])
    else:
        meta["albumartist"] = ""
        meta["albumartistsort"] = ""
        meta["musicbrainz_albumartistid"] = ""

    meta["artist"] = join([a.name for a in track.artists])
    meta["artistsort"] = join([a.sort_name for a in track.artists])
    meta["musicbrainz_artistid"] = join([a.id for a in track.artists])
    meta["musicbrainz_releasetrackid"] = track.id

    # clean up "redundant" data
    if meta["albumartist"] == meta["albumartistsort"]:
        meta["albumartistsort"] = ""
    if meta["artist"] == meta["artistsort"]:
        meta["artistsort"] = ""

    # finally, as musicbrainzngs returns str values if it's ascii, we force
    # everything to unicode now
    for key, value in iteritems(meta):
        meta[key] = text_type(value)

    return meta
Exemple #45
0
 def get_tracks(self, params):
     merged = {
         "q": "",
         "limit": self.PAGE_SIZE,
         "duration[from]": self.MIN_DURATION_SECS * 1000,
     }
     for k, v in iteritems(params):
         delim = " " if k == 'q' else ","
         merged[k] = delim.join(list(v))
     print_d("Getting tracks: params=%s" % merged)
     self._get('/tracks', self._on_track_data, **merged)
Exemple #46
0
    def __init__(self, songs, real_keys_only=True):
        keys = {}
        first = {}
        all = {}
        total = len(songs)
        self.songs = songs
        self.is_file = True
        can_multi = True
        can_change = True

        for song in songs:
            self.is_file &= song.is_file

            if real_keys_only:
                iter_func = song.iterrealitems
            else:
                iter_func = song.items

            for comment, val in iter_func():
                keys[comment] = keys.get(comment, 0) + 1
                first.setdefault(comment, val)
                all[comment] = all.get(comment, True) and first[comment] == val

            song_can_multi = song.can_multiple_values()
            if song_can_multi is not True:
                if can_multi is True:
                    can_multi = set(song_can_multi)
                else:
                    can_multi.intersection_update(song_can_multi)

            song_can_change = song.can_change()
            if song_can_change is not True:
                if can_change is True:
                    can_change = set(song_can_change)
                else:
                    can_change.intersection_update(song_can_change)

        self._can_multi = can_multi
        self._can_change = can_change

        # collect comment representations
        for tag, count in iteritems(keys):
            first_value = first[tag]
            if not isinstance(first_value, string_types):
                first_value = text_type(first_value)
            shared = all[tag]
            complete = count == total
            if shared and complete:
                values = first_value.split("\n")
            else:
                values = [first_value]
            for v in values:
                self.setdefault(tag,
                                []).append(Comment(v, count, total, shared))
Exemple #47
0
 def get_tracks(self, params):
     merged = {
         "q": "",
         "limit": self.PAGE_SIZE,
         "duration[from]": self.MIN_DURATION_SECS * 1000,
     }
     for k, v in iteritems(params):
         delim = " " if k == 'q' else ","
         merged[k] = delim.join(list(v))
     print_d("Getting tracks: params=%s" % merged)
     self._get('/tracks', self._on_track_data, **merged)
Exemple #48
0
def _get_sort_map(tags):
    """See TAG_TO_SORT"""

    tts = {}
    for name, tag in iteritems(tags):
        if tag.has_sort:
            if tag.user:
                tts[name] = "%ssort" % name
            if tag.internal:
                tts["~%s" % name] = "~%ssort" % name
    return tts
Exemple #49
0
    def __init__(self, songs, real_keys_only=True):
        keys = {}
        first = {}
        all = {}
        total = len(songs)
        self.songs = songs
        self.is_file = True
        can_multi = True
        can_change = True

        for song in songs:
            self.is_file &= song.is_file

            if real_keys_only:
                iter_func = song.iterrealitems
            else:
                iter_func = song.iteritems

            for comment, val in iter_func():
                keys[comment] = keys.get(comment, 0) + 1
                first.setdefault(comment, val)
                all[comment] = all.get(comment, True) and first[comment] == val

            song_can_multi = song.can_multiple_values()
            if song_can_multi is not True:
                if can_multi is True:
                    can_multi = set(song_can_multi)
                else:
                    can_multi.intersection_update(song_can_multi)

            song_can_change = song.can_change()
            if song_can_change is not True:
                if can_change is True:
                    can_change = set(song_can_change)
                else:
                    can_change.intersection_update(song_can_change)

        self._can_multi = can_multi
        self._can_change = can_change

        # collect comment representations
        for tag, count in iteritems(keys):
            first_value = first[tag]
            if not isinstance(first_value, string_types):
                first_value = text_type(first_value)
            shared = all[tag]
            complete = count == total
            if shared and complete:
                values = first_value.split("\n")
            else:
                values = [first_value]
            for v in values:
                self.setdefault(tag, []).append(
                    Comment(v, count, total, shared))
Exemple #50
0
def _get_sort_map(tags):
    """See TAG_TO_SORT"""

    tts = {}
    for name, tag in iteritems(tags):
        if tag.has_sort:
            if tag.user:
                tts[name] = "%ssort" % name
            if tag.internal:
                tts["~%s" % name] = "~%ssort" % name
    return tts
Exemple #51
0
    def test_all(self):
        tested_any = False

        for id_, plugin in iteritems(self.plugins):
            plugin = plugin.cls
            if hasattr(plugin, "PLUGIN_INSTANCE"):
                plugin = plugin()
            if hasattr(plugin, "PluginPreferences"):
                tested_any = True
                plugin.PluginPreferences(Gtk.Window())

        self.assertTrue(tested_any)
Exemple #52
0
    def next(self, playlist, current):
        super(PlaycountEqualizer, self).next(playlist, current)

        remaining = self.remaining(playlist)

        # Don't try to search through an empty / played playlist.
        if len(remaining) <= 0:
            return None

        # Set-up the search information.
        max_count = max([song('~#playcount') for song in remaining.values()])
        weights = {i: max_count - song('~#playcount')
                   for i, song in iteritems(remaining)}
        choice = int(max(1, math.ceil(sum(weights) * random.random())))

        # Search for a track.
        for i, weight in iteritems(weights):
            choice -= weight
            if choice <= 0:
                return playlist.get_iter([i])
        else:  # This should only happen if all songs have equal play counts.
            return playlist.get_iter([random.choice(list(remaining.keys()))])
Exemple #53
0
    def next(self, playlist, current):
        super(PlaycountEqualizer, self).next(playlist, current)

        remaining = self.remaining(playlist)

        # Don't try to search through an empty / played playlist.
        if len(remaining) <= 0:
            return None

        # Set-up the search information.
        max_count = max([song('~#playcount') for song in remaining.values()])
        weights = {i: max_count - song('~#playcount')
                   for i, song in iteritems(remaining)}
        choice = int(max(1, math.ceil(sum(weights) * random.random())))

        # Search for a track.
        for i, weight in iteritems(weights):
            choice -= weight
            if choice <= 0:
                return playlist.get_iter([i])
        else:  # This should only happen if all songs have equal play counts.
            return playlist.get_iter([random.choice(remaining.keys())])
Exemple #54
0
def generate_re_mapping(_diacritic_for_letters):
    letter_to_variants = {}

    # combine combining characters with the ascii chars
    for dia, letters in iteritems(_diacritic_for_letters):
        for c in letters:
            unichar = unicodedata.normalize("NFKC", c + dia)
            letter_to_variants.setdefault(c, []).append(unichar)

    # create strings to replace ascii with
    for k, v in letter_to_variants.items():
        letter_to_variants[k] = u"".join(sorted(v))

    return letter_to_variants
Exemple #55
0
    def failures(self):
        """module name: list of error message text lines"""

        errors = {}
        for name, error in iteritems(self.__scanner.failures):
            exception = error.exception
            if isinstance(exception, PluginImportException):
                if not exception.should_show():
                    continue
                errors[name] = [exception.desc]
            else:
                errors[name] = error.traceback

        return errors
Exemple #56
0
    def get_images(self):
        try:
            tag = mutagen.apev2.APEv2(self['~filename'])
        except Exception:
            return []

        images = []
        for key, value in iteritems(tag):
            image = parse_cover(key, value)
            if image is not None:
                images.append(image)

        images.sort(key=lambda c: c.sort_key)
        return images
Exemple #57
0
    def failures(self):
        """module name: list of error message text lines"""

        errors = {}
        for name, error in iteritems(self.__scanner.failures):
            exception = error.exception
            if isinstance(exception, PluginImportException):
                if not exception.should_show():
                    continue
                errors[name] = [exception.desc]
            else:
                errors[name] = error.traceback

        return errors