def do_activate(self): shell = self.object data = {} self.shell = shell self.entries = None self.action_group = ActionGroup(self.shell, 'FullscreenPluginActions') action = self.action_group.add_action(func=self.show_fullscreen, action_name='ToggleFullscreen', label='Full Screen', action_type='app', accel="F12") self._appshell = ApplicationShell(self.shell) self._appshell.insert_action_group(self.action_group) self._appshell.add_app_menuitems(ui_str, 'FullscreenPluginActions', 'view') w = self.shell.props.window 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.ALBUM_ART_H = monitor.height self.ALBUM_ART_W = monitor.height else: self.ALBUM_ART_H = monitor.width self.ALBUM_ART_W = monitor.width
def do_activate(self): shell = self.object data = {} self.shell = shell self.entries = None w = self.shell.props.window 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("Heigh: %s, Width: %s" % (monitor.height, monitor.width)) if monitor.height < monitor.width: self.ALBUM_ART_H = monitor.height self.ALBUM_ART_W = monitor.height else: self.ALBUM_ART_H = monitor.width self.ALBUM_ART_W = monitor.width self.action_group = ActionGroup(self.shell, 'FullscreenPluginActions') action = self.action_group.add_action(func=self.show_fullscreen, action_name='ToggleFullscreen', label='Full Screen', action_type='app', accel="F12") self._appshell = ApplicationShell(self.shell) self._appshell.insert_action_group(self.action_group) self._appshell.add_app_menuitems(ui_str, 'FullscreenPluginActions', 'view')
def do_activate(self): shell = self.object data = {} self.shell = shell self.entries = None self.action_group = ActionGroup(self.shell, "FullscreenPluginActions") action = self.action_group.add_action( func=self.show_fullscreen, action_name="ToggleFullscreen", label="Full Screen", action_type="app", accel="F12", ) self._appshell = ApplicationShell(self.shell) self._appshell.insert_action_group(self.action_group) self._appshell.add_app_menuitems(ui_str, "FullscreenPluginActions", "view")
class FullscreenView(GObject.Object, Peas.Activatable): __gtype_name = "FullscreenPlugin" object = GObject.property(type=GObject.Object) # @ReservedAssignment def __init__(self): super(FullscreenView, self).__init__() def do_activate(self): shell = self.object data = {} self.shell = shell self.entries = None self.action_group = ActionGroup(self.shell, "FullscreenPluginActions") action = self.action_group.add_action( func=self.show_fullscreen, action_name="ToggleFullscreen", label="Full Screen", action_type="app", accel="F12", ) self._appshell = ApplicationShell(self.shell) self._appshell.insert_action_group(self.action_group) self._appshell.add_app_menuitems(ui_str, "FullscreenPluginActions", "view") def do_deactivate(self): shell = self.object self._appshell.cleanup() 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 playpause(self): # Argument 'True' is unused # (see http://developer.gnome.org/rhythmbox/2.98/RBShellPlayer.html#rb-shell-player-playpause) self.player.playpause(True) def play_entry(self, index): if len(self.tracks) > index: self.player.play_entry(self.tracks[index].entry, self.shell.get_property("library-source")) def reload_play_pause(self, player, playing): if not self.window.track_widgets: return if playing: try: elapsed = player.get_playing_time() except: elapsed = (True, 0.0) self.window.track_widgets[self.window.current_track].paused = False self.window.track_widgets[self.window.current_track].start_progress_bar(elapsed) self.window.current_info = "Now playing..." self.window.track_infos[0] = FullscreenWindow.FullscreenWindow.INFO_STATUS_PAUSE else: self.window.track_widgets[self.window.current_track].paused = True self.window.current_info = FullscreenWindow.FullscreenWindow.INFO_STATUS_IDLE self.window.track_infos[0] = FullscreenWindow.FullscreenWindow.INFO_STATUS_PLAY def get_entries(self, player, entry, cnt): """Gets the next and previous entries to be played from both active source and queue Next entries: Everything from source and queue Previous entries: Everything just from the source Uses each source's query-model. player = player to use entry = entry to start from (as a kind of offset) cnt = number of entries to return """ if not entry: return [] entries = [entry] def get_entries(property_name, backwards): queue = player.get_property(property_name) if queue: querymodel = queue.get_property("query-model") if not backwards: l = querymodel.get_next_from_entry(entry) while l and len(entries) <= cnt: entries.append(l) l = querymodel.get_next_from_entry(l) else: l = querymodel.get_previous_from_entry(entry) while l and len(entries) <= cnt: entries.insert(0, l) l = querymodel.get_previous_from_entry(l) get_entries("queue-source", False) get_entries("source", True) get_entries("source", False) return entries def get_track_info(self, entry): artist = entry.get_string(RB.RhythmDBPropType.ARTIST) # .replace('&', '&') album = entry.get_string(RB.RhythmDBPropType.ALBUM) # .replace('&', '&') title = entry.get_string(RB.RhythmDBPropType.TITLE) # .replace('&', '&') duration = entry.get_ulong(RB.RhythmDBPropType.DURATION) track = FullscreenTrack(artist=artist, album=album, title=title, duration=duration, entry=entry) return track def notify_metadata(self, player, uri, prop, *args, **kwargs): """Subscribe to metadata changes from database""" self.set_cover_art(player.get_playing_entry()) def notify_cover_art_change(self, *args): self.set_cover_art(self.shell.props.shell_player.get_playing_entry()) def set_cover_art(self, entry): if entry: self.window.set_artwork(self.get_cover(entry)) 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 map( lambda x: x in path.splitext(f)[0].lower(), ["cover", "album", "albumart", "folder", "front"], ): return GdkPixbuf.Pixbuf.new_from_file_at_size(file_name, ALBUM_ART_W, 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 path.exists(art_location): return GdkPixbuf.Pixbuf.new_from_file_at_size(art_location, ALBUM_ART_W, ALBUM_ART_H) def reload_playlist(self, player, entry): entry = player.get_playing_entry() if not entry: # When there is no entry set for reload playlist, then what's happening? # Is everything fine and totally inactive? return # Set cover art self.set_cover_art(entry) self.entries = self.get_entries(player, entry, 100) self.tracks = [] for e in self.entries: self.tracks.append(self.get_track_info(e)) current_track_index = self.entries.index(entry) self.window.set_tracks(self.tracks, current_track=current_track_index) self.set_active_track_properties(player, entry, current_track_index) def set_active_track_properties(self, player, entry, current_track_index): try: elapsed = player.get_playing_time() except: elapsed = (True, 0.0) if player.get_playing(): self.window.track_widgets[current_track_index].start_progress_bar(elapsed) self.window.current_info = "Now playing..." # TODO else: self.window.track_widgets[current_track_index].set_elapsed(elapsed) self.window.current_info = FullscreenWindow.FullscreenWindow.INFO_STATUS_IDLE self.window.show_info() def on_playing_song_changed(self, player, entry): if not self.entries: return self.reload_playlist(player, entry) entry = player.get_playing_entry() if not entry: # When there is no entry set for reload playlist, then what's happening? # Is everything fine and totally inactive? return try: current_track_index = self.tracks.index(self.get_track_info(entry)) except ValueError: return self.reload_playlist(player, entry) self.window.change_playing_track(current_track_index) self.set_active_track_properties(player, entry, current_track_index)
class FullscreenView(GObject.Object, Peas.Activatable): __gtype_name = 'FullscreenPlugin' object = GObject.property(type=GObject.Object) # @ReservedAssignment # Scales the prefetched album art for later use ALBUM_ART_W = 800 ALBUM_ART_H = 800 def __init__(self): super(FullscreenView, self).__init__() def do_activate(self): shell = self.object data = {} self.shell = shell self.entries = None self.action_group = ActionGroup(self.shell, 'FullscreenPluginActions') action = self.action_group.add_action(func=self.show_fullscreen, action_name='ToggleFullscreen', label='Full Screen', action_type='app', accel="F12") self._appshell = ApplicationShell(self.shell) self._appshell.insert_action_group(self.action_group) self._appshell.add_app_menuitems(ui_str, 'FullscreenPluginActions', 'view') w = self.shell.props.window 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.ALBUM_ART_H = monitor.height self.ALBUM_ART_W = monitor.height else: self.ALBUM_ART_H = monitor.width self.ALBUM_ART_W = monitor.width def do_deactivate(self): shell = self.object self._appshell.cleanup() 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 playpause(self): # Argument 'True' is unused # (see http://developer.gnome.org/rhythmbox/2.98/RBShellPlayer.html#rb-shell-player-playpause) self.player.playpause(True) def play_entry(self, index): if len(self.tracks) > index: self.player.play_entry(self.tracks[index].entry, self.shell.get_property("library-source")) def reload_play_pause(self, player, playing): if not self.window.track_widgets: return if playing: try: elapsed = player.get_playing_time() except: elapsed = (True, 0.0) self.window.track_widgets[self.window.current_track].paused = False self.window.track_widgets[ self.window.current_track].start_progress_bar(elapsed) self.window.current_info = "Now playing..." self.window.track_infos[ 0] = FullscreenWindow.FullscreenWindow.INFO_STATUS_PAUSE else: self.window.track_widgets[self.window.current_track].paused = True self.window.current_info = FullscreenWindow.FullscreenWindow.INFO_STATUS_IDLE self.window.track_infos[ 0] = FullscreenWindow.FullscreenWindow.INFO_STATUS_PLAY def get_entries(self, player, entry, cnt): """Gets the next and previous entries to be played from both active source and queue Next entries: Everything from source and queue Previous entries: Everything just from the source Uses each source's query-model. player = player to use entry = entry to start from (as a kind of offset) cnt = number of entries to return """ if not entry: return [] entries = [entry] def get_entries(property_name, backwards): queue = player.get_property(property_name) if queue: querymodel = queue.get_property("query-model") if not backwards: l = querymodel.get_next_from_entry(entry) while l and len(entries) <= cnt: entries.append(l) l = querymodel.get_next_from_entry(l) else: l = querymodel.get_previous_from_entry(entry) while l and len(entries) <= cnt: entries.insert(0, l) l = querymodel.get_previous_from_entry(l) get_entries("queue-source", False) get_entries("source", True) get_entries("source", False) return entries def get_track_info(self, entry): artist = entry.get_string( RB.RhythmDBPropType.ARTIST) # .replace('&', '&') album = entry.get_string( RB.RhythmDBPropType.ALBUM) # .replace('&', '&') title = entry.get_string( RB.RhythmDBPropType.TITLE) # .replace('&', '&') duration = entry.get_ulong(RB.RhythmDBPropType.DURATION) track = FullscreenTrack(artist=artist, album=album, title=title, duration=duration, entry=entry) return track def notify_metadata(self, player, uri, prop, *args, **kwargs): """Subscribe to metadata changes from database""" self.set_cover_art(player.get_playing_entry()) def notify_cover_art_change(self, *args): self.set_cover_art(self.shell.props.shell_player.get_playing_entry()) def set_cover_art(self, entry): if entry: self.window.set_artwork(self.get_cover(entry)) 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 reload_playlist(self, player, entry): entry = player.get_playing_entry() if not entry: # When there is no entry set for reload playlist, then what's happening? # Is everything fine and totally inactive? return # Set cover art self.set_cover_art(entry) self.entries = self.get_entries(player, entry, 100) self.tracks = [] for e in self.entries: self.tracks.append(self.get_track_info(e)) current_track_index = self.entries.index(entry) self.window.set_tracks(self.tracks, current_track=current_track_index) self.set_active_track_properties(player, entry, current_track_index) def set_active_track_properties(self, player, entry, current_track_index): try: elapsed = player.get_playing_time() except: elapsed = (True, 0.0) if player.get_playing(): self.window.track_widgets[current_track_index].start_progress_bar( elapsed) self.window.current_info = "Now playing..." # TODO else: self.window.track_widgets[current_track_index].set_elapsed(elapsed) self.window.current_info = FullscreenWindow.FullscreenWindow.INFO_STATUS_IDLE self.window.show_info() def on_playing_song_changed(self, player, entry): if not self.entries: return self.reload_playlist(player, entry) entry = player.get_playing_entry() if not entry: # When there is no entry set for reload playlist, then what's happening? # Is everything fine and totally inactive? return try: current_track_index = self.tracks.index(self.get_track_info(entry)) except ValueError: return self.reload_playlist(player, entry) self.window.change_playing_track(current_track_index) self.set_active_track_properties(player, entry, current_track_index) def _pycharm_optimize(self): # dummy procedure required for pycharm to prevent removal of # preferences during optimization x = Preferences()