Beispiel #1
0
    def __init__(self, filename):
        with translate_errors():
            audio = Musepack(filename)

        super(MPCFile, self).__init__(filename, audio)
        self["~#length"] = audio.info.length
        self["~#bitrate"] = int(audio.info.bitrate / 1000)

        version = audio.info.version
        self["~codec"] = u"%s SV%d" % (self.format, version)

        try:
            if audio.info.title_gain:
                track_g = u"%+0.2f dB" % audio.info.title_gain
                self.setdefault("replaygain_track_gain", track_g)
            if audio.info.album_gain:
                album_g = u"%+0.2f dB" % audio.info.album_gain
                self.setdefault("replaygain_album_gain", album_g)
            if audio.info.title_peak:
                track_p = text_type(audio.info.title_peak * 2)
                self.setdefault("replaygain_track_peak", track_p)
            if audio.info.album_peak:
                album_p = text_type(audio.info.album_peak * 2)
                self.setdefault("replaygain_album_peak", album_p)
        except AttributeError:
            pass

        self.sanitize(filename)
Beispiel #2
0
def send_feedback(dsn, event_id, name, email, comment, timeout):
    """Send feedback, blocking.

    Args:
        dsn (str): The DSN
        event_id (str): The event ID this feedback should be attached to
        name (text_type): The user name
        email (text_type): The user email
        comment (text_type): The feedback text
        timeout (float): The timeout for this request
    Raises:
        SentryError: In case of timeout or other errors
    """

    name = text_type(name).encode("utf-8")
    email = text_type(email).encode("utf-8")
    comment = text_type(comment).encode("utf-8")

    data = urlencode(
        [('name', name), ('email', email), ('comments', comment)])
    if not isinstance(data, bytes):
        # py3
        data = data.encode("utf-8")

    headers = {"Referer": "https://quodlibet.github.io"}
    params = urlencode([("dsn", dsn), ("eventId", event_id)])

    try:
        req = Request(
            "https://sentry.io/api/embed/error-page/?" + params,
            data=data, headers=headers)

        urlopen(req, timeout=timeout).close()
    except EnvironmentError as e:
        raise SentryError(e)
Beispiel #3
0
    def _execute(self, options, args):
        if len(args) < 1:
            raise CommandError(_("Not enough arguments"))
        elif len(args) > 1:
            raise CommandError(_("Too many arguments"))

        path = args[0]
        song = self.load_song(path)

        headers = [_("Description"), _("Value")]
        nicks = ["desc", "value"]

        if not options.columns:
            order = nicks
        else:
            order = [n.strip() for n in options.columns.split(",")]

        if not options.terse:
            tags = []
            for key in ["~format", "~codec", "~encoding", "~length",
                        "~bitrate", "~filesize"]:
                tags.append((util.tag(key), text_type(song.comma(key))))

            print_table(tags, headers, nicks, order)
        else:
            tags = []
            for key in ["~format", "~codec", "~encoding", "~#length",
                        "~#bitrate", "~#filesize"]:
                tags.append((key.lstrip("#~"), text_type(song(key))))

            print_terse_table(tags, nicks, order)
Beispiel #4
0
def send_feedback(dsn, event_id, name, email, comment, timeout):
    """Send feedback, blocking.

    Args:
        dsn (str): The DSN
        event_id (str): The event ID this feedback should be attached to
        name (text_type): The user name
        email (text_type): The user email
        comment (text_type): The feedback text
        timeout (float): The timeout for this request
    Raises:
        SentryError: In case of timeout or other errors
    """

    name = text_type(name).encode("utf-8")
    email = text_type(email).encode("utf-8")
    comment = text_type(comment).encode("utf-8")

    data = urlencode([('name', name), ('email', email), ('comments', comment)])
    if not isinstance(data, bytes):
        # py3
        data = data.encode("utf-8")

    headers = {"Referer": "https://quodlibet.github.io"}
    params = urlencode([("dsn", dsn), ("eventId", event_id)])

    try:
        req = Request("https://sentry.io/api/embed/error-page/?" + params,
                      data=data,
                      headers=headers)

        urlopen(req, timeout=timeout).close()
    except EnvironmentError as e:
        raise SentryError(e)
