Beispiel #1
0
    def __fetch_cover(self, track, timestamp, force_download):
        def emit(cover):
            gobject.source_remove(self.__tid)
            self.emit("cover", timestamp, cover, force_download)
            return False

        gobject.source_remove(self.__tid)
        cover = None

        image_base = track.get_cover_basepath()
        if image_base is None:
            return

        if not force_download:
            if os.path.isfile("%s.jpg" % image_base):
                cover = "%s.jpg" % image_base
            elif os.path.isfile("%s.png" % image_base):
                cover = "%s.png" % image_base

        if cover is not None:
            return emit(cover)

        self.__tid = gobject.timeout_add(2000, emit, blaconst.COVER)
        cover = blafm.get_cover(track, image_base)
        # Don't try to get a cover from disk if we were specifically asked to
        # download it.
        if cover is None and not force_download:
            base = os.path.dirname(track.uri)
            images = [f for f in os.listdir(base)
                      if blautil.get_extension(f).lower() in ["jpg", "png"]]
            r = re.compile(
                r"front|cover|^folder|^albumart.*large", re.UNICODE)
            for image in images:
                name = image.lower()
                if r.search(name):
                    path = os.path.join(base, image)
                    name = os.path.basename(image_base)
                    images = [f for f in os.listdir(blaconst.COVERS)
                              if f.startswith(name)]
                    images = [os.path.join(blaconst.COVERS, f)
                              for f in images]
                    map(os.unlink, images)
                    cover = "%s.%s" % (
                        image_base, blautil.get_extension(path))
                    shutil.copy(path, cover)
                    break
        if cover is not None:
            emit(cover)
Beispiel #2
0
    def get_cover(self, restore=False):
        pixbuf = path = None
        path = ("%s-%s" % (self.artist_name, self.release_name)).replace(
            " ", "_")
        image_base = os.path.join(blaconst.RELEASES, path)
        for ext in ("jpg", "png"):
            try:
                path = "%s.%s" % (image_base, ext)
                pixbuf = gtk.gdk.pixbuf_new_from_file(path)
            except gobject.GError:
                pass
            else:
                pixbuf = pixbuf.scale_simple(IMAGE_SIZE, IMAGE_SIZE,
                                             gtk.gdk.INTERP_HYPER)
                break
        else:
            if not restore:
                url = blafm.get_image_url(self.__raw["image"])
                try:
                    image, _ = urllib.urlretrieve(url)
                    path = "%s.%s" % (image_base, blautil.get_extension(image))
                    shutil.move(image, path)
                    pixbuf = gtk.gdk.pixbuf_new_from_file(path).scale_simple(
                        IMAGE_SIZE, IMAGE_SIZE, gtk.gdk.INTERP_HYPER)
                except (IOError, gobject.GError):
                    pass

        self.cover = pixbuf or BlaRelease.__EMPTY_PIXBUF
        return path
Beispiel #3
0
def get_track(path):
    ext = blautil.get_extension(path).lower()
    try:
        track = formats[ext](path)
    except (KeyError, TagParseError):
        track = None
    return track
Beispiel #4
0
def retrieve_image(image_base, image_urls):
    image = None
    url = get_image_url(image_urls)
    if url:
        image, _ = urllib.urlretrieve(
            url, "%s.%s" % (image_base, blautil.get_extension(url)))
    return image
Beispiel #5
0
    def _read_tags(self):
        uri = self.uri
        baseclass, format_, encoding = self.__ext_to_format[
            blautil.get_extension(uri)]

        try:
            audio = baseclass(uri)
        except (OggVorbisError, OggFLACError, FLACError):
            raise TagParseError

        for key, values in (audio.tags or {}).iteritems():
            try:
                identifier = self.__tag_to_literal[key]
            except KeyError:
                identifier = key
            self[identifier] = map(unicode, values)

        # In vorbis comments tracknumber and number of total tracks are stored
        # in different keys. The same goes for discs. We construct the form we
        # normally work with here.
        for identifier, (num, total) in self.__split_keys.iteritems():
            if num in self.keys_tags():
                self[identifier] = self.pop(num)
            if self[identifier] and total in self.keys_tags():
                self[identifier] += "/" + self.pop(total)

        self._parse_info(audio.info)
        self[FORMAT] = format_
        self[ENCODING] = encoding
Beispiel #6
0
    def __save_playlist(self, window):
        diag = gtk.FileChooserDialog(
            "Save playlist", action=gtk.FILE_CHOOSER_ACTION_SAVE,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE,
                     gtk.RESPONSE_OK))
        diag.set_do_overwrite_confirmation(True)
        self.__set_file_chooser_directory(diag)

        items = [
            ("M3U", "audio/x-mpegurl", "m3u"),
            ("PlS", "audio/x-scpls", "pls", ),
            ("XSPF", "application/xspf+xml", "xspf"),
            ("Decide by extension", None, None)
        ]
        for label, mime_type, extension in items:
            filt = gtk.FileFilter()
            filt.set_name(label)
            filt.add_pattern("*.%s" % extension)
            if mime_type:
                filt.add_mime_type(mime_type)
            diag.add_filter(filt)

        # Add combobox to the dialog to choose whether to save relative or
        # absolute paths in the playlist.
        box = diag.child
        hbox = gtk.HBox()
        cb = gtk.combo_box_new_text()
        hbox.pack_end(cb, expand=False, fill=False)
        box.pack_start(hbox, expand=False, fill=False)
        box.show_all()
        map(cb.append_text, ["Relative paths", "Absolute paths"])
        cb.set_active(0)

        def filter_changed(diag, filt):
            filt = diag.get_filter()
            if diag.list_filters().index(filt) == 2:
                sensitive = False
            else:
                sensitive = True
            cb.set_sensitive(sensitive)
        diag.connect("notify::filter", filter_changed)

        response = diag.run()
        path = diag.get_filename()

        if response == gtk.RESPONSE_OK and path:
            filt = diag.get_filter()
            type_ = items[diag.list_filters().index(filt)][-1]
            path = path.strip()
            if type_ is None:
                type_ = blautil.get_extension(path)
            playlist_manager.save(path, type_, cb.get_active() == 0)
            blacfg.set("general", "filechooser.directory",
                       os.path.dirname(path))

        diag.destroy()
