def __init__(self, listeners, util): """ Initializer :param util: utility object :param listener: screen menu event listener """ self.util = util self.config = util.config Container.__init__(self, util, background=(0, 0, 0)) self.factory = Factory(util) self.bounding_box = self.config[SCREEN_RECT] 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) self.genres = util.load_menu(GENRE_ITEMS, GENRE) self.current_genre = self.genres[self.config[CURRENT][PLAYLIST]] self.items_per_line = self.items_per_line(layout.CENTER.w) self.playlist = Playlist(self.config[CURRENT][LANGUAGE], self.current_genre.genre, util, self.items_per_line) font_size = (layout.TOP.h * PERCENT_TITLE_FONT)/100.0 color_dark = self.config[COLORS][COLOR_DARK] color_contrast = self.config[COLORS][COLOR_CONTRAST] self.screen_title = self.factory.create_dynamic_text("station_screen_title", layout.TOP, color_dark, color_contrast, int(font_size)) Container.add_component(self, self.screen_title) self.station_menu = StationMenu(self.playlist, util, (0, 0, 0), layout.CENTER) self.screen_title.set_text(self.station_menu.button.state.l_name) Container.add_component(self, self.station_menu) self.create_left_panel(layout, listeners) self.create_right_panel(layout, listeners) self.home_button.add_release_listener(listeners["go home"]) self.genres_button.add_release_listener(listeners["go genres"]) self.shutdown_button.add_release_listener(listeners["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["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["set volume"]) self.volume.add_slide_listener(listeners["set config volume"]) self.volume.add_slide_listener(listeners["set screensaver volume"]) self.volume.add_knob_listener(listeners["mute"]) Container.add_component(self, self.volume)
class Screen(Container): """ Base class for all screens. Extends Container class """ def __init__(self, util, title_key): """ Initializer :param util: utility object :param title_key: the resource bundle key for the screen title """ Container.__init__(self, util) self.util = util factory = Factory(util) config = util.config self.bounding_box = config[SCREEN_RECT] self.bgr = (0, 0, 0) self.layout = BorderLayout(config[SCREEN_RECT]) self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, 0, 0, 0) font_size = (self.layout.TOP.h * PERCENT_TITLE_FONT)/100.0 d = config[COLORS][COLOR_DARK] c = config[COLORS][COLOR_CONTRAST] self.screen_title = factory.create_output_text("screen_title", self.layout.TOP, d, c, int(font_size)) label = config[LABELS][title_key] self.screen_title.set_text(label) self.add_component(self.screen_title) def add_menu(self, menu): """ Add menu to the screen :param menu: the menu to add """ self.menu = menu self.add_component(menu) def get_clickable_rect(self): """ Return the list of rectangles which define the clickable areas on screen. Used for web browser. :return: list of rectangles """ c = Component(self.util) c.name = "clickable_rect" c.content = self.menu.bounding_box c.bgr = c.fgr = (0, 0, 0) c.content_x = c.content_y = 0 d = [c] return d
def create_left_panel(self, layout, listeners): """ Create Station Screen left panel. Include Shutdown button, Left button and Home button. :param layout: left panel layout :param listeners: event listeners """ panel_layout = BorderLayout(layout.LEFT) panel_layout.set_percent_constraints(PERCENT_SIDE_BOTTOM_HEIGHT, PERCENT_SIDE_BOTTOM_HEIGHT, 0, 0) left = self.station_menu.button.state.index self.left_button = self.factory.create_left_button(panel_layout.CENTER, str(left)) self.page_down_button = self.factory.create_page_down_button(panel_layout.CENTER, str(left)) self.page_down_button.set_visible(False) self.shutdown_button = self.factory.create_shutdown_button(panel_layout.TOP) self.home_button = self.factory.create_home_button(panel_layout.BOTTOM) panel = Container(self.util, layout.LEFT) panel.add_component(self.shutdown_button) panel.add_component(self.left_button) panel.add_component(self.page_down_button) panel.add_component(self.home_button) Container.add_component(self, panel)
def create_right_panel(self, layout, listeners): """ Create Station Screen right panel. Include Genre button, right button and Play/Pause button :param layout: right panel layout :param listeners: event listeners """ panel_layout = BorderLayout(layout.RIGHT) panel_layout.set_percent_constraints(PERCENT_SIDE_BOTTOM_HEIGHT, PERCENT_SIDE_BOTTOM_HEIGHT, 0, 0) self.genres_button = self.factory.create_genre_button(panel_layout.TOP, self.current_genre) right = self.playlist.length - self.station_menu.button.state.index - 1 self.right_button = self.factory.create_right_button(panel_layout.CENTER, str(right)) self.page_up_button = self.factory.create_page_up_button(panel_layout.CENTER, str(right)) self.page_up_button.set_visible(False) self.play_button = self.factory.create_play_pause_button(panel_layout.BOTTOM, listeners["play-pause"]) panel = Container(self.util, layout.RIGHT) panel.add_component(self.genres_button) panel.add_component(self.right_button) panel.add_component(self.page_up_button) panel.add_component(self.play_button) Container.add_component(self, panel)
def __init__(self, util, title_key): """ Initializer :param util: utility object :param title_key: the resource bundle key for the screen title """ Container.__init__(self, util) self.util = util factory = Factory(util) config = util.config self.bounding_box = config[SCREEN_RECT] self.bgr = (0, 0, 0) self.layout = BorderLayout(config[SCREEN_RECT]) self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, 0, 0, 0) font_size = (self.layout.TOP.h * PERCENT_TITLE_FONT)/100.0 d = config[COLORS][COLOR_DARK] c = config[COLORS][COLOR_CONTRAST] self.screen_title = factory.create_output_text("screen_title", self.layout.TOP, d, c, int(font_size)) label = config[LABELS][title_key] self.screen_title.set_text(label) self.add_component(self.screen_title)
class Screen(Container): """ Base class for all screens. Extends Container class """ def __init__(self, util, title_key, percent_bottom_height=0, voice_assistant=None, screen_title_name="screen_title", create_dynamic_title=False, title_layout=None, title=None): """ Initializer :param util: utility object :param title_key: the resource bundle key for the screen title """ Container.__init__(self, util) self.util = util factory = Factory(util) self.config = util.config self.bounding_box = util.screen_rect self.bgr = (0, 0, 0) self.layout = BorderLayout(util.screen_rect) self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, percent_bottom_height, 0, 0) self.voice_assistant = voice_assistant self.font_size = int((self.layout.TOP.h * PERCENT_TITLE_FONT) / 100.0) d = self.config[COLORS][COLOR_DARK_LIGHT] c = self.config[COLORS][COLOR_CONTRAST] t_layout = self.layout.TOP if title_layout: t_layout = title_layout if create_dynamic_title: self.screen_title = factory.create_dynamic_text( screen_title_name, t_layout, d, c, self.font_size) else: self.screen_title = factory.create_output_text( screen_title_name, t_layout, d, c, self.font_size) if title: self.screen_title.set_text(title) else: if title_key and len(title_key) > 0: try: label = self.config[LABELS][title_key] self.screen_title.set_text(label) except: pass if voice_assistant: self.screen_title.add_select_listener(self.handle_voice_assistant) self.layout.TOP.w += 1 self.voice_command = factory.create_output_text( "voice_command", self.layout.TOP, d, c, self.font_size) self.voice_command.add_select_listener(self.handle_voice_assistant) self.voice_assistant.add_text_recognized_listener( self.text_recognized) self.voice_assistant.assistant.add_start_conversation_listener( self.start_conversation) self.voice_assistant.assistant.add_stop_conversation_listener( self.stop_conversation) if voice_assistant and voice_assistant.is_running(): self.title_selected = False else: self.title_selected = True self.draw_title_bar() self.player_screen = False self.update_web_observer = None self.update_web_title = None self.loading_listeners = [] self.LOADING = util.config[LABELS][KEY_LOADING] self.factory = factory def draw_title_bar(self): """ Draw title bar on top of the screen """ if len(self.components) != 0 and self.title_selected: self.components[0] = self.voice_command self.title_selected = False elif len(self.components) != 0 and not self.title_selected: self.components[0] = self.screen_title self.title_selected = True elif len(self.components) == 0 and self.title_selected: self.components.append(self.screen_title) elif len(self.components) == 0 and not self.title_selected: self.voice_command.set_text( self.config[LABELS][KEY_WAITING_FOR_COMMAND]) self.components.append(self.voice_command) def handle_voice_assistant(self, state=None): """ Start/Stop voice assistant :state: not used """ if self.title_selected: self.voice_assistant.start() else: self.voice_assistant.stop() def text_recognized(self, text): """ Handle text recognized event :text: recognized text """ c = self.config[LABELS][KEY_VA_COMMAND] + " " + text self.voice_command.set_text(c) self.voice_command.clean_draw_update() time.sleep(self.config[VOICE_ASSISTANT][VOICE_COMMAND_DISPLAY_TIME]) if self.update_web_title: self.update_web_title(self.voice_command) def start_conversation(self, event): """ Start voice conversation :event: not used """ if self.visible: self.voice_command.set_visible(True) self.voice_command.set_text_no_draw( self.config[LABELS][KEY_WAITING_FOR_COMMAND]) self.components[0] = self.voice_command self.title_selected = False if self.visible: self.voice_command.clean_draw_update() if self.update_web_observer: self.update_web_observer() def stop_conversation(self): """ Stop voice conversation """ if self.visible: self.screen_title.set_visible(True) self.components[0] = self.screen_title self.title_selected = True if self.visible: self.screen_title.clean_draw_update() if self.update_web_observer: self.update_web_observer() def add_menu(self, menu): """ Add menu to the screen :param menu: the menu to add """ self.menu = menu self.add_component(menu) def enable_player_screen(self, flag): """ Enable player screen :param flag: enable/disable flag """ pass def exit_screen(self): """ Complete actions required to save screen state """ self.set_visible(False) def add_screen_observers(self, update_observer, redraw_observer, title_to_json=None): """ Add screen observers. :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ self.update_web_observer = redraw_observer self.update_web_title = title_to_json def set_loading(self, name=None, menu_bb=None, text=None): """ Show Loading... sign :param name: screen title :param menu_bb: menu bounding box :param text: screen text """ b = self.config[COLORS][COLOR_DARK] f = self.config[COLORS][COLOR_BRIGHT] fs = int(self.bounding_box.h * 0.07) if menu_bb != None: bb = menu_bb else: bb = self.bounding_box t = self.factory.create_output_text(self.LOADING, bb, b, f, fs) if not text: t.set_text(self.LOADING) else: t.set_text(text) if name != None: self.screen_title.set_text(name) self.set_visible(True) self.add_component(t) self.clean_draw_update() self.notify_loading_listeners() def reset_loading(self): """ Remove Loading label """ del self.components[-1] self.notify_loading_listeners() def add_loading_listener(self, listener): """ Add loading listener :param listener: event listener """ if listener not in self.loading_listeners: self.loading_listeners.append(listener) def notify_loading_listeners(self): """ Notify all loading listeners """ for listener in self.loading_listeners: listener(None)
def __init__(self, state): """ Initializer. Define bounding boxes for button label (if any) and icon (if any) :param state: button state """ s = state bb = s.bounding_box self.show_image = getattr(s, "show_img", None) self.show_label = getattr(s, "show_label", False) self.image_location = getattr(s, "image_location", CENTER) self.label_location = getattr(s, "label_location", BOTTOM) self.image_area_percent = getattr(s, "image_area_percent", 0) self.label_area_percent = getattr(s, "label_area_percent", 0) self.layout = BorderLayout(bb) top = bottom = left = right = 0 self.image_rectangle = self.label_rectangle = None if self.show_image and self.show_label: if self.image_location == TOP and self.label_location == CENTER: top = self.image_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.TOP self.label_rectangle = self.layout.CENTER elif self.image_location == BOTTOM and self.label_location == CENTER: bottom = self.image_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.BOTTOM self.label_rectangle = self.layout.CENTER elif self.image_location == CENTER and self.label_location == TOP: top = self.label_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.CENTER self.label_rectangle = self.layout.TOP elif self.image_location == CENTER and self.label_location == BOTTOM: bottom = self.label_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.CENTER self.label_rectangle = self.layout.BOTTOM elif self.image_location == LEFT and self.label_location == CENTER: left = self.image_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.LEFT self.label_rectangle = self.layout.CENTER elif self.image_location == RIGHT and self.label_location == CENTER: right = self.image_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.RIGHT self.label_rectangle = self.layout.CENTER elif self.image_location == CENTER and self.label_location == LEFT: left = self.label_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.CENTER self.label_rectangle = self.layout.LEFT elif self.image_location == CENTER and self.label_location == RIGHT: right = self.label_area_percent self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.CENTER self.label_rectangle = self.layout.RIGHT elif self.show_image and not self.show_label: self.layout.set_percent_constraints(top, bottom, left, right) self.image_rectangle = self.layout.CENTER elif not self.show_image and self.show_label: self.layout.set_percent_constraints(top, bottom, left, right) self.label_rectangle = self.layout.CENTER
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 """ 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 = self.config[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. :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 """ self.cd_album = getattr(state, "album", None) if self.config[CURRENT][MODE] == AUDIO_FILES: 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]) 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 self.notify_play_listeners(state) 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 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)
class CollectionListNavigator(Container): """ Collection List navigator menu """ def __init__(self, util, bounding_box, listeners, collection_mode=GENRE): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners """ Container.__init__(self, util) self.factory = Factory(util) self.name = "collectionlist.navigator" self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.listeners = listeners self.menu_buttons = [] self.config = util.config self.use_web = self.config[USAGE][USE_WEB] self.go_keyboard = listeners[KEY_KEYBOARD_KEY] self.keyboard_callback = listeners[KEY_CALLBACK] self.go_abc = listeners[KEY_ABC] self.bgr = util.config[COLORS][COLOR_DARK_LIGHT] self.arrow_layout = BorderLayout(bounding_box) self.arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) self.collection_mode = collection_mode self.update_observer = None self.redraw_observer = None self.set_buttons(collection_mode) def set_buttons(self, collection_mode): """ Set navigator buttons :param collection_mode: mode """ if self.menu_buttons and collection_mode in TEXT_MODES and self.collection_mode in TEXT_MODES: self.collection_mode = collection_mode return self.collection_mode = collection_mode self.components = [] self.menu_buttons = [] constr = self.arrow_layout.LEFT self.left_button = self.factory.create_page_down_button(constr, "0", 40, 100) self.left_button.add_release_listener(self.listeners[GO_LEFT_PAGE]) self.add_component(self.left_button) self.menu_buttons.append(self.left_button) constr = self.arrow_layout.RIGHT self.right_button = self.factory.create_page_up_button(constr, "0", 40, 100) self.right_button.add_release_listener(self.listeners[GO_RIGHT_PAGE]) self.add_component(self.right_button) self.menu_buttons.append(self.right_button) if collection_mode in TEXT_MODES: n = 6 elif collection_mode == TYPE: n = 4 else: n = 5 layout = GridLayout(self.arrow_layout.CENTER) layout.set_pixel_constraints(1, n, 1, 0) layout.current_constraints = 0 self.add_button(KEY_HOME, KEY_HOME, layout, self.listeners[KEY_HOME]) self.add_button(KEY_BACK, KEY_BACK, layout, self.listeners[KEY_BACK]) self.add_button(COLLECTION, KEY_BACK, layout, self.listeners[COLLECTION]) if n == 6: self.add_button(IMAGE_ABC, KEY_HOME, layout, self.pre_abc) if n != 4: self.add_button(IMAGE_BOOK_GENRE, KEY_HOME, layout, self.pre_keyboard) self.add_button(KEY_PLAYER, KEY_PLAY_PAUSE, layout, self.listeners[KEY_PLAYER]) if self.use_web and self.update_observer != None: self.add_observers(self.update_observer, self.redraw_observer) def add_button(self, img_name, key, layout, listener): """ Add button :param img_name: button image name :param key: keyboard key :param layout: button layout :param listener: button listener """ c = layout.get_next_constraints() b = self.factory.create_button(img_name, key, c, listener, self.bgr, image_size_percent=IMAGE_SIZE_PERCENT) self.add_component(b) self.menu_buttons.append(b) def pre_abc(self, state=None): """ Called before openning ABC screen :param state: button state """ state.title = self.config[LABELS][self.collection_mode] state.visibility = False state.callback = self.keyboard_callback self.go_abc(state) def pre_keyboard(self, state=None): """ Called before openning keyboard screen :param state: button state """ state.title = self.config[LABELS][self.collection_mode] state.visibility = False state.callback = self.keyboard_callback self.go_keyboard(state) def add_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 """ if self.update_observer == None: self.update_observer = update_observer self.redraw_observer = redraw_observer for b in self.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
def __init__(self, util, bounding_box, listeners, bgr): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners :param bgr: menu background """ Container.__init__(self, util) self.factory = Factory(util) self.name = "navigator" self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.menu_buttons = [] arrow_layout = BorderLayout(bounding_box) arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) constr = arrow_layout.LEFT self.left_button = self.factory.create_page_down_button(constr, "0", 40, 100) self.left_button.add_release_listener(listeners[GO_LEFT_PAGE]) self.add_component(self.left_button) self.menu_buttons.append(self.left_button) constr = arrow_layout.RIGHT self.right_button = self.factory.create_page_up_button(constr, "0", 40, 100) self.right_button.add_release_listener(listeners[GO_RIGHT_PAGE]) self.add_component(self.right_button) self.menu_buttons.append(self.right_button) layout = GridLayout(arrow_layout.CENTER) layout.set_pixel_constraints(1, 5, 1, 0) layout.current_constraints = 0 image_size = 64 constr = layout.get_next_constraints() self.home_button = self.factory.create_button(KEY_HOME, KEY_HOME, constr, listeners[KEY_HOME], bgr, image_size_percent=image_size) self.add_component(self.home_button) self.menu_buttons.append(self.home_button) constr = layout.get_next_constraints() self.user_home_button = self.factory.create_button(KEY_USER_HOME, KEY_MENU, constr, listeners[GO_USER_HOME], bgr, image_size_percent=image_size) self.add_component(self.user_home_button) self.menu_buttons.append(self.user_home_button) constr = layout.get_next_constraints() self.root_button = self.factory.create_button(KEY_ROOT, KEY_ROOT, constr, listeners[GO_ROOT], bgr, image_size_percent=image_size) self.add_component(self.root_button) self.menu_buttons.append(self.root_button) constr = layout.get_next_constraints() self.parent_button = self.factory.create_button(KEY_PARENT, KEY_PARENT, constr, listeners[GO_TO_PARENT], bgr, image_size_percent=image_size) self.add_component(self.parent_button) self.menu_buttons.append(self.parent_button) constr = layout.get_next_constraints() self.back_button = self.factory.create_button(KEY_BACK, KEY_BACK, constr, None, bgr, image_size_percent=image_size) self.back_button.add_release_listener(listeners[GO_BACK]) self.back_button.add_release_listener(listeners[KEY_PLAY_FILE]) self.add_component(self.back_button) self.menu_buttons.append(self.back_button)
def __init__(self, util, bounding_box, listeners, bgr, pages): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners :param bgr: menu background """ Container.__init__(self, util) self.factory = Factory(util) self.name = "navigator" self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.menu_buttons = [] arrow_layout = BorderLayout(bounding_box) arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) if pages > 1: constr = arrow_layout.LEFT self.left_button = self.factory.create_page_down_button( constr, "0", 40, 100) self.left_button.add_release_listener(listeners[GO_LEFT_PAGE]) self.add_component(self.left_button) self.menu_buttons.append(self.left_button) constr = arrow_layout.RIGHT self.right_button = self.factory.create_page_up_button( constr, "0", 40, 100) self.right_button.add_release_listener(listeners[GO_RIGHT_PAGE]) self.add_component(self.right_button) self.menu_buttons.append(self.right_button) if pages > 1: layout = GridLayout(arrow_layout.CENTER) else: layout = GridLayout(bounding_box) layout.set_pixel_constraints(1, 3, 1, 0) layout.current_constraints = 0 image_size = 64 constr = layout.get_next_constraints() self.home_button = self.factory.create_button( KEY_HOME, KEY_HOME, constr, listeners[KEY_HOME], bgr, image_size_percent=image_size) self.add_component(self.home_button) self.menu_buttons.append(self.home_button) constr = layout.get_next_constraints() self.favorites_button = self.factory.create_button( KEY_FAVORITES, KEY_SETUP, constr, listeners[KEY_FAVORITES], bgr, image_size_percent=image_size) self.add_component(self.favorites_button) self.menu_buttons.append(self.favorites_button) constr = layout.get_next_constraints() self.player_button = self.factory.create_button( KEY_PLAYER, KEY_PLAY_PAUSE, constr, listeners[KEY_PLAYER], bgr, image_size_percent=image_size) self.add_component(self.player_button) self.menu_buttons.append(self.player_button)
def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.factory = Factory(util) self.check_internet_connectivity = listeners[KEY_CHECK_INTERNET] self.go_home = listeners[KEY_HOME] self.set_modes = listeners[KEY_SET_MODES] self.linux = self.config[LINUX_PLATFORM] self.wifi_util = WiFiUtil(util) self.bluetooth_util = self.util.get_bluetooth_util() self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) if self.linux and self.config[USAGE][USE_BLUETOOTH]: rows = 7 else: rows = 6 columns = 1 d = [rows, columns] MenuScreen.__init__(self, util, listeners, rows, columns, voice_assistant, d, None, page_in_title=False, show_loading=False) self.title = self.config[LABELS]["network"] self.set_title(1) center_layout = BorderLayout(self.menu_layout) center_layout.set_percent_constraints(0, 0, 47, 0) left_layout = center_layout.LEFT right_layout = center_layout.CENTER label_layout = GridLayout(left_layout) label_layout.set_pixel_constraints(rows, columns) label_layout.get_next_constraints() value_layout = GridLayout(right_layout) value_layout.set_pixel_constraints(rows, columns) value_layout.get_next_constraints() self.network_panel = Container(util, self.menu_layout) rect = pygame.Rect(self.menu_layout.x, self.menu_layout.y + 1, self.menu_layout.w, self.menu_layout.h - 1) b = util.config[BACKGROUND][MENU_BGR_COLOR] bgr = Component(util, rect, 0, 0, self.menu_layout, bgr=b) bgr.name = "network.panel.bgr" self.network_panel.add_component(bgr) self.internet_label = self.add_label(label_layout, self.network_panel, 1) self.ethernet_label = self.add_label(label_layout, self.network_panel, 2) self.wifi_network_label = self.add_label(label_layout, self.network_panel, 3) self.wifi_ip_label = self.add_label(label_layout, self.network_panel, 4) if self.linux and self.config[USAGE][USE_BLUETOOTH]: self.bluetooth_label = self.add_label(label_layout, self.network_panel, 5) self.internet = self.add_value(value_layout, self.network_panel, 1) self.ethernet_ip = self.add_value(value_layout, self.network_panel, 2) self.wifi_network = self.add_value(value_layout, self.network_panel, 3) self.wifi_ip = self.add_value(value_layout, self.network_panel, 4) if self.linux and self.config[USAGE][USE_BLUETOOTH]: self.bluetooth = self.add_value(value_layout, self.network_panel, 5) self.add_component(self.network_panel) listeners[KEY_REFRESH] = self.set_current listeners[KEY_DISCONNECT] = self.disconnect_wifi listeners[KEY_BLUETOOTH_REMOVE] = self.remove_bluetooth_devices self.navigator = NetworkNavigator(self.util, self.layout.BOTTOM, listeners) self.add_component(self.navigator) self.original_networks = None self.networks = None self.current_network = None self.current_wifi_network = None self.clicked = False
def __init__(self, util, bounding_box, listeners, language_url=None): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners :param language_url: language constant """ Container.__init__(self, util) self.factory = Factory(util) self.name = "navigator" arrow_layout = BorderLayout(bounding_box) arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) self.menu_buttons = [] constr = arrow_layout.LEFT self.left_button = self.factory.create_page_down_button( constr, "0", 34, 100) self.left_button.add_release_listener(listeners[GO_LEFT_PAGE]) self.add_component(self.left_button) self.menu_buttons.append(self.left_button) constr = arrow_layout.RIGHT self.right_button = self.factory.create_page_up_button( constr, "0", 34, 100) self.right_button.add_release_listener(listeners[GO_RIGHT_PAGE]) self.add_component(self.right_button) self.menu_buttons.append(self.right_button) layout = GridLayout(arrow_layout.CENTER) if language_url == "": # English-USA buttons = 5 elif language_url == None: #Russian buttons = 6 else: buttons = 4 layout.set_pixel_constraints(1, buttons, 1, 0) layout.current_constraints = 0 image_size = 56 b = util.config[BACKGROUND][FOOTER_BGR_COLOR] constr = layout.get_next_constraints() self.home_button = self.factory.create_button( KEY_HOME, KEY_HOME, constr, listeners[KEY_HOME], b, image_size_percent=image_size) self.add_component(self.home_button) self.menu_buttons.append(self.home_button) if language_url == None: constr = layout.get_next_constraints() self.abc_button = self.factory.create_button( IMAGE_ABC, KEY_SETUP, constr, listeners[GO_USER_HOME], b, image_size_percent=image_size) self.add_component(self.abc_button) self.menu_buttons.append(self.abc_button) constr = layout.get_next_constraints() self.new_books_button = self.factory.create_button( IMAGE_NEW_BOOKS, KEY_MENU, constr, listeners[GO_ROOT], b, image_size_percent=image_size) self.add_component(self.new_books_button) self.menu_buttons.append(self.new_books_button) if language_url == None or language_url == "": # English-USA or Russian constr = layout.get_next_constraints() self.genre_button = self.factory.create_button( IMAGE_BOOK_GENRE, KEY_ROOT, constr, listeners[GO_TO_PARENT], b, image_size_percent=image_size) self.add_component(self.genre_button) self.menu_buttons.append(self.genre_button) constr = layout.get_next_constraints() self.player_button = self.factory.create_button( IMAGE_PLAYER, KEY_PLAY_PAUSE, constr, listeners[GO_PLAYER], b, source=BOOK_NAVIGATOR, image_size_percent=image_size) self.add_component(self.player_button) self.menu_buttons.append(self.player_button) constr = layout.get_next_constraints() self.back_button = self.factory.create_button( KEY_BACK, KEY_BACK, constr, None, b, source=BOOK_NAVIGATOR_BACK, image_size_percent=image_size) self.back_button.add_release_listener(listeners[GO_BACK]) try: self.back_button.add_release_listener(listeners[KEY_PLAY_FILE]) except: pass self.add_component(self.back_button) self.menu_buttons.append(self.back_button)
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 = 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 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, self.config[ALIGN_BUTTON_CONTENT_X]) 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 __init__(self, util, bounding_box, name, items, arrow_items=None): """ Initializer :param util: utility object :param bounding_box: bounding box :param name: navigator name :param items: dictionary with button details :param arrow_items: dictionary with arrow buttons details """ Container.__init__(self, util) self.factory = Factory(util) self.name = name self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.buttons = [] if arrow_items: arrow_layout = BorderLayout(bounding_box) left_arrow = arrow_items[0] listeners = left_arrow[LISTENER] arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) constr = arrow_layout.LEFT button = self.factory.create_page_down_button(constr, "0", 40, 100) button.add_release_listener(listeners[0]) self.add_component(button) self.buttons.append(button) layout = GridLayout(arrow_layout.CENTER) else: layout = GridLayout(bounding_box) layout.set_pixel_constraints(1, len(items), 1, 0) layout.current_constraints = 0 image_size = 64 b = util.config[BACKGROUND][FOOTER_BGR_COLOR] for item in items: constr = layout.get_next_constraints() image_name = item[IMAGE_NAME] listeners = item[LISTENER] keybiard_key = item[KEYBOARD_KEY] source = item[SOURCE] if len(listeners) == 1: button = self.factory.create_button( image_name, keybiard_key, constr, listeners[0], b, image_size_percent=image_size, source=source) else: button = self.factory.create_button( image_name, keybiard_key, constr, None, b, image_size_percent=image_size, source=source) for listener in listeners: button.add_release_listener(listener) self.add_component(button) self.buttons.append(button) if arrow_items: right_arrow = arrow_items[1] listeners = right_arrow[LISTENER] constr = arrow_layout.RIGHT button = self.factory.create_page_up_button(constr, "0", 40, 100) button.add_release_listener(listeners[0]) self.add_component(button) self.buttons.append(button)
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) 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 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) 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, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listener: screen menu event listener """ self.util = util config = util.config screen_layout = BorderLayout(config[SCREEN_RECT]) top = int((config[SCREEN_RECT].h * PERCENT_SAVERS) / 100) bottom = config[SCREEN_RECT].h - top screen_layout.set_pixel_constraints(top, bottom, 0, 0) layout = BorderLayout(screen_layout.TOP) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, 0, 0, 0) Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant, "saver_title", title_layout=layout.TOP) factory = Factory(util) self.bounding_box = config[SCREEN_RECT] self.bgr = (0, 0, 0) self.saver_menu = SaverMenu(util, (0, 0, 0), layout.CENTER) self.add_component(self.saver_menu) d = config[COLORS][COLOR_DARK_LIGHT] c = config[COLORS][COLOR_CONTRAST] font_size = (layout.TOP.h * PERCENT_TITLE_FONT)/100.0 label = config[LABELS][SCREENSAVER] self.screen_title.set_text(label) layout = BorderLayout(screen_layout.BOTTOM) layout.set_percent_constraints(PERCENT_DELAY_TITLE, PERCENT_DELAY_TITLE, 0, 0) self.delay_menu = SaverDelayMenu(util, (0, 0, 0), layout.CENTER) self.add_component(self.delay_menu) layout.TOP.y += 1 layout.TOP.h -= 1 self.saver_delay_title = factory.create_output_text("saver_delay_title", layout.TOP, d, c, int(font_size)) label = config[LABELS][DELAY] self.saver_delay_title.set_text(label) self.add_component(self.saver_delay_title) buttons = factory.create_home_player_buttons(self, layout.BOTTOM, listeners) self.home_button = buttons[0] self.player_button = buttons[1] self.top_menu_enabled = True
class EqualizerMenu(Container): """ Equalizer Navigator Menu class """ def __init__(self, util, handle_slider_event, bgr=None, bounding_box=None): """ Initializer :param util: utility object :param handle_slider_event: slider event handler :param listeners: menu listeners :param bgr: menu background :param bounding_box: bounding box """ self.labels = ["31", "63", "125", "250", "500", "1k", "2k", "4k", "8k", "16k"] Container.__init__(self, util) name = "equalizermenu" self.factory = Factory(util) self.bounding_box = bounding_box self.bounding_box.y += 1 self.bounding_box.h -= 1 self.bgr_color = util.config[BACKGROUND][MENU_BGR_COLOR] self.eq_layout = BorderLayout(self.bounding_box) self.eq_layout.set_percent_constraints(0, 0, 5, 5) self.bands = 10 self.sliders = self.add_sliders(handle_slider_event) self.current_slider = -1 self.left_filler = Component(util, self.eq_layout.LEFT) self.left_filler.name = name + ".bgr.left" self.left_filler.bgr = self.bgr_color self.add_component(self.left_filler) self.right_filler = Component(util, self.eq_layout.RIGHT) self.right_filler.name = name + ".bgr.right" self.right_filler.bgr = self.bgr_color self.add_component(self.right_filler) self.SLOW_INCREMENT = 1 self.FAST_INCREMENT = self.sliders[0].slider.knob_height/2 def add_sliders(self, handle_slider_event): layout = GridLayout(self.eq_layout.CENTER) layout.set_pixel_constraints(1, self.bands, 0, 0) layout.current_constraints = 0 sliders = [] for n in range(self.bands): constr = layout.get_next_constraints() s = self.factory.create_equalizer_slider(n, constr, "band", handle_slider_event, self.labels[n], self.bgr_color) s.slider.active = False s.content = None s.slider.content = None self.add_component(s) sliders.append(s) return sliders def set_bands(self, values): for n, s in enumerate(self.sliders): v = values[n] s.slider.set_position(v) s.slider.update_position() s.set_value(str(v)) s.slider.set_knob_off() self.current_slider = -1 def set_parent_screen(self, scr): """ Add parent screen :param scr: parent screen """ self.left_filler.parent_screen = scr self.right_filler.parent_screen = scr for s in self.sliders: s.slider.parent_screen = scr s.top.parent_screen = scr s.bottom.parent_screen = scr def handle_event(self, event): """ Menu event handler :param event: menu event """ if not self.visible: return if event.type == USER_EVENT_TYPE and event.sub_type == SUB_TYPE_KEYBOARD: key_events = [kbd_keys[KEY_LEFT], kbd_keys[KEY_RIGHT], kbd_keys[KEY_UP], kbd_keys[KEY_DOWN], kbd_keys[KEY_PAGE_UP], kbd_keys[KEY_PAGE_DOWN]] if event.keyboard_key not in key_events: return if event.action == pygame.KEYUP: self.key_up(event) elif event.action == pygame.KEYDOWN: self.key_down(event) else: if not self.bounding_box.collidepoint(event.pos): return if event.type == pygame.MOUSEBUTTONDOWN: selected_slider = self.current_slider for i, b in enumerate(self.sliders): if b.slider.bounding_box.collidepoint(event.pos): selected_slider = i break if selected_slider != self.current_slider: self.deactivate_current_slider() self.current_slider = selected_slider Container.handle_event(self, event) if event.type == pygame.MOUSEBUTTONUP: slider = self.sliders[self.current_slider].slider slider.set_knob_on() slider.notify_slide_listeners() def key_up(self, event): avoided_keys = [kbd_keys[KEY_UP], kbd_keys[KEY_DOWN], kbd_keys[KEY_PAGE_UP], kbd_keys[KEY_PAGE_DOWN]] if self.current_slider == -1 and (event.keyboard_key in avoided_keys): return self.deactivate_current_slider() if event.keyboard_key == kbd_keys[KEY_LEFT]: if self.current_slider == 0 or self.current_slider == -1: self.current_slider = len(self.sliders) - 1 else: self.current_slider -= 1 elif event.keyboard_key == kbd_keys[KEY_RIGHT]: if self.current_slider == len(self.sliders) - 1: self.current_slider = 0 else: self.current_slider += 1 self.activate_slider() def key_down(self, event): if self.current_slider == -1: return slider = self.sliders[self.current_slider].slider if event.keyboard_key == kbd_keys[KEY_UP]: slider.release_action((slider.knob_x, slider.last_knob_position + slider.knob_height/2 - self.SLOW_INCREMENT)) elif event.keyboard_key == kbd_keys[KEY_DOWN] and event.action == pygame.KEYDOWN: slider.release_action((slider.knob_x, slider.last_knob_position + slider.knob_height/2 + self.SLOW_INCREMENT)) elif event.keyboard_key == kbd_keys[KEY_PAGE_UP] and event.action == pygame.KEYDOWN: slider.release_action((slider.knob_x, slider.last_knob_position - self.FAST_INCREMENT)) elif event.keyboard_key == kbd_keys[KEY_PAGE_DOWN] and event.action == pygame.KEYDOWN: slider.release_action((slider.knob_x, slider.last_knob_position + slider.knob_height/2 + self.FAST_INCREMENT)) slider.set_knob_on() def deactivate_current_slider(self): if self.current_slider == -1: return slider = self.sliders[self.current_slider].slider slider.release_action((slider.knob_x, slider.last_knob_position)) slider.clean_draw_update() def activate_slider(self): slider = self.sliders[self.current_slider].slider slider.press_action() slider.clean_draw_update() def add_menu_observers(self, update_observer, redraw_observer): for b in self.sliders: b.slider.add_slide_listener(update_observer) b.slider.add_knob_listener(update_observer) b.slider.add_press_listener(update_observer) b.slider.add_motion_listener(update_observer) b.web_seek_listener = update_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.info_button = None self.info_popup = None self.start_screensaver = listeners[SCREENSAVER] bottom_layout = BorderLayout(layout.BOTTOM) bottom_layout.set_percent_constraints(0, 0, 0, POPUP_WIDTH_PERCENT) 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
def __init__(self, util, title_key, percent_bottom_height=0, voice_assistant=None, screen_title_name="screen_title", create_dynamic_title=False, title_layout=None, title=None): """ Initializer :param util: utility object :param title_key: the resource bundle key for the screen title """ Container.__init__(self, util) self.util = util factory = Factory(util) self.config = util.config self.bounding_box = util.screen_rect self.bgr = (0, 0, 0) self.layout = BorderLayout(util.screen_rect) self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, percent_bottom_height, 0, 0) self.voice_assistant = voice_assistant self.font_size = int((self.layout.TOP.h * PERCENT_TITLE_FONT) / 100.0) d = self.config[COLORS][COLOR_DARK_LIGHT] c = self.config[COLORS][COLOR_CONTRAST] t_layout = self.layout.TOP if title_layout: t_layout = title_layout if create_dynamic_title: self.screen_title = factory.create_dynamic_text( screen_title_name, t_layout, d, c, self.font_size) else: self.screen_title = factory.create_output_text( screen_title_name, t_layout, d, c, self.font_size) if title: self.screen_title.set_text(title) else: if title_key and len(title_key) > 0: try: label = self.config[LABELS][title_key] self.screen_title.set_text(label) except: pass if voice_assistant: self.screen_title.add_select_listener(self.handle_voice_assistant) self.layout.TOP.w += 1 self.voice_command = factory.create_output_text( "voice_command", self.layout.TOP, d, c, self.font_size) self.voice_command.add_select_listener(self.handle_voice_assistant) self.voice_assistant.add_text_recognized_listener( self.text_recognized) self.voice_assistant.assistant.add_start_conversation_listener( self.start_conversation) self.voice_assistant.assistant.add_stop_conversation_listener( self.stop_conversation) if voice_assistant and voice_assistant.is_running(): self.title_selected = False else: self.title_selected = True self.draw_title_bar() self.player_screen = False self.update_web_observer = None self.update_web_title = None self.loading_listeners = [] self.LOADING = util.config[LABELS][KEY_LOADING] self.factory = factory
class TopicDetailNavigator(Container): """ Topic detail navigator """ def __init__(self, util, bounding_box, listeners): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners """ Container.__init__(self, util) self.factory = Factory(util) self.name = "collection.navigator" self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.listeners = listeners self.menu_buttons = [] self.config = util.config self.use_web = self.config[USAGE][USE_WEB] self.bgr = util.config[COLORS][COLOR_DARK_LIGHT] self.arrow_layout = BorderLayout(bounding_box) self.arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) self.update_observer = None self.redraw_observer = None self.menu_buttons = [] constr = self.arrow_layout.LEFT self.left_button = self.factory.create_page_down_button( constr, "0", 40, 100) self.left_button.add_release_listener(self.listeners[GO_LEFT_PAGE]) self.add_component(self.left_button) self.menu_buttons.append(self.left_button) constr = self.arrow_layout.RIGHT self.right_button = self.factory.create_page_up_button( constr, "0", 40, 100) self.right_button.add_release_listener(self.listeners[GO_RIGHT_PAGE]) self.add_component(self.right_button) self.menu_buttons.append(self.right_button) layout = GridLayout(self.arrow_layout.CENTER) layout.set_pixel_constraints(1, 5, 1, 0) layout.current_constraints = 0 self.add_button(KEY_HOME, KEY_HOME, layout, self.listeners[KEY_HOME]) self.add_button(KEY_BACK, KEY_BACK, layout, self.listeners[KEY_BACK]) self.add_button(COLLECTION, KEY_PARENT, layout, self.listeners[COLLECTION]) self.add_button(KEY_LIST, KEY_MENU, layout, self.listeners[COLLECTION_TOPIC]) self.add_button(KEY_PLAYER, KEY_PLAY_PAUSE, layout, self.listeners[KEY_PLAYER]) if self.use_web and self.update_observer != None: self.add_observers(self.update_observer, self.redraw_observer) def add_button(self, img_name, key, layout, listener): """ Add button to the navigator :param img_name: button image name :param key: keyboard key :param layout: button layout :param listener: button listener """ c = layout.get_next_constraints() b = self.factory.create_button(img_name, key, c, listener, self.bgr, source="navigator", image_size_percent=IMAGE_SIZE_PERCENT) self.add_component(b) self.menu_buttons.append(b) def add_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 """ if self.update_observer == None: self.update_observer = update_observer self.redraw_observer = redraw_observer for b in self.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
def __init__(self, util, connected_cd_drives, bounding_box, listeners, bgr): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners :param bgr: menu background """ Container.__init__(self, util) self.factory = Factory(util) self.name = "navigator" self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.menu_buttons = [] self.config = util.config arrow_layout = BorderLayout(bounding_box) arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) constr = arrow_layout.LEFT self.left_button = self.factory.create_page_down_button( constr, "0", 40, 100) self.left_button.add_release_listener(listeners[GO_LEFT_PAGE]) self.add_component(self.left_button) self.menu_buttons.append(self.left_button) constr = arrow_layout.RIGHT self.right_button = self.factory.create_page_up_button( constr, "0", 40, 100) self.right_button.add_release_listener(listeners[GO_RIGHT_PAGE]) self.add_component(self.right_button) self.menu_buttons.append(self.right_button) layout = GridLayout(arrow_layout.CENTER) p = self.config[AUDIO][PLAYER_NAME] show_drives = connected_cd_drives > 1 and (p == VLC or p == MPD) if show_drives: layout.set_pixel_constraints(1, 5, 1, 0) else: layout.set_pixel_constraints(1, 4, 1, 0) layout.current_constraints = 0 image_size = 56 constr = layout.get_next_constraints() self.home_button = self.factory.create_button( KEY_HOME, KEY_HOME, constr, listeners[KEY_HOME], bgr, image_size_percent=image_size) self.add_component(self.home_button) self.menu_buttons.append(self.home_button) if show_drives: constr = layout.get_next_constraints() self.cd_drives_button = self.factory.create_button( KEY_CD_PLAYERS, KEY_ROOT, constr, listeners[KEY_CD_PLAYERS], bgr, image_size_percent=image_size) self.add_component(self.cd_drives_button) self.menu_buttons.append(self.cd_drives_button) constr = layout.get_next_constraints() self.refresh_button = self.factory.create_button( KEY_REFRESH, KEY_SETUP, constr, listeners[KEY_REFRESH], bgr, image_size_percent=image_size) self.add_component(self.refresh_button) self.menu_buttons.append(self.refresh_button) constr = layout.get_next_constraints() self.eject_button = self.factory.create_button( KEY_EJECT, KEY_PARENT, constr, listeners[KEY_EJECT], bgr, image_size_percent=image_size) self.add_component(self.eject_button) self.menu_buttons.append(self.eject_button) constr = layout.get_next_constraints() self.back_button = self.factory.create_button( KEY_BACK, KEY_BACK, constr, None, bgr, image_size_percent=image_size) self.back_button.add_release_listener(listeners[GO_BACK]) self.back_button.add_release_listener(listeners[KEY_PLAYER]) self.add_component(self.back_button) self.menu_buttons.append(self.back_button)