def set_books(self, page_index, books): """ Set books :param page_index: page index :param books: books :return: books page """ self.total_pages = books[TOTAL_PAGES] left = str(self.current_page - 1) right = str(self.total_pages - self.current_page) if self.total_pages == 0: right = "0" if int(right) < 0: right = left self.navigator.left_button.change_label(left) self.navigator.right_button.change_label(right) self.set_title(self.current_page) folder_content = self.get_books_objects(books[BOOK_SUMMARIES], self.rows, self.columns, self.menu_layout) return Page(folder_content, self.rows, self.columns)
def turn_page(self, state=None): """ Turn screen page :param state: button state """ filelist = Page(self.episodes, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES) if state == None: pass filelist.current_page_index = self.current_page - 1 index = -1 else: if getattr(state, "status", None) == STATUS_LOADED: if hasattr(state, "original_url") and len(state.original_url.strip()) > 0: filelist.set_current_item_by_url(state.original_url) else: filelist.set_current_item_by_file_name(state.file_name) else: filelist.set_current_item_by_url(state.url) index = filelist.current_item_index self.current_item = self.config[PODCASTS][PODCAST_EPISODE_NAME] self.current_page = filelist.current_page_index + 1 page = filelist.get_current_page() d = self.episodes_menu.make_dict(page) self.episodes_menu.set_items(d, filelist.current_page_index, self.select_episode, False) self.set_title(self.current_page) self.episodes_menu.unselect() self.episodes_menu.select_by_index(index) for b in self.episodes_menu.buttons.values(): b.parent_screen = self self.navigator.get_button_by_name(KEY_PAGE_DOWN).change_label(str(filelist.get_left_items_number())) self.navigator.get_button_by_name(KEY_PAGE_UP).change_label(str(filelist.get_right_items_number())) self.episodes_menu.clean_draw_update() if hasattr(self, "update_observer"): self.episodes_menu.add_menu_observers(self.update_observer, self.redraw_observer) self.link_borders() menu_selected = self.menu.get_selected_index() if menu_selected == None: if self.current_item == None or len(self.current_item) == 0: self.menu.select_by_index(0) item = self.menu.get_selected_item() if item != None: self.current_item = item.state.name for b in self.menu.buttons.values(): b.parent_screen = self if self.current_item == b.state.name: self.menu.select_by_index(b.state.index) self.navigator.unselect() return
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)
def turn_page(self, state=None): """ Turn screen page :param state: button state """ filelist = Page(self.episodes, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES) if state == None: filelist.current_page_index = self.current_page - 1 index = filelist.current_page_index * PAGE_SIZE_EPISODES else: if getattr(state, "status", None) == STATUS_LOADED: if hasattr(state, "original_url") and len( state.original_url.strip()) > 0: filelist.set_current_item_by_url(state.original_url) else: filelist.set_current_item_by_file_name(state.file_name) else: filelist.set_current_item_by_url(state.url) index = filelist.current_item_index self.current_page = filelist.current_page_index + 1 page = filelist.get_current_page() d = self.episodes_menu.make_dict(page) self.episodes_menu.set_items(d, filelist.current_page_index, self.select_episode, False) self.set_title(self.current_page) self.episodes_menu.unselect() self.episodes_menu.select_by_index(index) self.navigator.left_button.change_label( str(filelist.get_left_items_number())) self.navigator.right_button.change_label( str(filelist.get_right_items_number())) self.episodes_menu.clean_draw_update() if hasattr(self, "update_observer"): self.episodes_menu.add_menu_observers(self.update_observer, self.redraw_observer)
def __init__(self, util, get_current_playlist, playlist_provider, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: file browser listeners """ self.util = util self.config = util.config 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, "file_browser_screen_title", True, layout.TOP) current_folder = self.util.file_util.current_folder d = {"current_title": current_folder} if self.config[FILE_PLAYBACK][ CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST: f = self.config[FILE_PLAYBACK][CURRENT_FOLDER] p = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] d = f + os.sep + p self.screen_title.set_text(d) rows = self.config[FILE_BROWSER_ROWS] columns = self.config[FILE_BROWSER_COLUMNS] self.filelist = None playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] if not playback_mode: self.config[FILE_PLAYBACK][ CURRENT_FILE_PLAYBACK_MODE] = playback_mode = FILE_AUDIO button_box = pygame.Rect(0, 0, layout.CENTER.w / columns, layout.CENTER.h / rows) if self.config[ALIGN_BUTTON_CONTENT_X] == 'center': location = TOP else: location = self.config[ALIGN_BUTTON_CONTENT_X] icon_box = self.factory.get_icon_bounding_box(button_box, location, self.config[IMAGE_AREA], self.config[IMAGE_SIZE], self.config[PADDING]) icon_box_without_label = self.factory.get_icon_bounding_box( button_box, location, 100, 100, self.config[PADDING], False) if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE: folder_content = self.util.load_folder_content( current_folder, rows, columns, icon_box, icon_box_without_label) self.filelist = Page(folder_content, rows, columns) elif playback_mode == FILE_PLAYLIST: s = State() s.folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER] s.music_folder = self.config[AUDIO][MUSIC_FOLDER] s.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] pl = self.get_filelist_items(get_current_playlist) if len(pl) == 0: pl = self.util.load_playlist(s, playlist_provider, rows, columns, (icon_box.w, icon_box.h)) else: pl = self.util.load_playlist_content(pl, rows, columns, (icon_box.w, icon_box.h)) self.filelist = Page(pl, rows, columns) self.file_menu = FileMenu(self.filelist, util, playlist_provider, layout.CENTER, location, icon_box, icon_box_without_label) self.file_menu.parent_screen = self self.file_menu.link_borders = self.link_borders self.file_menu.add_change_folder_listener(self.screen_title.set_text) self.file_menu.add_play_file_listener(listeners[KEY_PLAY_FILE]) listeners[GO_LEFT_PAGE] = self.file_menu.page_down listeners[GO_RIGHT_PAGE] = self.file_menu.page_up listeners[GO_USER_HOME] = self.file_menu.switch_to_user_home listeners[GO_ROOT] = self.file_menu.switch_to_root listeners[GO_TO_PARENT] = self.file_menu.switch_to_parent_folder self.navigator = FileNavigator(util, layout.BOTTOM, listeners) left = str(self.filelist.get_left_items_number()) right = str(self.filelist.get_right_items_number()) left_button = self.navigator.get_button_by_name(KEY_PAGE_DOWN) right_button = self.navigator.get_button_by_name(KEY_PAGE_UP) self.back_button = self.navigator.get_button_by_name(KEY_BACK) left_button.change_label(left) right_button.change_label(right) self.file_menu.add_left_number_listener(left_button.change_label) self.file_menu.add_right_number_listener(right_button.change_label) self.add_navigator(self.navigator) self.page_turned = False self.animated_title = True self.file_menu.navigator = self.navigator self.add_menu(self.file_menu) self.link_borders() self.back_button.set_selected(True)
class FileBrowserScreen(Screen): """ File Browser Screen """ def __init__(self, util, get_current_playlist, playlist_provider, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: file browser listeners """ self.util = util self.config = util.config 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, "file_browser_screen_title", True, layout.TOP) current_folder = self.util.file_util.current_folder d = {"current_title": current_folder} if self.config[FILE_PLAYBACK][ CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST: f = self.config[FILE_PLAYBACK][CURRENT_FOLDER] p = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] d = f + os.sep + p self.screen_title.set_text(d) rows = self.config[FILE_BROWSER_ROWS] columns = self.config[FILE_BROWSER_COLUMNS] self.filelist = None playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] if not playback_mode: self.config[FILE_PLAYBACK][ CURRENT_FILE_PLAYBACK_MODE] = playback_mode = FILE_AUDIO button_box = pygame.Rect(0, 0, layout.CENTER.w / columns, layout.CENTER.h / rows) if self.config[ALIGN_BUTTON_CONTENT_X] == 'center': location = TOP else: location = self.config[ALIGN_BUTTON_CONTENT_X] icon_box = self.factory.get_icon_bounding_box(button_box, location, self.config[IMAGE_AREA], self.config[IMAGE_SIZE], self.config[PADDING]) icon_box_without_label = self.factory.get_icon_bounding_box( button_box, location, 100, 100, self.config[PADDING], False) if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE: folder_content = self.util.load_folder_content( current_folder, rows, columns, icon_box, icon_box_without_label) self.filelist = Page(folder_content, rows, columns) elif playback_mode == FILE_PLAYLIST: s = State() s.folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER] s.music_folder = self.config[AUDIO][MUSIC_FOLDER] s.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] pl = self.get_filelist_items(get_current_playlist) if len(pl) == 0: pl = self.util.load_playlist(s, playlist_provider, rows, columns, (icon_box.w, icon_box.h)) else: pl = self.util.load_playlist_content(pl, rows, columns, (icon_box.w, icon_box.h)) self.filelist = Page(pl, rows, columns) self.file_menu = FileMenu(self.filelist, util, playlist_provider, layout.CENTER, location, icon_box, icon_box_without_label) self.file_menu.parent_screen = self self.file_menu.link_borders = self.link_borders self.file_menu.add_change_folder_listener(self.screen_title.set_text) self.file_menu.add_play_file_listener(listeners[KEY_PLAY_FILE]) listeners[GO_LEFT_PAGE] = self.file_menu.page_down listeners[GO_RIGHT_PAGE] = self.file_menu.page_up listeners[GO_USER_HOME] = self.file_menu.switch_to_user_home listeners[GO_ROOT] = self.file_menu.switch_to_root listeners[GO_TO_PARENT] = self.file_menu.switch_to_parent_folder self.navigator = FileNavigator(util, layout.BOTTOM, listeners) left = str(self.filelist.get_left_items_number()) right = str(self.filelist.get_right_items_number()) left_button = self.navigator.get_button_by_name(KEY_PAGE_DOWN) right_button = self.navigator.get_button_by_name(KEY_PAGE_UP) self.back_button = self.navigator.get_button_by_name(KEY_BACK) left_button.change_label(left) right_button.change_label(right) self.file_menu.add_left_number_listener(left_button.change_label) self.file_menu.add_right_number_listener(right_button.change_label) self.add_navigator(self.navigator) self.page_turned = False self.animated_title = True self.file_menu.navigator = self.navigator self.add_menu(self.file_menu) self.link_borders() self.back_button.set_selected(True) 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, 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) def handle_event(self, event): """ Handle screen event :param event: the event to handle """ if event.type == USER_EVENT_TYPE and event.sub_type == SUB_TYPE_KEYBOARD and ( event.action == pygame.KEYUP or event.action == pygame.KEYDOWN): menu_selected = self.file_menu.get_selected_index() navigator_selected = self.navigator.is_selected() if menu_selected != None: self.file_menu.handle_event(event) elif navigator_selected: self.navigator.handle_event(event) else: Screen.handle_event(self, event)
def __init__(self, util, get_current_playlist, playlist_provider, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: file browser listeners """ self.util = util self.config = util.config 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, "file_browser_screen_title", True, layout.TOP) color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT] current_folder = self.util.file_util.current_folder d = {"current_title" : current_folder} if self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST: f = self.config[FILE_PLAYBACK][CURRENT_FOLDER] p = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] d = f + os.sep + p self.screen_title.set_text(d) rows = 3 columns = 3 self.filelist = None playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] if not playback_mode: self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = playback_mode = FILE_AUDIO if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE: folder_content = self.util.load_folder_content(current_folder, rows, columns, layout.CENTER) self.filelist = Page(folder_content, rows, columns) elif playback_mode == FILE_PLAYLIST: s = State() s.folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER] s.music_folder = self.config[AUDIO][MUSIC_FOLDER] s.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] pl = self.get_filelist_items(get_current_playlist) if len(pl) == 0: pl = self.util.load_playlist(s, playlist_provider, rows, columns) else: pl = self.util.load_playlist_content(pl, rows, columns) self.filelist = Page(pl, rows, columns) self.file_menu = FileMenu(self.filelist, util, playlist_provider, (0, 0, 0), layout.CENTER) Container.add_component(self, self.file_menu) self.file_menu.add_change_folder_listener(self.screen_title.set_text) self.file_menu.add_play_file_listener(listeners[KEY_PLAY_FILE]) listeners[GO_LEFT_PAGE] = self.file_menu.page_down listeners[GO_RIGHT_PAGE] = self.file_menu.page_up listeners[GO_USER_HOME] = self.file_menu.switch_to_user_home listeners[GO_ROOT] = self.file_menu.switch_to_root listeners[GO_TO_PARENT] = self.file_menu.switch_to_parent_folder self.navigator = Navigator(util, layout.BOTTOM, listeners, color_dark_light) left = str(self.filelist.get_left_items_number()) right = str(self.filelist.get_right_items_number()) self.navigator.left_button.change_label(left) self.navigator.right_button.change_label(right) 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) Container.add_component(self, self.navigator) self.page_turned = False
class FileBrowserScreen(Screen): """ File Browser Screen """ def __init__(self, util, get_current_playlist, playlist_provider, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: file browser listeners """ self.util = util self.config = util.config 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, "file_browser_screen_title", True, layout.TOP) color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT] current_folder = self.util.file_util.current_folder d = {"current_title" : current_folder} if self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] == FILE_PLAYLIST: f = self.config[FILE_PLAYBACK][CURRENT_FOLDER] p = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] d = f + os.sep + p self.screen_title.set_text(d) rows = 3 columns = 3 self.filelist = None playback_mode = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] if not playback_mode: self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYBACK_MODE] = playback_mode = FILE_AUDIO if playback_mode == FILE_AUDIO or playback_mode == FILE_RECURSIVE: folder_content = self.util.load_folder_content(current_folder, rows, columns, layout.CENTER) self.filelist = Page(folder_content, rows, columns) elif playback_mode == FILE_PLAYLIST: s = State() s.folder = self.config[FILE_PLAYBACK][CURRENT_FOLDER] s.music_folder = self.config[AUDIO][MUSIC_FOLDER] s.file_name = self.config[FILE_PLAYBACK][CURRENT_FILE_PLAYLIST] pl = self.get_filelist_items(get_current_playlist) if len(pl) == 0: pl = self.util.load_playlist(s, playlist_provider, rows, columns) else: pl = self.util.load_playlist_content(pl, rows, columns) self.filelist = Page(pl, rows, columns) self.file_menu = FileMenu(self.filelist, util, playlist_provider, (0, 0, 0), layout.CENTER) Container.add_component(self, self.file_menu) self.file_menu.add_change_folder_listener(self.screen_title.set_text) self.file_menu.add_play_file_listener(listeners[KEY_PLAY_FILE]) listeners[GO_LEFT_PAGE] = self.file_menu.page_down listeners[GO_RIGHT_PAGE] = self.file_menu.page_up listeners[GO_USER_HOME] = self.file_menu.switch_to_user_home listeners[GO_ROOT] = self.file_menu.switch_to_root listeners[GO_TO_PARENT] = self.file_menu.switch_to_parent_folder self.navigator = Navigator(util, layout.BOTTOM, listeners, color_dark_light) left = str(self.filelist.get_left_items_number()) right = str(self.filelist.get_right_items_number()) self.navigator.left_button.change_label(left) self.navigator.right_button.change_label(right) 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) Container.add_component(self, self.navigator) self.page_turned = False 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)
def __init__(self, listeners, util, voice_assistant, screen_mode=STATION): """ Initializer :param util: utility object :param listener: screen menu event listener """ self.util = util self.config = util.config self.factory = Factory(util) self.screen_mode = screen_mode self.bounding_box = util.screen_rect self.favorites_util = FavoritesUtil(self.util) 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 layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, panel_width, panel_width) Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant, "station_screen_title", True, layout.TOP) tmp = Menu(util, (0, 0, 0), self.bounding_box, None, None) folders = self.util.get_stations_folders() if folders: panel_layout = BorderLayout(layout.RIGHT) panel_layout.set_percent_constraints(PERCENT_SIDE_BOTTOM_HEIGHT, PERCENT_SIDE_BOTTOM_HEIGHT, 0, 0) self.genres = util.load_stations_folders(panel_layout.BOTTOM) self.genres[ KEY_FAVORITES] = self.favorites_util.get_favorites_button_state( panel_layout.BOTTOM) current_genre_name = list(self.genres.keys())[0] self.current_genre = self.genres[current_genre_name] self.items_per_line = self.items_per_line(layout.CENTER.w) items = [] if self.screen_mode == STATION: k = STATIONS + "." + self.config[CURRENT][LANGUAGE] try: self.config[k] self.current_genre = self.genres[self.config[k] [CURRENT_STATIONS]] except: self.config[k] = {} self.config[k][CURRENT_STATIONS] = self.current_genre.name items = self.load_stations( self.config[CURRENT][LANGUAGE], self.current_genre.name, self.items_per_line * self.items_per_line) elif self.screen_mode == STREAM: items = util.load_streams(self.items_per_line * self.items_per_line) self.playlist = Page(items, self.items_per_line, self.items_per_line) self.station_menu = StationMenu(self.playlist, util, screen_mode, (0, 0, 0), layout.CENTER) if self.station_menu.is_button_defined(): d = {"current_title": self.station_menu.button.state.l_name} self.screen_title.set_text(d) Container.add_component(self, self.station_menu) self.stop_player = listeners[KEY_STOP] self.create_left_panel(layout, listeners) self.create_right_panel(layout, listeners) self.home_button.add_release_listener(listeners[KEY_HOME]) if self.screen_mode == STATION: self.genres_button.add_release_listener(listeners[KEY_GENRES]) self.shutdown_button.add_release_listener( self.favorites_util.save_favorites) self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN]) self.left_button.add_release_listener( self.station_menu.switch_to_previous_station) self.left_button.add_release_listener(self.update_arrow_button_labels) self.page_down_button.add_release_listener( self.station_menu.switch_to_previous_page) self.page_down_button.add_release_listener( self.update_arrow_button_labels) self.right_button.add_release_listener( self.station_menu.switch_to_next_station) self.right_button.add_release_listener(self.update_arrow_button_labels) self.page_up_button.add_release_listener( self.station_menu.switch_to_next_page) self.page_up_button.add_release_listener( self.update_arrow_button_labels) self.station_menu.add_listener(listeners[KEY_PLAY]) self.station_menu.add_listener(self.screen_title.set_state) self.station_menu.add_listener(self.update_arrow_button_labels) self.station_menu.add_mode_listener(self.mode_listener) self.volume = self.factory.create_volume_control(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]) Container.add_component(self, self.volume) self.player_screen = True if self.current_genre.name == KEY_FAVORITES: self.favorites_mode = True else: self.favorites_mode = False self.favorites_util.set_favorites_in_config(self.items_per_line)
def set_current(self, state=None): """ Set current station by index defined in current playlist :param state: button state (if any) """ items = [] current_language = self.config[CURRENT][LANGUAGE] selected_genre = None self.favorites_mode = False if self.screen_mode == STATION: key = STATIONS + "." + current_language s1 = state != None and getattr(state, "source", None) == KEY_FAVORITES s2 = state == None and self.config[key][ CURRENT_STATIONS] == KEY_FAVORITES if s1 or s2: self.favorites_mode = True self.config[key][CURRENT_STATIONS] = KEY_FAVORITES try: k = self.config[key][CURRENT_STATIONS] selected_genre = self.genres[k] self.store_previous_station(current_language) except: self.config[key] = {} selected_genre = self.current_genre genre = selected_genre.name size = self.items_per_line * self.items_per_line items = self.load_stations(current_language, genre, size) elif self.screen_mode == STREAM: items = self.util.load_streams(self.items_per_line * self.items_per_line) self.playlist = Page(items, self.items_per_line, self.items_per_line) if self.playlist.length == 0: return self.station_menu.set_playlist(self.playlist) if self.screen_mode == STATION: self.station_menu.genre = selected_genre.name previous_station_index = 0 try: previous_station_index = self.config[ STATIONS + "." + current_language][selected_genre.name] except KeyError: pass self.station_menu.set_station(previous_station_index) self.station_menu.set_station_mode(None) self.set_genre_button_image(selected_genre) if self.favorites_mode: self.current_genre = self.favorites_util.get_favorites_button_state( self.genres_button.state.bounding_box) else: self.current_genre = selected_genre elif self.screen_mode == STREAM: previous_station_index = 0 try: previous_station_index = self.config[CURRENT][STREAM] except KeyError: pass self.station_menu.set_station(previous_station_index) self.station_menu.set_station_mode(None) self.config[CURRENT][STREAM] = previous_station_index n = self.station_menu.get_current_station_name() self.screen_title.set_text(n) config_volume_level = int(self.config[PLAYER_SETTINGS][VOLUME]) if self.volume.get_position() != config_volume_level: self.volume.set_position(config_volume_level) self.volume.update_position()
def __init__(self, listeners, util, voice_assistant, screen_mode=STATION): """ Initializer :param util: utility object :param listener: screen menu event listener """ self.util = util self.config = util.config self.factory = Factory(util) self.screen_mode = screen_mode self.bounding_box = util.screen_rect self.favorites_util = FavoritesUtil(self.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.layout = self.get_layout() Screen.__init__(self, util, "", self.top_height, voice_assistant, "station_screen_title", True, self.layout.TOP) self.layout = self.get_layout() folders = self.util.get_stations_folders() if folders: panel_layout = self.get_panel_layout(self.layout, LOCATION_RIGHT) panel_layout.set_percent_constraints(self.button_height, self.button_height, 0, 0) self.genres = util.load_stations_folders(panel_layout.BOTTOM) self.genres[ KEY_FAVORITES] = self.favorites_util.get_favorites_button_state( panel_layout.BOTTOM) current_genre_name = list(self.genres.keys())[0] self.current_genre = self.genres[current_genre_name] self.items_per_line = self.items_per_line(self.layout.CENTER.w) items = [] if self.screen_mode == STATION: k = STATIONS + "." + self.config[CURRENT][LANGUAGE] try: self.config[k] self.current_genre = self.genres[self.config[k] [CURRENT_STATIONS]] except: self.config[k] = {} self.config[k][CURRENT_STATIONS] = self.current_genre.name items = self.load_stations( self.config[CURRENT][LANGUAGE], self.current_genre.name, self.items_per_line * self.items_per_line) elif self.screen_mode == STREAM: items = util.load_streams(self.items_per_line * self.items_per_line) self.playlist = Page(items, self.items_per_line, self.items_per_line) self.station_menu = StationMenu( self.playlist, util, screen_mode, self.config[BACKGROUND][SCREEN_BGR_COLOR], self.layout.CENTER) if self.station_menu.is_button_defined(): d = {"current_title": self.station_menu.button.state.l_name} self.screen_title.set_text(d) Container.add_component(self, self.station_menu) self.stop_player = listeners[KEY_STOP] self.create_left_panel(self.layout, listeners) self.create_right_panel(self.layout, listeners) self.home_button.add_release_listener(listeners[KEY_HOME]) if self.screen_mode == STATION: self.genres_button.add_release_listener(listeners[KEY_GENRES]) self.shutdown_button.add_release_listener( self.favorites_util.save_favorites) self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN]) self.left_button.add_release_listener( self.station_menu.switch_to_previous_station) self.left_button.add_release_listener(self.update_arrow_button_labels) self.page_down_button.add_release_listener( self.station_menu.switch_to_previous_page) self.page_down_button.add_release_listener( self.update_arrow_button_labels) self.right_button.add_release_listener( self.station_menu.switch_to_next_station) self.right_button.add_release_listener(self.update_arrow_button_labels) self.page_up_button.add_release_listener( self.station_menu.switch_to_next_page) self.page_up_button.add_release_listener( self.update_arrow_button_labels) self.station_menu.add_listener(listeners[KEY_PLAY]) self.station_menu.add_listener(self.screen_title.set_state) self.station_menu.add_listener(self.update_arrow_button_labels) self.station_menu.add_mode_listener(self.mode_listener) self.info_button = None self.info_popup = None self.start_screensaver = listeners[SCREENSAVER] bottom_layout = BorderLayout(self.layout.BOTTOM) bottom_layout.set_percent_constraints(0, 0, 0, self.popup_width) volume_layout = bottom_layout.CENTER volume_layout.w -= 2 volume_layout.x += 1 self.volume = self.factory.create_volume_control(volume_layout) 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.add_component(self.volume) self.player_screen = True self.add_popup(bottom_layout.RIGHT) if self.current_genre.name == KEY_FAVORITES: self.favorites_mode = True else: self.favorites_mode = False self.favorites_util.set_favorites_in_config(self.items_per_line) self.animated_title = True
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)