예제 #1
0
class AudioPlay(Screen):
    '''Screen that displays information of currently playing audio track.'''

    def __init__(self, media_player, music_library, track):
        Screen.__init__(self, 'AudioPlay', has_tabs=True)

        self.theme = self.config.theme
        album = track.album

        # Create album art (this is displayed on all tab pages
        if(album.has_album_art()):
            pixbuf = gtk.gdk.pixbuf_new_from_file(album.album_art_url)
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(
                self.theme.getImage("default_album_art"))
        self.art = EyeCandyTexture(0.1, 0.22, 0.3148, 0.5599, pixbuf)
        self.art.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0)
        self.add(self.art)

        media_player.set_media(track)
        media_player.play()

        # Tabs
        tab1 = PlayingTab(media_player, track)
        tab2 = LyricsTab(music_library, track)
        self.add_tab(tab1)
        self.add_tab(tab2)

    def update(self, track, event=None):
        '''Called when currently playing changes tracks. The provided track
        is used to update all the necessary labels'''
        self.tab_group.tab("playing").update(track)
예제 #2
0
class AudioPlay(Screen):
    '''Screen that displays information of currently playing audio track.'''
    def __init__(self, media_player, music_library, track):
        Screen.__init__(self, 'AudioPlay', has_tabs=True)

        self.theme = self.config.theme
        album = track.album

        # Create album art (this is displayed on all tab pages
        if (album.has_album_art()):
            pixbuf = gtk.gdk.pixbuf_new_from_file(album.album_art_url)
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(
                self.theme.getImage("default_album_art"))
        self.art = EyeCandyTexture(0.1, 0.22, 0.3148, 0.5599, pixbuf)
        self.art.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0)
        self.add(self.art)

        media_player.set_media(track)
        media_player.play()

        # Tabs
        tab1 = PlayingTab(media_player, track)
        tab2 = LyricsTab(music_library, track)
        self.add_tab(tab1)
        self.add_tab(tab2)

    def update(self, track, event=None):
        '''Called when currently playing changes tracks. The provided track
        is used to update all the necessary labels'''
        self.tab_group.tab("playing").update(track)
예제 #3
0
    def _create_album_preview(self, album):
        """
        Create a clutter.Group that contains album preview actors.
        """
        group = clutter.Group()
        group.set_position(self.get_abs_x(0.07), self.get_abs_y(0.1953))

        # Preview images
        images = album.get_preview_images(3)
        self.preview_textures = []

        max_w = 0.4026
        max_h = 0.5599
        abs_max_w = self.get_abs_x(max_w)
        abs_max_h = self.get_abs_y(max_h)

        for image in images:
            pix_buffer = gtk.gdk.pixbuf_new_from_file(image.get_thumbnail_url())
            ratio = float(pix_buffer.get_width())
            ratio /= float(pix_buffer.get_height())

            # Resize and center preview texture
            if ratio > 1:
                texture = EyeCandyTexture(0.0, 0.0, max_w, max_h / ratio,
                    pix_buffer)
                new_y = int((abs_max_h - abs_max_h / ratio) / 2.0)
                texture.set_position(0, new_y)
            else:
                texture = EyeCandyTexture(0.0, 0.0, max_w * ratio,
                    max_h, pix_buffer)
                new_x = int((abs_max_w - abs_max_w * ratio) / 2.0)
                texture.set_position(new_x, 0)

            texture.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0)
            texture.set_opacity(0)

            self.preview_textures.append(texture)
            group.add(texture)
        self.preview_textures[0].set_opacity(255)

        title = Label(0.03646, "title", 0.4649, 0, album.get_title(),
            font_weight="bold")
        title.width = 0.4758
        title.set_ellipsize(pango.ELLIPSIZE_END)
        group.add(title)

        desc = Label(0.026, "subtitle", 0.4649, 0.0521, album.get_description())
        desc.width = 0.4758
        group.add(desc)

        return group
예제 #4
0
    def _create_thumbnail_texture(self):
        """Create a thumbnail texture. This is called as menu is scrolled."""
        if self.thumb:
            self.thumb.hide()

        # Thumbnail. Use cover art if thumbnail doesn't exist
        thumbnail = self.menu.selected_userdata.thumbnail_url
        if (thumbnail is not None):
            pixbuf = gtk.gdk.pixbuf_new_from_file(thumbnail)
            thumb_width = 0.2928
            thumb_height = 0.2799
            thumb_x = 0.05
            thumb_y = 0.2
        else:
            thumb_width = 0.1098
            thumb_height = 0.2799
            thumb_x = 0.20
            thumb_y = 0.15
            if (self.tv_series.has_cover_art()):
                pixbuf = gtk.gdk.pixbuf_new_from_file(
                    self.tv_series.cover_art_url)
            else:
                pixbuf = gtk.gdk.pixbuf_new_from_file(
                    self.theme.getImage("default_movie_art"))

        self.thumb = EyeCandyTexture(thumb_x, thumb_y, thumb_width,
                                     thumb_height, pixbuf)
        self.add(self.thumb)