Beispiel #7
0
    def get_image(self, restore=False):
        image_base = os.path.join(
            blaconst.EVENTS, self.event_name.replace(" ", "_"))
        pixbuf = path = None
        for ext in ("jpg", "png"):
            path = "%s.%s" % (image_base, ext)
            try:
                pixbuf = gtk.gdk.pixbuf_new_from_file(path)
            except gobject.GError:
                continue
            break
        else:
            if not restore:
                url = blafm.get_image_url(self.__raw["image"])
                try:
                    image, _ = urllib.urlretrieve(url)
                    path = "%s.%s" % (
                        image_base, blautil.get_extension(image))
                    shutil.move(image, path)
                    pixbuf = gtk.gdk.pixbuf_new_from_file(path)
                except (IOError, gobject.GError):
                    pass

        # Resize until the smaller dimension reaches IMAGE_SIZE, then crop
        # IMAGE_SIZE x IMAGE_SIZE pixels from the center of the image in
        # case of a landscape image and from the top in case of a portrait.
        # FIXME: too much code in the try-block
        try:
            width, height = pixbuf.get_width(), pixbuf.get_height()
            # Portrait
            if width < height:
                height = int(height * (IMAGE_SIZE / float(width)))
                width = IMAGE_SIZE
                x = y = 0
            # Landscape
            else:
                width = int(width * (IMAGE_SIZE / float(height)))
                height = IMAGE_SIZE
                x = int((width - IMAGE_SIZE) / 2)
                y = 0
            pixbuf = pixbuf.scale_simple(
                width, height, gtk.gdk.INTERP_HYPER).subpixbuf(
                    x, y, IMAGE_SIZE, IMAGE_SIZE)

        except (AttributeError, gobject.GError):
            pass
        self.image = pixbuf or BlaEvent.__EMPTY_PIXBUF
        return path
Beispiel #8
0
    def _save(self):
        uri = self.uri
        baseclass, format_, encoding = self.__ext_to_format[
            blautil.get_extension(uri)]
        try:
            audio = baseclass(uri)
        except IOError:
            return False

        tags = audio.tags
        if tags is None:
            audio.add_tags()
            tags = audio.tags

        try:
            for tag in self._deleted_tags:
                try:
                    del tags[tag]
                except KeyError:
                    pass
            self._deleted_tags.clear()
        except AttributeError:
            pass

        for identifier in self.keys_tags():
            try:
                values = self.get(identifier)
                if not values:
                    raise KeyError
            except KeyError:
                continue

            try:
                tag = self.__literal_to_tag[identifier]
            except KeyError:
                tag = identifier

            if identifier in self.__split_keys:
                num, total = self.__split_keys[identifier]
                values = values.split("/", 1)
                tags[num] = values[0]
                if len(values) > 1 and total not in self.keys_tags():
                    tags[total] = values[1]
            else:
                tags[tag] = values

        audio.save()
        return True
Beispiel #9
0
def parse_uri(uri):
    stations = []
    if isinstance(uri, unicode):
        uri = uri.encode("utf-8")
    ext = blautil.get_extension(uri).lower()
    if ext in ("m3u", "pls", "asx"):
        f = urllib.urlopen(uri)

        if ext == "m3u":
            for line in f:
                line = line.strip()
                if line.startswith("http"):
                    stations.append(BlaRadioStation(uri, line))

        elif ext == "pls":
            parser = ConfigParser()
            parser.readfp(f)
            if "playlist" in parser.sections():
                kwargs = dict(parser.items("playlist"))
                entries = [key for key in kwargs.iterkeys()
                           if key.startswith("file")]
                stations.extend([BlaRadioStation(uri, kwargs[e])
                                 for e in entries])

        elif ext == "asx":
            try:
                tree = ETree.ElementTree(None, f)
            except SyntaxError:
                pass
            else:
                iterator = tree.getiterator()
                for node in iterator:
                    keys = node.keys()
                    try:
                        idx = map(str.lower, keys).index("href")
                    except ValueError:
                        continue
                    location = node.get(keys[idx]).strip()
                    stations.append(BlaRadioStation(uri, location))

        f.close()

    elif uri:
        stations.append(BlaRadioStation(uri, uri))
    return stations
Beispiel #10
0
    def set_cover(self, timestamp, path=None):
        track = self.__track

        # Stop any thread which still might be trying to retrieve a cover.
        self.__thread_cover.kill()

        # Remove any old images -- both user-set and downloaded.
        if path != blaconst.COVER:
            image_base = track.get_cover_basepath()
            if image_base is not None:
                name = os.path.basename(image_base)
                images = [
                    os.path.join(blaconst.COVERS, f)
                    for f in os.listdir(blaconst.COVERS) if f.startswith(name)]
                map(os.unlink, images)

        if path is not None:
            cover = "%s.%s" % (image_base, blautil.get_extension(path))
            shutil.copy(path, cover)
        else:
            cover = blaconst.COVER

        self.emit("cover", timestamp, cover, False)
Beispiel #11
0
 def __extension_cb(track):
     return blautil.get_extension(track.uri)