Beispiel #5
0
    def __init__(self, filename):
        with translate_errors():
            audio = Musepack(filename)

        super(MPCFile, self).__init__(filename, audio)
        self["~#length"] = audio.info.length
        self["~#bitrate"] = int(audio.info.bitrate / 1000)

        version = audio.info.version
        self["~codec"] = u"%s SV%d" % (self.format, version)

        try:
            if audio.info.title_gain:
                track_g = u"%+0.2f dB" % audio.info.title_gain
                self.setdefault("replaygain_track_gain", track_g)
            if audio.info.album_gain:
                album_g = u"%+0.2f dB" % audio.info.album_gain
                self.setdefault("replaygain_album_gain", album_g)
            if audio.info.title_peak:
                track_p = text_type(audio.info.title_peak * 2)
                self.setdefault("replaygain_track_peak", track_p)
            if audio.info.album_peak:
                album_p = text_type(audio.info.album_peak * 2)
                self.setdefault("replaygain_album_peak", album_p)
        except AttributeError:
            pass

        self.sanitize(filename)
Beispiel #6
0
    def _execute(self, options, args):
        if len(args) < 1:
            raise CommandError(_("Not enough arguments"))
        elif len(args) > 1:
            raise CommandError(_("Too many arguments"))

        path = args[0]
        song = self.load_song(path)

        headers = [_("Description"), _("Value")]
        nicks = ["desc", "value"]

        if not options.columns:
            order = nicks
        else:
            order = [n.strip() for n in options.columns.split(",")]

        if not options.terse:
            tags = []
            for key in ["~format", "~codec", "~encoding", "~length",
                        "~bitrate", "~filesize"]:
                tags.append((util.tag(key), text_type(song.comma(key))))

            print_table(tags, headers, nicks, order)
        else:
            tags = []
            for key in ["~format", "~codec", "~encoding", "~#length",
                        "~#bitrate", "~#filesize"]:
                tags.append((key.lstrip("#~"), text_type(song(key))))

            print_terse_table(tags, nicks, order)
Beispiel #7
0
 def upgettext(self, context, msgid):
     context = text_type(context)
     msgid = text_type(msgid)
     real_msgid = u"%s\x04%s" % (context, msgid)
     result = self.ugettext(real_msgid)
     if result == real_msgid:
         return msgid
     return result
Beispiel #8
0
 def upgettext(self, context, msgid):
     context = text_type(context)
     msgid = text_type(msgid)
     real_msgid = u"%s\x04%s" % (context, msgid)
     result = self.ugettext(real_msgid)
     if result == real_msgid:
         return msgid
     return result
Beispiel #9
0
 def ugettext(self, message):
     # force unicode here since __contains__ (used in gettext) ignores
     # our changed defaultencoding for coercion, so utf-8 encoded strings
     # fail at lookup.
     message = text_type(message)
     if PY2:
         return text_type(gettext.GNUTranslations.ugettext(self, message))
     else:
         return text_type(gettext.GNUTranslations.gettext(self, message))
Beispiel #10
0
 def ugettext(self, message):
     # force unicode here since __contains__ (used in gettext) ignores
     # our changed defaultencoding for coercion, so utf-8 encoded strings
     # fail at lookup.
     message = text_type(message)
     if PY2:
         return text_type(gettext.GNUTranslations.ugettext(self, message))
     else:
         return text_type(gettext.GNUTranslations.gettext(self, message))
Beispiel #11
0
 def ungettext(self, msgid1, msgid2, n):
     # see ugettext
     msgid1 = text_type(msgid1)
     msgid2 = text_type(msgid2)
     if PY2:
         return text_type(
             gettext.GNUTranslations.ungettext(self, msgid1, msgid2, n))
     else:
         return text_type(
             gettext.GNUTranslations.ngettext(self, msgid1, msgid2, n))
Beispiel #12
0
 def ungettext(self, msgid1, msgid2, n):
     # see ugettext
     msgid1 = text_type(msgid1)
     msgid2 = text_type(msgid2)
     if PY2:
         return text_type(
             gettext.GNUTranslations.ungettext(self, msgid1, msgid2, n))
     else:
         return text_type(
             gettext.GNUTranslations.ngettext(self, msgid1, msgid2, n))
