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)
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
def get_track(path): ext = blautil.get_extension(path).lower() try: track = formats[ext](path) except (KeyError, TagParseError): track = None return track
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
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
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()
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
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
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
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)
def __extension_cb(track): return blautil.get_extension(track.uri)