def get_cover(self, entry): if entry: # Try to find an album cover in the folder of the currently playing track cover_dir = path.dirname( url2pathname(entry.get_playback_uri()).replace('file://', '')) # TODO: use os.walk() if path.isdir(cover_dir): for f in listdir(cover_dir): file_name = path.join(cover_dir, f) mt = mimetypes.guess_type(file_name)[0] if mt and mt.startswith('image/'): if True in [ x in path.splitext(f)[0].lower() for x in ['cover', 'album', 'albumart', 'folder', 'front'] ]: return GdkPixbuf.Pixbuf.new_from_file_at_size( file_name, self.ALBUM_ART_W, self.ALBUM_ART_H) # Otherwise use what's found by the album art plugin key = entry.create_ext_db_key(RB.RhythmDBPropType.ALBUM) cover_db = RB.ExtDB(name='album-art') art_location = cover_db.lookup(key) if art_location and not isinstance(art_location, str): # RB 3.2 returns a tuple (path, key) art_location = art_location[0] if art_location and path.exists(art_location): return GdkPixbuf.Pixbuf.new_from_file_at_size( art_location, self.ALBUM_ART_W, self.ALBUM_ART_H)
def do_activate(self): shell = self.object self.db = shell.props.db self.artcache = os.path.join(RB.user_cache_dir(), "album-art", "") self.art_store = RB.ExtDB(name="album-art") self.art_store.connect("added", self.art_added_cb) self.shell_player = shell.props.shell_player self.shell_player.connect("playing-song-changed", self.playing_song_changed_cb) self.shell_player.connect("playing-song-property-changed", self.playing_song_property_changed_cb) self.shell_player.connect("playing-changed", self.playing_changed_cb) self.shell_player.connect("elapsed-nano-changed", self.elapsed_nano_changed_cb) self.playing_song_changed_cb(self.shell_player, self.shell_player.get_playing_entry()) self.http_server = Soup.Server() self.http_server.add_handler(path="/art/", callback=self.http_art_cb) self.http_server.add_handler(path="/icon/", callback=self.http_icon_cb) self.http_server.add_handler(path="/entry/current/stream", callback=self.http_track_cb) self.http_server.add_handler(path="/css/", callback=self.http_static_css_cb) self.http_server.add_handler(path="/js/", callback=self.http_static_js_cb) self.http_server.add_websocket_handler("/ws/player", None, None, self.player_websocket_cb) self.http_server.add_handler(path="/", callback=self.http_root_cb) self.http_listen()
def do_activate(self): self.art_store = RB.ExtDB(name="album-art") self.req_id = self.art_store.connect("request", self.album_art_requested) shell = self.object self.csi_id = shell.connect("create_song_info", self.create_song_info)
def __init__(self): RB.BrowserSource.__init__(self) self.hate = self self.__popup = None self.__settings = Gio.Settings("org.gnome.rhythmbox.plugins.magnatune") # source state self.__activated = False self.__db = None self.__info_screen = None # the loading screen # track data self.__sku_dict = {} self.__home_dict = {} self.__art_dict = {} # catalogue stuff self.__has_loaded = False # whether the catalog has been loaded yet self.__update_id = 0 # GLib.idle_add id for catalog updates self.__catalogue_loader = None self.__catalogue_check = None self.__load_progress = None self.__download_progress = None # album download stuff self.__downloads = {} # keeps track of download progress for each file self.__copies = {} # keeps copy objects for each file self.__art_store = RB.ExtDB(name="album-art")
def do_activate(self): """ Called by rhythmbox when the plugin is activated """ super(Caveman, self).do_activate() app = self.object.props.application self.track_ids = {} self.import_queue = { 'songs': [], 'playlists': [], } self.export_queue = { 'songs': [], 'playlists': [], } self.existing_songs = set() self.ext_db = RB.ExtDB(name="caveman") self.config = configparser.RawConfigParser() self.config_file = os.path.join(os.environ['HOME'], '.local/share/rhythmbox/cavemanrc') if os.path.isfile(self.config_file): self.config.read(self.config_file) else: self.config.read( os.path.join( os.environ['HOME'], '.local/share/rhythmbox/caveman/defaults.cavemanrc')) if self.config.get('DEFAULT', 'music_root_dir') == "XDG_MUSIC_DIR": self.config.set('DEFAULT', 'music_root_dir', self.get_xdg_music_dir()) self.our_prefix = 'file://' + self.config.get('DEFAULT', 'music_root_dir') if self.our_prefix[-1] != '/': self.our_prefix = self.our_prefix + "/" self.add_action('import-from-itunes', self.import_from_itunes, parentMenu='tools', menuName='Import from iTunes') self.add_action('export-to-itunes', self.export_to_itunes, parentMenu='tools', menuName='Export to iTunes') for row in self.object.props.library_source.props.base_query_model: entry = row[0] loc = self.object.props.db.entry_get(entry, prop.LOCATION) self.existing_songs.add(loc) if self.config.getboolean('DEFAULT', 'auto_import'): self.import_from_itunes()
def __init__(self, hostname, port, plugin): self.plugin = plugin self.running = True self.artist = None self.album = None self.title = None self.stream = None self.initial_playlist_rows = None self._httpd = make_server(hostname, port, self._wsgi) self._watch_cb_id = GObject.io_add_watch(self._httpd.socket, GObject.IO_IN, self._idle_cb) self._cover_db = RB.ExtDB(name='album-art')
def __init__(self, plugin, sprite_name, size=None): popups = rb.find_plugin_file(plugin, 'img/popups.xml') root = ET.parse(open(popups)).getroot() base = 'theme/theme[@folder_name="' + Theme(plugin).current \ + '"]/spritesheet[@name="' + sprite_name + '"]/' image = rb.find_plugin_file(plugin, 'img/' + Theme(plugin).current \ + '/' + root.xpath(base + 'image')[0].text) icon_width = int(root.xpath(base + 'icon')[0].attrib['width']) icon_height = int(root.xpath(base + 'icon')[0].attrib['height']) x_spacing = int(root.xpath(base + 'spacing')[0].attrib['x']) y_spacing = int(root.xpath(base + 'spacing')[0].attrib['y']) x_start = int(root.xpath(base + 'start-position')[0].attrib['x']) y_start = int(root.xpath(base + 'start-position')[0].attrib['y']) across_dimension = int( root.xpath(base + 'dimension')[0].attrib['across']) down_dimension = int(root.xpath(base + 'dimension')[0].attrib['down']) try: alpha_color = list( map(int, root.xpath(base + 'alpha')[0].text.split(' '))) except: alpha_color = None self.names = [] self.locale_names = {} cl = CoverLocale() lang = cl.get_locale() base = sprite_name + '/' + sprite_name + \ '[@spritesheet="' + sprite_name + '"]' for elem in root.xpath(base + '[not(@xml:lang)]'): self.names.append(elem.text) for elem in root.xpath(base + '[@xml:lang="' + lang + '"]'): self.locale_names[elem.text] = elem.attrib['name'] if (not self.locale_names) and len(lang) > 2: for elem in root.xpath(base + '[@xml:lang="' + \ lang[0:2] + '"]'): self.locale_names[elem.text] = elem.attrib['name'] self._sheet = SpriteSheet(image, icon_width, icon_height, x_spacing, y_spacing, x_start, y_start, across_dimension, down_dimension, alpha_color, size) self._genre_db = RB.ExtDB(name='cb_genre')
def __init__(self, db, uri): self.db = db self.it_db = RB.ExtDB(name="caveman") self.it_data = {} self.entry = db.entry_lookup_by_location(uri) if self.entry: self.isNew = False key = entry.create_ext_db_key(prop.LOCATION) self.it_db.request(key, it_data_fetched_cb) else: if uri[0:7] == 'file://': entry_type = db.entry_type_get_by_name('song') else: entry_type = db.entry_type_get_by_name('iradio') self.entry = RB.RhythmDBEntry.new(db, entry_type, uri) self.isNew = True
def do_activate(self): # activate source if inactive if not self.__activated: self.__activated = True self.__shell = self.props.shell self.__db = self.__shell.props.db self.__entry_type = self.props.entry_type # connect playing-song-changed signal self.__art_store = RB.ExtDB(name="album-art") self.__art_request = self.__art_store.connect("request", self.__album_art_requested) # create cache directory if it doesn't exist cache_path = os.path.dirname(self.__songs_cache_filename) if not os.path.exists(cache_path): os.mkdir(cache_path, 0o700) self.update(False)
def __init__(self): super(BaseSource, self).__init__() self.songs = [] # the song ids in this source self.activated = False # the tag of activate self.popup = None # the popup menu self.index = -1 # the index of position where insert song # get_status function self.updating = False # the status of update self.status = "" # the message of source's status self.progress = 0 # the progress of update self.entry_widgets = [] # a list includes the toolitems # set up the coverart self.__art_store = RB.ExtDB(name="album-art") self.__req_id = self.__art_store.connect( "request", self.__album_art_requested )
def show_fullscreen(self, *args): self.window = FullscreenWindow.FullscreenWindow(plugin=self) # Receive notification of song changes self.player = self.shell.props.shell_player self.player.connect("playing-source-changed", self.reload_playlist) self.player.connect("playing-song-changed", self.on_playing_song_changed) self.player.connect("playing-changed", self.reload_play_pause) # TODO: This signal is not fired - which should we listen for? # We should use the cover_db, # but what are its signals?? cover_db = RB.ExtDB(name='album-art') self.player.connect("playing-song-property-changed", self.notify_metadata) cover_db.connect("added", self.notify_cover_art_change) # Load current state self.reload_playlist(self.player, self.player.get_playing_entry())
def __init__(self, shell, song_info): self.visible = False self.art_key = None self.shell = shell self.song_info = song_info self.entry = song_info.props.current_entry self.art_store = RB.ExtDB(name="album-art") self.art_store.connect("added", self.art_added_cb) grid = Gtk.Grid(hexpand=True, vexpand=True, margin=6, row_spacing=6) self.image = RB.FadingImage(fallback="rhythmbox-missing-artwork", use_tooltip=False) self.image.props.hexpand = True self.image.props.vexpand = True grid.attach(self.image, 0, 0, 1, 1) buttons = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL) buttons.set_spacing(6) buttons.set_layout(Gtk.ButtonBoxStyle.CENTER) grid.attach(buttons, 0, 1, 1, 1) clear = Gtk.Button(label=_("Clear"), use_underline=True) clear.connect('clicked', self.clear_button_cb) buttons.add(clear) fetch = Gtk.Button(label=_("_Fetch"), use_underline=True) fetch.connect('clicked', self.fetch_button_cb) buttons.add(fetch) browse_file = Gtk.Button(label=_("_Browse"), use_underline=True) browse_file.connect('clicked', self.browse_button_cb) buttons.add(browse_file) self.page_num = song_info.append_page(_("Album Art"), grid) self.ec_id = song_info.connect("notify::current-entry", self.entry_changed_cb) self.sp_id = grid.get_parent().connect("switch-page", self.switch_page_cb)
def __init__(self, plugin, cover_model): ''' Initialises the loader, getting the needed objects from the plugin and saving the model that will be used to assign the loaded albums. ''' self.albums = {} self.db = plugin.shell.props.db self.cover_model = cover_model self.cover_db = RB.ExtDB(name='album-art') # connect the signal to update cover arts when added self.req_id = self.cover_db.connect('added', self._albumart_added_callback) # connect signals for updating the albums self.entry_changed_id = self.db.connect('entry-changed', self._entry_changed_callback) self.entry_added_id = self.db.connect('entry-added', self._entry_added_callback) self.entry_deleted_id = self.db.connect('entry-deleted', self._entry_deleted_callback) # initialise unkown cover for albums without cover Album.init_unknown_cover(plugin)
def get_cover(self, db_entry=None): # Find cover in music dir if db_entry: print("dbentry") cover_dir = path.dirname( url2pathname(db_entry.get_playback_uri()).replace( 'file://', '')) if path.isdir(cover_dir): print(cover_dir) for f in listdir(cover_dir): file_name = path.join(cover_dir, f) mt = mimetypes.guess_type(file_name)[0] if mt and mt.startswith('image/'): if path.splitext(f)[0].lower() in IMAGE_NAMES: print("spli") print(file_name) return file_name # Find cover saved by artdisplay plugin song_info = self.get_song_info(db_entry) for rb_cover_path in ('~/.gnome2/rhythmbox/covers', '~/.cache/rhythmbox/covers/'): for file_type in ('jpg', 'png', 'jpeg', 'gif', 'svg'): cover_file = path.join( path.expanduser(rb_cover_path), '%s - %s.%s' % (song_info['artist'], song_info['album'], file_type)) if path.isfile(cover_file): print("Found image in cache folder") print(cover_file) return cover_file key = db_entry.create_ext_db_key(RB.RhythmDBPropType.ALBUM) cover_db = RB.ExtDB(name='album-art') art_location = cover_db.lookup(key) if art_location and not isinstance(art_location, str): art_location = art_location[0] # hack for RB 3.2 api if art_location and path.exists(art_location): print(art_location) return art_location # Find the image from AlbumArt plugin #cover_art = self.db.entry_request_extra_metadata(db_entry, "rb:coverArt") # If image not found return #if cover_art==None: # print "Image not found, bloody timeouts" # return DesktopControl.UNKNOWN_COVER # Do the dirty work here cover_file = path.expanduser(STORAGE_LOC) + song_info[ 'title'] + "-" + song_info['artist'] + ".jpg" print(cover_file) cover_art.save(cover_file, "jpeg", {"quality": "100"}) print("Returning cover file") print(cover_file) return cover_file # No cover found print("no cover") return DesktopControl.UNKNOWN_COVER # Not playing print("not playing") return None
def setup(self): shell = self.props.shell builder = Gtk.Builder() builder.add_from_file(rb.find_plugin_file(self.props.plugin, "soundcloud.ui")) self.scrolled = builder.get_object("container-scrolled") self.scrolled.set_no_show_all(True) self.scrolled.hide() self.more_containers_idle = 0 adj = self.scrolled.get_vadjustment() adj.connect("changed", self.scroll_adjust_changed_cb) adj.connect("value-changed", self.scroll_adjust_changed_cb) self.search_entry = RB.SearchEntry(spacing=6) self.search_entry.props.explicit_mode = True self.fetch_more_button = Gtk.Button.new_with_label(_("Fetch more tracks")) self.fetch_more_button.connect("clicked", self.show_more_cb) action = Gio.SimpleAction.new("soundcloud-search-type", GLib.VariantType.new('s')) action.connect("activate", self.search_type_action_cb) shell.props.window.add_action(action) m = Gio.Menu() for st in sorted(self.search_types): i = Gio.MenuItem() i.set_label(self.search_types[st]['label']) i.set_action_and_target_value("win.soundcloud-search-type", GLib.Variant.new_string(st)) m.append_item(i) self.search_popup = Gtk.Menu.new_from_model(m) action.activate(GLib.Variant.new_string("tracks")) grid = builder.get_object("soundcloud-source") self.search_entry.connect("search", self.search_entry_cb) self.search_entry.connect("activate", self.search_entry_cb) self.search_entry.connect("show-popup", self.search_popup_cb) self.search_entry.set_size_request(400, -1) searchbox = builder.get_object("search-box") searchbox.pack_start(self.search_entry, False, True, 0) searchbox.pack_start(self.fetch_more_button, False, True, 0) self.search_popup.attach_to_widget(self.search_entry, None) self.containers = builder.get_object("container-store") self.container_view = builder.get_object("containers") self.container_view.set_model(self.containers) action = Gio.SimpleAction.new("soundcloud-open-uri", GLib.VariantType.new('s')) action.connect("activate", self.open_uri_action_cb) shell.props.window.add_action(action) r = Gtk.CellRendererText() c = Gtk.TreeViewColumn("", r, text=0) self.container_view.append_column(c) self.container_view.get_selection().connect('changed', self.selection_changed_cb) self.songs = RB.EntryView(db=shell.props.db, shell_player=shell.props.shell_player, is_drag_source=True, is_drag_dest=False, shadow_type=Gtk.ShadowType.NONE) self.songs.append_column(RB.EntryViewColumn.TITLE, True) self.songs.append_column(RB.EntryViewColumn.ARTIST, True) self.songs.append_column(RB.EntryViewColumn.DURATION, True) self.songs.append_column(RB.EntryViewColumn.YEAR, False) self.songs.append_column(RB.EntryViewColumn.GENRE, False) self.songs.append_column(RB.EntryViewColumn.BPM, False) self.songs.append_column(RB.EntryViewColumn.FIRST_SEEN, False) self.songs.set_model(self.props.query_model) self.songs.connect("notify::sort-order", self.sort_order_changed_cb) self.songs.connect("selection-changed", self.songs_selection_changed_cb) paned = builder.get_object("paned") paned.pack2(self.songs) self.bind_settings(self.songs, paned, None, True) self.sc_button = Gtk.MenuButton() self.sc_button.set_relief(Gtk.ReliefStyle.NONE) img = Gtk.Image.new_from_file(rb.find_plugin_file(self.props.plugin, "powered-by-soundcloud.png")) self.sc_button.add(img) box = builder.get_object("soundcloud-button-box") box.pack_start(self.sc_button, True, True, 0) self.build_sc_menu() self.pack_start(grid, expand=True, fill=True, padding=0) grid.show_all() self.art_store = RB.ExtDB(name="album-art") player = shell.props.shell_player player.connect('playing-song-changed', self.playing_entry_changed_cb)
def __init__(self, toggle_action_group, plugin): self.shell = plugin.object self.player = self.shell.props.shell_player self.backend = plugin # Plugin instance # The fullscreen window Gtk.Window.__init__(self) # Referenced in CSS self.set_name("szyrics-fullscreen-window") # If the window is closed in any event, 'delete_event' method is called self.connect("delete_event", self.delete_event) # For specific keyboard key presses self.connect("key_press_event", self.key_press) w = self s = w.get_screen() # Using the screen of the Window, the monitor it's on can be identified m = s.get_monitor_at_window(s.get_active_window()) # Then get the geometry of that monitor monitor = s.get_monitor_geometry(m) # This is an example output print("Height: %s, Width: %s" % (monitor.height, monitor.width)) if monitor.height < monitor.width: self._albumCoverHeight = monitor.height / 3 self._albumCoverWidth = monitor.height / 3 else: self._albumCoverHeight = monitor.width / 3 self._albumCoverWidth = monitor.width / 3 # Setting the icon that shows on Alt+Tab try: icon_theme = Gtk.icon_theme_get_default() self.set_icon(icon_theme.load_icon("view-fullscreen", Gtk.ICON_SIZE_DIALOG, Gtk.ICON_LOOKUP_FORCE_SVG)) except: pass # If no album art is available, the default image self.no_artwork = GdkPixbuf.Pixbuf.new_from_file_at_size( rb.find_plugin_file(self.backend, "img/missing-artwork.svg"), self._albumCoverWidth, self._albumCoverHeight ) # Retrieve the lyrics folder location self.lyrics_folder = Util.set_lyrics_folder() # Create and put together all the elements in the sidebar (but don't show yet) self.init_window(monitor) # If nothing is playing, opens fullscreen window -> (show default image) self.set_artwork() # Add the background colour, text properties self.gtk_style() # Show and go fullscreen self.show_all() self.fullscreen() # Initialise here, displays in file chooser dialog self.title = None self.artist = None # Must exist for file selected in chooser dialog to be copied self.path = None self.pause_circle_exists = False # Used for synchronized lyrics self.tags = None self.current_tag = None # Signal flags self.fsc_id = None self.fsrc_id = None self.fec_id = None self.fspc_id = None # The toggle switch for the plugin in the view menu bar self.toggle_action_group = toggle_action_group # If window opened with the song paused, show the play circle if self.player.get_playing_source(): if not self.player.get_playing()[1]: self.add_play_circle() # Colour for highlighting text rgba = Gdk.RGBA() rgba.parse("#009fd4") # tag to style headers bold and underlined self.tag = self.textbuffer.create_tag(None, size_points=24, underline=Pango.Underline.SINGLE, weight=Pango.Weight.BOLD, foreground_rgba=rgba, pixels_above_lines=10, pixels_below_lines=20) # tag to highlight synchronized lyrics self.sync_tag = self.textbuffer.create_tag(None, weight=Pango.Weight.BOLD, foreground_rgba=rgba) # Receive notification of song changes self.fsrc_id = self.player.connect("playing-source-changed", self.reload_lyrics) self.fsc_id = self.player.connect("playing-song-changed", self.reload_lyrics) # self.player.connect("playing-changed", self.reload_lyrics) # TODO: This signal is not fired - which should we listen for? # We should use the cover_db, # but what are its signals?? cover_db = RB.ExtDB(name='album-art') self.fspc_id = self.player.connect("playing-song-property-changed", self.notify_metadata) cover_db.connect("added", self.notify_cover_art_change) # Load lyrics on immediatley opening the fullscreen window self.reload_lyrics(self.player, self.player.get_playing_entry())
def do_activate (self): self.art_store = RB.ExtDB(name="album-art") self.req_id = self.art_store.connect("request", self.album_art_requested)