Beispiel #13
0
 def unpgettext(self, context, msgid, msgidplural, n):
     context = text_type(context)
     msgid = text_type(msgid)
     msgidplural = text_type(msgidplural)
     real_msgid = u"%s\x04%s" % (context, msgid)
     real_msgidplural = u"%s\x04%s" % (context, msgidplural)
     result = self.ngettext(real_msgid, real_msgidplural, n)
     if result == real_msgid:
         return msgid
     elif result == real_msgidplural:
         return msgidplural
     return result
Beispiel #14
0
    def __init__(self, pattern, mod_string):
        self.pattern = text_type(pattern)
        self.mod_string = text_type(mod_string)

        ignore_case = "c" not in self.mod_string or "i" in self.mod_string
        dot_all = "s" in self.mod_string
        asym = "d" in self.mod_string
        try:
            self.search = compile(self.pattern, ignore_case, dot_all, asym)
        except ValueError:
            raise ParseError(
                "The regular expression /%s/ is invalid." % self.pattern)
Beispiel #15
0
 def unpgettext(self, context, msgid, msgidplural, n):
     context = text_type(context)
     msgid = text_type(msgid)
     msgidplural = text_type(msgidplural)
     real_msgid = u"%s\x04%s" % (context, msgid)
     real_msgidplural = u"%s\x04%s" % (context, msgidplural)
     result = self.ngettext(real_msgid, real_msgidplural, n)
     if result == real_msgid:
         return msgid
     elif result == real_msgidplural:
         return msgidplural
     return result
Beispiel #16
0
    def setstringlist(self, section, option, values):
        """Saves a list of unicode strings using the csv module"""

        if PY2:
            sw = cBytesIO()
            values = [text_type(v).encode('utf-8') for v in values]
        else:
            sw = StringIO()
            values = [text_type(v) for v in values]

        writer = csv.writer(sw, lineterminator='\n', quoting=csv.QUOTE_MINIMAL)
        writer.writerow(values)
        self.set(section, option, sw.getvalue())
Beispiel #17
0
def decode_value(tag, value):
    """Returns a unicode representation of the passed value, based on
    the type and the tag it originated from.

    Not reversible.
    """

    if tag in FILESYSTEM_TAGS:
        return fsn2text(value)
    elif tag[:2] == "~#":
        if isinstance(value, float):
            return u"%.2f" % value
        else:
            return text_type(value)
    return text_type(value)
Beispiel #18
0
def build_issue_url(title, body):
    """Returns an URL which provides a pre-filled github issue.

    Args:
        title (text_type): The issue title
        body (text_type): The issue content
    Returns:
        str: the URL to open
    """

    title = text_type(title).encode("utf-8")
    body = text_type(body).encode("utf-8")
    params = urlencode([("title", title), ("body", body)])

    return "https://github.com/quodlibet/quodlibet/issues/new?%s" % params
Beispiel #19
0
def decode_value(tag, value):
    """Returns a unicode representation of the passed value, based on
    the type and the tag it originated from.

    Not reversible.
    """

    if tag in FILESYSTEM_TAGS:
        return fsn2text(value)
    elif tag[:2] == "~#":
        if isinstance(value, float):
            return u"%.2f" % value
        else:
            return text_type(value)
    return text_type(value)
Beispiel #20
0
 def plugin_songs(self, songs):
     # Check this is a launch, not a configure
     if self.chosen_site:
         url_pat = self.get_url_pattern(self.chosen_site)
         pat = Pattern(url_pat)
         urls = set()
         for song in songs:
             # Generate a sanitised AudioFile; allow through most tags
             subs = AudioFile()
             for k in (USER_TAGS + MACHINE_TAGS):
                 vals = song.comma(k)
                 if vals:
                     try:
                         encoded = text_type(vals).encode('utf-8')
                         subs[k] = (encoded if k == 'website'
                                    else quote_plus(encoded))
                     # Dodgy unicode problems
                     except KeyError:
                         print_d("Problem with %s tag values: %r"
                                 % (k, vals))
             url = str(pat.format(subs))
             if not url:
                 print_w("Couldn't build URL using \"%s\"."
                         "Check your pattern?" % url_pat)
                 return
             # Grr, set.add() should return boolean...
             if url not in urls:
                 urls.add(url)
                 website(url)
