예제 #1
0
    def __init__(self, songs):
        keys = {}
        first = {}
        all = {}
        total = len(songs)
        self.songs = songs

        for song in songs:
            self.is_file &= song.is_file
            self.multiple_values &= song.multiple_values
            for comment, val in song.iteritems():
                keys[comment] = keys.get(comment, 0) + 1
                first.setdefault(comment, val)
                all[comment] = all.get(comment, True) and first[comment] == val

        # collect comment representations
        for comment, count in keys.iteritems():
            if count < total:
                if all[comment]:
                    value = self.PartialSharedComment(first[comment])
                else:
                    value = self.PartialUnsharedComment(first[comment])
            else:
                decoded = first[comment]
                if isinstance(decoded, str):
                    decoded = util.decode(decoded)
                if all[comment]:
                    value = self.SharedComment(decoded)
                else:
                    value = self.UnsharedComment(decoded)
            value.have = count
            value.total = total
            value.missing = total - count

            self[comment] = value
예제 #2
0
    def __init__(self, track):
        super(IPodSong, self).__init__()
        self.sanitize(gpod.itdb_filename_on_ipod(track))

        # String keys
        for key in ['artist', 'album', 'title', 'genre', 'grouping',
            'composer', 'albumartist']:
            # albumartist since libgpod-0.4.2
            value = getattr(track, key, None)
            if value:
                self[key] = util.decode(value)
        # Sort keys (since libgpod-0.5.0)
        for key in ['artist', 'album', 'albumartist']:
            value = getattr(track, 'sort_' + key, None)
            if value:
                self[key + 'sort'] = util.decode(value)
        # Numeric keys
        for key in ['bitrate', 'playcount']:
            value = getattr(track, key)
            if value:
                self['~#'+key] = value

        try: self["date"] = unicode(track.year)
        except AttributeError: pass

        if track.cds:
            self["discnumber"] = u"%d/%d" % (track.cd_nr, track.cds)
        elif track.cd_nr:
            self["discnumber"] = u"%d" % track.cd_nr

        if track.tracks:
            self['tracknumber'] = u"%d/%d" % (track.track_nr, track.tracks)
        elif track.track_nr:
            self['tracknumber'] = u"%d" % track.track_nr

        for key, value in {
            '~#rating': min(1.0, track.rating / 100.0),
            '~#length': track.tracklen / 1000.0,
        }.items():
            if value != 0:
                self[key] = value
        self['~format'] = u"iPod: %s" % track.filetype
예제 #3
0
 def __error(self, player, song, error, librarian):
     newstr = u"%s: %s\n\n" % (
         util.decode(time.asctime(), const.ENCODING), error)
     self.__errors_in_a_row += 1
     if self.__errors_in_a_row > MAX_ERRORS:
         self.__errors_in_a_row = 0
         ErrorMessage(None, _("Too Many Errors"),
                      _("Stopping playback because there were %d errors "
                        "in a row.") % MAX_ERRORS).run()
         player.go_to(None)
         player.paused = True
     song["~errors"] = newstr + song.get("~errors", "")
예제 #4
0
def parse_gstreamer_taglist(tags):
    """Takes a GStreamer taglist and returns a dict containing only
    numeric and unicode values and str keys."""

    merged = {}
    for key in tags.keys():
        value = tags[key]
        # extended-comment sometimes containes a single vorbiscomment or
        # a list of them ["key=value", "key=value"]
        if key == "extended-comment":
            if not isinstance(value, list):
                value = [value]
            for val in value:
                if not isinstance(val, unicode): continue
                split = val.split("=", 1)
                sub_key = util.decode(split[0])
                val = split[-1]
                if sub_key in merged:
                    if val not in merged[sub_key].split("\n"):
                        merged[sub_key] += "\n" + val
                else:
                    merged[sub_key] = val
        elif isinstance(value, gst.Date):
                try: value = u"%d-%d-%d" % (value.year, value.month, value.day)
                except (ValueError, TypeError): continue
                merged[key] = value
        elif isinstance(value, list):
            # there are some lists for id3 containing gst.Buffer (binary data)
            continue
        else:
            if isinstance(value, str):
                value = util.decode(value)

            if not isinstance(value, unicode) and \
                not isinstance(value, (int, long, float)):
                value = unicode(value)

            merged[key] = value

    return merged
