class CdTracksNavigator(Container): """ File browser navigator menu """ def __init__(self, util, connected_cd_drives, 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 = "navigator" self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.menu_buttons = [] 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 = config[AUDIO][PLAYER_NAME] show_drives = connected_cd_drives > 1 and (p == VLC_NAME or p == MPD_NAME) 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 bgr = 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], 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) 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 """ for b in self.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class RadioGroupNavigator(Container): """ Radio group navigator menu """ 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 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) constr = layout.get_next_constraints() self.favorites_button = self.factory.create_button( KEY_FAVORITES, KEY_SETUP, constr, listeners[KEY_FAVORITES], b, 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], b, image_size_percent=image_size) self.add_component(self.player_button) self.menu_buttons.append(self.player_button) 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 """ for b in self.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class CollectionBrowserNavigator(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(COLLECTION, KEY_PARENT, layout, self.listeners[COLLECTION]) self.add_button(KEY_LIST, KEY_MENU, layout, self.listeners[COLLECTION_TOPIC]) self.add_button(KEY_DETAIL, KEY_SETUP, layout, self.listeners[TOPIC_DETAIL]) 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=KEY_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)
class BluetoothNavigator(Container): """ Bluetooth screen navigator menu """ def __init__(self, util, bounding_box, listeners, pages): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners :param pages: number of menu pages """ Container.__init__(self, util) self.factory = Factory(util) self.name = "bt.navigator" self.content = bounding_box self.content_x = bounding_box.x self.content_y = bounding_box.y self.menu_buttons = [] bgr = util.config[COLORS][COLOR_DARK_LIGHT] 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) layout = GridLayout(arrow_layout.CENTER) else: layout = GridLayout(bounding_box) layout.set_pixel_constraints(1, 4, 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.sort_strength = self.factory.create_button( KEY_REFRESH, KEY_SETUP, constr, listeners[KEY_REFRESH], bgr, image_size_percent=image_size) self.add_component(self.sort_strength) self.menu_buttons.append(self.sort_strength) constr = layout.get_next_constraints() self.network_button = self.factory.create_button( KEY_NETWORK, KEY_BACK, constr, listeners[KEY_NETWORK], bgr, image_size_percent=image_size) self.add_component(self.network_button) self.menu_buttons.append(self.network_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 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 """ for b in self.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class TopicNavigator(Container): """ Collection topic 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 = None 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_abc = listeners[KEY_ABC] self.go_keyboard = listeners[KEY_KEYBOARD_KEY] self.keyboard_callback = listeners[KEY_CALLBACK] self.bgr = util.config[BACKGROUND][FOOTER_BGR_COLOR] self.arrow_layout = BorderLayout(bounding_box) self.arrow_layout.set_percent_constraints(0, 0, PERCENT_ARROW_WIDTH, PERCENT_ARROW_WIDTH) self.collection_topic = None self.update_observer = None self.redraw_observer = None self.menu_button = None def set_buttons(self, topic): """ Set navigator buttons depending on topic :param topic: collection topic """ if self.collection_topic == topic: return if self.menu_buttons and topic in TEXT_TOPICS and self.collection_topic in TEXT_TOPICS: self.collection_topic = topic return self.collection_topic = topic 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) if topic in TEXT_TOPICS: n = 7 elif topic == TYPE: n = 5 else: n = 6 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_PARENT, layout, self.listeners[COLLECTION]) self.add_button(KEY_LIST, KEY_MENU, layout, self.listeners[KEY_LIST]) if n == 7: self.add_button(IMAGE_ABC, KEY_SETUP, layout, self.pre_abc) if n != 5: self.add_button(IMAGE_BOOK_GENRE, KEY_ROOT, layout, self.pre_keyboard) self.add_button(KEY_PLAYER, KEY_PLAY_PAUSE, layout, self.listeners[KEY_PLAYER]) 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 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) if key == KEY_PARENT: self.menu_button = b def pre_abc(self, state=None): """ Set state parameters and go to ABC screen :param state: button state """ state.title = self.config[LABELS][self.collection_topic] state.visibility = False state.callback = self.keyboard_callback self.go_abc(state) def pre_keyboard(self, state=None): """ Set state parameters and go to Keyboard screen :param state: button state """ state.title = self.config[LABELS][self.collection_topic] 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 set_parent_screen(self, scr): """ Add parent screen :param scr: parent screen """ for b in self.menu_buttons: b.parent_screen = scr def unselect(self): """ Unselect all navigator buttons """ for b in self.menu_buttons: b.set_selected(False) b.clean_draw_update()
class StationScreen(Screen): """ Station Screen """ def __init__(self, listeners, util, voice_assistant, screen_mode=STATION): """ Initializer :param util: utility object :param listener: screen menu event listener """ self.util = util self.config = util.config self.factory = Factory(util) self.screen_mode = screen_mode self.bounding_box = util.screen_rect self.favorites_util = FavoritesUtil(self.util) layout = BorderLayout(self.bounding_box) k = self.bounding_box.w / self.bounding_box.h percent_menu_width = (100.0 - PERCENT_TOP_HEIGHT - PERCENT_BOTTOM_HEIGHT) / k panel_width = (100.0 - percent_menu_width) / 2.0 layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, panel_width, panel_width) Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant, "station_screen_title", True, layout.TOP) tmp = Menu(util, (0, 0, 0), self.bounding_box, None, None) folders = self.util.get_stations_folders() if folders: panel_layout = BorderLayout(layout.RIGHT) panel_layout.set_percent_constraints(PERCENT_SIDE_BOTTOM_HEIGHT, PERCENT_SIDE_BOTTOM_HEIGHT, 0, 0) self.genres = util.load_stations_folders(panel_layout.BOTTOM) self.genres[ KEY_FAVORITES] = self.favorites_util.get_favorites_button_state( panel_layout.BOTTOM) current_genre_name = list(self.genres.keys())[0] self.current_genre = self.genres[current_genre_name] self.items_per_line = self.items_per_line(layout.CENTER.w) items = [] if self.screen_mode == STATION: k = STATIONS + "." + self.config[CURRENT][LANGUAGE] try: self.config[k] self.current_genre = self.genres[self.config[k] [CURRENT_STATIONS]] except: self.config[k] = {} self.config[k][CURRENT_STATIONS] = self.current_genre.name items = self.load_stations( self.config[CURRENT][LANGUAGE], self.current_genre.name, self.items_per_line * self.items_per_line) elif self.screen_mode == STREAM: items = util.load_streams(self.items_per_line * self.items_per_line) self.playlist = Page(items, self.items_per_line, self.items_per_line) self.station_menu = StationMenu(self.playlist, util, screen_mode, (0, 0, 0), layout.CENTER) if self.station_menu.is_button_defined(): d = {"current_title": self.station_menu.button.state.l_name} self.screen_title.set_text(d) Container.add_component(self, self.station_menu) self.stop_player = listeners[KEY_STOP] self.create_left_panel(layout, listeners) self.create_right_panel(layout, listeners) self.home_button.add_release_listener(listeners[KEY_HOME]) if self.screen_mode == STATION: self.genres_button.add_release_listener(listeners[KEY_GENRES]) self.shutdown_button.add_release_listener( self.favorites_util.save_favorites) self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN]) self.left_button.add_release_listener( self.station_menu.switch_to_previous_station) self.left_button.add_release_listener(self.update_arrow_button_labels) self.page_down_button.add_release_listener( self.station_menu.switch_to_previous_page) self.page_down_button.add_release_listener( self.update_arrow_button_labels) self.right_button.add_release_listener( self.station_menu.switch_to_next_station) self.right_button.add_release_listener(self.update_arrow_button_labels) self.page_up_button.add_release_listener( self.station_menu.switch_to_next_page) self.page_up_button.add_release_listener( self.update_arrow_button_labels) self.station_menu.add_listener(listeners[KEY_PLAY]) self.station_menu.add_listener(self.screen_title.set_state) self.station_menu.add_listener(self.update_arrow_button_labels) self.station_menu.add_mode_listener(self.mode_listener) self.volume = self.factory.create_volume_control(layout.BOTTOM) self.volume.add_slide_listener(listeners[KEY_SET_VOLUME]) self.volume.add_slide_listener(listeners[KEY_SET_CONFIG_VOLUME]) self.volume.add_slide_listener(listeners[KEY_SET_SAVER_VOLUME]) self.volume.add_knob_listener(listeners[KEY_MUTE]) Container.add_component(self, self.volume) self.player_screen = True if self.current_genre.name == KEY_FAVORITES: self.favorites_mode = True else: self.favorites_mode = False self.favorites_util.set_favorites_in_config(self.items_per_line) def load_stations(self, language, genre, stations_per_page): """ Load stations for specified language and genre :param language: the language :param genre: the genre :param stations_per_page: stations per page used to assign indexes :return: list of button state objects. State contains station icons, index, genre, name etc. """ if genre == KEY_FAVORITES: return self.favorites_util.get_favorites_playlist( language, stations_per_page) else: return self.util.get_stations_playlist(language, genre, stations_per_page) 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 self.playlist.length == 0: self.stop_player() left = right = "0" self.page_down_button.set_enabled(False) self.page_up_button.set_enabled(False) self.left_button.set_enabled(False) self.right_button.set_enabled(False) else: left = str(self.station_menu.button.state.index) right = str(self.playlist.length - self.station_menu.button.state.index - 1) self.page_down_button.set_enabled(True) self.page_up_button.set_enabled(True) self.left_button.set_enabled(True) self.right_button.set_enabled(True) self.left_button.change_label(left) self.right_button.change_label(right) self.page_down_button.change_label(left) self.page_up_button.change_label(right) 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 = 0 if self.station_menu.is_button_defined(): left = self.station_menu.button.state.index self.left_button = self.factory.create_left_button( panel_layout.CENTER, str(left), 40, 100) self.page_down_button = self.factory.create_page_down_button( panel_layout.CENTER, str(left), 40, 100) self.page_down_button.set_visible(False) 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.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) if self.screen_mode == STATION: self.genres_button = self.factory.create_genre_button( panel_layout.BOTTOM, self.current_genre, PERCENT_GENRE_IMAGE_AREA) elif self.screen_mode == STREAM: self.genres_button = self.factory.create_stream_button( panel_layout.BOTTOM) right = 0 if self.station_menu.is_button_defined(): right = self.playlist.length - self.station_menu.button.state.index - 1 self.right_button = self.factory.create_right_button( panel_layout.CENTER, str(right), 40, 100) self.page_up_button = self.factory.create_page_up_button( panel_layout.CENTER, str(right), 40, 100) self.page_up_button.set_visible(False) self.play_button = self.factory.create_play_pause_button( panel_layout.TOP, listeners[KEY_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 set_genre_button_image(self, genre): """ Set genre button image :param genre: genre button """ if self.favorites_mode: favorites_button_state = self.favorites_util.get_favorites_button_state( self.genres_button.state.bounding_box) self.genres_button.selected = False self.genres_button.set_state(favorites_button_state) else: 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.factory.scale_genre_button_image(s, PERCENT_GENRE_IMAGE_AREA) self.genres_button.set_state(s) def set_current(self, state=None): """ Set current station by index defined in current playlist :param state: button state (if any) """ items = [] current_language = self.config[CURRENT][LANGUAGE] selected_genre = None self.favorites_mode = False if self.screen_mode == STATION: key = STATIONS + "." + current_language s1 = state != None and getattr(state, "source", None) == KEY_FAVORITES s2 = state == None and self.config[key][ CURRENT_STATIONS] == KEY_FAVORITES if s1 or s2: self.favorites_mode = True self.config[key][CURRENT_STATIONS] = KEY_FAVORITES try: k = self.config[key][CURRENT_STATIONS] selected_genre = self.genres[k] self.store_previous_station(current_language) except: self.config[key] = {} selected_genre = self.current_genre genre = selected_genre.name size = self.items_per_line * self.items_per_line items = self.load_stations(current_language, genre, size) elif self.screen_mode == STREAM: items = self.util.load_streams(self.items_per_line * self.items_per_line) self.playlist = Page(items, self.items_per_line, self.items_per_line) if self.playlist.length == 0: return self.station_menu.set_playlist(self.playlist) if self.screen_mode == STATION: self.station_menu.genre = selected_genre.name previous_station_index = 0 try: previous_station_index = self.config[ STATIONS + "." + current_language][selected_genre.name] except KeyError: pass self.station_menu.set_station(previous_station_index) self.station_menu.set_station_mode(None) self.set_genre_button_image(selected_genre) if self.favorites_mode: self.current_genre = self.favorites_util.get_favorites_button_state( self.genres_button.state.bounding_box) else: self.current_genre = selected_genre elif self.screen_mode == STREAM: previous_station_index = 0 try: previous_station_index = self.config[CURRENT][STREAM] except KeyError: pass self.station_menu.set_station(previous_station_index) self.station_menu.set_station_mode(None) self.config[CURRENT][STREAM] = previous_station_index n = self.station_menu.get_current_station_name() self.screen_title.set_text(n) config_volume_level = int(self.config[PLAYER_SETTINGS][VOLUME]) if self.volume.get_position() != config_volume_level: self.volume.set_position(config_volume_level) self.volume.update_position() def store_previous_station(self, lang): """ Store previous station for the current language :param lang: previous language """ k = STATIONS + "." + lang try: self.config[k] except: self.config[k] = {} try: i = self.station_menu.get_current_station_index() self.config[k][self.current_genre.name] = i except: pass 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) self.station_menu.set_visible(flag) def enable_player_screen(self, flag): """ Enable player screen :param flag: enable/disable flag """ self.screen_title.active = flag def add_screen_observers(self, update_observer, redraw_observer, title_to_json): """ 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, 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(title_to_json) self.add_button_observers(self.play_button, update_observer, redraw_observer=None) self.add_button_observers(self.home_button, update_observer, redraw_observer, release=False) self.add_button_observers(self.left_button, update_observer, redraw_observer, release=False) self.add_button_observers(self.right_button, update_observer, redraw_observer, release=False) self.add_button_observers(self.page_down_button, update_observer, redraw_observer) self.add_button_observers(self.page_up_button, update_observer, redraw_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.genres_button, update_observer, redraw_observer, release=False) self.station_menu.add_listener(update_observer) self.station_menu.add_change_logo_listener(redraw_observer)
class EpisodeNavigator(Container): """ Episodes screen navigator menu """ def __init__(self, util, bounding_box, listeners, pages): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners :param pages: number of episodes menu pages """ Container.__init__(self, util) self.factory = Factory(util) self.name = "podcasts.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) layout = GridLayout(arrow_layout.CENTER) else: layout = GridLayout(bounding_box) layout.set_pixel_constraints(1, 4, 1, 0) layout.current_constraints = 0 image_size = 64 bgr = 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], bgr, image_size_percent=image_size - 1) self.add_component(self.home_button) self.menu_buttons.append(self.home_button) constr = layout.get_next_constraints() self.menu_button = self.factory.create_button( KEY_PODCASTS_MENU, KEY_PARENT, constr, listeners[PODCASTS], bgr, image_size_percent=image_size - 5) self.add_component(self.menu_button) self.menu_buttons.append(self.menu_button) constr = layout.get_next_constraints() self.back_button = self.factory.create_button( KEY_BACK, KEY_BACK, constr, listeners[GO_BACK], bgr, image_size_percent=image_size) self.add_component(self.back_button) self.menu_buttons.append(self.back_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 set_parent_screen(self, scr): """ Add parent screen :param scr: parent screen """ for b in self.menu_buttons: b.parent_screen = scr 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 """ for b in self.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
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 BookNavigator(Container): """ Book navigator menu """ def __init__(self, util, bounding_box, listeners, bgr, language_url=None): """ Initializer :param util: utility object :param bounding_box: bounding box :param listeners: buttons listeners :param bgr: menu background :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 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 language_url == None: constr = layout.get_next_constraints() self.abc_button = self.factory.create_button( IMAGE_ABC, KEY_SETUP, constr, listeners[GO_USER_HOME], bgr, 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], bgr, 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], bgr, 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], bgr, 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, bgr, 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 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 """ self.add_button_observers(self.left_button, update_observer, redraw_observer) self.add_button_observers(self.right_button, update_observer, redraw_observer) self.add_button_observers(self.home_button, update_observer, redraw_observer, release=False) self.add_button_observers(self.new_books_button, update_observer, redraw_observer) self.add_button_observers(self.player_button, update_observer, redraw_observer) self.add_button_observers(self.back_button, update_observer, redraw_observer, release=False) if getattr(self, "abc_button", None): self.add_button_observers(self.abc_button, update_observer, redraw_observer) if getattr(self, "genre_button", None): self.add_button_observers(self.genre_button, update_observer, redraw_observer)
class StationScreen(Screen): """ Station Screen """ def __init__(self, listeners, util, voice_assistant, screen_mode=STATION): """ Initializer :param util: utility object :param listener: screen menu event listener """ self.util = util self.config = util.config self.factory = Factory(util) self.screen_mode = screen_mode self.bounding_box = util.screen_rect self.favorites_util = FavoritesUtil(self.util) self.top_height = self.config[PLAYER_SCREEN][TOP_HEIGHT_PERCENT] self.bottom_height = self.config[PLAYER_SCREEN][BOTTOM_HEIGHT_PERCENT] self.button_height = self.config[PLAYER_SCREEN][BUTTON_HEIGHT_PERCENT] self.popup_width = self.config[PLAYER_SCREEN][POPUP_WIDTH_PERCENT] self.image_location = self.config[PLAYER_SCREEN][IMAGE_LOCATION] self.layout = self.get_layout() Screen.__init__(self, util, "", self.top_height, voice_assistant, "station_screen_title", True, self.layout.TOP) self.layout = self.get_layout() folders = self.util.get_stations_folders() if folders: panel_layout = self.get_panel_layout(self.layout, LOCATION_RIGHT) panel_layout.set_percent_constraints(self.button_height, self.button_height, 0, 0) self.genres = util.load_stations_folders(panel_layout.BOTTOM) self.genres[ KEY_FAVORITES] = self.favorites_util.get_favorites_button_state( panel_layout.BOTTOM) current_genre_name = list(self.genres.keys())[0] self.current_genre = self.genres[current_genre_name] self.items_per_line = self.items_per_line(self.layout.CENTER.w) items = [] if self.screen_mode == STATION: k = STATIONS + "." + self.config[CURRENT][LANGUAGE] try: self.config[k] self.current_genre = self.genres[self.config[k] [CURRENT_STATIONS]] except: self.config[k] = {} self.config[k][CURRENT_STATIONS] = self.current_genre.name items = self.load_stations( self.config[CURRENT][LANGUAGE], self.current_genre.name, self.items_per_line * self.items_per_line) elif self.screen_mode == STREAM: items = util.load_streams(self.items_per_line * self.items_per_line) self.playlist = Page(items, self.items_per_line, self.items_per_line) self.station_menu = StationMenu( self.playlist, util, screen_mode, self.config[BACKGROUND][SCREEN_BGR_COLOR], self.layout.CENTER) if self.station_menu.is_button_defined(): d = {"current_title": self.station_menu.button.state.l_name} self.screen_title.set_text(d) Container.add_component(self, self.station_menu) self.stop_player = listeners[KEY_STOP] self.create_left_panel(self.layout, listeners) self.create_right_panel(self.layout, listeners) self.home_button.add_release_listener(listeners[KEY_HOME]) if self.screen_mode == STATION: self.genres_button.add_release_listener(listeners[KEY_GENRES]) self.shutdown_button.add_release_listener( self.favorites_util.save_favorites) self.shutdown_button.add_release_listener(listeners[KEY_SHUTDOWN]) self.left_button.add_release_listener( self.station_menu.switch_to_previous_station) self.left_button.add_release_listener(self.update_arrow_button_labels) self.page_down_button.add_release_listener( self.station_menu.switch_to_previous_page) self.page_down_button.add_release_listener( self.update_arrow_button_labels) self.right_button.add_release_listener( self.station_menu.switch_to_next_station) self.right_button.add_release_listener(self.update_arrow_button_labels) self.page_up_button.add_release_listener( self.station_menu.switch_to_next_page) self.page_up_button.add_release_listener( self.update_arrow_button_labels) self.station_menu.add_listener(listeners[KEY_PLAY]) self.station_menu.add_listener(self.screen_title.set_state) self.station_menu.add_listener(self.update_arrow_button_labels) self.station_menu.add_mode_listener(self.mode_listener) self.info_button = None self.info_popup = None self.start_screensaver = listeners[SCREENSAVER] bottom_layout = BorderLayout(self.layout.BOTTOM) bottom_layout.set_percent_constraints(0, 0, 0, self.popup_width) volume_layout = bottom_layout.CENTER volume_layout.w -= 2 volume_layout.x += 1 self.volume = self.factory.create_volume_control(volume_layout) self.volume.add_slide_listener(listeners[KEY_SET_VOLUME]) self.volume.add_slide_listener(listeners[KEY_SET_CONFIG_VOLUME]) self.volume.add_slide_listener(listeners[KEY_SET_SAVER_VOLUME]) self.volume.add_knob_listener(listeners[KEY_MUTE]) self.add_component(self.volume) self.player_screen = True self.add_popup(bottom_layout.RIGHT) if self.current_genre.name == KEY_FAVORITES: self.favorites_mode = True else: self.favorites_mode = False self.favorites_util.set_favorites_in_config(self.items_per_line) self.animated_title = True def get_layout(self): """ Get the layout of the center area of the screen for image and buttons :return: layout rectangle """ layout = BorderLayout(self.bounding_box) k = self.bounding_box.w / self.bounding_box.h percent_menu_width = (100.0 - self.top_height - self.bottom_height) / k panel_width = (100.0 - percent_menu_width) / 2.0 if self.image_location == LOCATION_CENTER: layout.set_percent_constraints(self.top_height, self.bottom_height, panel_width, panel_width) elif self.image_location == LOCATION_LEFT: layout.set_percent_constraints(self.top_height, self.bottom_height, 0, panel_width * 2) elif self.image_location == LOCATION_RIGHT: layout.set_percent_constraints(self.top_height, self.bottom_height, panel_width * 2, 0) return layout def get_panel_layout(self, layout, panel_location): """ Get the layout of the panel for buttons :param layout: layout of the whole central area :param panel_location: panel location: left or right :return: panel layout rectangle """ if self.image_location == LOCATION_CENTER: if panel_location == LOCATION_LEFT: return BorderLayout(layout.LEFT) else: return BorderLayout(layout.RIGHT) elif self.image_location == LOCATION_LEFT: r = layout.RIGHT if panel_location == LOCATION_LEFT: return BorderLayout(Rect(r.x, r.y, r.w / 2, r.h)) else: return BorderLayout( Rect(r.x + r.w / 2 + 1, r.y, r.w / 2 - 1, r.h)) elif self.image_location == LOCATION_RIGHT: r = layout.LEFT if panel_location == LOCATION_LEFT: return BorderLayout(Rect(r.x, r.y, r.w / 2, r.h)) else: return BorderLayout( Rect(r.x + r.w / 2 + 1, r.y, r.w / 2 - 1, r.h)) def add_popup(self, bb): """ Add info popup menu :param bb: bounding box """ self.info_button = self.factory.create_info_button( bb, self.handle_info_button) self.info_popup = self.get_info_popup(self.bounding_box) self.add_component(self.info_button) self.add_component(self.info_popup) def handle_info_button(self, state): """ Handle info button :param state: button state """ self.info_popup.set_visible(True) self.clean_draw_update() def get_info_popup(self, bb): """ Create info popup menu :param bb: bounding box :return: popup menu """ items = [] items.append(CLOCK) items.append(WEATHER) items.append(LYRICS) layout = BorderLayout(bb) layout.set_percent_constraints(self.top_height, 0, 0, self.popup_width) popup = Popup(items, self.util, layout.RIGHT, self.clean_draw_update, self.handle_info_popup_selection) self.right_button.add_label_listener(popup.update_popup) return popup def handle_info_popup_selection(self, state): """ Handle info menu selection :param state: button state """ if state.name == LYRICS: a = None try: a = self.screen_title.text except: pass if a != None: s = State() s.album = a self.start_screensaver(state.name, s) else: self.start_screensaver(state.name) else: self.start_screensaver(state.name) def load_stations(self, language, genre, stations_per_page): """ Load stations for specified language and genre :param language: the language :param genre: the genre :param stations_per_page: stations per page used to assign indexes :return: list of button state objects. State contains station icons, index, genre, name etc. """ if genre == KEY_FAVORITES: return self.favorites_util.get_favorites_playlist( language, stations_per_page) else: return self.util.get_stations_playlist(language, genre, stations_per_page) 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 self.playlist.length == 0: self.stop_player() left = right = "0" self.page_down_button.set_enabled(False) self.page_up_button.set_enabled(False) self.left_button.set_enabled(False) self.right_button.set_enabled(False) else: left = str(self.station_menu.button.state.index) right = str(self.playlist.length - self.station_menu.button.state.index - 1) self.page_down_button.set_enabled(True) self.page_up_button.set_enabled(True) self.left_button.set_enabled(True) self.right_button.set_enabled(True) self.left_button.change_label(left) self.right_button.change_label(right) self.page_down_button.change_label(left) self.page_up_button.change_label(right) 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 = self.get_panel_layout(layout, LOCATION_LEFT) panel_layout.set_percent_constraints(self.button_height, self.button_height, 0, 0) left = 0 if self.station_menu.is_button_defined(): left = self.station_menu.button.state.index self.left_button = self.factory.create_left_button( panel_layout.CENTER, str(left), 40, 100) self.page_down_button = self.factory.create_page_down_button( panel_layout.CENTER, str(left), 40, 100) self.page_down_button.set_visible(False) panel_layout.TOP.y += 1 panel_layout.TOP.h -= 2 self.shutdown_button = self.factory.create_shutdown_button( panel_layout.TOP) panel_layout.BOTTOM.h += 1 self.home_button = self.factory.create_button(KEY_HOME, KEY_HOME, panel_layout.BOTTOM, image_size_percent=36) self.shutdown_button.parent_screen = self self.home_button.parent_screen = self self.left_button.parent_screen = self self.page_down_button.parent_screen = self 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 = self.get_panel_layout(layout, LOCATION_RIGHT) panel_layout.set_percent_constraints(self.button_height, self.button_height, 0, 0) panel_layout.BOTTOM.h += 1 if self.screen_mode == STATION: self.genres_button = self.factory.create_genre_button( panel_layout.BOTTOM, self.current_genre, PERCENT_GENRE_IMAGE_AREA) elif self.screen_mode == STREAM: self.genres_button = self.factory.create_stream_button( panel_layout.BOTTOM) right = 0 if self.station_menu.is_button_defined(): right = self.playlist.length - self.station_menu.button.state.index - 1 self.right_button = self.factory.create_right_button( panel_layout.CENTER, str(right), 40, 100) self.page_up_button = self.factory.create_page_up_button( panel_layout.CENTER, str(right), 40, 100) self.page_up_button.set_visible(False) panel_layout.TOP.y += 1 panel_layout.TOP.h -= 2 self.play_button = self.factory.create_play_pause_button( panel_layout.TOP, listeners[KEY_PLAY_PAUSE]) self.genres_button.parent_screen = self self.right_button.parent_screen = self self.page_up_button.parent_screen = self self.play_button.parent_screen = self 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 set_genre_button_image(self, genre): """ Set genre button image :param genre: genre button """ if self.favorites_mode: favorites_button_state = self.favorites_util.get_favorites_button_state( self.genres_button.state.bounding_box) self.genres_button.selected = False self.genres_button.set_state(favorites_button_state) else: 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.factory.scale_genre_button_image(s, PERCENT_GENRE_IMAGE_AREA) self.genres_button.set_state(s) def set_current(self, state=None): """ Set current station by index defined in current playlist :param state: button state (if any) """ items = [] current_language = self.config[CURRENT][LANGUAGE] selected_genre = None self.favorites_mode = False self.sync_state() if self.screen_mode == STATION: key = STATIONS + "." + current_language s1 = state != None and getattr(state, "source", None) == KEY_FAVORITES s2 = state == None and self.config[key][ CURRENT_STATIONS] == KEY_FAVORITES if s1 or s2: self.favorites_mode = True self.config[key][CURRENT_STATIONS] = KEY_FAVORITES try: k = self.config[key][CURRENT_STATIONS] selected_genre = self.genres[k] self.store_previous_station(current_language) except: self.config[key] = {} selected_genre = self.current_genre genre = selected_genre.name size = self.items_per_line * self.items_per_line items = self.load_stations(current_language, genre, size) elif self.screen_mode == STREAM: items = self.util.load_streams(self.items_per_line * self.items_per_line) self.playlist = Page(items, self.items_per_line, self.items_per_line) if self.playlist.length == 0: return self.station_menu.set_playlist(self.playlist) if self.screen_mode == STATION: self.station_menu.genre = selected_genre.name previous_station_index = 0 try: previous_station_index = self.config[ STATIONS + "." + current_language][selected_genre.name] except KeyError: pass src = getattr(state, "source", None) change_mode = getattr(state, "change_mode", False) n = change_mode or (src != KEY_HOME and src != GO_PLAYER and src != KEY_BACK) self.station_menu.set_station(previous_station_index, notify=n) self.station_menu.set_station_mode(None) self.set_genre_button_image(selected_genre) if self.favorites_mode: self.current_genre = self.favorites_util.get_favorites_button_state( self.genres_button.state.bounding_box) else: self.current_genre = selected_genre elif self.screen_mode == STREAM: previous_station_index = 0 try: previous_station_index = self.config[CURRENT][STREAM] except KeyError: pass self.station_menu.set_station(previous_station_index) self.station_menu.set_station_mode(None) self.config[CURRENT][STREAM] = previous_station_index n = self.station_menu.get_current_station_name() self.screen_title.set_text(n) config_volume_level = int(self.config[PLAYER_SETTINGS][VOLUME]) if self.volume.get_position() != config_volume_level: self.volume.set_position(config_volume_level) self.volume.update_position() def sync_state(self): # play-pause button if self.config[PLAYER_SETTINGS][PAUSE]: new_state = "play" else: new_state = "pause" states = self.play_button.states index = 0 for i, s in enumerate(states): if s.name == new_state: index = i break self.play_button.draw_state(index) # mute button if self.config[PLAYER_SETTINGS][MUTE]: self.volume.selected = False else: self.volume.selected = True self.volume.handle_knob_selection(False) def store_previous_station(self, lang): """ Store previous station for the current language :param lang: previous language """ k = STATIONS + "." + lang try: self.config[k] except: self.config[k] = {} try: i = self.station_menu.get_current_station_index() self.config[k][self.current_genre.name] = i except: pass 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) self.station_menu.set_visible(flag) def enable_player_screen(self, flag): """ Enable player screen :param flag: enable/disable flag """ self.screen_title.active = flag def add_screen_observers(self, update_observer, redraw_observer, title_to_json): """ 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, 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(title_to_json) self.add_button_observers(self.play_button, update_observer, redraw_observer=None) self.add_button_observers(self.home_button, update_observer, redraw_observer, release=False) self.add_button_observers(self.info_button, update_observer, redraw_observer) self.info_popup.add_menu_observers(update_observer, redraw_observer) self.add_button_observers(self.left_button, update_observer, redraw_observer, release=False) self.add_button_observers(self.right_button, update_observer, redraw_observer, release=False) self.add_button_observers(self.page_down_button, update_observer, redraw_observer) self.add_button_observers(self.page_up_button, update_observer, redraw_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.genres_button, update_observer, redraw_observer, release=False) self.station_menu.add_listener(update_observer) self.station_menu.add_change_logo_listener(redraw_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)
class Navigator(Container): """ File browser navigator menu """ 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, content="nav") 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 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 """ for b in self.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class Navigator(Container): """ Base class for all navigators """ 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) def add_button(self, items, name, key, listeners, source=None): """ Add button definition :param items: list of items :param name: button image name :param key: keyboard key (if any) :param listeners: list of listeners """ item = {} item[IMAGE_NAME] = name item[LISTENER] = listeners item[KEYBOARD_KEY] = key item[SOURCE] = source items.append(item) def set_parent_screen(self, scr): """ Add parent screen :param scr: parent screen """ for b in self.buttons: b.parent_screen = scr def unselect(self): """ Unselect all navigator buttons """ for b in self.buttons: b.set_selected(False) b.clean_draw_update() def get_clicked_button(self, event): """ Get the clicked button :param event: mouse event """ for b in self.buttons: if b.bounding_box.collidepoint(event.pos): return b return None def get_button_by_name(self, name): """ Get the button by its name :param name: button name """ for b in self.buttons: if b.state.name == name: return b return None def is_selected(self): """ Check if any button is selected :return: True - selected, False - unselected """ for b in self.buttons: if b and getattr(b, "selected", False): return True return False 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 not hasattr(self, "buttons"): return for b in self.buttons: self.add_button_observers(b, update_observer, redraw_observer)