Beispiel #21
0
def add_station(uri):
    """Fetches the URI content and extracts IRFiles
    Returns None in error, else a possibly filled list of stations"""

    irfs = []

    if uri.lower().endswith(".pls") or uri.lower().endswith(".m3u"):
        if not re.match('^([^/:]+)://', uri):
            # Assume HTTP if no protocol given. See #2731
            uri = 'http://' + uri
            print_d("Assuming http: %s" % uri)
        try:
            sock = urlopen(uri)
        except EnvironmentError as err:
            err = "%s\n\nURL: %s" % (text_type(err), uri)
            print_d("Got %s from %s" % (err, uri))
            ErrorMessage(None, _("Unable to add station"), escape(err)).run()
            return None

        if uri.lower().endswith(".pls"):
            irfs = ParsePLS(sock)
        elif uri.lower().endswith(".m3u"):
            irfs = ParseM3U(sock)

        sock.close()
    else:
        try:
            irfs = [IRFile(uri)]
        except ValueError as err:
            ErrorMessage(None, _("Unable to add station"), err).run()

    return irfs
Beispiel #22
0
    def get_grouping_key(self):
        """Given a stacktrace produced by the faulthandler module returns a
        short string for grouping similar stacktraces together.

        Args:
            stacktrace (text_type)
        Returns:
            text_type
        """

        stacktrace = text_type(self)
        if isinstance(stacktrace, bytes):
            stacktrace = stacktrace.decode("utf-8", "replace")

        assert isinstance(stacktrace, text_type)

        # Extract the basename and the function name for each line and hash
        # them. Could be smarter, but let's try this for now..
        reg = re.compile('.*?"([^"]+).*?(\w+$)')
        values = []
        for l in stacktrace.splitlines():
            m = reg.match(l)
            if m is not None:
                path, func = m.groups()
                path = os.path.basename(path)
                values.extend([path, func])
        return u"|".join(values)
Beispiel #23
0
    def get_grouping_key(self):
        """Given a stacktrace produced by the faulthandler module returns a
        short string for grouping similar stacktraces together.

        Args:
            stacktrace (text_type)
        Returns:
            text_type
        """

        stacktrace = text_type(self)
        if isinstance(stacktrace, bytes):
            stacktrace = stacktrace.decode("utf-8", "replace")

        assert isinstance(stacktrace, text_type)

        # Extract the basename and the function name for each line and hash
        # them. Could be smarter, but let's try this for now..
        reg = re.compile(r'.*?"([^"]+).*?(\w+$)')
        values = []
        for l in stacktrace.splitlines():
            m = reg.match(l)
            if m is not None:
                path, func = m.groups()
                path = os.path.basename(path)
                values.extend([path, func])
        return u"|".join(values)
Beispiel #24
0
def add_station(uri):
    """Fetches the URI content and extracts IRFiles
    Returns None in error, else a possibly filled list of stations"""

    irfs = []

    if uri.lower().endswith(".pls") or uri.lower().endswith(".m3u"):
        try:
            sock = urlopen(uri)
        except EnvironmentError as err:
            err = text_type(err)
            print_d("Got %s from %s" % (uri, err))
            ErrorMessage(None, _("Unable to add station"), escape(err)).run()
            return None

        if uri.lower().endswith(".pls"):
            irfs = ParsePLS(sock)
        elif uri.lower().endswith(".m3u"):
            irfs = ParseM3U(sock)

        sock.close()
    else:
        try:
            irfs = [IRFile(uri)]
        except ValueError as err:
            ErrorMessage(None, _("Unable to add station"), err).run()

    return irfs
Beispiel #25
0
    def _try_build_device(self, object_path, block, fs):
        """Returns a Device instance or None.

        None if it wasn't a media player etc..
        """

        drive = self._drives.get(block["Drive"])
        if not drive:
            # I think this shouldn't happen, but check anyway
            return

        dev_path = dbus_barray_to_bytes(block["Device"])
        print_d("Found device: %r" % dev_path)

        media_player_id = get_media_player_id(self._udev, dev_path)
        if not media_player_id:
            print_d("%r not a media player" % dev_path)
            return
        protocols = get_media_player_protocols(media_player_id)

        device_id = drive["Id"]

        dev = self.create_device(object_path, text_type(device_id), protocols)
        icon_name = block["HintIconName"]
        if icon_name:
            dev.icon = icon_name
        return dev
