class MoviesTab(Tab): """ Tab can be used as part of the TabGroup Tab is a very simple container that contains all the widgets and logic of the tab page. """ def __init__(self, video_library, move_to_new_screen_callback, name="movies", tab_title=_("Movies")): Tab.__init__(self, name, tab_title, move_to_new_screen_callback) self.video_library = video_library self.theme = self.config.theme self.list_indicator = None self.movie_info = None self.menu = None self.movie_plot = None self.movie_title = None if self.video_library.get_number_of_movies() == 0: self._create_empty_library_notice() else: # Start the loading animation while the menu is loading self.throbber = LoadingAnimation(0.1, 0.1) self.throbber.show() self.add(self.throbber) self.menu = self._create_menu() self.add(self.menu) self.menu.connect("moved", self._update_movie_info) self.menu.connect("selected", self._handle_select) self.menu.connect("activated", self._on_activated) self.menu.connect("filled", self._on_menu_filled) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) def can_activate(self): """ Allow if we have some movies indexed. """ if self.video_library.get_number_of_movies() == 0: return False else: return True def _create_empty_library_notice(self): """ Create an information box that is displayed if there are no indexed movies. """ message = _( "There are no indexed movies in Entertainer media library. To " "add movies, click on 'content' button on toolbar and open " "'videos' tab. Now click on 'add' button and select some folders " "which contains movie files.") Tab.show_empty_tab_notice(self, _("No movies available!"), message) def _create_menu(self): """ Create a view that is displayed when there is indexed movies in the video library. """ #Create movie menu menu = ImageMenu(0.06, 0.18, 0.12, 0.25) menu.items_per_col = 2 menu.visible_rows = 2 menu.visible_cols = 7 movies = self.video_library.get_movies() movies_list = [[movie.cover_art_url, movie] for movie in movies] menu.async_add_videos(movies_list) # Create list indicator self.list_indicator = ListIndicator(0.75, 0.76, 0.2, 0.045, ListIndicator.HORIZONTAL) self.list_indicator.set_maximum(len(movies)) self.show() self.add(self.list_indicator) # Create information labels self.movie_title = Label(0.042, "title", 0.2, 0.75, "", font_weight="bold") self.movie_title.set_ellipsize(pango.ELLIPSIZE_END) self.movie_title.set_line_wrap(False) self.movie_title.width = 0.5 self.add(self.movie_title) self.movie_info = Label(0.034, "subtitle", 0.2, 0.8, "") self.movie_info.set_ellipsize(pango.ELLIPSIZE_END) self.movie_info.set_line_wrap(False) self.movie_info.width = 0.5 self.add(self.movie_info) self.movie_plot = Label(0.025, "subtitle", 0.2, 0.85, "") self.movie_plot.width = 0.7 self.add(self.movie_plot) return menu def _update_movie_info(self, event=None): '''Update the movie information labels.''' if self.active: movie = self.menu.selected_userdata genres = movie.genres if len(genres) > 1: genre = genres[0] + "/" + genres[1] else: genre = genres[0] self.movie_title.set_text(_("%(title)s (%(year)s)") % \ {'title': movie.title, 'year': movie.year}) self.movie_info.set_text(_("%(min)d min, (%(genre)s)") % \ {'min': movie.runtime, 'genre': genre}) self.movie_plot.set_text(movie.short_plot) self.list_indicator.show() self.list_indicator.set_current(self.menu.selected_index + 1) else: self.movie_title.set_text("") self.movie_info.set_text("") self.movie_plot.set_text("") self.list_indicator.hide() def _handle_up(self): '''Handle the up user event.''' if self.menu.on_top: return True # Move control back to tab bar else: self.menu.up() return False def _handle_down(self): '''Handle the down user event.''' self.menu.down() return False def _handle_left(self): '''Handle the left user event.''' self.menu.left() return False def _handle_right(self): '''Handle the right user event.''' self.menu.right() return False def _handle_select(self, event=None): '''Handle the select user event.''' movie = self.menu.selected_userdata kwargs = { 'movie' : movie } self.callback("movie", kwargs) return False def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.menu.active = True self.active = True self._update_movie_info() return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.menu.active = False self._update_movie_info() return False def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class AlbumsTab(Tab): '''Tab to show album listings''' def __init__(self, albums, move_to_new_screen_callback, name="albums", tab_title=_("Albums")): Tab.__init__(self, name, tab_title, move_to_new_screen_callback) # Start the loading animation while the menu is loading self.throbber = LoadingAnimation(0.6, 0.1) self.throbber.show() self.add(self.throbber) if len(albums) < 4: x_percent = 0.2928 visible_rows = 1 visible_cols = 3 elif len(albums) < 13: x_percent = 0.1464 visible_rows = 2 visible_cols = 6 else: x_percent = 0.1098 visible_rows = 3 visible_cols = 8 # Create albums menu self.menu = ImageMenu(0.07, 0.16, x_percent, self.y_for_x(x_percent)) self.menu.visible_rows = visible_rows self.menu.visible_cols = visible_cols self.menu.items_per_col = self.menu.visible_rows self.add(self.menu) albums_list = [[album.album_art_url, album] for album in albums] self.menu.async_add_albums(albums_list) self.li = ListIndicator(0.77, 0.8, 0.18, 0.045, ListIndicator.HORIZONTAL) self.li.set_maximum(len(albums)) self.li.show() self.add(self.li) # Create album information (displays current menuitem information) self.album_title = Label(0.045, "title", 0.22, 0.79, "") self.album_title.set_ellipsize(pango.ELLIPSIZE_END) self.album_title.set_line_wrap(False) self.album_title.width = 0.366 self.add(self.album_title) self.album_artist = Label(0.037, "subtitle", 0.22, 0.86, "") self.album_artist.set_ellipsize(pango.ELLIPSIZE_END) self.album_artist.set_line_wrap(False) self.album_artist.width = 0.366 self.add(self.album_artist) self.album_tracks = Label(0.037, "subtitle", 0.22, 0.91, "") self.add(self.album_tracks) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) self.menu.connect("moved", self._update_album_info) self.menu.connect("selected", self._handle_select) self.menu.connect("activated", self._on_activated) self.menu.connect("filled", self._on_menu_filled) def can_activate(self): '''Albums tab will always be created from an existing artist with at least one album.''' return True def _update_album_info(self, event=None): '''Update the album information labels.''' if self.active: album = self.menu.selected_userdata self.album_title.set_text(album.title) self.album_artist.set_text(album.artist) self.album_tracks.set_text(_("%(total)s tracks") % \ {'total': len(album.tracks)}) self.li.show() self.li.set_current(self.menu.selected_index + 1) else: self.album_title.set_text("") self.album_artist.set_text("") self.album_tracks.set_text("") self.li.hide() def _handle_up(self): '''Handle the up user event.''' if self.menu.on_top: return True # Move control back to tab bar else: self.menu.up() return False def _handle_down(self): '''Handle the down user event.''' self.menu.down() return False def _handle_left(self): '''Handle the left user event.''' self.menu.left() return False def _handle_right(self): '''Handle the right user event.''' self.menu.right() return False def _handle_select(self, event=None): '''Handle the select user event.''' album = self.menu.selected_userdata kwargs = { 'album' : album } self.callback("album", kwargs) return False def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.menu.active = True self.active = True self._update_album_info() return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.menu.active = False self._update_album_info() return False def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class VideoClipsTab(Tab): """ Tab can be used as part of the TabGroup Tab is a very simple container that contains all the widgets and logic of the tab page. """ def __init__(self, media_player, video_library, move_to_new_screen_callback, name="clips", tab_title=_("Video clips")): Tab.__init__(self, name, tab_title, move_to_new_screen_callback) self.media_player = media_player self.video_library = video_library self.theme = self.config.theme self.list_indicator = None self.clip_info = None self.menu = None self.clip_title = None if self.video_library.get_number_of_video_clips() == 0: self._create_empty_library_notice() else: # Start the loading animation while the menu is loading self.throbber = LoadingAnimation(0.7, 0.1) self.throbber.show() self.add(self.throbber) self.menu = self._create_menu() self.add(self.menu) self.menu.connect("moved", self._update_clip_info) self.menu.connect("selected", self._handle_select) self.menu.connect("activated", self._on_activated) self.menu.connect("filled", self._on_menu_filled) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) def can_activate(self): """ Allow if we have some movies indexed. """ if self.video_library.get_number_of_video_clips() == 0: return False else: return True def _create_empty_library_notice(self): """ Create an information box that is displayed if there are no indexed movies. """ message = _( "There are no indexed Video Clips in the Entertainer media " "library. Please add some folders containing video clips " "to the Library using the configuration tool.") Tab.show_empty_tab_notice(self, _("No video clips available!"), message) def _create_menu(self): """ Create a view that is displayed when there are indexed clips in the video library. """ menu = ImageMenu(0.04, 0.16, 0.23, self.y_for_x(0.23) * 0.7) menu.items_per_col = 2 menu.visible_rows = 2 menu.visible_cols = 4 clips = self.video_library.get_video_clips() clips_list = [[clip.thumbnail_url, clip] for clip in clips] menu.async_add_clips(clips_list) # Create list indicator self.list_indicator = ListIndicator(0.7, 0.8, 0.2, 0.045, ListIndicator.HORIZONTAL) self.list_indicator.set_maximum(len(clips)) self.list_indicator.show() self.add(self.list_indicator) # Create information labels self.clip_title = Label(0.042, "title", 0.15, 0.77, "", font_weight="bold") self.clip_title.set_ellipsize(pango.ELLIPSIZE_END) self.clip_title.set_line_wrap(False) self.clip_title.width = 0.5 self.add(self.clip_title) self.clip_info = Label(0.034, "subtitle", 0.15, 0.85, "") self.clip_info.set_ellipsize(pango.ELLIPSIZE_END) self.clip_info.set_line_wrap(False) self.clip_info.width = 0.5 self.add(self.clip_info) return menu def _update_clip_info(self, event=None): '''Update the VideoClip information labels.''' if self.active: clip = self.menu.selected_userdata (folder, filename) = os.path.split(clip.filename) self.clip_title.set_text(filename) self.clip_info.set_text(folder) self.list_indicator.show() self.list_indicator.set_current(self.menu.selected_index + 1) else: self.clip_title.set_text("") self.clip_info.set_text("") self.list_indicator.hide() def _handle_up(self): '''Handle the up user event.''' if self.menu.on_top: return True # Move control back to tab bar else: self.menu.up() return False def _handle_down(self): '''Handle the down user event.''' self.menu.down() return False def _handle_left(self): '''Handle the left user event.''' self.menu.left() return False def _handle_right(self): '''Handle the right user event.''' self.menu.right() return False def _handle_select(self, event=None): '''Handle the select user event.''' clip = self.menu.selected_userdata self.media_player.set_media(clip) self.media_player.play() self.callback("video_osd") return False def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.menu.active = True self.active = True self._update_clip_info() return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.menu.active = False self._update_clip_info() return False def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class AlbumsTab(Tab): '''Tab to show album listings''' def __init__(self, albums, move_to_new_screen_callback, name="albums", tab_title=_("Albums")): Tab.__init__(self, name, tab_title, move_to_new_screen_callback) # Start the loading animation while the menu is loading self.throbber = LoadingAnimation(0.6, 0.1) self.throbber.show() self.add(self.throbber) if len(albums) < 4: x_percent = 0.2928 visible_rows = 1 visible_cols = 3 elif len(albums) < 13: x_percent = 0.1464 visible_rows = 2 visible_cols = 6 else: x_percent = 0.1098 visible_rows = 3 visible_cols = 8 # Create albums menu self.menu = ImageMenu(0.07, 0.16, x_percent, self.y_for_x(x_percent)) self.menu.visible_rows = visible_rows self.menu.visible_cols = visible_cols self.menu.items_per_col = self.menu.visible_rows self.add(self.menu) albums_list = [[album.album_art_url, album] for album in albums] self.menu.async_add_albums(albums_list) self.li = ListIndicator(0.77, 0.8, 0.18, 0.045, ListIndicator.HORIZONTAL) self.li.set_maximum(len(albums)) self.li.show() self.add(self.li) # Create album information (displays current menuitem information) self.album_title = Label(0.045, "title", 0.22, 0.79, "") self.album_title.set_ellipsize(pango.ELLIPSIZE_END) self.album_title.set_line_wrap(False) self.album_title.width = 0.366 self.add(self.album_title) self.album_artist = Label(0.037, "subtitle", 0.22, 0.86, "") self.album_artist.set_ellipsize(pango.ELLIPSIZE_END) self.album_artist.set_line_wrap(False) self.album_artist.width = 0.366 self.add(self.album_artist) self.album_tracks = Label(0.037, "subtitle", 0.22, 0.91, "") self.add(self.album_tracks) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) self.menu.connect("moved", self._update_album_info) self.menu.connect("selected", self._handle_select) self.menu.connect("activated", self._on_activated) self.menu.connect("filled", self._on_menu_filled) def can_activate(self): '''Albums tab will always be created from an existing artist with at least one album.''' return True def _update_album_info(self, event=None): '''Update the album information labels.''' if self.active: album = self.menu.selected_userdata self.album_title.set_text(album.title) self.album_artist.set_text(album.artist) self.album_tracks.set_text(_("%(total)s tracks") % \ {'total': len(album.tracks)}) self.li.show() self.li.set_current(self.menu.selected_index + 1) else: self.album_title.set_text("") self.album_artist.set_text("") self.album_tracks.set_text("") self.li.hide() def _handle_up(self): '''Handle the up user event.''' if self.menu.on_top: return True # Move control back to tab bar else: self.menu.up() return False def _handle_down(self): '''Handle the down user event.''' self.menu.down() return False def _handle_left(self): '''Handle the left user event.''' self.menu.left() return False def _handle_right(self): '''Handle the right user event.''' self.menu.right() return False def _handle_select(self, event=None): '''Handle the select user event.''' album = self.menu.selected_userdata kwargs = {'album': album} self.callback("album", kwargs) return False def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.menu.active = True self.active = True self._update_album_info() return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.menu.active = False self._update_album_info() return False def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class ArtistsTab(Tab): '''Tab for the music screen to show artist listings''' def __init__(self, music_library, artists, move_to_new_screen_callback, name="artists", tab_title=_("Artists")): Tab.__init__(self, name, tab_title, move_to_new_screen_callback) self.library = music_library # Start the loading animation while the menu is loading self.throbber = LoadingAnimation(0.1, 0.1) self.throbber.show() self.add(self.throbber) self.menu = TextMenu(0.057, 0.208, 0.293, 0.078) self.menu.items_per_row = 3 self.menu.visible_rows = 7 self.menu.visible_cols = 3 self.menu.active = False self.menu.cursor = None self.add(self.menu) artists_list = [[artist, None, artist] for artist in artists] self.menu.async_add_artists(artists_list) # Create artist label self.artist_title = Label(0.0416, "title", 0.22, 0.794, "") self.artist_title.set_ellipsize(pango.ELLIPSIZE_END) self.artist_title.set_line_wrap(False) self.artist_title.width = 0.366 self.add(self.artist_title) self.artist_albums = Label(0.0365, "subtitle", 0.22, 0.86, "") self.add(self.artist_albums) self.artist_tracks = Label(0.0365, "subtitle", 0.22, 0.911, "") self.add(self.artist_tracks) # Create artist menu list indicator self.li = ListIndicator(0.77, 0.8, 0.18, 0.045, ListIndicator.VERTICAL) self.li.set_maximum(len(artists)) self.add(self.li) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) self.menu.connect("moved", self._update_artist_info) self.menu.connect("selected", self._handle_select) self.menu.connect("activated", self._on_activated) self.menu.connect("filled", self._on_menu_filled) def can_activate(self): '''Albums tab will always be created from an existing artist with at least one album.''' return True def _update_artist_info(self, event=None): '''Update the artist information labels''' if self.active: artist = self.menu.selected_userdata self.artist_title.set_text(artist) self.artist_albums.set_text(_("%(albums)d albums") % {'albums': self.library.number_of_albums_by_artist(artist)}) self.artist_tracks.set_text(_("%(tracks)d tracks") % {'tracks': self.library.number_of_tracks_by_artist(artist)}) self.li.show() self.li.set_current(self.menu.selected_index + 1) else: self.artist_title.set_text("") self.artist_albums.set_text("") self.artist_tracks.set_text("") self.li.hide() def _handle_up(self): '''Handle the up user event.''' if self.menu.on_top: return True # Move control back to tab bar else: self.menu.up() return False def _handle_down(self): '''Handle the down user event.''' self.menu.down() return False def _handle_left(self): '''Handle the left user event.''' self.menu.left() return False def _handle_right(self): '''Handle the right user event.''' self.menu.right() return False def _handle_select(self, event=None): '''Handle the select user event.''' artist = self.menu.selected_userdata kwargs = { 'artist' : artist } self.callback("artist", kwargs) return False def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.menu.active = True self.active = True self._update_artist_info() return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.menu.active = False self._update_artist_info() def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class Photographs(Screen): '''Screen displays a grid of selectable photograph thumbnails.''' def __init__(self, move_to_new_screen_callback, title, images): Screen.__init__(self, 'Photographs', move_to_new_screen_callback) self.images = images # Screen Title (Displayed at the bottom left corner) screen_title = Label(0.13, "screentitle", 0, 0.87, title) self.add(screen_title) # Image Title (over album list) self.image_title = Label(0.04167, "title", 0.0586, 0.7943, " ") self.image_title.set_ellipsize(pango.ELLIPSIZE_END) self.add(self.image_title) self.image_desc = Label(0.04167, "subtitle", 0.0586, 0.9115, " ") self.image_desc.set_line_wrap(True) self.image_desc.set_ellipsize(pango.ELLIPSIZE_END) self.add(self.image_desc) # Display throbber animation while loading photographs self.throbber = LoadingAnimation(0.9, 0.9) self.throbber.show() self.add(self.throbber) # List indicator self.li = None self._create_list_indicator() # Create photomenu self.menu = ImageMenu(0.03, 0.08, 0.12, self.y_for_x(0.12)) self.menu.items_per_col = 3 self.menu.visible_rows = 3 self.menu.visible_cols = 8 self.menu.active = True self.add(self.menu) photos = self.images photos_list = [[Texture(photo.get_thumbnail_url()), photo] \ for photo in photos] self.menu.async_add(photos_list) self.menu.connect("selected", self._handle_select) self.menu.connect('moved', self._update_image_info) self.menu.connect("filled", self._on_menu_filled) def _update_image_info(self, event=None): """Update image information box.""" image = self.images[self.menu.selected_index] name = image.get_title() desc = image.get_description() self.image_title.set_text(name) self.image_title.set_size(0.366, 0.04167) self.image_desc.set_text(desc) self.image_desc.set_size(0.366, 0.0911) self.li.set_current(self.menu.selected_index + 1) def _create_list_indicator(self): '''Create list indicator for albums list.''' self.li = ListIndicator(0.77, 0.8, 0.18, 0.045, ListIndicator.HORIZONTAL) self.li.set_maximum(len(self.images)) self.add(self.li) def _handle_up(self): '''Handle UserEvent.NAVIGATE_UP.''' self.menu.up() def _handle_down(self): '''Handle UserEvent.NAVIGATE_DOWN.''' self.menu.down() def _handle_left(self): '''Handle UserEvent.NAVIGATE_LEFT.''' self.menu.left() def _handle_right(self): '''Handle UserEvent.NAVIGATE_RIGHT.''' self.menu.right() def _handle_select(self, event=None): '''Handle UserEvent.NAVIGATE_SELECT.''' index = self.menu.selected_index kwargs = {'current_photo_index': index, 'images': self.images} self.callback("photo", kwargs) def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class TracksTab(Tab): '''Tab for the artist screen to show track listings''' def __init__(self, tracks, move_to_new_screen_callback, name="tracks", tab_title=_("Tracks")): Tab.__init__(self, name, tab_title, move_to_new_screen_callback) # Start the loading animation while the menu is loading self.throbber = LoadingAnimation(0.1, 0.1) self.throbber.show() self.add(self.throbber) self.menu = TextMenu(0.0586, 0.2083, 0.2928, 0.0781) self.menu.items_per_row = 3 self.menu.visible_rows = 7 self.menu.visible_cols = 3 self.menu.active = False self.menu.cursor = None self.add(self.menu) tracks_list = [[track.title, None, track] for track in tracks] self.menu.async_add_artists(tracks_list) self.track_title = Label(0.045, "title", 0.22, 0.79, "") self.track_title.set_ellipsize(pango.ELLIPSIZE_END) self.track_title.set_line_wrap(False) self.track_title.width = 0.366 self.add(self.track_title) self.track_number = Label(0.037, "subtitle", 0.22, 0.86, "") self.track_number.set_ellipsize(pango.ELLIPSIZE_END) self.track_number.set_line_wrap(False) self.track_number.width = 0.366 self.add(self.track_number) self.track_length = Label(0.037, "subtitle", 0.22, 0.91, "") self.add(self.track_length) self.li = ListIndicator(0.77, 0.8, 0.18, 0.045, ListIndicator.VERTICAL) self.li.set_maximum(len(tracks)) self.li.show() self.add(self.li) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) self.menu.connect("moved", self._update_track_info) self.menu.connect("selected", self._handle_select) self.menu.connect("activated", self._on_activated) self.menu.connect("filled", self._on_menu_filled) def can_activate(self): '''Tracks tab will always be created from an existing artist with at least one track.''' return True def _update_track_info(self, event=None): '''Update the track information labels''' if self.active: track = self.menu.selected_userdata self.track_title.set_text(track.title) self.track_length.set_text(track.length_string) self.track_number.set_text(_("Track %(track)d from %(album)s") % \ {'track': track.number, 'album': track.album.title}) self.li.show() self.li.set_current(self.menu.selected_index + 1) else: self.track_title.set_text("") self.track_length.set_text("") self.track_number.set_text("") self.li.hide() def _handle_up(self): '''Handle the up user event.''' if self.menu.on_top: return True # Move control back to tab bar else: self.menu.up() return False def _handle_down(self): '''Handle the down user event.''' self.menu.down() return False def _handle_left(self): '''Handle the left user event.''' self.menu.left() return False def _handle_right(self): '''Handle the right user event.''' self.menu.right() return False def _handle_select(self, event=None): '''Handle the select user event.''' track = self.menu.selected_userdata kwargs = { 'track' : track } self.callback("audio_play", kwargs) return False def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.menu.active = True self.active = True self._update_track_info() return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.menu.active = False self._update_track_info() return False def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class LyricsTab(Tab): '''Tab for the audio play screen to show lyrics''' def __init__(self, music_library, track, name="lyrics", tab_title=_("Lyrics")): Tab.__init__(self, name, tab_title) self.track = track self.lyrics_area = None self.library = music_library self.lyrics_text = "" if self.track.has_lyrics(): self.lyrics_text = self.track.lyrics lyrics = Label(0.037, "subtitle", 0, 0, self.lyrics_text) lyrics.set_line_wrap_mode(pango.WRAP_WORD) lyrics.width = 0.366 self.lyrics_area = ScrollArea(0.5, 0.23, 0.4, 0.57, lyrics) self.lyrics_area.connect("activated", self._on_activated) self.add(self.lyrics_area) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) else: # Display throbber animation while searching for lyrics self.throbber = LoadingAnimation(0.7, 0.5, 0.1) self.throbber.show() self.add(self.throbber) self.track.fetch_lyrics(self._lyrics_search_callback) def _lyrics_search_callback(self, lyrics_text): '''This function is called when lyrics search is over.''' self.throbber.hide() # Save the results to help determine if the tab can activate. self.lyrics_text = lyrics_text if lyrics_text == "": no_lyrics = Label(0.037, "title", 0.7, 0.5, _("No lyrics found for this track")) no_lyrics.set_anchor_point_from_gravity(clutter.GRAVITY_CENTER) self.add(no_lyrics) else: lyrics = Label(0.037, "subtitle", 0, 0, lyrics_text) lyrics.set_line_wrap_mode(pango.WRAP_WORD) lyrics.width = 0.366 self.lyrics_area = ScrollArea(0.5, 0.23, 0.4, 0.57, lyrics) self.lyrics_area.connect("activated", self._on_activated) self.add(self.lyrics_area) self.library.save_lyrics(self.track, lyrics_text) def can_activate(self): ''' Lyrics tab can scroll the lyrics listing only if lyrics were found. ''' if self.lyrics_text == "": return False else: return True def _handle_up(self): '''Handle the up user event.''' if self.lyrics_area.on_top: return True # Move control back to tab bar else: return self.lyrics_area.scroll_up() def _handle_down(self): '''Handle the down user event.''' return self.lyrics_area.scroll_down() def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.lyrics_area.active = True self.active = True return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.lyrics_area.active = False return False
class Photographs(Screen): '''Screen displays a grid of selectable photograph thumbnails.''' def __init__(self, move_to_new_screen_callback, title, images): Screen.__init__(self, 'Photographs', move_to_new_screen_callback) self.images = images # Screen Title (Displayed at the bottom left corner) screen_title = Label(0.13, "screentitle", 0, 0.87, title) self.add(screen_title) # Image Title (over album list) self.image_title = Label(0.04167, "title", 0.0586, 0.7943, " ") self.image_title.set_ellipsize(pango.ELLIPSIZE_END) self.add(self.image_title) self.image_desc = Label(0.04167, "subtitle", 0.0586, 0.9115, " ") self.image_desc.set_line_wrap(True) self.image_desc.set_ellipsize(pango.ELLIPSIZE_END) self.add(self.image_desc) # Display throbber animation while loading photographs self.throbber = LoadingAnimation(0.9, 0.9) self.throbber.show() self.add(self.throbber) # List indicator self.li = None self._create_list_indicator() # Create photomenu self.menu = ImageMenu(0.03, 0.08, 0.12, self.y_for_x(0.12)) self.menu.items_per_col = 3 self.menu.visible_rows = 3 self.menu.visible_cols = 8 self.menu.active = True self.add(self.menu) photos = self.images photos_list = [[Texture(photo.get_thumbnail_url()), photo] \ for photo in photos] self.menu.async_add(photos_list) self.menu.connect("selected", self._handle_select) self.menu.connect('moved', self._update_image_info) self.menu.connect("filled", self._on_menu_filled) def _update_image_info(self, event=None): """Update image information box.""" image = self.images[self.menu.selected_index] name = image.get_title() desc = image.get_description() self.image_title.set_text(name) self.image_title.set_size(0.366, 0.04167) self.image_desc.set_text(desc) self.image_desc.set_size(0.366, 0.0911) self.li.set_current(self.menu.selected_index + 1) def _create_list_indicator(self): '''Create list indicator for albums list.''' self.li = ListIndicator(0.77, 0.8, 0.18, 0.045, ListIndicator.HORIZONTAL) self.li.set_maximum(len(self.images)) self.add(self.li) def _handle_up(self): '''Handle UserEvent.NAVIGATE_UP.''' self.menu.up() def _handle_down(self): '''Handle UserEvent.NAVIGATE_DOWN.''' self.menu.down() def _handle_left(self): '''Handle UserEvent.NAVIGATE_LEFT.''' self.menu.left() def _handle_right(self): '''Handle UserEvent.NAVIGATE_RIGHT.''' self.menu.right() def _handle_select(self, event=None): '''Handle UserEvent.NAVIGATE_SELECT.''' index = self.menu.selected_index kwargs = {'current_photo_index' : index, 'images' : self.images} self.callback("photo", kwargs) def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class MoviesTab(Tab): """ Tab can be used as part of the TabGroup Tab is a very simple container that contains all the widgets and logic of the tab page. """ def __init__(self, video_library, move_to_new_screen_callback, name="movies", tab_title=_("Movies")): Tab.__init__(self, name, tab_title, move_to_new_screen_callback) self.video_library = video_library self.theme = self.config.theme self.list_indicator = None self.movie_info = None self.menu = None self.movie_plot = None self.movie_title = None if self.video_library.get_number_of_movies() == 0: self._create_empty_library_notice() else: # Start the loading animation while the menu is loading self.throbber = LoadingAnimation(0.1, 0.1) self.throbber.show() self.add(self.throbber) self.menu = self._create_menu() self.add(self.menu) self.menu.connect("moved", self._update_movie_info) self.menu.connect("selected", self._handle_select) self.menu.connect("activated", self._on_activated) self.menu.connect("filled", self._on_menu_filled) self.connect('activated', self._on_activated) self.connect('deactivated', self._on_deactivated) def can_activate(self): """ Allow if we have some movies indexed. """ if self.video_library.get_number_of_movies() == 0: return False else: return True def _create_empty_library_notice(self): """ Create an information box that is displayed if there are no indexed movies. """ message = _( "There are no indexed movies in Entertainer media library. To " "add movies, click on 'content' button on toolbar and open " "'videos' tab. Now click on 'add' button and select some folders " "which contains movie files.") Tab.show_empty_tab_notice(self, _("No movies available!"), message) def _create_menu(self): """ Create a view that is displayed when there is indexed movies in the video library. """ #Create movie menu menu = ImageMenu(0.06, 0.18, 0.12, 0.25) menu.items_per_col = 2 menu.visible_rows = 2 menu.visible_cols = 7 movies = self.video_library.get_movies() movies_list = [[movie.cover_art_url, movie] for movie in movies] menu.async_add_videos(movies_list) # Create list indicator self.list_indicator = ListIndicator(0.75, 0.76, 0.2, 0.045, ListIndicator.HORIZONTAL) self.list_indicator.set_maximum(len(movies)) self.show() self.add(self.list_indicator) # Create information labels self.movie_title = Label(0.042, "title", 0.2, 0.75, "", font_weight="bold") self.movie_title.set_ellipsize(pango.ELLIPSIZE_END) self.movie_title.set_line_wrap(False) self.movie_title.width = 0.5 self.add(self.movie_title) self.movie_info = Label(0.034, "subtitle", 0.2, 0.8, "") self.movie_info.set_ellipsize(pango.ELLIPSIZE_END) self.movie_info.set_line_wrap(False) self.movie_info.width = 0.5 self.add(self.movie_info) self.movie_plot = Label(0.025, "subtitle", 0.2, 0.85, "") self.movie_plot.width = 0.7 self.add(self.movie_plot) return menu def _update_movie_info(self, event=None): '''Update the movie information labels.''' if self.active: movie = self.menu.selected_userdata genres = movie.genres if len(genres) > 1: genre = genres[0] + "/" + genres[1] else: genre = genres[0] self.movie_title.set_text(_("%(title)s (%(year)s)") % \ {'title': movie.title, 'year': movie.year}) self.movie_info.set_text(_("%(min)d min, (%(genre)s)") % \ {'min': movie.runtime, 'genre': genre}) self.movie_plot.set_text(movie.short_plot) self.list_indicator.show() self.list_indicator.set_current(self.menu.selected_index + 1) else: self.movie_title.set_text("") self.movie_info.set_text("") self.movie_plot.set_text("") self.list_indicator.hide() def _handle_up(self): '''Handle the up user event.''' if self.menu.on_top: return True # Move control back to tab bar else: self.menu.up() return False def _handle_down(self): '''Handle the down user event.''' self.menu.down() return False def _handle_left(self): '''Handle the left user event.''' self.menu.left() return False def _handle_right(self): '''Handle the right user event.''' self.menu.right() return False def _handle_select(self, event=None): '''Handle the select user event.''' movie = self.menu.selected_userdata kwargs = {'movie': movie} self.callback("movie", kwargs) return False def _on_activated(self, event=None): '''Tab activated.''' if self.tab_group is not None: self.tab_group.active = False self.menu.active = True self.active = True self._update_movie_info() return False def _on_deactivated(self, event=None): '''Tab deactivated.''' self.active = False self.menu.active = False self._update_movie_info() return False def _on_menu_filled(self, event=None): '''Handles filled event.''' self.throbber.hide()
class Disc(Screen): '''Screen allows user to play tracks from the current Audio CD.''' def __init__(self, music_library, media_player): Screen.__init__(self, 'Disc') self.theme = self.config.theme self.music_library = music_library self.media_player = media_player # When album info is loaded we create Playlist object self.playlist = None self.art = None self.art2 = None self.in_behaviour = None self.out_behaviour = None self.li = None self.track_menu = None # Screen Title (Displayed at the bottom left corner) screen_title = Label(0.13, "screentitle", 0, 0.87, _("Audio Disc"), "screen_title") self.add(screen_title) # Display throbber animation while loading CD metadata self.throbber = LoadingAnimation(0.5, 0.5, 0.1) self.throbber.show() self.add(self.throbber) # Create and initialize screen items self.has_disc = True gobject.timeout_add(500, self._get_disc_information) def _get_disc_information(self): """ Fetch album information from the Internet and create widgets based on received data. """ try: disc = self.music_library.get_compact_disc_information() title = disc.title artist = disc.artist tracks = disc.tracks self.playlist = Playlist(tracks) self._create_album_info(title, artist, tracks, disc.length) self.track_menu = self._create_track_menu(tracks) self.add(self.track_menu) self._create_album_cover_texture(artist, title) self.li = ListIndicator(0.75, 0.8, 0.2, 0.045, ListIndicator.VERTICAL) self.li.set_maximum(len(tracks)) self.add(self.li) art_file = os.path.join(self.config.ALBUM_ART_DIR, artist + " - " + title + ".jpg") if artist != "Unknown artist" and not os.path.exists(art_file): art_search = AlbumArtDownloader(title, artist, self.config.ALBUM_ART_DIR, self._update_albumart) art_search.start() except cdrom.error: # No disc in drive self.has_disc = False no_disc = Label(0.05, "title", 0.5, 0.5, _("No audio disc in drive")) no_disc.set_anchor_point_from_gravity(clutter.GRAVITY_CENTER) self.add(no_disc) # Remove loading animation self.throbber.hide() self.remove(self.throbber) del self.throbber # This function should be called only once (gobject timeout) return False def _update_albumart(self, artist, title): """ Search album art for current audio disc. This function is called only if album art doesn't exist already. If album art is found then we replace current disc icon with the new album art. @param artist: Artist name @param title: Album title """ art_file = os.path.join(self.config.ALBUM_ART_DIR, artist + " - " + title + ".jpg") if os.path.exists(art_file): clutter.threads_enter() self.art2 = Texture(art_file, 0.1, 0.165) clutter.threads_leave() self.art2.set_size(self.get_abs_x(0.3148), self.get_abs_y(0.5599)) self.art2.set_opacity(0) self.add(self.art2) timeline_in = clutter.Timeline(35, 26) alpha_in = clutter.Alpha(timeline_in, clutter.smoothstep_inc_func) self.in_behaviour = clutter.BehaviourOpacity(0, 255, alpha_in) self.in_behaviour.apply(self.art2) timeline_out = clutter.Timeline(35, 26) alpha_out = clutter.Alpha(timeline_out, clutter.smoothstep_inc_func) self.out_behaviour = clutter.BehaviourOpacity(255, 0, alpha_out) self.out_behaviour.apply(self.art) timeline_out.start() timeline_in.start() def _create_album_cover_texture(self, artist, title): """ Create a texture that is displayed next to track list. This texture displays album cover art. @param artist: Artist @param title: Title of the album """ coverfile = os.path.join(self.config.ALBUM_ART_DIR, artist + " - " + title + ".jpg") if(os.path.exists(coverfile)): pixbuf = gtk.gdk.pixbuf_new_from_file(coverfile) else: pixbuf = gtk.gdk.pixbuf_new_from_file(self.theme.getImage("disc")) self.art = EyeCandyTexture(0.1, 0.13, 0.3148, 0.5599, pixbuf) self.art.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0) self.add(self.art) def _create_album_info(self, title, artist_name, tracks, length): """ Create album info labels. @param title: Album title @param artist_name: Artist @param tracks: List of CompactDisc objects """ album = Label(0.04167, "text", 0.50146, 0.13, artist_name + " - " + title, font_weight="bold") album.set_size(0.4393, 0.06510) album.set_ellipsize(pango.ELLIPSIZE_END) self.add(album) minutes = str(length / 60) num_of_tracks = Label(0.02604, "subtitle", 0.50146, 0.18, _("%(total)s tracks, %(time)s minutes") % \ {'total': len(tracks), 'time': minutes}, font_weight="bold") self.add(num_of_tracks) def _create_track_menu(self, tracks): """ Create a track menu. This menu contains list of all tracks on album. @param tracks: List of CompactDisc objects """ menu = TextMenu(0.4978, 0.2344, 0.4393, 0.0781) menu.visible_rows = 7 tracks_list = [[track.title, track.length_string, index] \ for index, track in enumerate(tracks)] menu.async_add(tracks_list) menu.active = True menu.connect('selected', self._handle_select) menu.connect('moved', self._display_selected_track) return menu def _handle_up(self): '''Handle UserEvent.NAVIGATE_UP.''' self.track_menu.up() def _handle_down(self): '''Handle UserEvent.NAVIGATE_DOWN.''' self.track_menu.down() def _handle_select(self, event=None): '''Handle UserEvent.NAVIGATE_SELECT.''' track_index = self.track_menu.selected_userdata self.playlist.set_current(track_index) self.media_player.set_playlist(self.playlist) self.media_player.play() def handle_user_event(self, event): '''Handle user events unless there is no disc.''' if self.has_disc: Screen.handle_user_event(self, event) def _display_selected_track(self, event=None): '''Update of the list indicator.''' self.li.set_current(self.track_menu.selected_index + 1)