예제 #5
0
    def setUp(self):
        '''Set up the test.'''
        EntertainerTest.setUp(self)

        filename = os.path.join(THIS_DIR, 'data/ImageThumbnailer/test.jpg')
        pix_buffer = gtk.gdk.pixbuf_new_from_file(filename)
        self.eyecandy = EyeCandyTexture(0.5, 0.9, 0.40, 0.4, pix_buffer)
예제 #6
0
    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)
예제 #7
0
 def _create_series_cover_texture(self):
     """
     Create a texture that is displayed next to track list. This texture
     displays album cover art.
     """
     if (self.tv_series.has_cover_art()):
         pixbuf = gtk.gdk.pixbuf_new_from_file(self.tv_series.cover_art_url)
     else:
         pixbuf = gtk.gdk.pixbuf_new_from_file(
             self.theme.getImage("default_movie_art"))
     self.art = EyeCandyTexture(0.16, 0.15, 0.2196, 0.5859, pixbuf)
     self.add(self.art)
예제 #8
0
 def _create_album_cover_texture(self):
     """
     Create a texture that is displayed next to track list. This texture
     displays album cover art.
     """
     if(self.album.has_album_art()):
         pixbuf = gtk.gdk.pixbuf_new_from_file(self.album.album_art_url)
     else:
         pixbuf = gtk.gdk.pixbuf_new_from_file(
             self.theme.getImage("default_album_art"))
     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)
예제 #9
0
    def __init__(self, media_player, music_library, track):
        Screen.__init__(self, 'AudioPlay', has_tabs=True)

        self.theme = self.config.theme
        album = track.album

        # Create album art (this is displayed on all tab pages
        if (album.has_album_art()):
            pixbuf = gtk.gdk.pixbuf_new_from_file(album.album_art_url)
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(
                self.theme.getImage("default_album_art"))
        self.art = EyeCandyTexture(0.1, 0.22, 0.3148, 0.5599, pixbuf)
        self.art.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0)
        self.add(self.art)

        media_player.set_media(track)
        media_player.play()

        # Tabs
        tab1 = PlayingTab(media_player, track)
        tab2 = LyricsTab(music_library, track)
        self.add_tab(tab1)
        self.add_tab(tab2)
예제 #10
0
    def __init__(self, media_player, music_library, track):
        Screen.__init__(self, 'AudioPlay', has_tabs=True)

        self.theme = self.config.theme
        album = track.album

        # Create album art (this is displayed on all tab pages
        if(album.has_album_art()):
            pixbuf = gtk.gdk.pixbuf_new_from_file(album.album_art_url)
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(
                self.theme.getImage("default_album_art"))
        self.art = EyeCandyTexture(0.1, 0.22, 0.3148, 0.5599, pixbuf)
        self.art.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0)
        self.add(self.art)

        media_player.set_media(track)
        media_player.play()

        # Tabs
        tab1 = PlayingTab(media_player, track)
        tab2 = LyricsTab(music_library, track)
        self.add_tab(tab1)
        self.add_tab(tab2)