Beispiel #26
0
    def _try_build_device(self, object_path, block, fs):
        """Returns a Device instance or None.

        None if it wasn't a media player etc..
        """

        drive = self._drives.get(block["Drive"])
        if not drive:
            # I think this shouldn't happen, but check anyway
            return

        dev_path = dbus_barray_to_bytes(block["Device"])
        print_d("Found device: %r" % dev_path)

        media_player_id = get_media_player_id(self._udev, dev_path)
        if not media_player_id:
            print_d("%r not a media player" % dev_path)
            return
        protocols = get_media_player_protocols(media_player_id)

        device_id = drive["Id"]

        dev = self.create_device(object_path, text_type(device_id), protocols)
        icon_name = block["HintIconName"]
        if icon_name:
            dev.icon = icon_name
        return dev
Beispiel #27
0
def add_station(uri):
    """Fetches the URI content and extracts IRFiles
    Returns None in error, else a possibly filled list of stations"""

    irfs = []

    if uri.lower().endswith(".pls") or uri.lower().endswith(".m3u"):
        try:
            sock = urlopen(uri)
        except EnvironmentError as err:
            err = text_type(err)
            print_d("Got %s from %s" % (uri, err))
            ErrorMessage(None, _("Unable to add station"), escape(err)).run()
            return None

        if uri.lower().endswith(".pls"):
            irfs = ParsePLS(sock)
        elif uri.lower().endswith(".m3u"):
            irfs = ParseM3U(sock)

        sock.close()
    else:
        try:
            irfs = [IRFile(uri)]
        except ValueError as err:
            ErrorMessage(None, _("Unable to add station"), err).run()

    return irfs
Beispiel #28
0
    def __init__(self, filename):
        with translate_errors():
            audio = MP4(filename)
        self["~codec"] = audio.info.codec_description
        self["~#length"] = audio.info.length
        self["~#bitrate"] = int(audio.info.bitrate / 1000)
        if audio.info.channels:
            self["~#channels"] = audio.info.channels
        self["~#samplerate"] = audio.info.sample_rate
        self["~#bitdepth"] = audio.info.bits_per_sample

        for key, values in audio.items():
            if key in self.__tupletranslate:
                if values:
                    name = self.__tupletranslate[key]
                    cur, total = values[0]
                    if total:
                        self[name] = u"%d/%d" % (cur, total)
                    else:
                        self[name] = text_type(cur)
            elif key in self.__translate:
                name = self.__translate[key]
                if key == "tmpo":
                    self[name] = u"\n".join(map(text_type, values))
                elif key.startswith("----"):
                    self[name] = "\n".join(
                        map(lambda v: decode(v).strip("\x00"), values))
                else:
                    self[name] = "\n".join(values)
            elif key == "covr":
                self.has_images = True
        self.sanitize(filename)
Beispiel #29
0
    def __init__(self, filename):
        with translate_errors():
            audio = MP4(filename)
        self["~codec"] = audio.info.codec_description
        self["~#length"] = audio.info.length
        self["~#bitrate"] = int(audio.info.bitrate / 1000)
        if audio.info.channels:
            self["~#channels"] = audio.info.channels

        for key, values in audio.items():
            if key in self.__tupletranslate:
                if values:
                    name = self.__tupletranslate[key]
                    cur, total = values[0]
                    if total:
                        self[name] = u"%d/%d" % (cur, total)
                    else:
                        self[name] = text_type(cur)
            elif key in self.__translate:
                name = self.__translate[key]
                if key == "tmpo":
                    self[name] = u"\n".join(map(text_type, values))
                elif key.startswith("----"):
                    self[name] = "\n".join(
                        map(lambda v: decode(v).strip("\x00"), values))
                else:
                    self[name] = "\n".join(values)
            elif key == "covr":
                self.has_images = True
        self.sanitize(filename)