예제 #5
0
def parse_taglist(data):
    """Parses a dump file like list of tags and returns a list of IRFiles

    uri=http://...
    tag=value1
    tag2=value
    tag=value2
    uri=http://...
    ...

    """

    stations = []
    station = None

    for l in data.split("\n"):
        key = l.split("=")[0]
        value = l.split("=", 1)[1]
        if key == "uri":
            if station:
                stations.append(station)
            station = IRFile(value)
            continue

        value = util.decode(value)
        san = sanitize_tags({key: value}, stream=True).items()
        if not san:
            continue

        key, value = san[0]
        if isinstance(value, str):
            value = value.decode("utf-8")
            if value not in station.list(key):
                station.add(key, value)
        else:
            station[key] = value

    if station:
        stations.append(station)

    return stations
예제 #6
0
 def __init__(self, filename):
     audio = MP4(filename)
     self["~#length"] = int(audio.info.length)
     self["~#bitrate"] = int(audio.info.bitrate / 1000)
     for key, values in audio.items():
         if key in self.__tupletranslate:
             name = self.__tupletranslate[key]
             cur, total = values[0]
             if total:
                 self[name] = u"%d/%d" % (cur, total)
             else:
                 self[name] = unicode(cur)
         elif key in self.__translate:
             name = self.__translate[key]
             if key == "tmpo":
                 self[name] = "\n".join(map(unicode, values))
             elif key.startswith("----"):
                 self[name] = "\n".join(
                     map(lambda v: util.decode(v).strip("\x00"), values))
             else:
                 self[name] = "\n".join(values)
         elif key == "covr":
             self["~picture"] = "y"
     self.sanitize(filename)
예제 #7
0
    def __save_files(self, save, revert, model, library):
        updated = {}
        deleted = {}
        added = {}
        renamed = {}
        for row in model:
            if row[EDITED] and not (row[DELETED] or row[RENAMED]):
                if row[ORIGVALUE] is not None:
                    updated.setdefault(row[TAG], [])
                    updated[row[TAG]].append((util.decode(row[VALUE]), util.decode(row[ORIGVALUE])))
                else:
                    added.setdefault(row[TAG], [])
                    added[row[TAG]].append(util.decode(row[VALUE]))
            if row[EDITED] and row[DELETED]:
                if row[ORIGVALUE] is not None:
                    deleted.setdefault(row[TAG], [])
                    deleted[row[TAG]].append(util.decode(row[ORIGVALUE]))

            if row[EDITED] and row[RENAMED] and not row[DELETED]:
                renamed.setdefault(row[TAG], [])
                renamed[row[TAG]].append(
                    (util.decode(row[ORIGTAG]), util.decode(row[VALUE]), util.decode(row[ORIGVALUE]))
                )

        was_changed = []
        songs = self.__songinfo.songs
        win = WritingWindow(self, len(songs))
        for song in songs:
            if (
                not song.valid()
                and not qltk.ConfirmAction(
                    self,
                    _("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

            changed = False
            for key, values in updated.iteritems():
                for (new_value, old_value) in values:
                    new_value = util.unescape(new_value)
                    if song.can_change(key):
                        if old_value is None:
                            song.add(key, new_value)
                        else:
                            song.change(key, old_value, new_value)
                        changed = True
            for key, values in added.iteritems():
                for value in values:
                    value = util.unescape(value)
                    if song.can_change(key):
                        song.add(key, value)
                        changed = True
            for key, values in deleted.iteritems():
                for value in values:
                    value = util.unescape(value)
                    if song.can_change(key) and key in song:
                        song.remove(key, value)
                        changed = True
            save_rename = []
            for new_tag, values in renamed.iteritems():
                for old_tag, new_value, old_value in values:
                    old_tag = util.unescape(old_tag)
                    old_value = util.unescape(old_value)
                    new_value = util.unescape(new_value)
                    if song.can_change(new_tag) and song.can_change(old_tag) and old_tag in song:
                        if not is_special(new_value):
                            song.remove(old_tag, old_value)
                            save_rename.append((new_tag, new_value))
                        elif is_missing(new_value):
                            value = strip_missing(old_value)
                            song.remove(old_tag, old_value)
                            save_rename.append((new_tag, new_value))
                        else:
                            save_rename.append((new_tag, song[old_tag]))
                            song.remove(old_tag, None)
                        changed = True
            for tag, value in save_rename:
                song.add(tag, value)

            if changed:
                try:
                    song.write()
                except:
                    util.print_exc()
                    qltk.ErrorMessage(
                        self,
                        _("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

        win.destroy()
        library.changed(was_changed)
        for b in [save, revert]:
            b.set_sensitive(False)
예제 #8
0
 def test_invalid(self):
     self.failUnlessEqual(
         util.decode("fo\xde"), u'fo\ufffd [Invalid Encoding]')
예제 #9
0
 def test_safe(self):
     self.failUnlessEqual(util.decode("foo!"), "foo!")
예제 #10
0
 def test_empty(self):
     self.failUnlessEqual(util.decode(""), "")