Ejemplo n.º 1
0
    def __init__(self, util, bgr=None, bounding_box=None, font_size=None):
        """ Initializer

        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.util = util
        self.factory = Factory(util)
        self.config = util.config
        self.cdutil = CdUtil(util)

        self.bb = bounding_box
        self.horizontal_layout = True
        self.rows = None
        self.cols = None
        items = self.get_menu_items()
        cell_bb = items[2]

        m = self.create_home_menu_button
        label_area = (cell_bb.h / 100) * (100 - ICON_AREA)
        font_size = int((label_area / 100) * FONT_HEIGHT)
        Menu.__init__(self,
                      util,
                      bgr,
                      bounding_box,
                      None,
                      None,
                      create_item_method=m,
                      font_size=font_size)
        self.set_modes(*items)
Ejemplo n.º 2
0
class CdDrivesScreen(Screen):
    """ File Browser Screen """
    def __init__(self, util, listeners, voice_assistant):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.bounding_box = util.screen_rect
        layout = BorderLayout(self.bounding_box)
        layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                       PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "cd_drives_screen_title", True, layout.TOP)

        self.cd_drive_id = self.config[CD_PLAYBACK][CD_DRIVE_ID]
        self.cd_track = self.config[CD_PLAYBACK][CD_TRACK]
        self.cd_track_time = self.config[CD_PLAYBACK][CD_TRACK_TIME]
        self.screen_title.set_text(self.config[LABELS][KEY_CD_DRIVES])

        self.cd_drives_menu = CdDrivesMenu(util, layout.CENTER,
                                           listeners[KEY_CD_TRACKS])
        drives_info = self.cdutil.get_cd_drives_info()
        l = self.cd_drives_menu.get_layout(drives_info)
        bb = l.get_next_constraints()
        drives = self.cdutil.get_cd_drives(self.font_size, (bb.w, bb.h))
        self.cd_drives_menu.set_items(drives, 0, listeners[KEY_CD_TRACKS])

        for b in self.cd_drives_menu.buttons.values():
            b.parent_screen = self

        Container.add_component(self, self.cd_drives_menu)

        factory = Factory(util)
        self.menu_buttons = factory.create_home_player_buttons(
            self, self.layout.BOTTOM, listeners)
        self.home_button = self.menu_buttons[0]
        self.player_button = self.menu_buttons[1]

    def add_screen_observers(self, update_observer, redraw_observer):
        """ Add screen observers
        
        :param update_observer: observer for updating the screen
        :param redraw_observer: observer to redraw the whole screen
        """
        Screen.add_screen_observers(self, update_observer, redraw_observer)

        self.cd_drives_menu.add_menu_observers(update_observer,
                                               redraw_observer)
        for b in self.menu_buttons:
            self.add_button_observers(b, update_observer, redraw_observer)
Ejemplo n.º 3
0
    def __init__(self, util, listeners, voice_assistant, state):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.bounding_box = util.screen_rect
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "cd_tracks_screen_title", True, self.layout.TOP)
        color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT]
        self.current_cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
        self.current_cd_drive_id = self.config[CD_PLAYBACK][CD_DRIVE_ID]

        self.filelist = self.get_filelist()

        self.file_menu = FileMenu(self.filelist,
                                  util,
                                  None, (0, 0, 0),
                                  self.layout.CENTER,
                                  align=ALIGN_LEFT)

        self.go_cd_player = listeners[KEY_PLAYER]
        self.file_menu.add_play_file_listener(self.play_track)
        Container.add_component(self, self.file_menu)

        listeners[GO_LEFT_PAGE] = self.file_menu.page_down
        listeners[GO_RIGHT_PAGE] = self.file_menu.page_up
        listeners[KEY_EJECT] = self.eject_cd
        listeners[KEY_REFRESH] = self.refresh_tracks
        connected_cd_drives = self.cdutil.get_cd_drives_number()
        self.navigator = CdTracksNavigator(util, connected_cd_drives,
                                           self.layout.BOTTOM, listeners,
                                           color_dark_light)
        Container.add_component(self, self.navigator)

        self.file_menu.add_left_number_listener(
            self.navigator.left_button.change_label)
        self.file_menu.add_right_number_listener(
            self.navigator.right_button.change_label)
        self.file_menu.update_buttons()
        self.page_turned = False
        self.animated_title = True
Ejemplo n.º 4
0
    def __init__(self, util, bgr=None, bounding_box=None, font_size=None):
        """ Initializer

        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.util = util
        self.factory = Factory(util)
        self.config = util.config
        m = self.factory.create_home_menu_button
        Menu.__init__(self,
                      util,
                      bgr,
                      bounding_box,
                      None,
                      None,
                      create_item_method=m,
                      font_size=font_size)
        self.cdutil = CdUtil(util)
        self.set_modes()
Ejemplo n.º 5
0
    def __init__(self, util, listeners, voice_assistant):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.bounding_box = util.screen_rect
        layout = BorderLayout(self.bounding_box)
        layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                       PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "cd_drives_screen_title", True, layout.TOP)

        self.cd_drive_id = self.config[CD_PLAYBACK][CD_DRIVE_ID]
        self.cd_track = self.config[CD_PLAYBACK][CD_TRACK]
        self.cd_track_time = self.config[CD_PLAYBACK][CD_TRACK_TIME]
        self.screen_title.set_text(self.config[LABELS][KEY_CD_DRIVES])

        self.cd_drives_menu = CdDrivesMenu(util, layout.CENTER,
                                           listeners[KEY_CD_TRACKS])
        drives_info = self.cdutil.get_cd_drives_info()
        l = self.cd_drives_menu.get_layout(drives_info)
        bb = l.get_next_constraints()
        drives = self.cdutil.get_cd_drives(self.font_size, (bb.w, bb.h))
        self.cd_drives_menu.set_items(drives, 0, listeners[KEY_CD_TRACKS])

        for b in self.cd_drives_menu.buttons.values():
            b.parent_screen = self

        self.add_menu(self.cd_drives_menu)

        self.navigator = CdDrivesNavigator(util, self.layout.BOTTOM, listeners)
        self.navigator.get_button_by_name(KEY_HOME).set_selected(True)
        self.add_navigator(self.navigator)
        self.link_borders()
Ejemplo n.º 6
0
    def __init__(self, util, listeners, voice_assistant):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.bounding_box = self.config[SCREEN_RECT]
        layout = BorderLayout(self.bounding_box)
        layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                       PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "file_browser_screen_title", True, layout.TOP)
        color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT]

        self.cd_drive_id = self.config[CD_PLAYBACK][CD_DRIVE_ID]
        self.cd_track = self.config[CD_PLAYBACK][CD_TRACK]
        self.cd_track_time = self.config[CD_PLAYBACK][CD_TRACK_TIME]
        self.screen_title.set_text(self.config[LABELS][KEY_CD_DRIVES])

        self.cd_drives_menu = CdDrivesMenu(None, util, (0, 0, 0),
                                           layout.CENTER,
                                           listeners[KEY_CD_TRACKS])
        drives_info = self.cdutil.get_cd_drives_info()
        l = self.cd_drives_menu.get_layout(drives_info)
        bb = l.get_next_constraints()
        drives = self.cdutil.get_cd_drives(self.font_size, (bb.w, bb.h))
        self.cd_drives_menu.set_items(drives, 0, listeners[KEY_CD_TRACKS])
        Container.add_component(self, self.cd_drives_menu)

        factory = Factory(util)
        self.menu_buttons = factory.create_home_player_buttons(
            self, self.layout.BOTTOM, listeners)
        self.home_button = self.menu_buttons[0]
        self.player_button = self.menu_buttons[1]