Beispiel #30
0
def add_station(uri):
    """Fetches the URI content and extracts IRFiles
    Returns None in error, else a possibly filled list of stations"""

    irfs = []

    if uri.lower().endswith(".pls") or uri.lower().endswith(".m3u"):
        if not re.match('^([^/:]+)://', uri):
            # Assume HTTP if no protocol given. See #2731
            uri = 'http://' + uri
            print_d("Assuming http: %s" % uri)
        try:
            sock = urlopen(uri)
        except EnvironmentError as err:
            err = "%s\n\nURL: %s" % (text_type(err), uri)
            print_d("Got %s from %s" % (err, uri))
            ErrorMessage(None, _("Unable to add station"), escape(err)).run()
            return None

        if uri.lower().endswith(".pls"):
            irfs = ParsePLS(sock)
        elif uri.lower().endswith(".m3u"):
            irfs = ParseM3U(sock)

        sock.close()
    else:
        try:
            irfs = [IRFile(uri)]
        except ValueError as err:
            ErrorMessage(None, _("Unable to add station"), err).run()

    return irfs
Beispiel #31
0
 def plugin_songs(self, songs):
     # Check this is a launch, not a configure
     if self.chosen_site:
         url_pat = self.get_url_pattern(self.chosen_site)
         pat = Pattern(url_pat)
         urls = set()
         for song in songs:
             # Generate a sanitised AudioFile; allow through most tags
             subs = AudioFile()
             for k in (USER_TAGS + MACHINE_TAGS):
                 vals = song.comma(k)
                 if vals:
                     try:
                         encoded = text_type(vals).encode('utf-8')
                         subs[k] = (encoded if k == 'website' else
                                    quote_plus(encoded))
                     # Dodgy unicode problems
                     except KeyError:
                         print_d("Problem with %s tag values: %r" %
                                 (k, vals))
             url = str(pat.format(subs))
             if not url:
                 print_w("Couldn't build URL using \"%s\"."
                         "Check your pattern?" % url_pat)
                 return
             # Grr, set.add() should return boolean...
             if url not in urls:
                 urls.add(url)
                 website(url)
Beispiel #32
0
def get_github_issue_url(exc_info):
    """Gives an URL for a pre-filled github issue based on an exception

    Returns:
        str
    """

    error_title = (text_type(exc_info[1]).strip() or u"\n").splitlines()[0]
    title = u"[Error] %s: %s" % (exc_info[0].__name__, error_title)
    error_text = u"\n".join(format_exception(*exc_info))
    body = u"""\
* What did you try to do when the error occurred?

Error Details:
```
%s

Version: %s
Python: %s
Platform: %s
```
""" % (error_text, quodlibet.get_build_description(), sys.version,
       platform.platform())

    return build_issue_url(title, body)
Beispiel #33
0
    def _apply_value(self, model, iter_, cell, value):
        if isinstance(value, float):
            text = u"%.2f" % round(value, 2)
        else:
            text = text_type(value)

        cell.set_property('text', text)
        self._recalc_width(model.get_path(iter_), text)
Beispiel #34
0
    def _apply_value(self, model, iter_, cell, value):
        if isinstance(value, float):
            text = u"%.2f" % round(value, 2)
        else:
            text = text_type(value)

        cell.set_property('text', text)
        self._recalc_width(model.get_path(iter_), text)
Beispiel #35
0
    def _validated_name(self, new_name):
        """Returns a transformed (or not) name, or raises a `ValueError`
        if the name is not allowed
        """

        new_name = text_type(new_name)
        if not new_name:
            raise ValueError(_("Playlists must have a name"))
        return new_name
Beispiel #36
0
    def _validated_name(self, new_name):
        """Returns a transformed (or not) name, or raises a `ValueError`
        if the name is not allowed
        """

        new_name = text_type(new_name)
        if not new_name:
            raise ValueError(_("Playlists must have a name"))
        return new_name
Beispiel #37
0
    def settext(self, section, option, value):
        value = text_type(value)

        if PY2:
            value = value.encode("utf-8")
        else:
            # make sure there are no surrogates
            value.encode("utf-8")

        self.set(section, option, value)
    def setUp(self):
        config.init()
        self.library = SongLibrary()
        backend = quodlibet.player.init_backend("nullbe")
        self.device = backend.init(self.library)

        self.songs = [AudioFile({"title": x}) for x in
                      ["song1", "song2", "song3"]]
        for song in self.songs:
            song.sanitize(fsnative(text_type(song["title"])))
