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]
class Screen(Container): """ Base class for all screens with menu and navigator """ 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, bgr=None): """ Initializer :param util: utility object :param title_key: the resource bundle key for the screen title """ self.util = util self.factory = Factory(util) self.config = util.config self.bounding_box = util.screen_rect if title_key: self.name = title_key else: self.name = "tmp" bg = self.util.get_background(self.name, bgr) self.bgr_type = bg[0] self.bgr = bg[1] self.bgr_key = bg[5] Container.__init__(self, util, bounding_box=self.bounding_box, background=bg[1], content=bg[2], image_filename=bg[3]) self.original_image_filename = None try: self.original_image_filename = bg[4].replace("\\", "/") except: pass 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) b = self.config[BACKGROUND][HEADER_BGR_COLOR] 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 = self.factory.create_dynamic_text(screen_title_name, t_layout, b, c, self.font_size) else: self.screen_title = self.factory.create_output_text(screen_title_name, t_layout, b, 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 = self.factory.create_output_text("voice_command", self.layout.TOP, b, 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.animated_title = False def add_component(self, c): """ Add screen component :param c: component to add """ if c: c.set_parent_screen(self) Container.add_component(self, c) def draw_title_bar(self): """ Draw title bar on top of the screen """ if len(self.components) != 0 and self.title_selected: self.add_component(self.voice_command) self.title_selected = False elif len(self.components) != 0 and not self.title_selected: self.add_component(self.screen_title) self.title_selected = True elif len(self.components) == 0 and self.title_selected: self.add_component(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.add_component(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 add_navigator(self, navigator): """ Add navigator to the screen :param menu: the menu to add """ self.navigator = navigator self.add_component(navigator) 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[BACKGROUND][MENU_BGR_COLOR] 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 bb = Rect(bb.x, bb.y + 1, bb.w, bb.h - 1) t = self.factory.create_output_text(self.LOADING, bb, b, f, fs) if not text: t.set_text_no_draw(self.LOADING) else: t.set_text_no_draw(text) if name != None: self.screen_title.set_text(name) self.set_visible(True) self.add_component(t) if getattr(self, "menu", None) != None: self.menu.buttons = {} self.menu.components = [] 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 handle_event(self, event): """ Event handler :param event: event to handle """ if not self.visible: return mouse_events = [pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN] if event.type in mouse_events and getattr(self, "menu", None) and getattr(self, "navigator", None): event_component = None for comp in self.menu.components: if getattr(comp, "state", None): bb = comp.state.bounding_box else: bb = comp.bounding_box if bb == None: continue if bb.collidepoint(event.pos): event_component = comp for c in self.menu.components: if hasattr(c, "set_selected") and c != comp: c.set_selected(False) c.clean_draw_update() if event_component: self.navigator.unselect() event_component.handle_event(event) if hasattr(self.menu, "current_slider"): self.menu.current_slider = event_component.id if self.update_web_observer: self.update_web_observer() return for comp in self.navigator.components: if getattr(comp, "state", None): bb = comp.state.bounding_box else: bb = comp.bounding_box if bb == None: continue if bb.collidepoint(event.pos): event_component = comp break if event_component: for c in self.menu.components: if getattr(c, "selected", False): c.set_selected(False) c.clean_draw_update() elif hasattr(c, "slider"): c.slider.set_knob_off() self.navigator.unselect() event_component.handle_event(event) if self.update_web_observer: self.update_web_observer() else: Container.handle_event(self, event) self.update_web_observer() def get_menu_bottom_exit_xy(self, x): """ Get bottom exit coordinates :param x: event x coordinate """ button = None xy = None for b in self.menu.components: if getattr(b, "bounding_box", None) == None: continue y = b.bounding_box.y + 5 if b.bounding_box.collidepoint((x, y)): button = b if button == None: num = len(self.menu.components) if num != 0: button = self.menu.components[num - 1] if button != None and getattr(button, "bounding_box", None) != None: xy = (button.bounding_box.x + (button.bounding_box.w / 2), button.bounding_box.y) return xy def link_borders(self, navigator_top_bottom_exit=True, first_index=None, last_index=None): """ Link components borders for the arrow keys navigation :param navigator_top_bottom_exit: """ if not hasattr(self.navigator, "components"): return margin = 10 num = len(self.navigator.components) first_menu_comp = last_menu_comp = None if getattr(self, "menu", None): self.menu.exit_top_y = self.menu.exit_bottom_y = self.menu.bounding_box.y + self.menu.bounding_box.h + margin first_nav_comp = self.navigator.components[0] last_nav_comp = self.navigator.components[num - 1] self.menu.exit_right_x = first_nav_comp.bounding_box.x + margin self.menu.exit_right_y = first_nav_comp.bounding_box.y + margin self.menu.exit_left_x = last_nav_comp.bounding_box.x + last_nav_comp.bounding_box.w - margin self.menu.exit_left_y = last_nav_comp.bounding_box.y + margin if first_index == None: first_index = 0 if last_index == None: last_index = len(self.menu.components) - 1 if len(self.menu.components) > 0: first_menu_comp = self.menu.components[first_index] last_menu_comp = self.menu.components[last_index] if getattr(self, "menu", None) and len(self.menu.components) == 0: navigator_top_bottom_exit = False for index, comp in enumerate(self.navigator.components): if navigator_top_bottom_exit and getattr(self, "menu", None): xy = self.get_menu_bottom_exit_xy(comp.bounding_box.x + 5) if xy: comp.exit_top_y = xy[1] + margin comp.exit_bottom_y = self.menu.bounding_box.y + margin comp.exit_x = xy[0] else: comp.exit_top_y = None comp.exit_bottom_y = None comp.exit_x = None if index == 0: if last_menu_comp != None: comp.exit_left_x = last_menu_comp.bounding_box.x + margin comp.exit_left_y = last_menu_comp.bounding_box.y + margin else: comp.exit_left_x = self.navigator.components[num - 1].bounding_box.x + margin comp.exit_left_y = self.navigator.components[num - 1].bounding_box.y + margin c = self.navigator.components[index + 1] comp.exit_right_x = c.bounding_box.x + margin elif index == (num - 1): c = self.navigator.components[num - 2] comp.exit_left_x = c.bounding_box.x + margin if first_menu_comp != None: comp.exit_right_x = first_menu_comp.bounding_box.x + margin comp.exit_right_y = first_menu_comp.bounding_box.y + margin else: comp.exit_right_x = self.navigator.components[0].bounding_box.x + margin comp.exit_right_y = self.navigator.components[0].bounding_box.y + margin else: c = self.navigator.components[index - 1] comp.exit_left_x = c.bounding_box.x + margin c = self.navigator.components[index + 1] comp.exit_right_x = c.bounding_box.x + margin
class StationScreen(Container): """ Station Screen. Extends Container class """ 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) def mode_listener(self, mode): """ Station screen menu mode event listener :param mode: menu mode """ if mode == self.station_menu.STATION_MODE: self.left_button.set_visible(True) self.right_button.set_visible(True) self.page_down_button.set_visible(False) self.page_up_button.set_visible(False) self.left_button.clean_draw_update() self.right_button.clean_draw_update() else: self.left_button.set_visible(False) self.right_button.set_visible(False) self.page_down_button.set_visible(True) self.page_up_button.set_visible(True) if self.playlist.total_pages == 1: self.page_down_button.set_enabled(False) self.page_up_button.set_enabled(False) else: self.page_down_button.set_enabled(True) self.page_up_button.set_enabled(True) self.page_down_button.clean_draw_update() self.page_up_button.clean_draw_update() def update_arrow_button_labels(self, state): """ Update arrow buttons state :param state: button state used for update """ if not self.station_menu.STATION_MODE: return left = self.station_menu.button.state.index right = self.playlist.length - self.station_menu.button.state.index - 1 self.left_button.state.l_name = str(left) self.left_button.add_label(self.left_button.state, self.left_button.layout.get_label_rectangle()) self.page_down_button.state.l_name = str(left) self.page_down_button.add_label(self.page_down_button.state, self.page_down_button.layout.get_label_rectangle()) self.right_button.state.l_name = str(right) self.right_button.add_label(self.right_button.state, self.right_button.layout.get_label_rectangle()) self.page_up_button.state.l_name = str(right) self.page_up_button.add_label(self.page_up_button.state, self.page_up_button.layout.get_label_rectangle()) if self.station_menu.current_mode == self.station_menu.STATION_MODE: self.left_button.clean_draw_update() self.right_button.clean_draw_update() else: self.page_down_button.clean_draw_update() self.page_up_button.clean_draw_update() 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 items_per_line(self, width): """ Return the number of station menu items in line for specified screen width :param width: screen width :return: number of menu items per line """ if width <= 102: return 1 elif width <= 203: return 2 elif width <= 304: return 3 elif width <= 405: return 4 elif width <= 506: return 5 else: return 6 def set_genre_button_image(self, genre): """ Set genre button image :param genre: genre button """ s = State() s.__dict__ = genre.__dict__ s.bounding_box = self.genres_button.state.bounding_box s.bgr = self.genres_button.bgr s.show_label = False s.keyboard_key = kbd_keys[KEY_MENU] self.genres_button.set_state(s) def set_current(self): """ Set current station by index defined in current playlist """ selected_genre = self.genres[self.config[CURRENT][PLAYLIST]] if selected_genre == self.current_genre: return self.config[PREVIOUS][self.station_menu.playlist.genre] = self.station_menu.get_current_station_index() self.playlist = Playlist(self.config[CURRENT][LANGUAGE], selected_genre.genre, self.util, self.items_per_line) if self.playlist.length == 0: return self.station_menu.set_playlist(self.playlist) previous_station_index = 0 try: previous_station_index = self.config[PREVIOUS][selected_genre.name.lower()] except KeyError: pass self.station_menu.set_station(previous_station_index) self.station_menu.set_station_mode(None) self.config[CURRENT][STATION] = previous_station_index self.set_genre_button_image(selected_genre) self.current_genre = selected_genre self.screen_title.set_text(self.station_menu.get_current_station_name()) pass 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 """ bb = self.screen_title.bounding_box x = 0 y = bb.h w = bb.width h = self.station_menu.bounding_box.height c = Component(self.util) c.name = "clickable_rect" c.content = pygame.Rect(x, y, w, h) c.bgr = c.fgr = (0, 0, 0) c.content_x = c.content_y = 0 d = [c] return d def set_visible(self, flag): """ Set visibility flag :param flag: True - screen visible, False - screen invisible """ self.visible = flag self.screen_title.set_visible(flag)
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, bgr=None): """ Initializer :param util: utility object :param title_key: the resource bundle key for the screen title """ self.util = util self.factory = Factory(util) self.config = util.config self.bounding_box = util.screen_rect if title_key: self.name = title_key else: self.name = "tmp" bg = self.util.get_background(self.name, bgr) self.bgr_type = bg[0] self.bgr = bg[1] self.bgr_key = bg[5] Container.__init__(self, util, bounding_box=self.bounding_box, background=bg[1], content=bg[2], image_filename=bg[3]) self.original_image_filename = None try: self.original_image_filename = bg[4].replace("\\", "/") except: pass 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) b = self.config[BACKGROUND][HEADER_BGR_COLOR] 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 = self.factory.create_dynamic_text( screen_title_name, t_layout, b, c, self.font_size) else: self.screen_title = self.factory.create_output_text( screen_title_name, t_layout, b, 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 = self.factory.create_output_text( "voice_command", self.layout.TOP, b, 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.animated_title = False def add_component(self, c): """ Add screen component :param c: component to add """ if c: c.set_parent_screen(self) Container.add_component(self, c) def draw_title_bar(self): """ Draw title bar on top of the screen """ if len(self.components) != 0 and self.title_selected: self.add_component(self.voice_command) self.title_selected = False elif len(self.components) != 0 and not self.title_selected: self.add_component(self.screen_title) self.title_selected = True elif len(self.components) == 0 and self.title_selected: self.add_component(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.add_component(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[BACKGROUND][MENU_BGR_COLOR] 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 bb = Rect(bb.x, bb.y + 1, bb.w, bb.h - 1) t = self.factory.create_output_text(self.LOADING, bb, b, f, fs) if not text: t.set_text_no_draw(self.LOADING) else: t.set_text_no_draw(text) if name != None: self.screen_title.set_text(name) self.set_visible(True) self.add_component(t) if getattr(self, "menu", None) != None: self.menu.buttons = {} self.menu.components = [] 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)