예제 #11
0
class Album(Screen):
    '''Screen that allows user to browse and play tracks of the music album.'''

    def __init__(self, media_player, music_library, move_to_new_screen_callback,
        album):
        Screen.__init__(self, 'Album', move_to_new_screen_callback)

        self.media_player = media_player
        self.theme = self.config.theme
        self.library = music_library
        self.album = album
        self.art = None
        self.track_menu = None

        # Create and initialize screen items
        self.track_menu = self._create_track_menu()
        self.add(self.track_menu)
        self._create_album_cover_texture()
        self._create_album_info()

        self.screen_title = Label(0.13, "screentitle", 0, 0.87, "")
        self.screen_title.set_ellipsize(pango.ELLIPSIZE_END)
        self.screen_title.width = 0.8
        self.add(self.screen_title)

        #List indicator
        self.li = ListIndicator(0.74, 0.85, 0.2, 0.045, ListIndicator.VERTICAL)
        self.li.set_maximum(len(self.album.tracks))
        self.add(self.li)

        self.track_menu.active = True
        self.track_menu.connect('selected', self._on_menu_selected)
        self.track_menu.connect('moved', self._display_selected_track)

    def _create_album_cover_texture(self):
        """
        Create a texture that is displayed next to track list. This texture
        displays album cover art.
        """
        if(self.album.has_album_art()):
            pixbuf = gtk.gdk.pixbuf_new_from_file(self.album.album_art_url)
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(
                self.theme.getImage("default_album_art"))
        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):
        """
        Create album info labels.
        """
        if self.album.year != 0:
            album_text = self.album.title + ", " + str(self.album.year)
        else:
            album_text = self.album.title
        album = Label(0.0416, "text", 0.5, 0.13, album_text, font_weight="bold")
        album.set_ellipsize(pango.ELLIPSIZE_END)
        album.set_line_wrap(False)
        album.width = 0.45
        self.add(album)

        length = str(self.album.length / 60)
        num_of_tracks_text = _("%(total)s tracks, %(time)s minutes") % \
            {'total': len(self.album.tracks), 'time': length}
        num_of_tracks = Label(0.028, "subtitle", 0.5, 0.18,
            num_of_tracks_text, font_weight="bold")
        self.add(num_of_tracks)

    def _create_track_menu(self):
        """
        Create track menu. This menu contains list of all tracks on album.
        """
        menu = TextMenu(0.4978, 0.2344, 0.4393, 0.0781)

        tracks = self.album.tracks
        tracks_list = [[track.title, track.length_string, track] \
            for track in tracks]
        menu.async_add(tracks_list)

        return menu

    def is_interested_in_play_action(self):
        """
        Override function from Screen class. See Screen class for
        better documentation.
        """
        return True

    def execute_play_action(self):
        """
        Override function from Screen class. See Screen class for
        better documentation.
        """
        track = self.track_menu.selected_userdata
        self.media_player.set_media(track)
        self.media_player.play()

    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 = self.track_menu.selected_userdata
        kwargs = { 'track' : track }
        self.callback("audio_play", kwargs)

    def _on_menu_selected(self, actor=None):
        '''Handle a *select command* if an item was selected.'''
        self._handle_select()

    def _display_selected_track(self, actor=None):
        '''Update of the list indicator and the screen's title'''
        self.li.set_current(self.track_menu.selected_index + 1)
        track = self.track_menu.selected_userdata
        self.screen_title.set_text(track.artist)
        self.screen_title.show()