Ejemplo n.º 7
0
class HomeMenu(Menu):
    """ Home Menu class. Extends base Menu class """
    def __init__(self, util, bgr=None, bounding_box=None, font_size=None):
        """ Initializer

        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.util = util
        self.factory = Factory(util)
        self.config = util.config
        self.cdutil = CdUtil(util)

        self.bb = bounding_box
        self.horizontal_layout = True
        self.rows = None
        self.cols = None
        items = self.get_menu_items()
        cell_bb = items[2]

        m = self.create_home_menu_button
        label_area = (cell_bb.h / 100) * (100 - ICON_AREA)
        font_size = int((label_area / 100) * FONT_HEIGHT)
        Menu.__init__(self,
                      util,
                      bgr,
                      bounding_box,
                      None,
                      None,
                      create_item_method=m,
                      font_size=font_size)
        self.set_modes(*items)

    def get_menu_items(self):
        """ Prepare menu items

        :return: array containing menu items, disabled items, cell bounding box snf icon box
        """
        items = []
        disabled_items = []
        player = self.config[AUDIO][PLAYER_NAME]

        if self.config[HOME_MENU][RADIO]:
            items.append(RADIO)
            if not self.util.is_radio_enabled(
            ) or not self.util.connected_to_internet:
                disabled_items.append(RADIO)

        if self.config[HOME_MENU][AUDIO_FILES]:
            items.append(AUDIO_FILES)

        if self.config[HOME_MENU][AUDIOBOOKS]:
            items.append(AUDIOBOOKS)
            if not self.util.is_audiobooks_enabled(
            ) or not self.util.connected_to_internet:
                disabled_items.append(AUDIOBOOKS)

        if self.config[HOME_MENU][STREAM]:
            items.append(STREAM)
            if not self.util.connected_to_internet:
                disabled_items.append(STREAM)

        if self.config[HOME_MENU][CD_PLAYER]:
            cd_drives_info = self.cdutil.get_cd_drives_info()
            if len(cd_drives_info) == 0 or player == MPV_NAME:
                disabled_items.append(CD_PLAYER)
            items.append(CD_PLAYER)

        if self.config[HOME_MENU][PODCASTS]:
            podcasts_util = self.util.get_podcasts_util()
            podcasts = podcasts_util.get_podcasts_links()
            downloads = podcasts_util.are_there_any_downloads()
            connected = self.util.connected_to_internet
            valid_players = [VLC_NAME, MPV_NAME]
            if (connected and len(podcasts) == 0 and not downloads) or (
                    not connected
                    and not downloads) or player not in valid_players:
                disabled_items.append(PODCASTS)
            items.append(PODCASTS)

        if self.config[HOME_MENU][AIRPLAY]:
            items.append(AIRPLAY)
            if not self.util.config[LINUX_PLATFORM]:
                disabled_items.append(AIRPLAY)

        if self.config[HOME_MENU][SPOTIFY_CONNECT]:
            items.append(SPOTIFY_CONNECT)
            if not self.util.config[LINUX_PLATFORM]:
                disabled_items.append(SPOTIFY_CONNECT)

        if self.config[HOME_MENU][COLLECTION]:
            items.append(COLLECTION)
            db_util = self.util.get_db_util()
            if db_util.conn == None:
                disabled_items.append(COLLECTION)

        l = self.get_layout(items)
        bounding_box = l.get_next_constraints()
        box = self.factory.get_icon_bounding_box(bounding_box, ICON_LOCATION,
                                                 ICON_AREA, ICON_SIZE,
                                                 BUTTON_PADDING)

        return (items, disabled_items, bounding_box, box)

    def set_current_modes(self):
        """ Set current player modes """

        items = self.get_menu_items()
        self.set_modes(*items)

    def set_modes(self, items, disabled_items, bounding_box, box):
        """ Set menu items

        :param items: menu items
        :param disabled_items: disabled menu items
        :param bounding_box: cell bounding box
        :param box: image boundng box
        """
        self.modes = self.util.load_menu(items,
                                         NAME,
                                         disabled_items,
                                         V_ALIGN_TOP,
                                         bb=box)
        va_commands = self.util.get_voice_commands()

        if self.config[USAGE][USE_VOICE_ASSISTANT]:
            self.add_voice_command(RADIO, ["VA_RADIO", "VA_GO_RADIO"],
                                   va_commands)
            self.add_voice_command(AUDIO_FILES, ["VA_FILES", "VA_GO_FILES"],
                                   va_commands)
            self.add_voice_command(
                AUDIOBOOKS, ["VA_AUDIOBOOKS", "VA_BOOKS", "VA_GO_BOOKS"],
                va_commands)
            self.add_voice_command(STREAM, ["VA_STREAM", "VA_GO_STREAM"],
                                   va_commands)
            self.add_voice_command(CD_PLAYER, ["VA_CD_PLAYER"], va_commands)
            self.add_voice_command(PODCASTS, ["VA_PODCAST", "VA_PODCASTS"],
                                   va_commands)

        if not items:
            return

        if not self.config[CURRENT][MODE]:
            for i in items:
                if i not in disabled_items:
                    mode = i
                    break
        else:
            mode = self.config[CURRENT][MODE]

        self.set_items(self.modes, 0, self.change_mode, False)
        self.current_mode = self.modes[mode.lower()]
        self.item_selected(self.current_mode)

    def create_home_menu_button(self, s, constr, action, scale, font_size):
        """ Create Home Menu button

        :param s: button state
        :param constr: scaling constraints
        :param action: button event listener
        :param scale: True - scale images, False - don't scale images
        :param font_size: label font height in pixels

        :return: home menu button
        """
        s.padding = BUTTON_PADDING
        s.image_area_percent = ICON_AREA

        return self.factory.create_menu_button(s,
                                               constr,
                                               action,
                                               scale,
                                               font_size=font_size)

    def add_voice_command(self, name, commands, va_commands):
        """ Add voice command

        :param name: item name
        :param commands: item commands
        :param va_commands: voice commands
        """
        if not self.config[HOME_MENU][name]:
            return
        c = []
        for m in commands:
            c.append(va_commands[m].strip())
        self.modes[name].voice_commands = c

    def change_mode(self, state):
        """ Change mode event listener

        :param state: button state
        """
        if not self.visible:
            return
        state.previous_mode = self.current_mode.name
        self.current_mode = state
        self.config[CURRENT][MODE] = state.name
        self.notify_listeners(state)
Ejemplo n.º 8
0
class FilePlayerScreen(Screen):
    """ File Player Screen """
    def __init__(self,
                 listeners,
                 util,
                 get_current_playlist,
                 voice_assistant,
                 player_stop=None):
        """ Initializer
        
        :param listeners: screen listeners
        :param util: utility object
        :param get_current_playlist: current playlist getter
        :param voice_assistant:   voice assistant
        :param player_stop: stop player function
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.stop_player = player_stop
        self.get_current_playlist = get_current_playlist
        self.bounding_box = util.screen_rect
        self.layout = BorderLayout(self.bounding_box)
        k = self.bounding_box.w / self.bounding_box.h
        percent_menu_width = (100.0 - PERCENT_TOP_HEIGHT -
                              PERCENT_BOTTOM_HEIGHT) / k
        panel_width = (100.0 - percent_menu_width) / 2.0
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, panel_width,
                                            panel_width)
        self.voice_assistant = voice_assistant
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "file_player_screen_title", True, self.layout.TOP)
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, panel_width,
                                            panel_width)

        self.create_left_panel(self.layout, listeners)
        self.create_right_panel(self.layout, listeners)

        self.file_button = self.factory.create_file_button(
            self.layout.CENTER, listeners[AUDIO_FILES])

        Container.add_component(self, self.file_button)
        self.audio_files = self.get_audio_files()
        self.home_button.add_release_listener(listeners[KEY_HOME])
        self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN])
        self.left_button.add_release_listener(self.go_left)
        self.right_button.add_release_listener(self.go_right)

        self.volume = self.factory.create_volume_control(self.layout.BOTTOM)
        self.volume.add_slide_listener(listeners[KEY_SET_VOLUME])
        self.volume.add_slide_listener(listeners[KEY_SET_CONFIG_VOLUME])
        self.volume.add_slide_listener(listeners[KEY_SET_SAVER_VOLUME])
        self.volume.add_knob_listener(listeners[KEY_MUTE])
        self.volume_visible = False
        self.volume.set_visible(self.volume_visible)
        Container.add_component(self, self.volume)

        self.time_control = self.factory.create_time_control(
            self.layout.BOTTOM)
        self.time_control.add_seek_listener(listeners[KEY_SEEK])

        self.play_button.add_listener(PAUSE, self.time_control.pause)
        self.play_button.add_listener(KEY_PLAY, self.time_control.resume)
        self.left_button.add_release_listener(
            self.play_button.draw_default_state)
        self.right_button.add_release_listener(
            self.play_button.draw_default_state)

        if self.config[PLAYER_SETTINGS][PAUSE]:
            self.time_control.pause()

        Container.add_component(self, self.time_control)

        self.play_listeners = []
        self.add_play_listener(listeners[KEY_PLAY])

        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        self.file_button.state.cover_art_folder = self.util.file_util.get_cover_art_folder(
            self.current_folder)
        self.playlist_size = 0
        self.player_screen = True
        self.cd_album = None

    def get_audio_files(self):
        """ Return the list of audio files in current folder
        
        :return: list of audio files
        """
        files = []
        if self.config[CURRENT][MODE] == CD_PLAYER:
            af = getattr(self, "audio_files", None)
            if af == None:
                cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
                files = self.cdutil.get_cd_tracks_summary(cd_drive_name)
            else:
                return self.audio_files
        else:
            folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
            files = self.util.get_audio_files_in_folder(folder)

        return files

    def get_current_track_index(self, state=None):
        """ Return current track index.
        In case of files goes through the file list.
        In case of playlist takes track index from the state object.
        
        :param state: button state

        :return: current track index
        """
        if self.config[CURRENT][MODE] == AUDIOBOOKS:
            t = None
            try:
                t = state["file_name"]
            except:
                pass

            if t == None:
                try:
                    t = state["current_title"]
                except:
                    pass

            if t == None:
                try:
                    t = state
                except:
                    pass

            for i, f in enumerate(self.audio_files):
                try:
                    s = f["file_name"]
                except:
                    pass

                if getattr(f, "file_name", None):
                    s = getattr(f, "file_name", None)

                if s.endswith(t):
                    return i
            return 0

        mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
        if state and mode == FILE_PLAYLIST:
            try:
                n = state["Track"]
                if n: return int(n) - 1
            except:
                pass

        if self.config[CURRENT][MODE] == CD_PLAYER:
            cmp = int(self.config[CD_PLAYBACK][CD_TRACK]) - 1
        else:
            cmp = self.config[FILE_PLAYBACK][CURRENT_FILE]
            if state and isinstance(state, State):
                cmp = state.file_name

        for f in self.audio_files:
            if self.config[CURRENT][MODE] == CD_PLAYER:
                if f.index == cmp:
                    return f.index
            else:
                if f.file_name == cmp:
                    return f.index
        return 0

    def stop_recursive_playback(self):
        """ Stop recursive playback """

        self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
        self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] = None
        self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
        self.stop_timer()
        self.time_control.stop_thread()
        self.time_control.reset()
        if self.stop_player != None:
            self.stop_player()

    def go_left(self, state):
        """ Switch to the previous track
        
        :param state: not used state object
        """
        if getattr(self, "current_track_index", None) == None:
            return

        filelist_size = self.get_filelist_size()

        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
            self.stop_recursive_playback()
            return

        if self.current_track_index == 0:
            self.current_track_index = filelist_size - 1
        else:
            self.current_track_index -= 1
        self.change_track(self.current_track_index)

    def go_right(self, state):
        """ Switch to the next track
        
        :param state: not used state object
        """
        if getattr(self, "current_track_index", None) == None:
            return

        filelist_size = self.get_filelist_size()

        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE and self.current_track_index == filelist_size - 1:
            self.stop_timer()
            self.time_control.stop_thread()
            self.recursive_change_folder()
            self.current_track_index = 0
            self.change_track(self.current_track_index)
            self.file_button.clean_draw_update()
            return

        if self.current_track_index == filelist_size - 1:
            self.current_track_index = 0
        else:
            self.current_track_index += 1

        self.change_track(self.current_track_index)

    def get_filelist_size(self):
        """ Return the file list size
        
        :return: file list size
        """
        if self.audio_files:
            return len(self.audio_files)
        else:
            return 0

    def change_track(self, track_index):
        """ Change track
        
        :param track_index: index track
        """
        a = [AUDIOBOOKS, CD_PLAYER]
        m = self.config[CURRENT][MODE]
        if not (m in a):
            self.config[FILE_PLAYBACK][CURRENT_FILE] = self.get_filename(
                track_index)

        self.stop_timer()
        time.sleep(0.3)
        s = State()
        if m == FILE_PLAYBACK:
            s.playback_mode = self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE]

        s.playlist_track_number = track_index
        s.index = track_index
        s.source = ARROW_BUTTON
        s.file_name = self.get_filename(track_index)

        if self.cd_album != None:
            s.album = self.cd_album

        self.set_current(True, s)

    def stop_timer(self):
        """ Stop time control timer """

        self.time_control.stop_timer()

    def get_filename(self, index):
        """ Get filename by index
        
        :param index: file index
        
        :return: filename
        """
        for b in self.audio_files:
            if b.index == index:
                return b.file_name
        return ""

    def is_valid_mode(self):
        current_mode = self.config[CURRENT][MODE]
        modes = [AUDIO_FILES, AUDIOBOOKS, CD_PLAYER]
        if current_mode in modes:
            return True
        else:
            return False

    def update_arrow_button_labels(self, state=None):
        """ Update left/right arrow button labels
        
        :param state: state object representing current track
        """
        if (not self.is_valid_mode()) or (not self.screen_title.active): return

        self.set_current_track_index(state)
        left = self.current_track_index
        right = 0

        if self.audio_files and len(self.audio_files) > 1:
            right = len(self.audio_files) - self.current_track_index - 1

        self.left_button.change_label(str(left))
        self.right_button.change_label(str(right))

    def set_current_track_index(self, state):
        """ Set current track index
        
        :param state: state object representing current track
        """
        if not self.is_valid_mode(): return

        if self.config[CURRENT][MODE] == CD_PLAYER and getattr(
                state, "cd_track_id", None):
            self.config[CD_PLAYBACK][CD_TRACK] = state["cd_track_id"]

        self.current_track_index = 0

        if self.playlist_size == 1:
            return

        if not self.audio_files:
            self.audio_files = self.get_audio_files()
            if not self.audio_files: return

        i = self.get_current_track_index(state)
        self.current_track_index = i

    def create_left_panel(self, layout, listeners):
        """ Create left side buttons panel
        
        :param layout: panel layout 
        :param listeners: button listeners 
        """
        panel_layout = BorderLayout(layout.LEFT)
        panel_layout.set_percent_constraints(PERCENT_SIDE_BOTTOM_HEIGHT,
                                             PERCENT_SIDE_BOTTOM_HEIGHT, 0, 0)
        self.left_button = self.factory.create_left_button(
            panel_layout.CENTER, '', 40, 100)
        self.shutdown_button = self.factory.create_shutdown_button(
            panel_layout.TOP)
        self.home_button = self.factory.create_button(KEY_HOME,
                                                      KEY_HOME,
                                                      panel_layout.BOTTOM,
                                                      image_size_percent=36)
        panel = Container(self.util, layout.LEFT)
        panel.add_component(self.shutdown_button)
        panel.add_component(self.left_button)
        panel.add_component(self.home_button)
        Container.add_component(self, panel)

    def create_right_panel(self, layout, listeners):
        """ Create right side buttons panel
        
        :param layout: panel layout 
        :param listeners: button listeners 
        """
        panel_layout = BorderLayout(layout.RIGHT)
        panel_layout.set_percent_constraints(PERCENT_SIDE_BOTTOM_HEIGHT,
                                             PERCENT_SIDE_BOTTOM_HEIGHT, 0, 0)
        self.play_button = self.factory.create_play_pause_button(
            panel_layout.TOP, listeners[KEY_PLAY_PAUSE])
        self.right_button = self.factory.create_right_button(
            panel_layout.CENTER, '', 40, 100)
        self.time_volume_button = self.factory.create_time_volume_button(
            panel_layout.BOTTOM, self.toggle_time_volume)
        panel = Container(self.util, layout.RIGHT)
        panel.add_component(self.play_button)
        panel.add_component(self.right_button)
        panel.add_component(self.time_volume_button)
        Container.add_component(self, panel)

    def toggle_time_volume(self):
        """ Switch between time and volume controls """

        if self.volume_visible:
            self.volume.set_visible(False)
            self.time_control.set_visible(True)
            self.volume_visible = False
        else:
            volume_level = int(self.config[PLAYER_SETTINGS][VOLUME])
            self.volume.set_position(volume_level)
            self.volume.update_position()
            self.volume.set_visible(True)
            self.time_control.set_visible(False)
            self.volume_visible = True
        self.clean_draw_update()

    def eject_cd(self, state):
        """ Eject CD
        
        :param state: button state object
        """
        self.audio_files = []
        self.screen_title.set_text(" ")
        self.update_arrow_button_labels(state)
        self.time_control.reset()
        self.cd_album = None
        self.set_cd_album_art_image()

    def set_current(self, new_track=False, state=None):
        """ Set current file or playlist
        
        :param new_track: True - new audio file
        :param state: button state
        """
        self.cd_album = getattr(state, "album", None)

        if self.config[CURRENT][MODE] == AUDIO_FILES:
            if getattr(state, "url", None) is None:
                state.url = None
            state.full_screen_image = self.set_audio_file_image()
        elif self.config[CURRENT][MODE] == CD_PLAYER and getattr(
                state, "source", None) != INIT:
            state.full_screen_image = self.set_cd_album_art_image()
            state.image_base = self.file_button.components[1].content

        config_volume_level = int(self.config[PLAYER_SETTINGS][VOLUME])
        if state:
            state.volume = config_volume_level

        self.set_audio_file(new_track, state)

        if self.volume.get_position() != config_volume_level:
            self.volume.set_position(config_volume_level)
            self.volume.update_position()

    def set_audio_file_image(self):
        """ Set audio file image """

        f = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        if not f: return None

        img_tuple = self.util.get_audio_file_icon(f, self.bounding_box)
        self.set_file_button(img_tuple)

        return img_tuple[1]

    def set_cd_album_art_image(self):
        """ Set CD album art image """

        img_tuple = self.util.get_cd_album_art(self.cd_album,
                                               self.bounding_box)
        if img_tuple == None:
            return None
        self.set_file_button(img_tuple)
        self.file_button.clean_draw_update()

        return img_tuple[1]

    def set_file_button(self, img_tuple):
        """ Set image in file button
        
        :param img_tuple: tuple where first element is image location, second element image itself 
        """
        full_screen_image = img_tuple[1]
        self.file_button.state.full_screen_image = full_screen_image

        scale_ratio = self.util.get_scale_ratio(
            (self.layout.CENTER.w, self.layout.CENTER.h), full_screen_image)
        img = self.util.scale_image(full_screen_image, scale_ratio)

        self.file_button.components[1].content = img
        self.file_button.state.icon_base = img
        self.file_button.components[
            1].image_filename = self.file_button.state.image_filename = img_tuple[
                0]

        self.file_button.components[1].content_x = self.layout.CENTER.x + (
            self.layout.CENTER.w - img.get_size()[0]) / 2

        if self.layout.CENTER.h > img.get_size()[1]:
            self.file_button.components[
                1].content_y = self.layout.CENTER.y + int(
                    (self.layout.CENTER.h - img.get_size()[1]) / 2) + 1
        else:
            self.file_button.components[1].content_y = self.layout.CENTER.y

    def set_audio_file(self, new_track, s=None):
        """ Set new audio file
        
        :param new_track: True - new audio file
        "param s" button state object
        """
        state = State()

        if s:
            state.playback_mode = getattr(s, "playback_mode", FILE_AUDIO)
            state.playlist_track_number = getattr(s, "playlist_track_number",
                                                  None)
            if self.config[CURRENT][MODE] == CD_PLAYER and getattr(
                    s, "source", None) != INIT:
                image_base = getattr(s, "image_base", None)
                if image_base != None:
                    state.image_base = image_base
        else:
            m = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
            if m:
                state.playback_mode = m
            else:
                state.playback_mode = FILE_AUDIO

        if self.config[CURRENT][MODE] == AUDIO_FILES:
            self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
            if not self.current_folder:
                return
            state.folder = self.current_folder
            state.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE]
            if state.folder[-1] == os.sep:
                state.folder = state.folder[:-1]

            if os.sep in state.file_name:
                state.url = "\"" + state.file_name + "\""
            else:
                state.url = "\"" + state.folder + os.sep + state.file_name + "\""

            state.music_folder = self.config[AUDIO][MUSIC_FOLDER]
        elif self.config[CURRENT][MODE] == CD_PLAYER:
            state.file_name = s.file_name
            state.url = getattr(s, "url", s.file_name)
            parts = s.file_name.split()
            self.config[CD_PLAYBACK][CD_DRIVE_NAME] = parts[0][len("cdda:///"
                                                                   ):]
            id = self.cdutil.get_cd_drive_id_by_name(
                self.config[CD_PLAYBACK][CD_DRIVE_NAME])
            self.config[CD_PLAYBACK][CD_DRIVE_ID] = int(id)
            self.config[CD_PLAYBACK][CD_TRACK] = int(parts[1].split("=")[1])

        self.config[PLAYER_SETTINGS][PAUSE] = False
        state.mute = self.config[PLAYER_SETTINGS][MUTE]
        state.pause = self.config[PLAYER_SETTINGS][PAUSE]
        state.file_type = FILE_AUDIO
        state.dont_notify = True
        state.source = FILE_AUDIO

        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_AUDIO or self.config[
                    CURRENT][MODE] == CD_PLAYER:
            self.audio_files = self.get_audio_files()
        elif self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST:
            state.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
            self.load_playlist(state)
            state.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE]
            self.audio_files = self.get_audio_files_from_playlist()
            state.playback_mode = FILE_PLAYLIST
            n = getattr(s, "file_name", None)
            if n:
                state.file_name = n

            try:
                state.playlist_track_number = int(state.file_name) - 1
            except:
                state.playlist_track_number = self.get_current_track_index(
                    state)

        source = None
        if s:
            source = getattr(s, "source", None)

        if new_track:
            tt = 0.0
        else:
            if self.config[CURRENT][MODE] == CD_PLAYER:
                tt = self.config[CD_PLAYBACK][CD_TRACK_TIME]
            else:
                tt = self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME]

        if (isinstance(tt, str) and len(tt) != 0) or (
                isinstance(tt, float) or
            (source and source == RESUME)) or isinstance(tt, int):
            state.track_time = tt

        self.time_control.slider.set_position(0)

        if self.file_button and self.file_button.components[
                1] and self.file_button.components[1].content:
            state.icon_base = self.file_button.components[1].content

        if s and s.volume:
            state.volume = s.volume

        if self.config[CURRENT][MODE] == CD_PLAYER and s and getattr(
                s, "source", None) == INIT:
            try:
                self.cd_album = self.util.cd_titles[self.config[CD_PLAYBACK]
                                                    [CD_DRIVE_NAME]]
                self.set_cd_album_art_image()
                state.image_base = self.file_button.components[1].content
            except:
                self.cd_album = None

        if getattr(s, "full_screen_image", None) != None:
            state.full_screen_image = s.full_screen_image

        song_name = self.get_song_name(s)
        if song_name != None:
            state.album = song_name

        self.notify_play_listeners(state)

    def get_song_name(self, state):
        """ Get song name in the format: Artist - Song name
        
        :param state: state object
        """
        album = getattr(state, "album", None)
        if album == None:
            return None

        artist = album
        if "/" in album:
            artist = album.split("/")[0].strip()

        if artist == None or len(artist) == 0:
            return None

        name = getattr(state, "l_name", None)
        file_name = getattr(state, "file_name", None)
        if name == None:
            if file_name == None:
                return None
            else:
                if file_name.startswith("cdda:"):
                    id = int(file_name.split("=")[1].strip())
                    name = self.audio_files[id - 1].name
                else:
                    name = file_name

        pos = name.find(".")
        if pos != -1:
            tokens = name.split(".")
            if tokens[0].strip().isdigit():
                name = name[pos + 1:].strip()

        if name == None or len(name) == 0:
            return None
        else:
            return artist + " - " + name

    def get_audio_files_from_playlist(self):
        """ Call player for files in the playlist 
        
        :return: list of files from playlist
        """
        playlist = self.get_current_playlist()
        files = []
        if playlist:
            for n in range(len(playlist)):
                st = State()
                st.index = st.comparator_item = n
                st.file_type = FILE_AUDIO
                st.file_name = playlist[n]
                files.append(st)
        return files

    def restore_current_folder(self, state=None):
        """ Set current folder in config object
        
        :param state: not used
        """
        self.config[FILE_PLAYBACK][CURRENT_FOLDER] = self.current_folder

    def set_audio_file_playlist(self, index):
        """ Set file in playlist
        
        :param index: file index in playlist
        """
        state = State()
        state.playback_mode = FILE_PLAYLIST
        state.playlist_track_number = index
        state.file_type = FILE_AUDIO
        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        self.notify_play_listeners(state)

    def go_back(self):
        """ Go back """

        if self.config[CURRENT][MODE] == CD_PLAYER:
            return

        img_tuple = self.util.get_audio_file_icon(self.current_folder,
                                                  self.layout.CENTER)
        img = img_tuple[1]
        self.file_button.components[1].content = img
        self.file_button.state.icon_base = img_tuple

        self.file_button.components[1].content_x = self.layout.CENTER.x
        if self.layout.CENTER.h > img.get_size()[1]:
            self.file_button.components[
                1].content_y = self.layout.CENTER.y + int(
                    (self.layout.CENTER.h - img.get_size()[1]) / 2)
        else:
            self.file_button.components[1].content_y = self.layout.CENTER.y

    def recursive_change_folder(self):
        start_folder = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
        current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        f = self.util.file_util.get_next_folder_with_audio_files(
            start_folder, current_folder)
        if f == None or (f != None and f[0] == None):
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] = None
            return False

        self.config[FILE_PLAYBACK][CURRENT_FOLDER] = f[0]
        self.config[FILE_PLAYBACK][CURRENT_FILE] = f[1]
        self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
        state = State()
        state.file_type = FOLDER
        state.url = f[0]
        state.long_press = True
        state.playback_mode = FILE_RECURSIVE
        self.current_track_index = 0
        state.dont_notify = True
        self.audio_files = self.get_audio_files()
        self.recursive_notifier(f[0])
        return True

    def end_of_track(self):
        """ Handle end of track """

        if not self.screen_title.active:
            return

        i = getattr(self, "current_track_index", None)
        if i == None: return
        self.stop_timer()
        mode = self.config[CURRENT][MODE]
        if mode == RADIO or mode == STREAM or not self.audio_files:
            return

        self.time_control.stop_thread()

        if self.config[AUTO_PLAY_NEXT_TRACK]:
            if self.current_track_index == len(self.audio_files) - 1:
                if self.config[FILE_PLAYBACK][
                        CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
                    if not self.recursive_change_folder():
                        self.stop_recursive_playback()
                        return
                elif self.config[CYCLIC_PLAYBACK]:
                    self.current_track_index = 0
                elif not self.config[CYCLIC_PLAYBACK]:
                    return
            else:
                self.current_track_index += 1

            if mode == AUDIO_FILES:
                self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
            elif mode == AUDIOBOOKS:
                self.config[AUDIOBOOKS][BROWSER_BOOK_TIME] = None

            self.change_track(self.current_track_index)

            if self.config[FILE_PLAYBACK][
                    CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
                self.file_button.clean_draw_update()

    def set_playlist_size(self, size):
        """ Set playlist size
        
        :param size: playlist size
        """
        self.playlist_size = size
        self.stop_timer()

    def set_visible(self, flag):
        """ Set visibility flag
         
        :param flag: True - screen visible, False - screen invisible
        """
        Container.set_visible(self, flag)

        if flag:
            if self.volume_visible:
                self.volume.set_visible(True)
                self.time_control.set_visible(False)
            else:
                self.volume.set_visible(False)
                self.time_control.set_visible(True)

    def add_play_listener(self, listener):
        """ Add play listener
        
        :param listener: event listener
        """
        if listener not in self.play_listeners:
            self.play_listeners.append(listener)

    def notify_play_listeners(self, state):
        """ Notify all play listeners
        
        :param state: button state
        """
        if not self.screen_title.active:
            return

        m = getattr(state, "playback_mode", None)
        if m != None and m != FILE_PLAYLIST:
            state.icon_base = self.file_button.state.icon_base
        folder = getattr(state, "folder", None)
        if folder:
            state.cover_art_folder = self.util.file_util.get_cover_art_folder(
                state.folder)

        for listener in self.play_listeners:
            listener(state)

    def enable_player_screen(self, flag):
        """ Enable player screen
        
        :param flag: enable/disable flag
        """
        self.screen_title.active = flag
        self.time_control.active = flag

    def add_screen_observers(self, update_observer, redraw_observer,
                             start_time_control, stop_time_control,
                             title_to_json):
        """ Add screen observers
        
        :param update_observer: observer for updating the screen
        :param redraw_observer: observer to redraw the whole screen
        :param start_time_control:
        :param stop_time_control:
        :param title_to_json:
        """
        Screen.add_screen_observers(self, update_observer, redraw_observer,
                                    title_to_json)

        self.add_button_observers(self.shutdown_button,
                                  update_observer,
                                  redraw_observer=None)
        self.shutdown_button.add_cancel_listener(redraw_observer)
        self.screen_title.add_listener(redraw_observer)

        self.add_button_observers(self.play_button,
                                  update_observer,
                                  redraw_observer=None)
        self.add_button_observers(self.home_button, update_observer,
                                  redraw_observer)

        self.add_button_observers(self.left_button,
                                  update_observer,
                                  redraw_observer=None)
        self.left_button.add_label_listener(update_observer)
        self.add_button_observers(self.right_button,
                                  update_observer,
                                  redraw_observer=None)
        self.right_button.add_label_listener(update_observer)

        self.volume.add_slide_listener(update_observer)
        self.volume.add_knob_listener(update_observer)
        self.volume.add_press_listener(update_observer)
        self.volume.add_motion_listener(update_observer)

        self.add_button_observers(self.time_volume_button,
                                  update_observer,
                                  redraw_observer,
                                  release=False)
        self.add_button_observers(self.file_button,
                                  update_observer,
                                  redraw_observer,
                                  press=False,
                                  release=False)

        self.time_control.web_seek_listener = update_observer
        self.time_control.add_start_timer_listener(start_time_control)
        self.time_control.add_stop_timer_listener(stop_time_control)
        self.time_control.slider.add_slide_listener(update_observer)
        self.time_control.slider.add_knob_listener(update_observer)
        self.time_control.slider.add_press_listener(update_observer)
        self.time_control.slider.add_motion_listener(update_observer)
Ejemplo n.º 9
0
class FileMenu(Menu):
    """ File Menu class. Extends base Menu class """
    def __init__(self,
                 filelist,
                 util,
                 playlist_provider,
                 bgr=None,
                 bounding_box=None,
                 align=ALIGN_CENTER):
        """ Initializer
        
        :param filelist: file list
        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.factory = Factory(util)
        self.util = util
        self.cdutil = CdUtil(self.util)
        self.playlist_provider = playlist_provider
        self.config = self.util.config
        self.filelist = filelist
        m = self.factory.create_file_menu_button
        self.bounding_box = bounding_box

        r = c = 3
        if filelist:
            r = filelist.rows
            c = filelist.columns
        Menu.__init__(self,
                      util,
                      bgr,
                      self.bounding_box,
                      r,
                      c,
                      create_item_method=m,
                      align=align,
                      button_padding_x=5)

        self.browsing_history = {}
        self.left_number_listeners = []
        self.right_number_listeners = []
        self.change_folder_listeners = []
        self.play_file_listeners = []
        self.playlist_size_listeners = []
        self.menu_navigation_listeners = []
        self.page_turned = False
        self.separator = os.sep
        self.empty_state = State()
        url = selection = None
        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        folder = self.current_folder

        playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
        if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE:
            if not self.current_folder.endswith(os.sep):
                self.current_folder += os.sep

            if self.config[CURRENT][MODE] == CD_PLAYER:
                cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
                track = self.config[CD_PLAYBACK][CD_TRACK]
                url = self.cdutil.get_cd_track_url(cd_drive_name, track)
            else:
                url = self.current_folder + self.config[FILE_PLAYBACK][
                    CURRENT_FILE]
        elif playback_mode == FILE_PLAYLIST:
            url = self.config[FILE_PLAYBACK][CURRENT_FILE]
            self.browsing_history[self.current_folder] = 0
            p = self.current_folder + self.separator + self.config[
                FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
            self.browsing_history[p] = 0
            folder = p
            self.current_folder = folder
        selection = url

        if url and self.filelist:
            self.filelist.set_current_item_by_url(url)

        p_index = self.filelist.current_page_index
        pl = self.filelist.items
        self.change_folder(folder,
                           page_index=p_index,
                           playlist=pl,
                           selected=selection)

        if not self.config[FILE_PLAYBACK][CURRENT_FOLDER] and not self.config[
                FILE_PLAYBACK][CURRENT_FILE]:
            self.select_first_item()

    def recursive_change_folder(self, state):
        """ Change recursive folder
        
        :param state: state object
        """
        f = self.util.file_util.get_first_folder_with_audio_files(state.url)
        if f == None:
            self.change_folder(state.url)
            self.select_item_on_page(0)
            return

        self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_RECURSIVE

        self.config[FILE_PLAYBACK][CURRENT_FOLDER] = f[0]
        state.folder = f[0]
        state.file_name = f[1]
        state.file_type = FILE_AUDIO
        state.url = f[1]
        self.change_folder(f[0])
        self.handle_file(state)

    def select_item(self, state):
        """ Select menu item
        
        :param state: state object defining selected object
        """
        if self.visible and (state.file_type == FILE_AUDIO
                             or state.file_type == FILE_PLAYLIST):
            self.config[FILE_PLAYBACK][
                CURRENT_FOLDER] = self.util.file_util.current_folder

        if state.file_type == FOLDER or state.file_type == FOLDER_WITH_ICON:
            if getattr(state, "long_press", False):
                if self.config[FILE_PLAYBACK][
                        CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
                    self.config[FILE_PLAYBACK][
                        CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
                    self.change_folder(state.url)
                    self.select_item_on_page(0)
                else:
                    self.config[FILE_PLAYBACK][
                        CURRENT_FILE_PLAYLIST] = state.url
                    self.recursive_change_folder(state)
            else:
                self.config[FILE_PLAYBACK][
                    CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
                self.change_folder(state.url)
                self.select_item_on_page(0)
        elif state.file_type == FILE_AUDIO:
            if getattr(state, "long_press",
                       False) and self.config[FILE_PLAYBACK][
                           CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
                self.config[FILE_PLAYBACK][
                    CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO

            m = getattr(state, "playback_mode", FILE_AUDIO)
            mode = self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] or FILE_AUDIO
            if m == FILE_AUDIO and mode == FILE_AUDIO:
                self.handle_file(state)
            else:
                self.config[FILE_PLAYBACK][CURRENT_FILE] = state.file_name
                self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
                if not getattr(state, "dont_notify", None):
                    self.notify_play_file_listeners(state)
                else:
                    n = self.config[AUDIO][CLIENT_NAME]
                    if n == MPLAYER or n == VLC:
                        self.handle_file(state)
        elif state.file_type == FILE_PLAYLIST:
            self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] = FILE_PLAYLIST
            i = state.url.rfind(self.separator)
            url = state.url[i + 1:]
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] = url
            state.music_folder = self.config[AUDIO][MUSIC_FOLDER]
            pl = self.util.load_playlist(state, self.playlist_provider,
                                         self.filelist.rows,
                                         self.filelist.columns)
            url = state.url
            if pl:
                self.notify_playlist_size_listener(len(pl))
            else:
                url = state.url[0:i]
            u = getattr(state, "url", None)
            if u == None:
                state.url = state.folder + os.sep + state.file_name
                url = state.url

            self.change_folder(url, playlist=pl)

        if self.visible:
            self.draw()

    def handle_event(self, event):
        """ File menu event handler
        
        :param event: event to handle
        """
        if not self.visible: return

        if event.type == USER_EVENT_TYPE and event.sub_type == SUB_TYPE_KEYBOARD and event.action == pygame.KEYUP:
            if event.keyboard_key == kbd_keys[KEY_LEFT]:
                if (self.filelist.current_item_index_in_page == 0
                        and self.filelist.current_item_index != 0
                    ) or self.filelist.current_item_index == 0:
                    if self.filelist.length <= self.filelist.items_per_page:
                        self.select_item_on_page(self.filelist.length - 1)
                    else:
                        self.turn_page_left()
                else:
                    self.select_item_on_page(self.filelist.current_item_index -
                                             1)
            elif event.keyboard_key == kbd_keys[KEY_RIGHT]:
                if self.filelist.current_item_index == self.filelist.length - 1 or self.filelist.current_item_index_in_page == self.filelist.items_per_page - 1:
                    if self.filelist.length <= self.filelist.items_per_page:
                        self.select_item_on_page(0)
                    else:
                        self.turn_page_right()
                else:
                    self.select_item_on_page(self.filelist.current_item_index +
                                             1)
            elif event.keyboard_key == kbd_keys[
                    KEY_UP] or event.keyboard_key == kbd_keys[KEY_DOWN]:
                Menu.handle_event(self, event)
                self.filelist.set_current_item(self.selected_index)
                self.notify_menu_navigation_listeners(self.empty_state)
            elif event.keyboard_key == kbd_keys[KEY_SELECT]:
                Menu.handle_event(self, event)
        else:
            Menu.handle_event(self, event)

    def page_up(self, state=None):
        """ Called by page up button
        
        :param state: not used
        """
        if self.filelist.length <= self.filelist.items_per_page:
            return

        self.switch_to_next_page(None)
        self.select_item_on_page(self.filelist.current_page_index *
                                 self.filelist.items_per_page)

    def page_down(self, state=None):
        """ Called by page down button
        
        :param state: not used
        """
        if self.filelist.length <= self.filelist.items_per_page:
            return

        self.switch_to_previous_page(None)
        self.select_item_on_page(self.filelist.current_page_index *
                                 self.filelist.items_per_page)

    def turn_page_left(self, state=None):
        """ Turn page left
        
        :param state: not used
        """
        if self.filelist.length <= self.filelist.items_per_page:
            return

        self.switch_to_previous_page(None)
        if self.filelist.current_item_index == 0:
            self.select_item_on_page(self.filelist.length - 1)
        elif self.filelist.current_item_index_in_page == 0 and self.filelist.current_item_index != 0:
            self.select_item_on_page(self.filelist.current_item_index - 1)
        else:
            self.select_item_on_page(self.filelist.current_page_index *
                                     self.filelist.items_per_page)

    def turn_page_right(self, state=None):
        """ Turn page right
        
        :param state: not used
        """
        if self.filelist.length <= self.filelist.items_per_page:
            return

        self.switch_to_next_page(None)
        if self.filelist.current_item_index == self.filelist.length - 1:
            self.select_item_on_page(0)
        elif self.filelist.current_item_index_in_page == self.filelist.items_per_page - 1:
            self.select_item_on_page(self.filelist.current_item_index + 1)
        else:
            self.select_item_on_page(self.filelist.current_page_index *
                                     self.filelist.items_per_page)

    def select_item_on_page(self, selected_index):
        """ Select item on page
        
        :param selected_index: index of the selected item
        """
        if self.filelist.length == 0: return
        self.filelist.set_current_item(selected_index)
        self.unselect()
        self.select_by_index(selected_index)
        self.notify_menu_navigation_listeners(self.empty_state)

    def handle_file(self, state):
        """ Handle audio file
        
        :param state: state object defining audio file
        """

        state.track_time = '0'

        if not state.file_name.startswith("cdda:"):
            self.config[FILE_PLAYBACK][CURRENT_FILE] = state.file_name
            self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = state.track_time

        if self.is_in_filelist(state.file_name):
            b = self.get_button_by_filename(state.file_name)
            if not b:
                self.switch_to_next_page(state)
            else:
                state.comparator_item = b.state.comparator_item

        if not self.config[FILE_PLAYBACK][CURRENT_FILE].startswith("cdda:"):
            url = self.config[FILE_PLAYBACK][
                CURRENT_FOLDER] + os.sep + self.config[FILE_PLAYBACK][
                    CURRENT_FILE]
            self.filelist.set_current_item_by_url(url)

        mode = getattr(state, "playback_mode", None)
        if mode == None:
            if state.file_type == FILE_AUDIO:
                state.playback_mode = FILE_AUDIO
            else:
                state.playback_mode = FILE_PLAYLIST

        self.item_selected(state)
        if not getattr(state, "dont_notify", None):
            self.notify_play_file_listeners(state)

    def update_playlist_menu(self, state):
        """ Update playlist menu
        This is initiated by player
        
        :param state: state object from player defining current playlist file
        """
        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] != FILE_PLAYLIST:
            return

        s = State()
        s.dont_notify = True

        i = self.util.get_dictionary_value(state, "current_track_id")
        s.track_time = self.util.get_dictionary_value(state, "seek_time", "0")
        self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = s.track_time

        if i != None:
            b = self.get_button_by_index_in_page(int(i) - 1)
            if not b:
                self.switch_to_next_page(s)
            s.comparator_item = int(i)

        name = self.util.get_dictionary_value(state, "Track")

        if not name:
            name = self.util.get_dictionary_value(state, "file_name")

        if name != None:
            self.config[FILE_PLAYBACK][CURRENT_FILE] = name

        self.item_selected(state)

    def get_comparator(self, state):
        """ Return comparator object from state
        
        :param state: state object containing comparator item
        """
        try:
            p = state["Pos"]
            return int(p)
        except:
            pass

        try:
            s_comp = getattr(state, "comparator_item", None)
            if s_comp != None:
                return s_comp
        except:
            pass

        s_name = None

        if isinstance(state, dict):
            try:
                s_name = state["file_name"]
            except:
                pass
        elif isinstance(state, State):
            s_name = getattr(state, "file_name", None)

        for button in self.buttons.values():
            b_name = getattr(button.state, "file_name", None)
            if s_name and b_name and s_name == button.state.file_name:
                return button.state.comparator_item
        return None

    def set_current_folder(self, folder):
        """ Current folder setter
        
        :param folder: new current folder
        """
        self.current_folder = folder

    def set_filelist(self, filelist):
        """ Set filelist
        
        :param filelist: the filelist to set
        """
        self.filelist = filelist

    def init_page(self, index):
        """ Page initializer
        
        :param index: new current page index
        """
        url = self.config[FILE_PLAYBACK][CURRENT_FILE]
        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_AUDIO:
            url = self.config[FILE_PLAYBACK][
                CURRENT_FOLDER] + os.sep + self.config[FILE_PLAYBACK][
                    CURRENT_FILE]

        if url:
            self.filelist.set_current_item_by_url(url)

        self.filelist.current_page_index = index
        page = self.filelist.get_current_page()
        self.set_page(self.filelist.current_item_index_in_page, page)

        if not self.filelist.current_item:
            self.select_first_item()
        else:
            self.item_selected(self.filelist.current_item)

    def set_page(self, index_on_page, page, align=ALIGN_CENTER):
        """ Page setter
        
        :param index_on_page: current item index on page
        :param page: current page content
        """
        if page == None: return

        self.set_items(self.make_dict(page), index_on_page, self.select_item)
        self.draw()

    def switch_to_next_page(self, state):
        """ Switch to the next page
        
        :param state: button state
        """
        if len(self.filelist.items) == 0:
            return
        self.turn_page(state, self.filelist.next_page())

    def switch_to_previous_page(self, state):
        """ Switch to the previous page
        
        :param state: button state
        """
        if len(self.filelist.items) == 0:
            return
        self.turn_page(state, self.filelist.previous_page())

    def turn_page(self, state, page):
        """ Change current page
        
        :param state: state object defining current item on page
        :param page: new page content
        """
        self.set_page(self.filelist.current_item_index, page)
        if getattr(state, "url", None):
            self.filelist.set_current_item_by_url(state.url)
        if self.visible:
            self.item_selected(self.filelist.current_item)
        self.update_buttons()
        if not getattr(state, "dont_notify", None):
            self.draw()
        self.page_turned = True

        f = self.current_folder

        if f[-1] == self.separator:
            f = f[:-1]

        self.browsing_history[f] = self.filelist.current_page_index

    def switch_to_root(self, state):
        """ Switch to the root folder
        
        :param state: not used state object
        """
        self.switch_folder(self.util.file_util.ROOT)

    def switch_to_user_home(self, state):
        """ Switch to the user home folder
        
        :param state: not used state object
        """
        self.switch_folder(self.util.file_util.USER_HOME)

    def switch_folder(self, folder):
        """ Switch to folder
        
        :param folder: folder to switch to
        """
        self.switch_file_playback_mode()
        self.change_folder(folder)
        self.select_first_item()

    def switch_file_playback_mode(self):
        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST:
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO

    def switch_to_parent_folder(self, state):
        """ Switch to the parent folder
        
        :param state: not used state object
        """
        if self.current_folder == self.separator:
            return

        self.switch_file_playback_mode()

        if self.current_folder and self.current_folder[-1] == self.separator:
            self.current_folder = self.current_folder[:-1]

        tmp = self.current_folder

        sep_index = self.current_folder.rfind(self.separator)
        self.browsing_history.pop(self.current_folder, None)

        folder = self.current_folder
        page_index = 0
        selected_item = None

        if sep_index == -1: return

        if sep_index != 0:
            folder = self.current_folder[0:sep_index]

            if len(self.browsing_history) == 0:
                page_index = -1
                selected_item = tmp
            else:
                page_index = self.browsing_history.get(folder, 0)
        elif sep_index == 0:
            folder = self.separator
            try:
                page_index = self.browsing_history[folder]
            except:
                pass

        try:
            self.change_folder(folder, page_index, selected=selected_item)
        except:
            pass

        if self.filelist.length != 0 and tmp != None:
            self.filelist.set_current_item_by_url(tmp)
            self.unselect()
            i = self.filelist.current_item_index
            self.select_by_index(i)

    def change_folder(self,
                      folder,
                      page_index=0,
                      playlist=None,
                      selected=None):
        """ Change folder
        
        :param folder: new folder name
        :param page_index: new page index
        :param playlist: playlist content
        """
        if not folder:
            if self.config[AUDIO][MUSIC_FOLDER]:
                folder = self.config[AUDIO][MUSIC_FOLDER]
            else:
                folder = self.util.file_util.current_folder

        self.current_folder = folder
        self.selected_index = None

        folder_content = playlist
        if not folder_content and self.config[CURRENT][MODE] != CD_PLAYER:
            folder_content = self.util.load_folder_content(
                folder, self.filelist.rows, self.filelist.columns,
                self.bounding_box)

        if not folder_content:
            self.buttons = {}
            self.components = []
        self.filelist = Page(folder_content, self.filelist.rows,
                             self.filelist.columns)

        if selected:
            self.filelist.set_current_item_by_url(selected)
            page_index = self.filelist.current_page_index

        self.browsing_history[folder] = page_index

        self.init_page(page_index)
        self.notify_change_folder_listeners(folder)
        self.update_buttons()
        self.draw()
        self.page_turned = True

    def select_first_item(self, state=None):
        """ Select the first item in menu """

        if self.filelist.length == 0: return

        self.filelist.set_current_item(0)
        self.unselect()
        self.select_by_index(0)

    def update_buttons(self):
        """ Update left/right buttons """

        left = str(self.filelist.get_left_items_number())
        right = str(self.filelist.get_right_items_number())
        self.notify_left_number_listeners(left)
        self.notify_right_number_listeners(right)

    def get_button_by_index_in_page(self, index):
        """ Return the button by its index on page
        
        :param index: button index
        :return: the button
        """
        for button in self.buttons.values():
            if button.state.comparator_item == index:
                return button
        return None

    def get_button_by_filename(self, file_name):
        """ Return the button by its file name
        
        :param file_name: file name
        :return: the button
        """
        for button in self.buttons.values():
            if button.state.file_name == file_name:
                return button
        return None

    def is_in_filelist(self, file_name):
        """ Check that file is in the current file list
        
        :param file_name: file name
        :return: True - in file list, False- not in file list
        """
        for item in self.filelist.items:
            if item.file_name == file_name:
                return True
        return False

    def get_button_by_index(self, index):
        """ Return the button by its index on page
        
        :param index: button index
        :return: the button
        """
        for button in self.buttons.values():
            if button.state.index == index:
                return button
        return None

    def draw(self):
        """ Draw menu """

        self.clean()
        self.select_by_index(self.selected_index)
        super(FileMenu, self).draw()
        self.update()

    def add_left_number_listener(self, listener):
        """ Add left button event listener
        
        :param listener: event listener
        """
        if listener not in self.left_number_listeners:
            self.left_number_listeners.append(listener)

    def notify_left_number_listeners(self, index):
        """ Notify left number button listeners
        
        :param index: file index
        """
        for listener in self.left_number_listeners:
            listener(index)

    def add_right_number_listener(self, listener):
        """ Add right button event listener
        
        :param listener: event listener
        """
        if listener not in self.right_number_listeners:
            self.right_number_listeners.append(listener)

    def notify_right_number_listeners(self, index):
        """ Notify right number button listeners
        
        :param index: file index
        """
        for listener in self.right_number_listeners:
            listener(index)

    def add_change_folder_listener(self, listener):
        """ Add change folder event listener
        
        :param listener: event listener
        """
        if listener not in self.change_folder_listeners:
            self.change_folder_listeners.append(listener)

    def notify_change_folder_listeners(self, state):
        """ Notify change folder listeners
        
        :param state: state object defining new folder
        """
        for listener in self.change_folder_listeners:
            listener(state)

    def add_play_file_listener(self, listener):
        """ Add play file event listener
        
        :param listener: event listener
        """
        if listener not in self.play_file_listeners:
            self.play_file_listeners.append(listener)

    def notify_play_file_listeners(self, state):
        """ Notify play file listeners
        
        :param state: state object defining file
        """
        for listener in self.play_file_listeners:
            listener(state)

    def add_playlist_size_listener(self, listener):
        """ Add playlist size event listener
        
        :param listener: event listener
        """
        if listener not in self.playlist_size_listeners:
            self.playlist_size_listeners.append(listener)

    def notify_playlist_size_listener(self, size):
        """ Notify playlist size listeners
        
        :param size: playlist size
        """
        for listener in self.playlist_size_listeners:
            listener(size)

    def add_menu_navigation_listeners(self, listener):
        """ Add menu navigation event listener
        
        :param listener: event listener
        """
        if listener not in self.menu_navigation_listeners:
            self.menu_navigation_listeners.append(listener)

    def notify_menu_navigation_listeners(self, state):
        """ Notify menu navigation listeners """

        for listener in self.menu_navigation_listeners:
            listener(state)
Ejemplo n.º 10
0
    def __init__(self,
                 filelist,
                 util,
                 playlist_provider,
                 bgr=None,
                 bounding_box=None,
                 align=ALIGN_CENTER):
        """ Initializer
        
        :param filelist: file list
        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.factory = Factory(util)
        self.util = util
        self.cdutil = CdUtil(self.util)
        self.playlist_provider = playlist_provider
        self.config = self.util.config
        self.filelist = filelist
        m = self.factory.create_file_menu_button
        self.bounding_box = bounding_box

        r = c = 3
        if filelist:
            r = filelist.rows
            c = filelist.columns
        Menu.__init__(self,
                      util,
                      bgr,
                      self.bounding_box,
                      r,
                      c,
                      create_item_method=m,
                      align=align,
                      button_padding_x=5)

        self.browsing_history = {}
        self.left_number_listeners = []
        self.right_number_listeners = []
        self.change_folder_listeners = []
        self.play_file_listeners = []
        self.playlist_size_listeners = []
        self.menu_navigation_listeners = []
        self.page_turned = False
        self.separator = os.sep
        self.empty_state = State()
        url = selection = None
        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        folder = self.current_folder

        playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
        if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE:
            if not self.current_folder.endswith(os.sep):
                self.current_folder += os.sep

            if self.config[CURRENT][MODE] == CD_PLAYER:
                cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
                track = self.config[CD_PLAYBACK][CD_TRACK]
                url = self.cdutil.get_cd_track_url(cd_drive_name, track)
            else:
                url = self.current_folder + self.config[FILE_PLAYBACK][
                    CURRENT_FILE]
        elif playback_mode == FILE_PLAYLIST:
            url = self.config[FILE_PLAYBACK][CURRENT_FILE]
            self.browsing_history[self.current_folder] = 0
            p = self.current_folder + self.separator + self.config[
                FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
            self.browsing_history[p] = 0
            folder = p
            self.current_folder = folder
        selection = url

        if url and self.filelist:
            self.filelist.set_current_item_by_url(url)

        p_index = self.filelist.current_page_index
        pl = self.filelist.items
        self.change_folder(folder,
                           page_index=p_index,
                           playlist=pl,
                           selected=selection)

        if not self.config[FILE_PLAYBACK][CURRENT_FOLDER] and not self.config[
                FILE_PLAYBACK][CURRENT_FILE]:
            self.select_first_item()
Ejemplo n.º 11
0
class HomeMenu(Menu):
    """ Home Menu class. Extends base Menu class """
    def __init__(self, util, bgr=None, bounding_box=None, font_size=None):
        """ Initializer

        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.util = util
        self.factory = Factory(util)
        self.config = util.config
        m = self.factory.create_home_menu_button
        Menu.__init__(self,
                      util,
                      bgr,
                      bounding_box,
                      None,
                      None,
                      create_item_method=m,
                      font_size=font_size)
        self.cdutil = CdUtil(util)
        self.set_modes()

    def set_modes(self):
        items = []
        disabled_items = []
        player = self.config[AUDIO][PLAYER_NAME]

        if self.config[HOME_MENU][RADIO]:
            items.append(RADIO)
            if not self.util.is_radio_enabled(
            ) or not self.util.connected_to_internet:
                disabled_items.append(RADIO)

        if self.config[HOME_MENU][AUDIO_FILES]:
            items.append(AUDIO_FILES)

        if self.config[HOME_MENU][AUDIOBOOKS]:
            items.append(AUDIOBOOKS)
            if not self.util.is_audiobooks_enabled(
            ) or not self.util.connected_to_internet:
                disabled_items.append(AUDIOBOOKS)

        if self.config[HOME_MENU][STREAM]:
            items.append(STREAM)
            if not self.util.connected_to_internet:
                disabled_items.append(STREAM)

        if self.config[HOME_MENU][CD_PLAYER]:
            cd_drives_info = self.cdutil.get_cd_drives_info()
            if len(cd_drives_info) == 0 or player == MPV_NAME:
                disabled_items.append(CD_PLAYER)
            items.append(CD_PLAYER)

        if self.config[HOME_MENU][PODCASTS]:
            podcasts_util = self.util.get_podcasts_util()
            podcasts = podcasts_util.get_podcasts_links()
            downloads = podcasts_util.are_there_any_downloads()
            connected = self.util.connected_to_internet
            valid_players = [VLC_NAME, MPV_NAME]
            if (connected and len(podcasts) == 0 and not downloads) or (
                    not connected
                    and not downloads) or player not in valid_players:
                disabled_items.append(PODCASTS)
            items.append(PODCASTS)

        if self.config[HOME_MENU][AIRPLAY]:
            items.append(AIRPLAY)
            if not self.util.config[LINUX_PLATFORM]:
                disabled_items.append(AIRPLAY)

        if self.config[HOME_MENU][SPOTIFY_CONNECT]:
            items.append(SPOTIFY_CONNECT)
            if not self.util.config[LINUX_PLATFORM]:
                disabled_items.append(SPOTIFY_CONNECT)

        if self.config[HOME_MENU][COLLECTION]:
            items.append(COLLECTION)
            db_util = self.util.get_db_util()
            if db_util.conn == None:
                disabled_items.append(COLLECTION)

        l = self.get_layout(items)
        bounding_box = l.get_next_constraints()
        self.modes = self.util.load_menu(items,
                                         NAME,
                                         disabled_items,
                                         V_ALIGN_TOP,
                                         bb=bounding_box,
                                         scale=0.5)
        va_commands = self.util.get_voice_commands()

        if self.config[USAGE][USE_VOICE_ASSISTANT]:
            self.add_voice_command(RADIO, ["VA_RADIO", "VA_GO_RADIO"],
                                   va_commands)
            self.add_voice_command(AUDIO_FILES, ["VA_FILES", "VA_GO_FILES"],
                                   va_commands)
            self.add_voice_command(
                AUDIOBOOKS, ["VA_AUDIOBOOKS", "VA_BOOKS", "VA_GO_BOOKS"],
                va_commands)
            self.add_voice_command(STREAM, ["VA_STREAM", "VA_GO_STREAM"],
                                   va_commands)
            self.add_voice_command(CD_PLAYER, ["VA_CD_PLAYER"], va_commands)
            self.add_voice_command(PODCASTS, ["VA_PODCAST", "VA_PODCASTS"],
                                   va_commands)

        if not items:
            return

        if not self.config[CURRENT][MODE]:
            for i in items:
                if i not in disabled_items:
                    mode = i
                    break
        else:
            mode = self.config[CURRENT][MODE]

        self.set_items(self.modes, 0, self.change_mode, False)
        self.current_mode = self.modes[mode.lower()]
        self.item_selected(self.current_mode)

    def add_voice_command(self, name, commands, va_commands):
        """ Add voice command

        :param name: item name
        :param commands: item commands
        :param va_commands: voice commands
        """
        if not self.config[HOME_MENU][name]:
            return
        c = []
        for m in commands:
            c.append(va_commands[m].strip())
        self.modes[name].voice_commands = c

    def change_mode(self, state):
        """ Change mode event listener

        :param state: button state
        """
        if not self.visible:
            return
        state.previous_mode = self.current_mode.name
        self.current_mode = state
        self.config[CURRENT][MODE] = state.name
        self.notify_listeners(state)
Ejemplo n.º 12
0
    def __init__(self, filelist, util, playlist_provider, bounding_box=None, align=ALIGN_CENTER, icon_box=None, icon_box_without_label=None):
        """ Initializer
        
        :param filelist: file list
        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.factory = Factory(util)
        self.util = util
        self.cdutil = CdUtil(self.util)
        self.playlist_provider = playlist_provider
        self.config = self.util.config
        self.filelist = filelist
        self.icon_box = icon_box
        self.icon_box_without_label = icon_box_without_label

        m = self.create_file_menu_button
        self.bounding_box = bounding_box
        bgr = util.config[BACKGROUND][MENU_BGR_COLOR]
        
        r = c = 3
        if filelist:
            r = filelist.rows
            c = filelist.columns

        h = self.config[HORIZONTAL_LAYOUT]
        button_height = (self.bounding_box.h / r) - (self.config[PADDING] * 2)

        if self.config[ALIGN_BUTTON_CONTENT_X] == 'center':
            font_size = int(((100 - self.config[IMAGE_AREA]) / 100) * self.config[FONT_HEIGHT_PERCENT])
        else:
            font_size = int((button_height / 100) * self.config[FONT_HEIGHT_PERCENT])

        Menu.__init__(self, util, bgr, self.bounding_box, r, c, create_item_method=m, align=align, horizontal_layout=h, font_size=font_size)

        self.browsing_history = {}        
        self.left_number_listeners = []
        self.right_number_listeners = []
        self.change_folder_listeners = []
        self.play_file_listeners = []
        self.playlist_size_listeners = []
        self.menu_navigation_listeners = []
        self.page_turned = False
        self.separator = os.sep
        self.empty_state = State()
        url = selection = None
        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        folder = self.current_folder

        playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
        if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE:
            if not self.current_folder.endswith(os.sep):
                self.current_folder += os.sep                
                        
            if self.config[CURRENT][MODE] == CD_PLAYER:
                cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
                track = self.config[CD_PLAYBACK][CD_TRACK]
                url = self.cdutil.get_cd_track_url(cd_drive_name, track)
            else:
                url = self.current_folder + self.config[FILE_PLAYBACK][CURRENT_FILE]                            
        elif playback_mode == FILE_PLAYLIST:
            url = self.config[FILE_PLAYBACK][CURRENT_FILE]
            self.browsing_history[self.current_folder] = 0
            p = self.current_folder + self.separator + self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
            self.browsing_history[p] = 0
            folder = p
            self.current_folder = folder
        selection = url
        
        if url and self.filelist:        
            self.filelist.set_current_item_by_url(url)
        
        p_index = self.filelist.current_page_index
        pl = self.filelist.items
        self.change_folder(folder, page_index=p_index, playlist=pl, selected=selection)            
Ejemplo n.º 13
0
    def __init__(self,
                 listeners,
                 util,
                 get_current_playlist,
                 voice_assistant,
                 player_stop=None):
        """ Initializer
        
        :param listeners: screen listeners
        :param util: utility object
        :param get_current_playlist: current playlist getter
        :param voice_assistant:   voice assistant
        :param player_stop: stop player function
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.stop_player = player_stop
        self.get_current_playlist = get_current_playlist
        self.bounding_box = util.screen_rect
        self.layout = BorderLayout(self.bounding_box)
        k = self.bounding_box.w / self.bounding_box.h
        percent_menu_width = (100.0 - PERCENT_TOP_HEIGHT -
                              PERCENT_BOTTOM_HEIGHT) / k
        panel_width = (100.0 - percent_menu_width) / 2.0
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, panel_width,
                                            panel_width)
        self.voice_assistant = voice_assistant
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "file_player_screen_title", True, self.layout.TOP)
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, panel_width,
                                            panel_width)

        self.create_left_panel(self.layout, listeners)
        self.create_right_panel(self.layout, listeners)

        self.file_button = self.factory.create_file_button(
            self.layout.CENTER, listeners[AUDIO_FILES])

        Container.add_component(self, self.file_button)
        self.audio_files = self.get_audio_files()
        self.home_button.add_release_listener(listeners[KEY_HOME])
        self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN])
        self.left_button.add_release_listener(self.go_left)
        self.right_button.add_release_listener(self.go_right)

        self.volume = self.factory.create_volume_control(self.layout.BOTTOM)
        self.volume.add_slide_listener(listeners[KEY_SET_VOLUME])
        self.volume.add_slide_listener(listeners[KEY_SET_CONFIG_VOLUME])
        self.volume.add_slide_listener(listeners[KEY_SET_SAVER_VOLUME])
        self.volume.add_knob_listener(listeners[KEY_MUTE])
        self.volume_visible = False
        self.volume.set_visible(self.volume_visible)
        Container.add_component(self, self.volume)

        self.time_control = self.factory.create_time_control(
            self.layout.BOTTOM)
        self.time_control.add_seek_listener(listeners[KEY_SEEK])

        self.play_button.add_listener(PAUSE, self.time_control.pause)
        self.play_button.add_listener(KEY_PLAY, self.time_control.resume)
        self.left_button.add_release_listener(
            self.play_button.draw_default_state)
        self.right_button.add_release_listener(
            self.play_button.draw_default_state)

        if self.config[PLAYER_SETTINGS][PAUSE]:
            self.time_control.pause()

        Container.add_component(self, self.time_control)

        self.play_listeners = []
        self.add_play_listener(listeners[KEY_PLAY])

        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        self.file_button.state.cover_art_folder = self.util.file_util.get_cover_art_folder(
            self.current_folder)
        self.playlist_size = 0
        self.player_screen = True
        self.cd_album = None
Ejemplo n.º 14
0
class HomeMenu(Menu):
    """ Home Menu class. Extends base Menu class """
    def __init__(self, util, bgr=None, bounding_box=None, font_size=None):
        """ Initializer
        
        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.util = util
        self.factory = Factory(util)
        self.config = util.config
        m = self.factory.create_home_menu_button
        Menu.__init__(self,
                      util,
                      bgr,
                      bounding_box,
                      None,
                      None,
                      create_item_method=m,
                      font_size=font_size)
        self.cdutil = CdUtil(util)
        self.set_modes()

    def set_modes(self):
        items = []
        disabled_items = []

        if self.config[HOME_MENU][RADIO]:
            items.append(RADIO)
            if not self.util.is_radio_enabled(
            ) or not self.util.connected_to_internet:
                disabled_items.append(RADIO)

        if self.config[HOME_MENU][AUDIO_FILES]:
            items.append(AUDIO_FILES)

        if self.config[HOME_MENU][AUDIOBOOKS]:
            items.append(AUDIOBOOKS)
            if not self.util.is_audiobooks_enabled(
            ) or not self.util.connected_to_internet:
                disabled_items.append(AUDIOBOOKS)

        if self.config[HOME_MENU][STREAM]:
            items.append(STREAM)
            if not self.util.connected_to_internet:
                disabled_items.append(STREAM)

        if self.config[HOME_MENU][CD_PLAYER]:
            cd_drives_info = self.cdutil.get_cd_drives_info()
            if len(cd_drives_info) == 0:
                disabled_items.append(CD_PLAYER)
            items.append(CD_PLAYER)

        if self.config[HOME_MENU][PODCASTS]:
            podcasts_util = self.util.get_podcasts_util()
            podcasts = podcasts_util.get_podcasts_links()
            downloads = podcasts_util.are_there_any_downloads()
            connected = self.util.connected_to_internet
            player = self.config[AUDIO][PLAYER_NAME]
            if (connected and len(podcasts) == 0
                    and not downloads) or (not connected
                                           and not downloads) or player != VLC:
                disabled_items.append(PODCASTS)
            items.append(PODCASTS)

        l = self.get_layout(items)
        bounding_box = l.get_next_constraints()
        self.modes = self.util.load_menu(items,
                                         NAME,
                                         disabled_items,
                                         V_ALIGN_TOP,
                                         bb=bounding_box,
                                         scale=0.5)
        va_commands = self.util.get_voice_commands()

        if self.config[USAGE][USE_VOICE_ASSISTANT]:
            if self.config[HOME_MENU][RADIO]:
                r = [
                    va_commands["VA_RADIO"].strip(),
                    va_commands["VA_GO_RADIO"].strip()
                ]
                self.modes[RADIO].voice_commands = r
            if self.config[HOME_MENU][AUDIO_FILES]:
                f = [
                    va_commands["VA_FILES"].strip(),
                    va_commands["VA_GO_FILES"].strip(),
                    va_commands["VA_AUDIO_FILES"].strip()
                ]
                self.modes[AUDIO_FILES].voice_commands = f
            if self.config[HOME_MENU][AUDIOBOOKS]:
                a = [
                    va_commands["VA_AUDIOBOOKS"].strip(),
                    va_commands["VA_BOOKS"].strip(),
                    va_commands["VA_GO_BOOKS"].strip()
                ]
                self.modes[AUDIOBOOKS].voice_commands = a
            if self.config[HOME_MENU][STREAM]:
                s = [
                    va_commands["VA_STREAM"].strip(),
                    va_commands["VA_GO_STREAM"].strip()
                ]
                self.modes[STREAM].voice_commands = s
            if self.config[HOME_MENU][CD_PLAYER]:
                s = [va_commands["VA_CD_PLAYER"].strip()]
                self.modes[STREAM].voice_commands = s

        if not items:
            return

        if not self.config[CURRENT][MODE]:
            for i in items:
                if i not in disabled_items:
                    mode = i
                    break
        else:
            mode = self.config[CURRENT][MODE]

        self.set_items(self.modes, 0, self.change_mode, False)
        self.current_mode = self.modes[mode.lower()]
        self.item_selected(self.current_mode)

    def change_mode(self, state):
        """ Change mode event listener
        
        :param state: button state
        """
        if not self.visible:
            return
        state.previous_mode = self.current_mode.name
        self.current_mode = state
        self.config[CURRENT][MODE] = state.name
        self.notify_listeners(state)
Ejemplo n.º 15
0
class FileMenu(Menu):
    """ File Menu class. Extends base Menu class """
    
    def __init__(self, filelist, util, playlist_provider, bounding_box=None, align=ALIGN_CENTER, icon_box=None, icon_box_without_label=None):
        """ Initializer
        
        :param filelist: file list
        :param util: utility object
        :param bgr: menu background
        :param bounding_box: bounding box
        """
        self.factory = Factory(util)
        self.util = util
        self.cdutil = CdUtil(self.util)
        self.playlist_provider = playlist_provider
        self.config = self.util.config
        self.filelist = filelist
        self.icon_box = icon_box
        self.icon_box_without_label = icon_box_without_label

        m = self.create_file_menu_button
        self.bounding_box = bounding_box
        bgr = util.config[BACKGROUND][MENU_BGR_COLOR]
        
        r = c = 3
        if filelist:
            r = filelist.rows
            c = filelist.columns

        h = self.config[HORIZONTAL_LAYOUT]
        button_height = (self.bounding_box.h / r) - (self.config[PADDING] * 2)

        if self.config[ALIGN_BUTTON_CONTENT_X] == 'center':
            font_size = int(((100 - self.config[IMAGE_AREA]) / 100) * self.config[FONT_HEIGHT_PERCENT])
        else:
            font_size = int((button_height / 100) * self.config[FONT_HEIGHT_PERCENT])

        Menu.__init__(self, util, bgr, self.bounding_box, r, c, create_item_method=m, align=align, horizontal_layout=h, font_size=font_size)

        self.browsing_history = {}        
        self.left_number_listeners = []
        self.right_number_listeners = []
        self.change_folder_listeners = []
        self.play_file_listeners = []
        self.playlist_size_listeners = []
        self.menu_navigation_listeners = []
        self.page_turned = False
        self.separator = os.sep
        self.empty_state = State()
        url = selection = None
        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        folder = self.current_folder

        playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
        if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE:
            if not self.current_folder.endswith(os.sep):
                self.current_folder += os.sep                
                        
            if self.config[CURRENT][MODE] == CD_PLAYER:
                cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
                track = self.config[CD_PLAYBACK][CD_TRACK]
                url = self.cdutil.get_cd_track_url(cd_drive_name, track)
            else:
                url = self.current_folder + self.config[FILE_PLAYBACK][CURRENT_FILE]                            
        elif playback_mode == FILE_PLAYLIST:
            url = self.config[FILE_PLAYBACK][CURRENT_FILE]
            self.browsing_history[self.current_folder] = 0
            p = self.current_folder + self.separator + self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
            self.browsing_history[p] = 0
            folder = p
            self.current_folder = folder
        selection = url
        
        if url and self.filelist:        
            self.filelist.set_current_item_by_url(url)
        
        p_index = self.filelist.current_page_index
        pl = self.filelist.items
        self.change_folder(folder, page_index=p_index, playlist=pl, selected=selection)            
    
    def create_file_menu_button(self, s, constr, action, scale, font_size):
        """ Create File Menu button

        :param s: button state
        :param constr: scaling constraints
        :param action: button event listener
        :param scale: True - scale images, False - don't scale images

        :return: file menu button
        """
        scale = False
        s.padding = self.config[PADDING]
        s.image_area_percent = self.config[IMAGE_AREA]
        label_area_percent = 100 - s.image_area_percent
        if self.config[ALIGN_BUTTON_CONTENT_X] == 'left':
            s.image_location = LEFT
            s.label_location = LEFT
            s.h_align = H_ALIGN_LEFT
        elif self.config[ALIGN_BUTTON_CONTENT_X] == 'right':
            s.image_location = RIGHT
            s.label_location = RIGHT
            s.h_align = H_ALIGN_RIGHT
        elif self.config[ALIGN_BUTTON_CONTENT_X] == 'center':
            s.image_location = TOP
            s.label_location = BOTTOM
            s.h_align = H_ALIGN_CENTER
        s.v_align = CENTER
        s.wrap_labels = self.config[WRAP_LABELS]
        s.fixed_height = font_size

        if s.file_type == FOLDER_WITH_ICON or (s.file_type == FILE_AUDIO and getattr(s, "has_embedded_image", None)):
            scale = True
        if hasattr(s, "show_label"):
            return self.factory.create_menu_button(s, constr, action, scale, label_area_percent=label_area_percent, show_label=s.show_label, font_size=font_size)
        else:
            return self.factory.create_menu_button(s, constr, action, scale, label_area_percent=label_area_percent, font_size=font_size)

    def recursive_change_folder(self, state):
        """ Change recursive folder
        
        :param state: state object
        """
        f = self.util.file_util.get_first_folder_with_audio_files(state.url)
        if f == None:
            self.change_folder(state.url)
            return
        
        self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_RECURSIVE
        
        self.config[FILE_PLAYBACK][CURRENT_FOLDER] = f[0]
        state.folder = f[0]
        state.file_name = f[1]
        state.file_type = FILE_AUDIO
        state.url = os.path.join(f[0], f[1])
        self.change_folder(f[0])
        self.handle_file(state)
        
    def select_item(self, state):
        """ Select menu item
        
        :param state: state object defining selected object
        """ 
        if self.visible:
            if state.file_type == FILE_AUDIO or state.file_type == FILE_PLAYLIST:
                self.config[FILE_PLAYBACK][CURRENT_FOLDER] = self.util.file_util.current_folder
                if self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST:
                    if hasattr(state, "file_name") and hasattr(state, "name"):
                        file_name = state.file_name
                        name = state.name
                        index = file_name.rfind(name)
                        if index != -1:
                            folder = file_name[0 : index]
                            if len(folder.strip()) > 0:
                                self.config[FILE_PLAYBACK][CURRENT_FOLDER] = folder
        
        if state.file_type == FOLDER or state.file_type == FOLDER_WITH_ICON:
            if getattr(state, "long_press", False):
                if self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
                    self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
                    self.change_folder(state.url)
                else:
                    self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] = state.url
                    self.recursive_change_folder(state)
            else:
                self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO  
                self.change_folder(state.url)
        elif state.file_type == FILE_AUDIO:
            if getattr(state, "long_press", False) and self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
                self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
            
            m = getattr(state, "playback_mode", FILE_AUDIO)
            mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] or FILE_AUDIO
            if m == FILE_AUDIO and mode == FILE_AUDIO:
                self.handle_file(state)
            else:
                self.config[FILE_PLAYBACK][CURRENT_FILE] = state.file_name
                self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
                if not getattr(state, "dont_notify", None):            
                    self.notify_play_file_listeners(state)
                else:
                    n = self.config[AUDIO][CLIENT_NAME]
                    if n == VLC or n == MPV:
                        self.handle_file(state)
            self.handle_border_links()
        elif state.file_type == FILE_PLAYLIST:
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_PLAYLIST
            i = state.url.rfind(self.separator)
            url = state.url[i + 1:]
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] = url
            state.music_folder = self.config[AUDIO][MUSIC_FOLDER]
            pl = self.util.load_playlist(state, self.playlist_provider, self.filelist.rows, self.filelist.columns, (self.icon_box.w, self.icon_box.h))
            url = state.url
            if pl:
                self.notify_playlist_size_listener(len(pl))
            else:
                url = state.url[0 : i]
            u = getattr(state, "url", None)            
            if u == None:
                state.url = state.folder + os.sep + state.file_name
                url = state.url
                                
            self.change_folder(url, playlist=pl)
            
        if self.visible:
            self.draw()
   
    def page_up(self, state=None):
        """ Called by page up button
        
        :param state: not used
        """        
        if self.filelist.length <= self.filelist.items_per_page:
            return
        
        self.switch_to_next_page(None)
        
    def page_down(self, state=None):
        """ Called by page down button
        
        :param state: not used
        """        
        if self.filelist.length <= self.filelist.items_per_page:
            return
        
        self.switch_to_previous_page(None)
   
    def handle_file(self, state):
        """ Handle audio file
        
        :param state: state object defining audio file
        """
        
        state.track_time = '0'
        
        if not state.file_name.startswith("cdda:"):
            self.config[FILE_PLAYBACK][CURRENT_FILE] = state.file_name
            self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = state.track_time
        
        if self.is_in_filelist(state.file_name):
            b = self.get_button_by_filename(state.file_name)
            if not b:
                self.switch_to_next_page(state)
            else:
                state.comparator_item = b.state.comparator_item
        
        if not self.config[FILE_PLAYBACK][CURRENT_FILE].startswith("cdda:"):
            if not self.config[FILE_PLAYBACK][CURRENT_FOLDER].endswith(os.sep):
                url = self.config[FILE_PLAYBACK][CURRENT_FOLDER] + os.sep + self.config[FILE_PLAYBACK][CURRENT_FILE]
            else:
                url = self.config[FILE_PLAYBACK][CURRENT_FOLDER] + self.config[FILE_PLAYBACK][CURRENT_FILE]
            self.filelist.set_current_item_by_url(url)
        
        mode = getattr(state, "playback_mode", None)
        if mode == None:
            if state.file_type == FILE_AUDIO:
                state.playback_mode = FILE_AUDIO
            else:
                state.playback_mode = FILE_PLAYLIST

        self.item_selected(state)
        if not getattr(state, "dont_notify", None):
            self.notify_play_file_listeners(state)
    
    def update_playlist_menu(self, state):
        """ Update playlist menu
        This is initiated by player
        
        :param state: state object from player defining current playlist file
        """
        if self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] != FILE_PLAYLIST:
            return 
        
        s = State()
        s.dont_notify = True
        
        i = self.util.get_dictionary_value(state, "current_track_id")
        s.track_time = self.util.get_dictionary_value(state, "seek_time", "0")
        self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = s.track_time
        
        if i != None:            
            b = self.get_button_by_index_in_page(int(i) - 1)
            if not b:
                self.switch_to_next_page(s)
            s.comparator_item = int(i) 
            
        name = self.util.get_dictionary_value(state, "Track")
        
        if not name:
            name = self.util.get_dictionary_value(state, "file_name")
        
        if name != None:
            self.config[FILE_PLAYBACK][CURRENT_FILE] = name
        
        self.item_selected(state)
    
    def get_comparator(self, state):
        """ Return comparator object from state
        
        :param state: state object containing comparator item
        """
        try:
            p = state["Pos"]
            return int(p)
        except:
            pass
        
        try:
            s_comp = getattr(state, "comparator_item", None)
            if s_comp != None:
                return s_comp
        except:
            pass
        
        s_name = None
        
        if isinstance(state, dict):
            try:
                s_name = state["file_name"]
            except:
                pass
        elif isinstance(state, State):
            s_name = getattr(state, "file_name", None)
        
        for button in self.buttons.values():            
            b_name = getattr(button.state, "file_name", None)
            if s_name and b_name and s_name == button.state.file_name:
                return button.state.comparator_item
        return None
    
    def set_current_folder(self, folder):
        """ Current folder setter
        
        :param folder: new current folder
        """
        self.current_folder = folder
    
    def set_filelist(self, filelist):
        """ Set filelist
        
        :param filelist: the filelist to set
        """
        self.filelist = filelist        
    
    def init_page(self, index):
        """ Page initializer
        
        :param index: new current page index
        """
        url = self.config[FILE_PLAYBACK][CURRENT_FILE]
        if self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] == FILE_AUDIO:  
            url = self.config[FILE_PLAYBACK][CURRENT_FOLDER] + os.sep + self.config[FILE_PLAYBACK][CURRENT_FILE]
            
        if url:
            self.filelist.set_current_item_by_url(url)
            
        self.filelist.current_page_index = index        
        page = self.filelist.get_current_page()
        self.set_page(self.filelist.current_item_index_in_page, page)
        
        if not self.filelist.current_item:
            self.filelist.current_page_index = index

    def set_page(self, index_on_page, page, align=ALIGN_CENTER):
        """ Page setter
        
        :param index_on_page: current item index on page
        :param page: current page content
        """
        if page == None: return
        
        self.set_items(self.make_dict(page), index_on_page, self.select_item)

        for b in self.buttons.values():
            b.parent_screen = self.parent_screen

        self.draw() 

    def switch_to_next_page(self, state):
        """ Switch to the next page
        
        :param state: button state
        """
        if len(self.filelist.items) == 0:
            return
        self.turn_page(state, self.filelist.next_page())
            
    def switch_to_previous_page(self, state):
        """ Switch to the previous page
        
        :param state: button state
        """
        if len(self.filelist.items) == 0:
            return        
        self.turn_page(state, self.filelist.previous_page())
        
    def turn_page(self, state, page):
        """ Change current page
        
        :param state: state object defining current item on page
        :param page: new page content
        """
        self.set_page(self.filelist.current_item_index, page)
        if getattr(state, "url", None):
            self.filelist.set_current_item_by_url(state.url)
        if self.visible:
            self.item_selected(self.filelist.current_item)        
        self.update_buttons()
        if not getattr(state, "dont_notify", None):
            self.draw()            
        self.page_turned = True
        
        f = self.current_folder
        
        if f[-1] == self.separator:
            f = f[:-1]

        self.browsing_history[f] = self.filelist.current_page_index
        self.handle_border_links()
    
    def handle_border_links(self):
        """ Handle border links and menu/navigator selection """

        if hasattr(self, "link_borders"):
            self.link_borders()

        if hasattr(self, "navigator"):
            if self.get_selected_item() != None:
                self.navigator.unselect()
            else:
                if not self.navigator.is_selected():
                    b = self.navigator.get_button_by_name(KEY_HOME)
                    b.set_selected(True)
                    b.clean_draw_update()

    def switch_to_root(self, state):
        """ Switch to the root folder
        
        :param state: not used state object
        """
        self.switch_folder(self.util.file_util.ROOT)
            
    def switch_to_user_home(self, state):
        """ Switch to the user home folder
        
        :param state: not used state object
        """
        self.switch_folder(self.util.file_util.USER_HOME)  
    
    def switch_folder(self, folder):
        """ Switch to folder
        
        :param folder: folder to switch to
        """
        self.switch_file_playback_mode()
        self.change_folder(folder)
    
    def switch_file_playback_mode(self):
        if self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST:
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
    
    def switch_to_parent_folder(self, state):
        """ Switch to the parent folder
        
        :param state: not used state object
        """
        if self.current_folder == self.separator:
            return
        
        self.switch_file_playback_mode()
        
        if self.current_folder and self.current_folder[-1] == self.separator:
            self.current_folder = self.current_folder[:-1]

        tmp = self.current_folder    
        
        sep_index = self.current_folder.rfind(self.separator)
        self.browsing_history.pop(self.current_folder, None)
        
        folder = self.current_folder
        page_index = 0 
        selected_item = tmp
        
        if sep_index == -1: return
        
        if sep_index != 0:
            folder = self.current_folder[0:sep_index]
            
            if len(self.browsing_history) == 0:
                page_index = -1
            else:
                page_index = self.browsing_history.get(folder, 0)
        elif sep_index == 0:
            folder = self.separator            
            try:
                page_index = self.browsing_history[folder]
            except:
                pass
            
        try:
            self.change_folder(folder, page_index, selected=selected_item)
        except:
            pass
                    
        if self.filelist.length != 0 and tmp != None:
            self.filelist.set_current_item_by_url(tmp)
            self.unselect()
            i = self.filelist.current_item_index
            self.select_by_index(i)
            if hasattr(self, "navigator") and self.get_selected_item() != None:
                self.navigator.unselect()
    
    def change_folder(self, folder, page_index=0, playlist=None, selected=None):
        """ Change folder
        
        :param folder: new folder name
        :param page_index: new page index
        :param playlist: playlist content
        """
        if not folder:
            if self.config[AUDIO][MUSIC_FOLDER]:
                folder = self.config[AUDIO][MUSIC_FOLDER]
            else:
                folder = self.util.file_util.current_folder        
        
        self.current_folder = folder
        self.selected_index = None
        
        folder_content = playlist
        if not folder_content and self.config[CURRENT][MODE] != CD_PLAYER:
            folder_content = self.util.load_folder_content(folder, self.filelist.rows, self.filelist.columns, self.icon_box, self.icon_box_without_label)
            
        if not folder_content:
            self.buttons = {}
            self.components = []            
        self.filelist = Page(folder_content, self.filelist.rows, self.filelist.columns)

        if selected:
            self.filelist.set_current_item_by_url(selected)
            page_index = self.filelist.current_item_page_index

        self.browsing_history[folder] = page_index 
        self.init_page(page_index)
        self.notify_change_folder_listeners(folder)
        self.update_buttons()
        self.page_turned = True

        self.handle_border_links()               
    
    def update_buttons(self):
        """ Update left/right buttons """
        
        left = str(self.filelist.get_left_items_number())
        right = str(self.filelist.get_right_items_number())        
        self.notify_left_number_listeners(left)
        self.notify_right_number_listeners(right)    
            
    def get_button_by_index_in_page(self, index):
        """ Return the button by its index on page
        
        :param index: button index
        :return: the button
        """
        for button in self.buttons.values():
            if button.state.comparator_item == index:
                return button
        return None
    
    def get_button_by_filename(self, file_name):
        """ Return the button by its file name
        
        :param file_name: file name
        :return: the button
        """
        for button in self.buttons.values():
            if button.state.file_name == file_name:
                return button
        return None
    
    def is_in_filelist(self, file_name):
        """ Check that file is in the current file list
        
        :param file_name: file name
        :return: True - in file list, False- not in file list
        """
        if not self.filelist.items:
            return False

        for item in self.filelist.items:
            if item.file_name == file_name:
                return True
        return False
    
    def get_button_by_index(self, index):
        """ Return the button by its index on page
        
        :param index: button index
        :return: the button
        """
        for button in self.buttons.values():
            if button.state.index == index:
                return button
        return None
    
    def draw(self):
        """ Draw menu """
        
        self.clean()
        super(FileMenu, self).draw()        
        self.update()
     
    def add_left_number_listener(self, listener):
        """ Add left button event listener
        
        :param listener: event listener
        """
        if listener not in self.left_number_listeners:
            self.left_number_listeners.append(listener)     
 
    def notify_left_number_listeners(self, index):
        """ Notify left number button listeners
        
        :param index: file index
        """
        for listener in self.left_number_listeners:
            listener(index)
            
    def add_right_number_listener(self, listener):
        """ Add right button event listener
        
        :param listener: event listener
        """
        if listener not in self.right_number_listeners:
            self.right_number_listeners.append(listener)     
 
    def notify_right_number_listeners(self, index):
        """ Notify right number button listeners
        
        :param index: file index
        """
        for listener in self.right_number_listeners:
            listener(index)
            
    def add_change_folder_listener(self, listener):
        """ Add change folder event listener
        
        :param listener: event listener
        """
        if listener not in self.change_folder_listeners:
            self.change_folder_listeners.append(listener)     
 
    def notify_change_folder_listeners(self, state):
        """ Notify change folder listeners
        
        :param state: state object defining new folder
        """
        for listener in self.change_folder_listeners:
            listener(state)
            
    def add_play_file_listener(self, listener):
        """ Add play file event listener
        
        :param listener: event listener
        """
        if listener not in self.play_file_listeners:
            self.play_file_listeners.append(listener)     
 
    def notify_play_file_listeners(self, state):
        """ Notify play file listeners
        
        :param state: state object defining file
        """
        for listener in self.play_file_listeners:
            listener(state)
            
    def add_playlist_size_listener(self, listener):
        """ Add playlist size event listener
        
        :param listener: event listener
        """
        if listener not in self.playlist_size_listeners:
            self.playlist_size_listeners.append(listener)     
 
    def notify_playlist_size_listener(self, size):
        """ Notify playlist size listeners
        
        :param size: playlist size
        """
        for listener in self.playlist_size_listeners:
            listener(size)
            
    def add_menu_navigation_listeners(self, listener):
        """ Add menu navigation event listener
        
        :param listener: event listener
        """
        if listener not in self.menu_navigation_listeners:
            self.menu_navigation_listeners.append(listener)     
 
    def notify_menu_navigation_listeners(self, state):
        """ Notify menu navigation listeners """
        
        for listener in self.menu_navigation_listeners:
            listener(state)
            