Beispiel #39
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
Beispiel #40
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
Beispiel #41
0
def N_(message):
    """
    Args:
        message (text_type)
    Returns:
        text_type

    Only marks a string for translation
    """

    return text_type(message)
Beispiel #42
0
    def __init__(self, name, library=None):
        super(Playlist, self).__init__()
        self.__inhibit_library_signals = False
        self.__instances.append(self)

        name = text_type(name)
        if not name:
            raise ValueError("Playlists must have a name")
        self.name = name
        self.library = library
        self._list = HashedList()
Beispiel #43
0
def N_(message):
    """
    Args:
        message (text_type)
    Returns:
        text_type

    Only marks a string for translation
    """

    return text_type(message)
Beispiel #44
0
    def __init__(self, name, library=None):
        super(Playlist, self).__init__()
        self.__inhibit_library_signals = False
        self.__instances.append(self)

        name = text_type(name)
        if not name:
            raise ValueError("Playlists must have a name")
        self.name = name
        self.library = library
        self._list = HashedList()
Beispiel #45
0
    def setUp(self):
        config.init()
        self.library = SongLibrary()
        backend = quodlibet.player.init_backend("nullbe")
        self.device = backend.init(self.library)

        self.songs = [
            AudioFile({"title": x}) for x in ["song1", "song2", "song3"]
        ]
        for song in self.songs:
            song.sanitize(fsnative(text_type(song["title"])))
Beispiel #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))
Beispiel #47
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))
Beispiel #48
0
 def test_lyrics_from_file(self):
     with temp_filename() as filename:
         af = AudioFile(artist='Motörhead', title='this: again')
         af.sanitize(filename)
         lyrics = "blah!\nblasé 😬\n"
         lyrics_dir = os.path.dirname(af.lyric_filename)
         mkdir(lyrics_dir)
         with io.open(af.lyric_filename, "w", encoding='utf-8') as lf:
             lf.write(text_type(lyrics))
         self.failUnlessEqual(
             af("~lyrics").splitlines(), lyrics.splitlines())
         os.remove(af.lyric_filename)
         os.rmdir(lyrics_dir)
Beispiel #49
0
 def validate(self, value):
     value = value.strip()
     try:
         f = float(value)
     except (TypeError, ValueError):
         try:
             f = locale.atof(value)
         except (TypeError, ValueError):
             raise ValidationError
     else:
         if f < 0 or f >= 2:
             raise ValidationError
         return text_type(f)
Beispiel #50
0
 def validate(self, value):
     value = value.strip()
     try:
         f = float(value)
     except (TypeError, ValueError):
         try:
             f = locale.atof(value)
         except (TypeError, ValueError):
             raise ValidationError
     else:
         if f < 0 or f >= 2:
             raise ValidationError
         return text_type(f)
Beispiel #51
0
 def test_lyrics_from_file(self):
     with temp_filename() as filename:
         af = AudioFile(artist='Motörhead', title='this: again')
         af.sanitize(filename)
         lyrics = "blah!\nblasé 😬\n"
         lyrics_dir = os.path.dirname(af.lyric_filename)
         mkdir(lyrics_dir)
         with io.open(af.lyric_filename, "w", encoding='utf-8') as lf:
             lf.write(text_type(lyrics))
         self.failUnlessEqual(af("~lyrics").splitlines(),
                              lyrics.splitlines())
         os.remove(af.lyric_filename)
         os.rmdir(lyrics_dir)