예제 #12
0
    def create_movie_information(self):
        '''Create clutter parts related to movie information'''

        # Movie art texture
        if self.movie.has_cover_art():
            pixbuf = gtk.gdk.pixbuf_new_from_file(self.movie.cover_art_url)
        else:
            pixbuf = gtk.gdk.pixbuf_new_from_file(
                self.theme.getImage("default_movie_art"))
        movie_art = EyeCandyTexture(0.33, 0.1, 0.1, 0.25, pixbuf)
        self.add(movie_art)

        # Movie title
        title = Label(0.04, "title", 0.47, 0.1, self.movie.title,
            font_weight="bold")
        title.set_ellipsize(pango.ELLIPSIZE_END)
        title.set_size(0.5124, 0.05208)
        self.add(title)

        # Movie release year
        year_text = _("Released in %(year)s") % {'year': self.movie.year}
        year = Label(0.032, "subtitle", 0.47, 0.3, year_text)
        year.set_ellipsize(pango.ELLIPSIZE_END)
        year.set_size(0.5124, 0.05208)
        self.add(year)

        # Show only 2 genres (or one if there is only one)
        genres_list = self.movie.genres
        if len(genres_list) == 0:
            genres_text = _("Unknown")
        else:
            genres_text = "/".join(genres_list[:2])

        # Runtime and genres
        info_text = _("%(runtime)s min, %(genre)s") % \
            {'runtime': self.movie.runtime, 'genre': genres_text}
        info = Label(0.032, "subtitle", 0.47, 0.24, info_text)
        info.set_ellipsize(pango.ELLIPSIZE_END)
        info.set_size(0.5124, 0.05208)
        self.add(info)

        # Stars (rating)
        star = Texture(self.theme.getImage("star"))
        star.hide()
        self.add(star)
        star2 = Texture(self.theme.getImage("star2"))
        star2.hide()
        self.add(star2)

        for i in range(self.movie.rating):
            tex = clutter.Clone(star)
            tex.set_position(
                self.get_abs_x(0.47) + (self.get_abs_x(0.0366) * i),
                self.get_abs_y(0.17))
            tex.set_size(self.get_abs_x(0.024), self.get_abs_y(0.04))
            self.add(tex)

        dark_star = 5 - self.movie.rating
        for i in range(dark_star):
            tex = clutter.Clone(star2)
            tex.set_position(self.get_abs_x(0.47) + (self.get_abs_x(0.0366) * \
                (i + self.movie.rating)), self.get_abs_y(0.17))
            tex.set_size(self.get_abs_x(0.024), self.get_abs_y(0.04))
            self.add(tex)

        # Plot
        plot = Label(0.029, "subtitle", 0, 0, self.movie.plot)
        plot.set_justify(True)
        plot.set_line_wrap_mode(pango.WRAP_WORD)
        plot.set_line_wrap(True)
        plot.width = 0.5124
        self.scroll_area = ScrollArea(0.33, 0.38, 0.5124, 0.3516, plot)
        self.add(self.scroll_area)

        # Actors
        self.add(Label(0.032, "title", 0.33, 0.8, _("Starring")))

        actors_list = self.movie.actors
        if len(actors_list) == 0:
            actors_text = _("Unknown")
        else:
            actors_text = ", ".join(actors_list[:5])
        actors = Label(0.032, "subtitle", 0.46, 0.8, actors_text)
        actors.set_ellipsize(pango.ELLIPSIZE_END)
        actors.set_size(0.5124, 0.05208)
        self.add(actors)

        # Directors
        self.add(Label(0.032, "title", 0.33, 0.86, _("Directed by")))

        directors_list = self.movie.directors
        if len(directors_list) == 0:
            directors_text = _("Unknown")
        else:
            directors_text = ", ".join(directors_list[:2])
        directors = Label(0.032, "subtitle", 0.46, 0.86, directors_text)
        directors.set_ellipsize(pango.ELLIPSIZE_END)
        directors.set_size(0.5124, 0.05208)
        self.add(directors)

        # Writers
        self.add(Label(0.032, "title", 0.33, 0.92, _("Written by")))

        writers_list = self.movie.writers
        if len(directors_list) == 0:
            writers_text = _("Unknown")
        else:
            writers_text = ", ".join(writers_list[:2])
        writers = Label(0.032, "subtitle", 0.46, 0.92, writers_text)
        writers.set_ellipsize(pango.ELLIPSIZE_END)
        writers.set_size(0.5124, 0.05208)
        self.add(writers)
예제 #13
0
    def _create_album_preview(self, album):
        """
        Create a clutter.Group that contains album preview actors.
        """
        group = clutter.Group()
        group.set_position(self.get_abs_x(0.07), self.get_abs_y(0.1953))

        # Preview images
        images = album.get_preview_images(3)
        self.preview_textures = []

        max_w = 0.4026
        max_h = 0.5599
        abs_max_w = self.get_abs_x(max_w)
        abs_max_h = self.get_abs_y(max_h)

        for image in images:
            pix_buffer = gtk.gdk.pixbuf_new_from_file(
                image.get_thumbnail_url())
            ratio = float(pix_buffer.get_width())
            ratio /= float(pix_buffer.get_height())

            # Resize and center preview texture
            if ratio > 1:
                texture = EyeCandyTexture(0.0, 0.0, max_w, max_h / ratio,
                                          pix_buffer)
                new_y = int((abs_max_h - abs_max_h / ratio) / 2.0)
                texture.set_position(0, new_y)
            else:
                texture = EyeCandyTexture(0.0, 0.0, max_w * ratio, max_h,
                                          pix_buffer)
                new_x = int((abs_max_w - abs_max_w * ratio) / 2.0)
                texture.set_position(new_x, 0)

            texture.set_rotation(clutter.Y_AXIS, 25, 0, 0, 0)
            texture.set_opacity(0)

            self.preview_textures.append(texture)
            group.add(texture)
        self.preview_textures[0].set_opacity(255)

        title = Label(0.03646,
                      "title",
                      0.4649,
                      0,
                      album.get_title(),
                      font_weight="bold")
        title.width = 0.4758
        title.set_ellipsize(pango.ELLIPSIZE_END)
        group.add(title)

        desc = Label(0.026, "subtitle", 0.4649, 0.0521,
                     album.get_description())
        desc.width = 0.4758
        group.add(desc)

        return group
예제 #14
0
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)