Ejemplo n.º 16
0
class FilePlayerScreen(Screen):
    """ File Player Screen """
    def __init__(self,
                 listeners,
                 util,
                 get_current_playlist,
                 voice_assistant,
                 player_stop=None,
                 arrow_labels=True,
                 active_file_button=True,
                 show_time_control=True,
                 show_order=True,
                 show_info=True):
        """ Initializer
        
        :param listeners: screen listeners
        :param util: utility object
        :param get_current_playlist: current playlist getter
        :param voice_assistant:   voice assistant
        :param player_stop: stop player function
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.image_util = util.image_util

        self.top_height = self.config[PLAYER_SCREEN][TOP_HEIGHT_PERCENT]
        self.bottom_height = self.config[PLAYER_SCREEN][BOTTOM_HEIGHT_PERCENT]
        self.button_height = self.config[PLAYER_SCREEN][BUTTON_HEIGHT_PERCENT]
        self.popup_width = self.config[PLAYER_SCREEN][POPUP_WIDTH_PERCENT]
        self.image_location = self.config[PLAYER_SCREEN][IMAGE_LOCATION]

        self.stop_player = player_stop
        self.get_current_playlist = get_current_playlist
        self.show_time_control = show_time_control

        self.bounding_box = util.screen_rect
        self.layout = self.get_layout()

        self.voice_assistant = voice_assistant
        Screen.__init__(self, util, "", self.top_height, voice_assistant,
                        "file_player_screen_title", True, self.layout.TOP)
        self.layout = self.get_layout()

        self.create_left_panel(self.layout, listeners, arrow_labels)
        self.create_right_panel(self.layout, listeners, arrow_labels)

        if not active_file_button:
            listeners[AUDIO_FILES] = None

        self.file_button = self.factory.create_file_button(
            self.layout.CENTER, listeners[AUDIO_FILES])
        self.add_component(self.file_button)

        self.audio_files = self.get_audio_files()
        self.home_button.add_release_listener(listeners[KEY_HOME])
        self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN])
        self.left_button.add_release_listener(self.go_left)
        self.right_button.add_release_listener(self.go_right)

        self.show_order = show_order
        self.show_info = show_info
        self.order_button = None
        self.info_button = None
        self.order_popup = None
        self.info_popup = None
        self.playback_order = self.config[PLAYER_SETTINGS][PLAYBACK_ORDER]
        self.bottom_center_layout = self.layout.BOTTOM

        if self.show_order or self.show_info:
            self.start_screensaver = listeners[SCREENSAVER]
            self.go_info_screen = listeners[KEY_INFO]
            self.add_popups()

        self.volume = self.factory.create_volume_control(
            self.bottom_center_layout)
        self.volume.add_slide_listener(
            self.get_listener(listeners, KEY_SET_VOLUME))
        self.volume.add_slide_listener(
            self.get_listener(listeners, KEY_SET_CONFIG_VOLUME))
        self.volume.add_slide_listener(
            self.get_listener(listeners, KEY_SET_SAVER_VOLUME))
        self.volume.add_knob_listener(self.get_listener(listeners, KEY_MUTE))
        self.volume_visible = False
        self.volume.set_visible(self.volume_visible)
        self.add_component(self.volume)

        if self.show_time_control:
            self.time_control = self.factory.create_time_control(
                self.bottom_center_layout)
            if KEY_SEEK in listeners.keys():
                self.time_control.add_seek_listener(listeners[KEY_SEEK])

            self.play_button.add_listener(PAUSE, self.time_control.pause)
            self.play_button.add_listener(KEY_PLAY, self.time_control.resume)

            if self.config[PLAYER_SETTINGS][PAUSE]:
                self.time_control.pause()
            self.add_component(self.time_control)

        self.left_button.add_release_listener(
            self.play_button.draw_default_state)
        self.right_button.add_release_listener(
            self.play_button.draw_default_state)

        self.play_listeners = []
        self.add_play_listener(self.get_listener(listeners, KEY_PLAY))

        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        self.file_button.state.cover_art_folder = self.util.file_util.get_cover_art_folder(
            self.current_folder)
        self.playlist_size = 0
        self.player_screen = True
        self.cd_album = None
        self.animated_title = True

        if self.order_popup:
            Container.add_component(self, self.order_popup)

        if self.info_popup:
            Container.add_component(self, self.info_popup)

    def get_layout(self):
        """ Get the layout of the center area of the screen for image and buttons

        :return: layout rectangle
        """
        layout = BorderLayout(self.bounding_box)
        k = self.bounding_box.w / self.bounding_box.h
        percent_menu_width = (100.0 - self.top_height - self.bottom_height) / k
        panel_width = (100.0 - percent_menu_width) / 2.0

        if self.image_location == LOCATION_CENTER:
            layout.set_percent_constraints(self.top_height, self.bottom_height,
                                           panel_width, panel_width)
        elif self.image_location == LOCATION_LEFT:
            layout.set_percent_constraints(self.top_height, self.bottom_height,
                                           0, panel_width * 2)
        elif self.image_location == LOCATION_RIGHT:
            layout.set_percent_constraints(self.top_height, self.bottom_height,
                                           panel_width * 2, 0)

        return layout

    def get_panel_layout(self, layout, panel_location):
        """ Get the layout of the panel for buttons

        :param layout: layout of the whole central area
        :param panel_location: panel location: left or right

        :return: panel layout rectangle
        """
        if self.image_location == LOCATION_CENTER:
            if panel_location == LOCATION_LEFT:
                return BorderLayout(layout.LEFT)
            else:
                return BorderLayout(layout.RIGHT)
        elif self.image_location == LOCATION_LEFT:
            r = layout.RIGHT
            if panel_location == LOCATION_LEFT:
                return BorderLayout(Rect(r.x, r.y, r.w / 2, r.h))
            else:
                return BorderLayout(
                    Rect(r.x + r.w / 2 + 1, r.y, r.w / 2 - 1, r.h))
        elif self.image_location == LOCATION_RIGHT:
            r = layout.LEFT
            if panel_location == LOCATION_LEFT:
                return BorderLayout(Rect(r.x, r.y, r.w / 2, r.h))
            else:
                return BorderLayout(
                    Rect(r.x + r.w / 2 + 1, r.y, r.w / 2 - 1, r.h))

    def add_popups(self):
        """ Add popup menus: playback order & info """

        self.bottom_layout = BorderLayout(self.layout.BOTTOM)
        if self.show_order and not self.show_info:
            self.bottom_layout.set_percent_constraints(0, 0, self.popup_width,
                                                       0)
            self.order_button = self.factory.create_order_button(
                self.bottom_layout.LEFT, self.handle_order_button,
                self.playback_order)
            self.order_popup = self.get_order_popup(self.bounding_box)
            self.add_component(self.order_button)
        elif self.show_order and self.show_info:
            self.bottom_layout.set_percent_constraints(0, 0, self.popup_width,
                                                       self.popup_width)
            self.order_button = self.factory.create_order_button(
                self.bottom_layout.LEFT, self.handle_order_button,
                self.playback_order)
            self.info_button = self.factory.create_info_button(
                self.bottom_layout.RIGHT, self.handle_info_button)
            self.order_popup = self.get_order_popup(self.bounding_box)
            self.info_popup = self.get_info_popup(self.bounding_box)
            self.add_component(self.order_button)
            self.add_component(self.info_button)
        elif not self.show_order and self.show_info:
            self.bottom_layout.set_percent_constraints(0, 0, 0,
                                                       self.popup_width)
            self.info_button = self.factory.create_info_button(
                self.bottom_layout.RIGHT, self.handle_info_button)
            self.info_popup = self.get_info_popup(self.bounding_box)
            self.add_component(self.info_button)

        self.bottom_layout.CENTER.w -= 2
        self.bottom_layout.CENTER.x += 1
        self.bottom_center_layout = self.bottom_layout.CENTER

    def handle_order_button(self, state):
        """ Handle playback order button

        :param state: button state
        """
        self.order_popup.set_visible(True)
        self.clean_draw_update()

    def handle_info_button(self, state):
        """ Handle info button

        :param state: button state
        """
        self.info_popup.set_visible(True)
        self.clean_draw_update()

    def get_order_popup(self, bb):
        """ Create playback order popup menu

        :param bb: bounding box

        :return: popup menu
        """
        items = []
        items.append(PLAYBACK_CYCLIC)
        items.append(PLAYBACK_REGULAR)
        items.append(PLAYBACK_SINGLE_TRACK)
        items.append(PLAYBACK_SHUFFLE)
        items.append(PLAYBACK_SINGLE_CYCLIC)

        layout = BorderLayout(bb)
        layout.set_percent_constraints(self.top_height, 0, self.popup_width, 0)
        popup = Popup(items,
                      self.util,
                      layout.LEFT,
                      self.clean_draw_update,
                      self.handle_order_popup_selection,
                      default_selection=self.playback_order)
        self.left_button.add_label_listener(popup.update_popup)

        return popup

    def get_info_popup(self, bb):
        """ Create info popup menu

        :param bb: bounding box

        :return: popup menu
        """
        items = []
        mode = self.config[CURRENT][MODE]

        items.append(CLOCK)
        items.append(WEATHER)
        items.append(LYRICS)

        if mode == AUDIO_FILES or mode == COLLECTION:
            items.append(FILE_INFO)

        layout = BorderLayout(bb)
        layout.set_percent_constraints(self.top_height, 0, 0, self.popup_width)
        popup = Popup(items, self.util, layout.RIGHT, self.clean_draw_update,
                      self.handle_info_popup_selection)
        self.right_button.add_label_listener(popup.update_popup)

        return popup

    def handle_order_popup_selection(self, state):
        """ Handle playback order menu selection

        :param state: button state
        """
        b = self.factory.create_order_button(self.bottom_layout.LEFT,
                                             self.handle_order_button,
                                             state.name)
        i = self.components.index(self.order_button)
        self.components[i] = b
        self.order_button = b
        self.add_button_observers(self.order_button, self.update_observer,
                                  self.redraw_observer)
        self.order_button.clean_draw_update()
        self.config[PLAYER_SETTINGS][PLAYBACK_ORDER] = state.name

    def handle_info_popup_selection(self, state):
        """ Handle info menu selection

        :param state: button state
        """
        n = state.name

        if n == CLOCK or n == WEATHER:
            self.start_screensaver(n)
        elif n == LYRICS:
            a = None
            try:
                m = self.util.get_file_metadata()
                a = m["artist"] + " - " + m["title"]
            except:
                pass
            if a != None:
                s = State()
                s.album = a
                self.start_screensaver(n, s)
            else:
                self.start_screensaver(n)
        else:
            self.go_info_screen(state)

    def get_audio_files(self):
        """ Return the list of audio files in current folder
        
        :return: list of audio files
        """
        files = []
        if self.config[CURRENT][MODE] == CD_PLAYER:
            af = getattr(self, "audio_files", None)
            if af == None:
                cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
                files = self.cdutil.get_cd_tracks_summary(cd_drive_name)
            else:
                return self.audio_files
        else:
            folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
            files = self.util.get_audio_files_in_folder(folder)

        return files

    def get_current_track_index(self, state=None):
        """ Return current track index.
        In case of files goes through the file list.
        In case of playlist takes track index from the state object.
        
        :param state: button state

        :return: current track index
        """
        if self.config[CURRENT][MODE] == AUDIOBOOKS:
            t = None
            try:
                t = state["file_name"]
            except:
                pass

            if t == None:
                try:
                    t = state["current_title"]
                except:
                    pass

            if t == None:
                try:
                    t = state
                except:
                    pass

            for i, f in enumerate(self.audio_files):
                try:
                    s = f["file_name"]
                except:
                    pass

                if getattr(f, "file_name", None):
                    s = getattr(f, "file_name", None)

                if s.endswith(t):
                    return i
            return 0

        mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
        if state and mode == FILE_PLAYLIST:
            try:
                n = state["Track"]
                if n: return int(n) - 1
            except:
                pass

        if self.config[CURRENT][MODE] == CD_PLAYER:
            cmp = int(self.config[CD_PLAYBACK][CD_TRACK]) - 1
        else:
            cmp = self.config[FILE_PLAYBACK][CURRENT_FILE]
            if state and isinstance(state, State):
                cmp = state.file_name

        for f in self.audio_files:
            if self.config[CURRENT][MODE] == CD_PLAYER:
                if f.index == cmp:
                    return f.index
            else:
                if f.file_name == cmp:
                    return f.index
        return 0

    def stop_recursive_playback(self):
        """ Stop recursive playback """

        self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
        self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] = None
        self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
        self.stop_timer()
        if self.show_time_control:
            self.time_control.stop_thread()
            self.time_control.reset()
        if self.stop_player != None:
            self.stop_player()

    def go_left(self, state):
        """ Switch to the previous track
        
        :param state: not used state object
        """
        if getattr(self, "current_track_index", None) == None:
            return

        filelist_size = self.get_filelist_size()

        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE:
            self.stop_recursive_playback()
            return

        if self.current_track_index == 0:
            self.current_track_index = filelist_size - 1
        else:
            self.current_track_index -= 1
        self.change_track(self.current_track_index)

    def go_right(self, state):
        """ Switch to the next track
        
        :param state: not used state object
        """
        if getattr(self, "current_track_index", None) == None:
            return

        filelist_size = self.get_filelist_size()

        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_RECURSIVE and self.current_track_index == filelist_size - 1:
            self.stop_timer()
            if self.show_time_control:
                self.time_control.stop_thread()
            self.recursive_change_folder()
            self.current_track_index = 0
            self.change_track(self.current_track_index)
            self.file_button.clean_draw_update()
            return

        if self.current_track_index == filelist_size - 1:
            self.current_track_index = 0
        else:
            self.current_track_index += 1

        self.change_track(self.current_track_index)

    def get_filelist_size(self):
        """ Return the file list size
        
        :return: file list size
        """
        if self.audio_files:
            return len(self.audio_files)
        else:
            return 0

    def change_track(self, track_index):
        """ Change track
        
        :param track_index: index track
        """
        a = [AUDIOBOOKS, CD_PLAYER]
        m = self.config[CURRENT][MODE]
        if not (m in a):
            self.config[FILE_PLAYBACK][CURRENT_FILE] = self.get_filename(
                track_index)

        self.stop_timer()
        time.sleep(0.3)
        s = State()
        if m == FILE_PLAYBACK:
            s.playback_mode = self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE]

        s.playlist_track_number = track_index
        s.index = track_index
        s.source = ARROW_BUTTON
        s.file_name = self.get_filename(track_index)

        if self.cd_album != None:
            s.album = self.cd_album

        if self.config[CURRENT][MODE] == AUDIO_FILES:
            folder = self.current_folder
            if not folder.endswith(os.sep):
                folder += os.sep
            s.url = folder + s.file_name

        self.set_current(True, s)

    def stop_timer(self):
        """ Stop time control timer """

        if self.show_time_control:
            self.time_control.stop_timer()

    def get_filename(self, index):
        """ Get filename by index
        
        :param index: file index
        
        :return: filename
        """
        for b in self.audio_files:
            if b.index == index:
                return b.file_name
        return ""

    def is_valid_mode(self):
        current_mode = self.config[CURRENT][MODE]
        modes = [AUDIO_FILES, AUDIOBOOKS, CD_PLAYER]
        if current_mode in modes:
            return True
        else:
            return False

    def update_arrow_button_labels(self, state=None):
        """ Update left/right arrow button labels
        
        :param state: state object representing current track
        """
        if (not self.is_valid_mode()) or (not self.screen_title.active): return

        self.set_current_track_index(state)
        left = self.current_track_index
        right = 0

        if self.audio_files and len(self.audio_files) > 1:
            right = len(self.audio_files) - self.current_track_index - 1

        self.left_button.change_label(str(left))
        self.right_button.change_label(str(right))

    def set_current_track_index(self, state):
        """ Set current track index
        
        :param state: state object representing current track
        """
        if not self.is_valid_mode(): return

        if self.config[CURRENT][MODE] == CD_PLAYER and getattr(
                state, "cd_track_id", None):
            self.config[CD_PLAYBACK][CD_TRACK] = state["cd_track_id"]

        self.current_track_index = 0

        if self.playlist_size == 1:
            return

        if not self.audio_files:
            self.audio_files = self.get_audio_files()
            if not self.audio_files: return

        i = self.get_current_track_index(state)
        self.current_track_index = i

    def create_left_panel(self, layout, listeners, arrow_labels):
        """ Create left side buttons panel
        
        :param layout: panel layout 
        :param listeners: button listeners
        :param arrow_labels: show arrow label or not
        """
        panel_layout = self.get_panel_layout(layout, LOCATION_LEFT)
        panel_layout.set_percent_constraints(self.button_height,
                                             self.button_height, 0, 0)
        self.left_button = self.factory.create_left_button(
            panel_layout.CENTER, '', 40, 100, arrow_labels)
        panel_layout.TOP.y += 1
        panel_layout.TOP.h -= 2
        self.shutdown_button = self.factory.create_shutdown_button(
            panel_layout.TOP)
        panel_layout.BOTTOM.h += 1
        self.home_button = self.factory.create_button(KEY_HOME,
                                                      KEY_HOME,
                                                      panel_layout.BOTTOM,
                                                      image_size_percent=36)
        panel = Container(self.util, layout.LEFT)
        panel.add_component(self.shutdown_button)
        panel.add_component(self.left_button)
        panel.add_component(self.home_button)
        self.add_component(panel)

    def create_right_panel(self, layout, listeners, arrow_labels):
        """ Create right side buttons panel
        
        :param layout: panel layout 
        :param listeners: button listeners
        :param arrow_labels: show arrow label or not
        """
        panel_layout = self.get_panel_layout(layout, LOCATION_RIGHT)
        panel_layout.set_percent_constraints(self.button_height,
                                             self.button_height, 0, 0)
        panel_layout.TOP.y += 1
        panel_layout.TOP.h -= 2
        self.play_button = self.factory.create_play_pause_button(
            panel_layout.TOP, self.get_listener(listeners, KEY_PLAY_PAUSE))
        self.right_button = self.factory.create_right_button(
            panel_layout.CENTER, '', 40, 100, arrow_labels)
        panel_layout.BOTTOM.h += 1
        self.time_volume_button = self.factory.create_time_volume_button(
            panel_layout.BOTTOM, self.toggle_time_volume)
        panel = Container(self.util, layout.RIGHT)
        panel.add_component(self.play_button)
        panel.add_component(self.right_button)
        panel.add_component(self.time_volume_button)
        self.add_component(panel)

    def get_listener(self, listeners, name):
        """ Return listener

        :param listeners: all listeners
        :param name: listener name

        :return: listener if avaialble, None - otherwise
        """
        if name in listeners.keys():
            return listeners[name]
        else:
            return None

    def toggle_time_volume(self):
        """ Switch between time and volume controls """

        if self.volume_visible:
            self.volume.set_visible(False)
            if self.show_time_control:
                self.time_control.set_visible(True)
            self.volume_visible = False
        else:
            volume_level = int(self.config[PLAYER_SETTINGS][VOLUME])
            self.volume.set_position(volume_level)
            self.volume.update_position()
            self.volume.set_visible(True)
            if self.show_time_control:
                self.time_control.set_visible(False)
            self.volume_visible = True
        self.clean_draw_update()
        if hasattr(self, "time_control"):
            self.time_control.slider.clean_draw_update()

    def eject_cd(self, state):
        """ Eject CD
        
        :param state: button state object
        """
        self.audio_files = []
        self.screen_title.set_text(" ")
        self.update_arrow_button_labels(state)
        if self.show_time_control:
            self.time_control.reset()
        self.cd_album = None
        self.set_cd_album_art_image()

    def set_current(self, new_track=False, state=None):
        """ Set current file or playlist
        
        :param new_track: True - new audio file
        :param state: button state
        """
        self.cd_album = getattr(state, "album", None)

        if self.config[CURRENT][MODE] == AUDIO_FILES:
            if getattr(state, "url", None) is None:
                state.url = None
            state.full_screen_image = self.set_audio_file_image(state.url)
        elif self.config[CURRENT][MODE] == CD_PLAYER and getattr(
                state, "source", None) != INIT:
            state.full_screen_image = self.set_cd_album_art_image()
            state.image_base = self.file_button.components[1].content

        config_volume_level = int(self.config[PLAYER_SETTINGS][VOLUME])
        if state:
            if self.config[VOLUME_CONTROL][
                    VOLUME_CONTROL_TYPE] == VOLUME_CONTROL_TYPE_PLAYER:
                state.volume = config_volume_level
            else:
                state.volume = None

        self.set_audio_file(new_track, state)

        if self.volume.get_position() != config_volume_level:
            self.volume.set_position(config_volume_level)
            self.volume.update_position()

    def set_audio_file_image(self, url=None, folder=None):
        """ Set audio file image

        :param url: audio file name
        :param folder: folder name

        :return: image
        """
        if folder:
            f = folder
        else:
            f = self.config[FILE_PLAYBACK][CURRENT_FOLDER]

        if not f: return None

        img_tuple = self.image_util.get_audio_file_icon(
            f, self.bounding_box, url)
        self.set_file_button(img_tuple)
        self.file_button.clean_draw_update()

        return img_tuple[1]

    def set_cd_album_art_image(self):
        """ Set CD album art image """

        img_tuple = self.image_util.get_cd_album_art(self.cd_album,
                                                     self.bounding_box)
        if img_tuple == None:
            return None
        self.set_file_button(img_tuple)
        self.file_button.clean_draw_update()

        return img_tuple[1]

    def set_file_button(self, img_tuple):
        """ Set image in file button
        
        :param img_tuple: tuple where first element is image location, second element image itself 
        """
        full_screen_image = img_tuple[1]
        self.file_button.state.full_screen_image = full_screen_image

        scale_ratio = self.image_util.get_scale_ratio(
            (self.layout.CENTER.w, self.layout.CENTER.h), full_screen_image)
        img = self.image_util.scale_image(full_screen_image, scale_ratio)

        self.file_button.components[1].content = img
        self.file_button.state.icon_base = img
        self.file_button.components[
            1].image_filename = self.file_button.state.image_filename = img_tuple[
                0]

        self.file_button.components[1].content_x = self.layout.CENTER.x + (
            self.layout.CENTER.w - img.get_size()[0]) / 2

        if self.layout.CENTER.h > img.get_size()[1]:
            self.file_button.components[
                1].content_y = self.layout.CENTER.y + int(
                    (self.layout.CENTER.h - img.get_size()[1]) / 2) + 1
        else:
            self.file_button.components[1].content_y = self.layout.CENTER.y

    def set_audio_file(self, new_track, s=None):
        """ Set new audio file
        
        :param new_track: True - new audio file
        "param s" button state object
        """
        state = State()

        if s:
            state.playback_mode = getattr(s, "playback_mode", FILE_AUDIO)
            state.playlist_track_number = getattr(s, "playlist_track_number",
                                                  None)
            if self.config[CURRENT][MODE] == CD_PLAYER and getattr(
                    s, "source", None) != INIT:
                image_base = getattr(s, "image_base", None)
                if image_base != None:
                    state.image_base = image_base
        else:
            m = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
            if m:
                state.playback_mode = m
            else:
                state.playback_mode = FILE_AUDIO

        if self.config[CURRENT][MODE] == AUDIO_FILES:
            self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
            if not self.current_folder:
                return
            state.folder = self.current_folder
            state.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE]
            if state.folder[-1] == os.sep:
                state.folder = state.folder[:-1]

            if os.sep in state.file_name:
                state.url = "\"" + state.file_name + "\""
            else:
                state.url = "\"" + state.folder + os.sep + state.file_name + "\""

            if s.url == None and state.url != None:
                state.full_screen_image = self.set_audio_file_image(
                    state.url.replace('\"', ""))

            state.music_folder = self.config[AUDIO][MUSIC_FOLDER]
        elif self.config[CURRENT][MODE] == CD_PLAYER:
            state.file_name = s.file_name
            state.url = getattr(s, "url", s.file_name)
            parts = s.file_name.split()
            self.config[CD_PLAYBACK][CD_DRIVE_NAME] = parts[0][len("cdda:///"
                                                                   ):]
            id = self.cdutil.get_cd_drive_id_by_name(
                self.config[CD_PLAYBACK][CD_DRIVE_NAME])
            self.config[CD_PLAYBACK][CD_DRIVE_ID] = int(id)
            self.config[CD_PLAYBACK][CD_TRACK] = int(parts[1].split("=")[1])

        self.config[PLAYER_SETTINGS][PAUSE] = False
        state.mute = self.config[PLAYER_SETTINGS][MUTE]
        state.pause = self.config[PLAYER_SETTINGS][PAUSE]
        self.play_button.draw_default_state(None)
        state.file_type = FILE_AUDIO
        state.dont_notify = True
        state.source = FILE_AUDIO

        if self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_AUDIO or self.config[
                    CURRENT][MODE] == CD_PLAYER:
            self.audio_files = self.get_audio_files()
        elif self.config[FILE_PLAYBACK][
                CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST:
            state.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
            self.load_playlist(state)
            state.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE]
            self.audio_files = self.get_audio_files_from_playlist()
            state.playback_mode = FILE_PLAYLIST
            n = getattr(s, "file_name", None)
            if n:
                state.file_name = n

            try:
                state.playlist_track_number = int(state.file_name) - 1
            except:
                state.playlist_track_number = self.get_current_track_index(
                    state)

        source = None
        if s:
            source = getattr(s, "source", None)

        if new_track:
            tt = 0.0
        else:
            if self.config[CURRENT][MODE] == CD_PLAYER:
                tt = self.config[CD_PLAYBACK][CD_TRACK_TIME]
            else:
                tt = self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME]

        if (isinstance(tt, str) and len(tt) != 0) or (
                isinstance(tt, float) or
            (source and source == RESUME)) or isinstance(tt, int):
            state.track_time = tt

        if self.show_time_control:
            self.time_control.slider.set_position(0)

        if self.file_button and self.file_button.components[
                1] and self.file_button.components[1].content:
            state.icon_base = self.file_button.components[1].content

        if s and hasattr(s, "volume"):
            state.volume = s.volume

        if self.config[CURRENT][MODE] == CD_PLAYER and s and getattr(
                s, "source", None) == INIT:
            try:
                self.cd_album = self.util.cd_titles[self.config[CD_PLAYBACK]
                                                    [CD_DRIVE_NAME]]
                self.set_cd_album_art_image()
                state.image_base = self.file_button.components[1].content
            except:
                self.cd_album = None

        if getattr(s, "full_screen_image", None) != None:
            state.full_screen_image = s.full_screen_image

        song_name = self.get_song_name(s)
        if song_name != None:
            state.album = song_name

        self.notify_play_listeners(state)

    def get_song_name(self, state):
        """ Get song name in the format: Artist - Song name
        
        :param state: state object
        """
        album = getattr(state, "album", None)
        if album == None:
            return None

        artist = album
        if "/" in album:
            artist = album.split("/")[0].strip()

        if artist == None or len(artist) == 0:
            return None

        name = getattr(state, "l_name", None)
        file_name = getattr(state, "file_name", None)
        if name == None:
            if file_name == None:
                return None
            else:
                if file_name.startswith("cdda:"):
                    id = int(file_name.split("=")[1].strip())
                    name = self.audio_files[id - 1].name
                else:
                    name = file_name

        pos = name.find(".")
        if pos != -1:
            tokens = name.split(".")
            if tokens[0].strip().isdigit():
                name = name[pos + 1:].strip()

        if name == None or len(name) == 0:
            return None
        else:
            return artist + " - " + name

    def get_audio_files_from_playlist(self):
        """ Call player for files in the playlist 
        
        :return: list of files from playlist
        """
        playlist = self.get_current_playlist()
        files = []
        if playlist:
            for n in range(len(playlist)):
                st = State()
                st.index = st.comparator_item = n
                st.file_type = FILE_AUDIO
                st.file_name = playlist[n]
                files.append(st)

        return files

    def restore_current_folder(self, state=None):
        """ Set current folder in config object
        
        :param state: not used
        """
        self.config[FILE_PLAYBACK][CURRENT_FOLDER] = self.current_folder

    def set_audio_file_playlist(self, index):
        """ Set file in playlist
        
        :param index: file index in playlist
        """
        state = State()
        state.playback_mode = FILE_PLAYLIST
        state.playlist_track_number = index
        state.file_type = FILE_AUDIO
        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        self.notify_play_listeners(state)

    def go_back(self):
        """ Go back """
        pass

    def recursive_change_folder(self):
        start_folder = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST]
        current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        f = self.util.file_util.get_next_folder_with_audio_files(
            start_folder, current_folder)
        if f == None or (f != None and f[0] == None):
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = FILE_AUDIO
            self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] = None
            return False

        self.config[FILE_PLAYBACK][CURRENT_FOLDER] = f[0]
        self.config[FILE_PLAYBACK][CURRENT_FILE] = f[1]
        self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
        state = State()
        state.file_type = FOLDER
        state.url = f[0]
        state.long_press = True
        state.playback_mode = FILE_RECURSIVE
        self.current_track_index = 0
        state.dont_notify = True
        self.audio_files = self.get_audio_files()
        self.recursive_notifier(f[0])
        return True

    def end_of_track(self):
        """ Handle end of track """

        if not self.screen_title.active:
            return

        i = getattr(self, "current_track_index", None)
        if i == None: return
        self.stop_timer()
        mode = self.config[CURRENT][MODE]
        if mode == RADIO or mode == STREAM or not self.audio_files:
            return

        if self.show_time_control:
            self.time_control.stop_thread()

        playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE]
        if playback_mode == FILE_RECURSIVE:
            if self.current_track_index == (len(self.audio_files) - 1):
                if not self.recursive_change_folder():
                    self.stop_recursive_playback()
                    return
                else:
                    index = 0
            else:
                index = self.current_track_index + 1
        else:
            index = self.get_next_index()

        if index == None:
            self.time_control.stop_thread()
            self.time_control.reset()
            return
        else:
            self.current_track_index = index

        if mode == AUDIO_FILES:
            self.config[FILE_PLAYBACK][CURRENT_TRACK_TIME] = None
        elif mode == AUDIOBOOKS:
            self.config[AUDIOBOOKS][BROWSER_BOOK_TIME] = None

        self.change_track(index)

        if playback_mode == FILE_RECURSIVE:
            self.file_button.clean_draw_update()

    def get_next_index(self):
        """ Return next file index

        :return: file index or None
        """
        order = self.config[PLAYER_SETTINGS][PLAYBACK_ORDER]
        n = self.current_track_index
        last = len(self.audio_files) - 1

        if order == PLAYBACK_SINGLE_TRACK:
            return None

        if order == PLAYBACK_SINGLE_CYCLIC:
            return n

        if order == PLAYBACK_CYCLIC:
            if n == last:
                return 0
            else:
                return n + 1
        elif order == PLAYBACK_REGULAR:
            if n == last:
                return None
            else:
                return n + 1
        elif order == PLAYBACK_SHUFFLE:
            if len(self.audio_files) == 1:
                return n
            else:
                return random.randint(0, last)

    def set_playlist_size(self, size):
        """ Set playlist size
        
        :param size: playlist size
        """
        self.playlist_size = size
        self.stop_timer()

    def set_visible(self, flag):
        """ Set visibility flag
         
        :param flag: True - screen visible, False - screen invisible
        """
        Container.set_visible(self, flag)

        if flag:
            if self.volume_visible:
                self.volume.set_visible(True)
                if self.show_time_control:
                    self.time_control.set_visible(False)
            else:
                self.volume.set_visible(False)
                if self.show_time_control:
                    self.time_control.set_visible(True)

    def add_play_listener(self, listener):
        """ Add play listener
        
        :param listener: event listener
        """
        if listener not in self.play_listeners:
            self.play_listeners.append(listener)

    def notify_play_listeners(self, state):
        """ Notify all play listeners
        
        :param state: button state
        """
        if not self.screen_title.active:
            return

        m = getattr(state, "playback_mode", None)
        if m != None and m != FILE_PLAYLIST:
            state.icon_base = self.file_button.state.icon_base
        folder = getattr(state, "folder", None)
        if folder:
            state.cover_art_folder = self.util.file_util.get_cover_art_folder(
                state.folder)

        for listener in self.play_listeners:
            listener(state)

    def enable_player_screen(self, flag):
        """ Enable player screen
        
        :param flag: enable/disable flag
        """
        self.screen_title.active = flag
        if self.show_time_control:
            self.time_control.active = flag

    def add_screen_observers(self, update_observer, redraw_observer,
                             start_time_control, stop_time_control,
                             title_to_json):
        """ Add screen observers
        
        :param update_observer: observer for updating the screen
        :param redraw_observer: observer to redraw the whole screen
        :param start_time_control:
        :param stop_time_control:
        :param title_to_json:
        """
        self.update_observer = update_observer
        self.redraw_observer = redraw_observer
        Screen.add_screen_observers(self, update_observer, redraw_observer,
                                    title_to_json)

        self.add_button_observers(self.shutdown_button,
                                  update_observer,
                                  redraw_observer=None)
        self.shutdown_button.add_cancel_listener(redraw_observer)
        self.screen_title.add_listener(redraw_observer)

        self.add_button_observers(self.play_button,
                                  update_observer,
                                  redraw_observer=None)
        self.add_button_observers(self.home_button, update_observer,
                                  redraw_observer)

        if self.order_button:
            self.add_button_observers(self.order_button, update_observer,
                                      redraw_observer)
        if self.info_button:
            self.add_button_observers(self.info_button, update_observer,
                                      redraw_observer)

        self.add_button_observers(self.left_button,
                                  update_observer,
                                  redraw_observer=None)
        self.left_button.add_label_listener(update_observer)
        self.add_button_observers(self.right_button,
                                  update_observer,
                                  redraw_observer=None)
        self.right_button.add_label_listener(update_observer)

        self.volume.add_slide_listener(update_observer)
        self.volume.add_knob_listener(update_observer)
        self.volume.add_press_listener(update_observer)
        self.volume.add_motion_listener(update_observer)

        self.add_button_observers(self.file_button,
                                  update_observer,
                                  redraw_observer,
                                  press=False,
                                  release=False)

        if self.order_popup:
            self.order_popup.add_menu_observers(update_observer,
                                                redraw_observer)

        if self.info_popup:
            self.info_popup.add_menu_observers(update_observer,
                                               redraw_observer)

        if self.show_time_control:
            self.add_button_observers(self.time_volume_button,
                                      update_observer,
                                      redraw_observer,
                                      release=False)
            self.time_control.web_seek_listener = update_observer
            if start_time_control:
                self.time_control.add_start_timer_listener(start_time_control)
            if stop_time_control:
                self.time_control.add_stop_timer_listener(stop_time_control)
            self.time_control.slider.add_slide_listener(update_observer)
            self.time_control.slider.add_knob_listener(update_observer)
            self.time_control.slider.add_press_listener(update_observer)
            self.time_control.slider.add_motion_listener(update_observer)
Ejemplo n.º 17
0
class CdTracksScreen(Screen):
    """ File Browser Screen """
    def __init__(self, util, listeners, voice_assistant, state):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.bounding_box = util.screen_rect
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "cd_tracks_screen_title", True, self.layout.TOP)
        self.current_cd_drive_name = self.config[CD_PLAYBACK][CD_DRIVE_NAME]
        self.current_cd_drive_id = self.config[CD_PLAYBACK][CD_DRIVE_ID]
        self.filelist = self.get_filelist()

        self.file_menu = FileMenu(self.filelist,
                                  util,
                                  None,
                                  self.layout.CENTER,
                                  align=ALIGN_LEFT)

        self.go_cd_player = listeners[KEY_PLAYER]
        self.file_menu.add_play_file_listener(self.play_track)
        self.add_component(self.file_menu)

        listeners[GO_LEFT_PAGE] = self.file_menu.page_down
        listeners[GO_RIGHT_PAGE] = self.file_menu.page_up
        listeners[KEY_EJECT] = self.eject_cd
        listeners[KEY_REFRESH] = self.refresh_tracks
        connected_cd_drives = self.cdutil.get_cd_drives_number()
        self.navigator = CdTracksNavigator(util, connected_cd_drives,
                                           self.layout.BOTTOM, listeners)
        self.add_component(self.navigator)

        self.file_menu.add_left_number_listener(
            self.navigator.left_button.change_label)
        self.file_menu.add_right_number_listener(
            self.navigator.right_button.change_label)
        self.file_menu.update_buttons()
        self.page_turned = False
        self.animated_title = True

    def play_track(self, state):
        """ Set config and go to player
        
        :param state: state object with track info
        """
        self.config[CD_PLAYBACK][CD_DRIVE_ID] = self.current_cd_drive_id
        self.config[CD_PLAYBACK][CD_DRIVE_NAME] = self.current_cd_drive_name
        self.config[CD_PLAYBACK][CD_TRACK_TIME] = "0"

        if self.current_cd_drive_name != self.screen_title.text:
            state.album = self.screen_title.text

        self.go_cd_player(state)

    def get_filelist(self):
        """ Return CD tracks
        
        :return: page with CD tracks
        """
        rows = 5
        columns = 2

        layout = GridLayout(self.layout.CENTER)
        layout.set_pixel_constraints(rows, columns, 1, 1)
        constr = layout.get_next_constraints()
        fixed_height = int((constr.h * 35) / 100.0)

        tracks = self.cdutil.get_cd_tracks(rows, columns, fixed_height,
                                           self.current_cd_drive_name)
        if tracks == None:
            tracks = []
        return Page(tracks, rows, columns)

    def set_current(self, state):
        """ Set current CD drive
        
        :param state: state object with drive info
        """
        if not self.current_cd_drive_name or (
                getattr(state, "name", None)
                and self.current_cd_drive_name != state.name):
            change_menu = False
            if not self.current_cd_drive_name:
                self.current_cd_drive_name = self.cdutil.get_default_cd_drive(
                )[1]
                change_menu = True
            elif state.name != "cd":
                self.current_cd_drive_name = state.name
                change_menu = True

            name = self.current_cd_drive_name
            tracks = len(self.file_menu.filelist.items)
            empty = self.cdutil.is_drive_empty(name)
            if name and empty != 1 and tracks == 0:
                change_menu = True

            if change_menu:
                id = self.cdutil.get_cd_drive_id_by_name(
                    self.current_cd_drive_name)
                self.current_cd_drive_id = id
                self.file_menu.selected_index = 0
                self.set_file_menu()

            self.set_screen_title()

    def set_screen_title(self):
        """ Set screen title """

        title = drive_name = self.current_cd_drive_name
        try:
            title = self.util.cd_titles[drive_name]
        except:
            pass
        self.screen_title.set_text(title)

    def eject_cd(self, state):
        """ Eject CD
        
        :param state: state object with drive info
        """
        if len(str(self.current_cd_drive_id)) == 0:
            return

        del self.util.cd_track_names_cache[self.current_cd_drive_id]
        if state == None or getattr(state, "no_physical_eject", None) == None:
            self.cdutil.eject_cd(int(self.current_cd_drive_id))
        self.util.cd_titles[
            self.current_cd_drive_name] = self.current_cd_drive_name
        self.file_menu.selected_index = 0
        self.set_file_menu()
        self.set_screen_title()

    def refresh_tracks(self, state):
        """ Refresh tracks menu
        
        :param state: not used
        """
        name = self.current_cd_drive_name
        if name and self.cdutil.is_drive_empty(name):
            s = State()
            s.no_physical_eject = True
            self.eject_cd(s)

        self.set_file_menu()
        self.set_screen_title()

    def set_file_menu(self):
        """ Set file menu """

        filelist = self.get_filelist()
        self.file_menu.filelist = filelist
        self.file_menu.update_buttons()
        page = filelist.get_current_page()
        self.file_menu.set_page(filelist.current_item_index_in_page, page)

        for b in self.file_menu.buttons.values():
            b.parent_screen = self

    def get_filelist_items(self, get_current_playlist):
        """ Call player for files in the playlist 
        
        :return: list of files from playlist
        """
        playlist = get_current_playlist()
        files = []
        if playlist:
            for n in range(len(playlist)):
                st = State()
                st.index = st.comparator_item = n
                st.file_type = FILE_AUDIO
                st.file_name = st.url = playlist[n]
                files.append(st)
        return files

    def add_screen_observers(self, update_observer, redraw_observer):
        """ Add screen observers
        
        :param update_observer: observer for updating the screen
        :param redraw_observer: observer to redraw the whole screen
        """
        Screen.add_screen_observers(self, update_observer, redraw_observer)
        self.file_menu.add_menu_observers(update_observer,
                                          redraw_observer=None,
                                          release=False)
        self.file_menu.add_change_folder_listener(redraw_observer)
        self.file_menu.add_menu_navigation_listeners(redraw_observer)

        self.file_menu.add_left_number_listener(redraw_observer)
        self.file_menu.add_right_number_listener(redraw_observer)

        self.navigator.add_observers(update_observer, redraw_observer)
Ejemplo n.º 18
0
 def __init__(self, util, bgr=None, bounding_box=None, font_size=None):
     """ Initializer
     
     :param util: utility object
     :param bgr: menu background
     :param bounding_box: bounding box
     """   
     self.factory = Factory(util)
     self.config = util.config
     m = self.factory.create_home_menu_button
     Menu.__init__(self, util, bgr, bounding_box, None, None, create_item_method=m, font_size=font_size)
     cdutil = CdUtil(util)
     
     items = []
     disabled_items = []
     
     if self.config[HOME_MENU][RADIO]: 
         items.append(RADIO)
         if not util.is_radio_enabled() or not util.connected_to_internet:
             disabled_items.append(RADIO)
             
     if self.config[HOME_MENU][AUDIO_FILES]: 
         items.append(AUDIO_FILES)
         
     if self.config[HOME_MENU][AUDIOBOOKS]: 
         items.append(AUDIOBOOKS)
         if not util.is_audiobooks_enabled() or not util.connected_to_internet:
             disabled_items.append(AUDIOBOOKS)
             
     if self.config[HOME_MENU][STREAM]:
         items.append(STREAM)
         if not util.connected_to_internet:
             disabled_items.append(STREAM)
             
     if self.config[HOME_MENU][CD_PLAYER]: 
         cd_drives_info = cdutil.get_cd_drives_info()
         player = self.config[AUDIO][PLAYER_NAME]
         if len(cd_drives_info) == 0:
             disabled_items.append(CD_PLAYER)
         items.append(CD_PLAYER)
     
     l = self.get_layout(items)
     bounding_box = l.get_next_constraints()
     self.modes = util.load_menu(items, NAME, disabled_items, V_ALIGN_TOP, bb=bounding_box, scale=0.5)
     va_commands = self.util.get_voice_commands()
     
     if self.config[USAGE][USE_VOICE_ASSISTANT]:
         if self.config[HOME_MENU][RADIO]:
             r = [va_commands["VA_RADIO"].strip(), va_commands["VA_GO_RADIO"].strip()]
             self.modes[RADIO].voice_commands = r            
         if self.config[HOME_MENU][AUDIO_FILES]:
             f = [va_commands["VA_FILES"].strip(), va_commands["VA_GO_FILES"].strip(), va_commands["VA_AUDIO_FILES"].strip()]
             self.modes[AUDIO_FILES].voice_commands = f
         if self.config[HOME_MENU][AUDIOBOOKS]:    
             a = [va_commands["VA_AUDIOBOOKS"].strip(), va_commands["VA_BOOKS"].strip(), va_commands["VA_GO_BOOKS"].strip()]
             self.modes[AUDIOBOOKS].voice_commands = a
         if self.config[HOME_MENU][STREAM]:    
             s = [va_commands["VA_STREAM"].strip(), va_commands["VA_GO_STREAM"].strip()]
             self.modes[STREAM].voice_commands = s
         if self.config[HOME_MENU][CD_PLAYER]:    
             s = [va_commands["VA_CD_PLAYER"].strip()]
             self.modes[STREAM].voice_commands = s
         
     if not items:
         return
     
     if not self.config[CURRENT][MODE]:
         for i in items:
             if i not in disabled_items:            
                 mode = i
                 break            
     else:
         mode = self.config[CURRENT][MODE]
     
     self.set_items(self.modes, 0, self.change_mode, False)
     self.current_mode = self.modes[mode.lower()]
     self.item_selected(self.current_mode) 
Ejemplo n.º 19
0
    def __init__(self,
                 listeners,
                 util,
                 get_current_playlist,
                 voice_assistant,
                 player_stop=None,
                 arrow_labels=True,
                 active_file_button=True,
                 show_time_control=True,
                 show_order=True,
                 show_info=True):
        """ Initializer
        
        :param listeners: screen listeners
        :param util: utility object
        :param get_current_playlist: current playlist getter
        :param voice_assistant:   voice assistant
        :param player_stop: stop player function
        """
        self.util = util
        self.config = util.config
        self.cdutil = CdUtil(util)
        self.factory = Factory(util)
        self.image_util = util.image_util

        self.top_height = self.config[PLAYER_SCREEN][TOP_HEIGHT_PERCENT]
        self.bottom_height = self.config[PLAYER_SCREEN][BOTTOM_HEIGHT_PERCENT]
        self.button_height = self.config[PLAYER_SCREEN][BUTTON_HEIGHT_PERCENT]
        self.popup_width = self.config[PLAYER_SCREEN][POPUP_WIDTH_PERCENT]
        self.image_location = self.config[PLAYER_SCREEN][IMAGE_LOCATION]

        self.stop_player = player_stop
        self.get_current_playlist = get_current_playlist
        self.show_time_control = show_time_control

        self.bounding_box = util.screen_rect
        self.layout = self.get_layout()

        self.voice_assistant = voice_assistant
        Screen.__init__(self, util, "", self.top_height, voice_assistant,
                        "file_player_screen_title", True, self.layout.TOP)
        self.layout = self.get_layout()

        self.create_left_panel(self.layout, listeners, arrow_labels)
        self.create_right_panel(self.layout, listeners, arrow_labels)

        if not active_file_button:
            listeners[AUDIO_FILES] = None

        self.file_button = self.factory.create_file_button(
            self.layout.CENTER, listeners[AUDIO_FILES])
        self.add_component(self.file_button)

        self.audio_files = self.get_audio_files()
        self.home_button.add_release_listener(listeners[KEY_HOME])
        self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN])
        self.left_button.add_release_listener(self.go_left)
        self.right_button.add_release_listener(self.go_right)

        self.show_order = show_order
        self.show_info = show_info
        self.order_button = None
        self.info_button = None
        self.order_popup = None
        self.info_popup = None
        self.playback_order = self.config[PLAYER_SETTINGS][PLAYBACK_ORDER]
        self.bottom_center_layout = self.layout.BOTTOM

        if self.show_order or self.show_info:
            self.start_screensaver = listeners[SCREENSAVER]
            self.go_info_screen = listeners[KEY_INFO]
            self.add_popups()

        self.volume = self.factory.create_volume_control(
            self.bottom_center_layout)
        self.volume.add_slide_listener(
            self.get_listener(listeners, KEY_SET_VOLUME))
        self.volume.add_slide_listener(
            self.get_listener(listeners, KEY_SET_CONFIG_VOLUME))
        self.volume.add_slide_listener(
            self.get_listener(listeners, KEY_SET_SAVER_VOLUME))
        self.volume.add_knob_listener(self.get_listener(listeners, KEY_MUTE))
        self.volume_visible = False
        self.volume.set_visible(self.volume_visible)
        self.add_component(self.volume)

        if self.show_time_control:
            self.time_control = self.factory.create_time_control(
                self.bottom_center_layout)
            if KEY_SEEK in listeners.keys():
                self.time_control.add_seek_listener(listeners[KEY_SEEK])

            self.play_button.add_listener(PAUSE, self.time_control.pause)
            self.play_button.add_listener(KEY_PLAY, self.time_control.resume)

            if self.config[PLAYER_SETTINGS][PAUSE]:
                self.time_control.pause()
            self.add_component(self.time_control)

        self.left_button.add_release_listener(
            self.play_button.draw_default_state)
        self.right_button.add_release_listener(
            self.play_button.draw_default_state)

        self.play_listeners = []
        self.add_play_listener(self.get_listener(listeners, KEY_PLAY))

        self.current_folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER]
        self.file_button.state.cover_art_folder = self.util.file_util.get_cover_art_folder(
            self.current_folder)
        self.playlist_size = 0
        self.player_screen = True
        self.cd_album = None
        self.animated_title = True

        if self.order_popup:
            Container.add_component(self, self.order_popup)

        if self.info_popup:
            Container.add_component(self, self.info_popup)