Beispiel #52
0
def run_error_dialogs(exc_info, sentry_error):
    error_text = u"%s: %s" % (exc_info[0].__name__,
                              (text_type(exc_info[1]).strip()
                               or u"\n").splitlines()[0])
    error_text += u"\n------\n"
    error_text += u"\n".join(format_exception(*exc_info))

    # Don't reshow the error dialog in case the user wanted to quit the app
    # but due to the error state more errors pile up..
    if app.is_quitting:
        return

    window = find_active_window()
    if window is None:
        return

    # XXX: This does blocking IO and uses nested event loops... but it's simple
    dialog = ErrorDialog(window,
                         error_text,
                         show_bug_report=(sentry_error is None))
    while 1:
        response = dialog.run()
        if response == ErrorDialog.RESPONSE_QUIT:
            dialog.destroy()
            app.quit()
        elif response == ErrorDialog.RESPONSE_SUBMIT:
            dialog.hide()
            submit_dialog = SubmitErrorDialog(window,
                                              sentry_error.get_report())
            submit_response = submit_dialog.run()

            if submit_response == SubmitErrorDialog.RESPONSE_SUBMIT:
                sentry_error.set_comment(submit_dialog.get_comment())
                timeout_seconds = 5
                try:
                    sentry_error.send(timeout_seconds)
                except SentryError:
                    print_exc()
                submit_dialog.destroy()
                dialog.destroy()
            else:
                submit_dialog.destroy()
                dialog.show()
                continue
        elif response == ErrorDialog.RESPONSE_BUGREPORT:
            url = get_github_issue_url(exc_info)
            website(url)
            dialog.destroy()
        else:
            dialog.destroy()
        break
Beispiel #53
0
def escape_filename(s):
    """Escape a string in a manner suitable for a filename.

    Args:
        s (text_type)
    Returns:
        fsnative
    """

    s = text_type(s)
    s = quote(s.encode("utf-8"), safe=b"")
    if isinstance(s, text_type):
        s = s.encode("ascii")
    return bytes2fsn(s, "utf-8")
Beispiel #54
0
    def __preview_tracks(self, ctx, start, total, model, save, revert):
        start = start.get_value_as_int()
        total = total.get_value_as_int()
        for row in model:
            if total:
                s = u"%d/%d" % (row.path.get_indices()[0] + start, total)
            else:
                s = text_type(row.path.get_indices()[0] + start)
            entry = row[0]
            entry.tracknumber = s
            model.row_changed(row.path, row.iter)

        save.set_sensitive(True)
        revert.set_sensitive(True)
Beispiel #55
0
def escape_filename(s):
    """Escape a string in a manner suitable for a filename.

    Args:
        s (text_type)
    Returns:
        fsnative
    """

    s = text_type(s)
    s = quote(s.encode("utf-8"), safe=b"")
    if isinstance(s, text_type):
        s = s.encode("ascii")
    return bytes2fsn(s, "utf-8")
Beispiel #56
0
    def __init__(self, row_pattern):
        parts = re.split(r"(?<!\\):", row_pattern)
        parts = list(map(lambda p: p.replace(r"\:", ":"), parts))

        is_numeric = lambda s: s[:2] == "~#" and "~" not in s[2:]
        is_pattern = lambda s: '<' in s
        f_round = lambda s: (isinstance(s, float) and "%.2f" % s) or s

        disp = (len(parts) >= 2 and parts[1]) or r"[i](<~#tracks>)[/i]"
        cat = parts[0]

        if is_pattern(cat):
            title = util.pattern(cat, esc=True, markup=True)
            try:
                pc = XMLFromPattern(cat)
            except ValueError:
                pc = XMLFromPattern("")
            tags = pc.tags
            format = pc.format_list
            has_markup = True
        else:
            title = util.tag(cat)
            tags = util.tagsplit(cat)
            has_markup = False
            if is_numeric(cat):

                def format(song):
                    v = text_type(f_round(song(cat)))
                    return [(v, v)]
            else:
                format = lambda song: song.list_separate(cat)

        if is_pattern(disp):
            try:
                pd = XMLFromPattern(disp)
            except ValueError:
                pd = XMLFromPattern("")
            format_display = pd.format
        else:
            if is_numeric(disp):
                format_display = lambda coll: text_type(f_round(coll(disp)))
            else:
                format_display = lambda coll: util.escape(coll.comma(disp))

        self.title = title
        self.tags = set(tags)
        self.format = format
        self.format_display = format_display
        self.has_markup = has_markup
Beispiel #57
0
    def __init__(self, name, library=None):
        super(Playlist, self).__init__()
        self.__inhibit_library_signals = False
        self.__instances.append(self)

        name = text_type(name)
        if not name:
            raise ValueError("Playlists must have a name")

        # we require a file library here with masking
        assert library is None or hasattr(library, "masked")

        self.name = name
        self.library = library
        self._list = HashedList()