def __init__(self): self.__is_fullscreen = False self.__zoom_handler = None # whether the slideshow is playing self.__is_playing = False # slideshow handler self.__slideshow_handler = None # slideshow timeout in milliseconds self.__slideshow_timeout = 3000 Player.__init__(self) self.__image = Image() self.__image.set_background(theme.color_image_viewer_background) #self.add(self.__image) kscr = KineticScroller(self.__image) gestures = Gestures(self.__image) gestures.connect_twirl(self.__on_twirl_gesture, kscr) gestures.connect_release(self.__on_release, kscr) #gestures.connect_hold(self.__on_hold) #gestures.connect_tap_hold(self.__on_tap_hold) gestures.connect_tap_tap(self.__on_tap_tap) gestures.connect_swipe(self.__on_swipe) # toolbar self.__btn_play = ToolbarButton(theme.mb_btn_play_1) self.__btn_play.connect_clicked(self.__on_btn_play) btn_previous = ToolbarButton(theme.mb_btn_previous_1) btn_previous.connect_clicked(self.__on_btn_previous) btn_next = ToolbarButton(theme.mb_btn_next_1) btn_next.connect_clicked(self.__on_btn_next) self.__toolbar = Toolbar() self.__toolbar.set_toolbar(btn_previous, self.__btn_play, btn_next) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__image, "image") self.__arr.add(self.__toolbar, "toolbar") #self.__arr.add(self.__volume_slider, "slider") self.add(self.__arr)
def __init__(self): # the current mode self.__mode = _MODE_NORMAL # list of available dialog windows self.__dialogs = [] self.__widgets = [] # the file that is currently playing self.__current_file = None # list of files for playing self.__play_folder = None self.__play_files = [] # list for choosing random files from when in shuffle mode self.__random_files = [] # current window size (for detecting resizing) self.__window_size = (0, 0) self.__is_searching = False self.__filter_term = "" self.__key_hold_down_timestamp = 0 self.__skip_letter = False # scheduler for creating thumbnails one by one self.__tn_scheduler = ItemScheduler() # whether we are shutting down self.__is_shutdown = False Component.__init__(self) Window.__init__(self, Window.TYPE_TOPLEVEL) self.set_flag(windowflags.CATCH_VOLUME_KEYS, True) self.connect_key_pressed(self.__on_key_press) self.connect_closed(self.__on_close_window) # [Now Playing] button self.__now_playing = NowPlaying() #self.__now_playing.set_visible(False) # file browser self.__browser = StorageBrowser() #self.__browser.set_root_device(self.__root_dev) self.__browser.connect_folder_begin(self.__on_begin_folder) self.__browser.connect_folder_progress(self.__on_progress_folder) self.__browser.connect_folder_complete(self.__on_complete_folder) self.__browser.connect_file_opened(self.__on_open_file) self.__browser.connect_item_shifted(self.__on_shift_item) # toolbar self.__toolbar = Toolbar() self.__btn_home = ToolbarButton(theme.mb_btn_home_1) self.__btn_home.connect_clicked(self.__on_btn_home) self.__btn_history = ToolbarButton(theme.mb_btn_history_1) self.__btn_history.connect_clicked(self.__on_btn_history) self.__btn_bookmarks = ToolbarButton(theme.mb_btn_bookmark_1) self.__btn_bookmarks.connect_clicked(self.__on_btn_bookmarks) self.__btn_back = ToolbarButton(theme.mb_btn_dir_up_1) self.__btn_back.connect_clicked(self.__on_btn_back) self.__btn_select_all = ToolbarButton(theme.mb_btn_select_all_1) self.__btn_select_all.connect_clicked(self.__on_btn_select_all) self.__btn_select_none = ToolbarButton(theme.mb_btn_select_none_1) self.__btn_select_none.connect_clicked(self.__on_btn_select_none) self.__btn_select_done = ToolbarButton(theme.mb_btn_select_done_1) self.__btn_select_done.connect_clicked(self.__on_btn_select_done) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__now_playing, "now-playing") self.__arr.add(self.__browser, "browser") self.__arr.add(self.__toolbar, "toolbar") self.add(self.__arr) self.__arr.set_visible(False) # we have to fill the menu with content before showing the window on # Maemo5 or the window will show no menu at all self.__update_menu() self.set_visible(True)
class Navigator(Component, Window): """ Navigator dialog for browsing media. """ def __init__(self): # the current mode self.__mode = _MODE_NORMAL # list of available dialog windows self.__dialogs = [] self.__widgets = [] # the file that is currently playing self.__current_file = None # list of files for playing self.__play_folder = None self.__play_files = [] # list for choosing random files from when in shuffle mode self.__random_files = [] # current window size (for detecting resizing) self.__window_size = (0, 0) self.__is_searching = False self.__filter_term = "" self.__key_hold_down_timestamp = 0 self.__skip_letter = False # scheduler for creating thumbnails one by one self.__tn_scheduler = ItemScheduler() # whether we are shutting down self.__is_shutdown = False Component.__init__(self) Window.__init__(self, Window.TYPE_TOPLEVEL) self.set_flag(windowflags.CATCH_VOLUME_KEYS, True) self.connect_key_pressed(self.__on_key_press) self.connect_closed(self.__on_close_window) # [Now Playing] button self.__now_playing = NowPlaying() #self.__now_playing.set_visible(False) # file browser self.__browser = StorageBrowser() #self.__browser.set_root_device(self.__root_dev) self.__browser.connect_folder_begin(self.__on_begin_folder) self.__browser.connect_folder_progress(self.__on_progress_folder) self.__browser.connect_folder_complete(self.__on_complete_folder) self.__browser.connect_file_opened(self.__on_open_file) self.__browser.connect_item_shifted(self.__on_shift_item) # toolbar self.__toolbar = Toolbar() self.__btn_home = ToolbarButton(theme.mb_btn_home_1) self.__btn_home.connect_clicked(self.__on_btn_home) self.__btn_history = ToolbarButton(theme.mb_btn_history_1) self.__btn_history.connect_clicked(self.__on_btn_history) self.__btn_bookmarks = ToolbarButton(theme.mb_btn_bookmark_1) self.__btn_bookmarks.connect_clicked(self.__on_btn_bookmarks) self.__btn_back = ToolbarButton(theme.mb_btn_dir_up_1) self.__btn_back.connect_clicked(self.__on_btn_back) self.__btn_select_all = ToolbarButton(theme.mb_btn_select_all_1) self.__btn_select_all.connect_clicked(self.__on_btn_select_all) self.__btn_select_none = ToolbarButton(theme.mb_btn_select_none_1) self.__btn_select_none.connect_clicked(self.__on_btn_select_none) self.__btn_select_done = ToolbarButton(theme.mb_btn_select_done_1) self.__btn_select_done.connect_clicked(self.__on_btn_select_done) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__now_playing, "now-playing") self.__arr.add(self.__browser, "browser") self.__arr.add(self.__toolbar, "toolbar") self.add(self.__arr) self.__arr.set_visible(False) # we have to fill the menu with content before showing the window on # Maemo5 or the window will show no menu at all self.__update_menu() self.set_visible(True) def __update_menu(self): folder = self.__browser.get_current_folder() repeat_selected = [mb_config.REPEAT_MODE_NONE, mb_config.REPEAT_MODE_ALL, mb_config.REPEAT_MODE_ONE] \ .index(mb_config.repeat_mode()) shuffle_selected = [mb_config.SHUFFLE_MODE_NONE, mb_config.SHUFFLE_MODE_ONE] \ .index(mb_config.shuffle_mode()) self.set_menu_choice("repeat", [(theme.mb_repeat_none, "No Repeat"), (theme.mb_repeat_all, "Repeat All"), (theme.mb_repeat_one, "Repeat One")], repeat_selected, True, self.__on_menu_repeat) self.set_menu_choice("shuffle", [(theme.mb_shuffle_none, "No Shuffle"), (theme.mb_shuffle_one, "Shuffle")], shuffle_selected, True, self.__on_menu_shuffle) if (folder and folder.folder_flags & folder.ITEMS_ADDABLE): self.set_menu_item("add", "Add New", True, self.__on_menu_add) else: self.set_menu_item("add", "Add New", False, self.__on_menu_add) self.set_menu_item("openurl", "Open URL...", True, self.__on_menu_open_url) self.set_menu_item("downloads", "Active Downloads", True, self.__on_menu_downloads) self.set_menu_item("select", "Select Items for Action", True, self.__on_menu_select) #self.set_menu_item("rearrange", "Rearrange Items", True, # self.__on_menu_rearrange) #self.set_menu_item("info", "About", True, # self.__on_menu_info) def __update_layout(self): w, h = self.get_size() if (w < h): # portrait mode self.__arr.set_xml(_PORTRAIT_ARRANGEMENT) else: # landscape mode self.__arr.set_xml(_LANDSCAPE_ARRANGEMENT) def __update_toolbar(self): """ Updates the contents of the toolbar. """ cwd = self.__browser.get_current_folder() if (self.__mode == _MODE_NORMAL): items = [self.__btn_home, self.__btn_history, self.__btn_back] else: items = [ self.__btn_select_all, self.__btn_select_none, self.__btn_select_done ] self.__toolbar.set_toolbar(*items) def __update_items_per_row(self, folder): w, h = self.get_size() if (w > h): w -= 180 if (folder and folder.folder_flags & folder.ITEMS_COMPACT): if (w > 0): per_row = w / 160 else: per_row = 3 #if (w < h): self.__browser.set_items_per_row(per_row) #else: # self.__browser.set_items_per_row(4) else: self.__browser.set_items_per_row(1) #self.__browser.invalidate() #self.__browser.render() """ def _visibility_changed(self): Window._visibility_changed(self) if (self.is_visible()): self.__tn_scheduler.resume() else: self.__tn_scheduler.halt() """ def __on_key_press(self, keycode): w, h = self.get_size() if (w < h and mb_config.portrait_swap_volume() and keycode in _PORTRAIT_MODE_KEYSWAP): keycode = _PORTRAIT_MODE_KEYSWAP[keycode] handled = self.call_service(msgs.INPUT_SVC_SEND_KEY, keycode, True) if (not handled): """ if (len(keycode) == 1 and ord(keycode) > 31): cnt = 0 for item in self.__browser.get_items(): if (item.get_name().upper().startswith(keycode.upper())): self.__browser.scroll_to_item(cnt) break cnt += 1 #end for """ if (len(keycode) == 1 and ord(keycode) > 31): self.__filter_term += keycode self.__update_filter() elif (keycode == "BackSpace" and self.__filter_term): self.__filter_term = self.__filter_term[:len(self.__filter_term ) - 1] self.__update_filter() def __update_filter(self): def filter_func(item): return self.__filter_term.upper() in item.get_name().upper() + "#" + \ item.get_file().info.upper() if (self.__filter_term): self.__browser.set_filter(filter_func) self.__browser.set_message("Filter: %s (%d matches)" \ % (self.__filter_term, self.__browser.count_items())) else: self.__browser.set_filter() self.__browser.set_message("") self.__browser.invalidate() self.__browser.render() def __on_close_window(self): self.emit_message(msgs.MEDIA_ACT_STOP) self.emit_message(msgs.COM_EV_APP_SHUTDOWN) gtk.main_quit() def __on_menu_repeat(self, choice): if (choice == 0): mb_config.set_repeat_mode(mb_config.REPEAT_MODE_NONE) elif (choice == 1): mb_config.set_repeat_mode(mb_config.REPEAT_MODE_ALL) elif (choice == 2): mb_config.set_repeat_mode(mb_config.REPEAT_MODE_ONE) def __on_menu_shuffle(self, choice): if (choice == 0): mb_config.set_shuffle_mode(mb_config.SHUFFLE_MODE_NONE) elif (choice == 1): mb_config.set_shuffle_mode(mb_config.SHUFFLE_MODE_ONE) def __on_menu_rearrange(self): def on_done(): for item in self.__browser.get_items(): item.set_draggable(False) self.__browser.invalidate() self.__update_toolbar() for item in self.__browser.get_items(): item.set_draggable(True) self.__browser.invalidate() btn_done = ImageButton(theme.mb_btn_history_1, theme.mb_btn_history_2) btn_done.connect_clicked(on_done) self.__toolbar.set_toolbar(btn_done) def __on_menu_open_url(self): dlg = InputDialog("URL to open") dlg.add_input("URL", "http://") if (dlg.run() == dlg.RETURN_OK): url = dlg.get_values()[0] self.__load_uri(url, "") #end if def __on_menu_downloads(self): self.emit_message(msgs.UI_ACT_SHOW_DIALOG, "downloader.DownloadManager") def __on_menu_fmtx(self): import platforms platforms.plugin_execute("libcpfmtx.so") def __on_menu_select(self): if (self.__browser.begin_bulk_action()): self.__mode = _MODE_SELECT self.__update_toolbar() #end if def __on_menu_add(self): folder = self.__browser.get_current_folder() if (folder): folder.new_file() def __on_menu_info(self): self.__show_dialog("core.AboutDialog") def __on_open_file(self, f): self.__load_file(f, True) def __on_begin_folder(self, f): self.__tn_scheduler.new_schedule(25, self.__on_load_thumbnail) self.__tn_scheduler.halt() self.set_flag(windowflags.BUSY, True) self.__browser.set_filter() self.__filter_term = "" self.__update_layout() self.__update_menu() self.__update_items_per_row(f) self.__browser.render() # set platform-specific click behavior if (platforms.MAEMO4): self.__browser.set_click_behavior( self.__browser.CLICK_BEHAVIOR_DOUBLE) else: self.__browser.set_click_behavior( self.__browser.CLICK_BEHAVIOR_SINGLE) def __on_progress_folder(self, f, c): if (not c.icon): items = self.__browser.get_items() item = items[-1] thumbpath, is_final = \ self.call_service(msgs.THUMBNAIL_SVC_LOOKUP_THUMBNAIL, c) item.set_icon(thumbpath) if (not is_final): self.__tn_scheduler.add(item, c, False) #end if def __on_complete_folder(self, f): self.set_flag(windowflags.BUSY, False) names = [p.name for p in self.__browser.get_path()] #title = u" \u00bb ".join(names) title = names[-1] names.reverse() acoustic_title = "Entering " + " in ".join(names) self.set_title(title) self.emit_message(msgs.UI_ACT_TALK, acoustic_title) self.emit_message(msgs.CORE_EV_FOLDER_VISITED, f) self.__update_toolbar() if (self.is_visible()): self.__tn_scheduler.resume() def __on_shift_item(self, pos, amount): if (self.__browser.get_current_folder() == self.__play_folder): # force invalidation of play files self.__play_files = [] def __update_thumbnail(self, item, thumbpath): item.set_icon(thumbpath) try: idx = self.__browser.get_items().index(item) self.__browser.invalidate_item(idx) except: pass def __on_load_thumbnail(self, item, f, quick): """ Scheduler callback handler for loading the next thumbnail. """ def on_loaded(thumbpath): if (thumbpath): self.__update_thumbnail(item, thumbpath) # priorize visible items top_idx = self.__browser.get_item_at(0, 0) if (top_idx != -1): items = self.__browser.get_items() if (top_idx < len(items)): self.__tn_scheduler.priorize(items[top_idx:top_idx + 12]) #end if gobject.idle_add(self.__tn_scheduler.resume) # load thumbnail self.__tn_scheduler.halt() if (quick): thumbpath, is_final = \ self.call_service(msgs.THUMBNAIL_SVC_LOOKUP_THUMBNAIL, f) on_loaded(thumbpath) if (not is_final): #print "SCHEDULING THUMBNAIL", c self.__tn_scheduler.add(item, f, False) self.__tn_scheduler.resume() else: self.call_service(msgs.THUMBNAIL_SVC_LOAD_THUMBNAIL, f, on_loaded) def __on_btn_home(self): """ Reacts on pressing the [Home] button. """ self.emit_message(msgs.SSDP_ACT_SEARCH_DEVICES) self.__browser.go_root() def __on_btn_history(self): """ Reacts on pressing the [History] button. """ f = self.call_service(msgs.CORE_SVC_GET_FILE, "history:///") if (f): self.__browser.load_folder(f, self.__browser.GO_CHILD, True) def __on_btn_bookmarks(self): """ Reacts on pressing the [Bookmarks] button. """ f = self.call_service(msgs.CORE_SVC_GET_FILE, "bookmarks://generic/") if (f): self.__browser.load_folder(f, self.__browser.GO_PARENT, True) def __on_btn_back(self): """ Reacts on pressing the [Back] button. """ self.__browser.go_parent() #self.__update_items_per_row(self.__browser.get_current_folder()) def __on_btn_select_all(self): """ Reacts on pressing the [Select All] button. """ self.__browser.select_all() def __on_btn_select_none(self): """ Reacts on pressing the [Select None] button. """ self.__browser.unselect_all() def __on_btn_select_done(self): """ Reacts on pressing the [Select Done] button. """ self.__mode = _MODE_NORMAL self.__update_toolbar() self.__browser.perform_bulk_action() def __load_uri(self, uri, mimetype): if (not mimetype): ext = os.path.splitext(uri)[1] mimetype = mimetypes.ext_to_mimetype(ext) f = self.call_service(msgs.CORE_SVC_GET_FILE, "adhoc://" + File.pack_path("/", uri, mimetype)) print "Loading URI:", f if (f): self.__load_file(f, True) def __load_file(self, f, is_manual): """ Loads the given file. """ #if (f.mimetype == "application/x-applet"): # applet_id = f.resource # self.call_service(msgs.CORE_SVC_LAUNCH_APPLET, applet_id) stopwatch = logging.stopwatch() if (f.mimetype == f.CONFIGURATOR): cfg_name = f.resource self.emit_message(msgs.UI_ACT_SHOW_DIALOG, cfg_name) else: if (is_manual): self.__show_dialog("player.PlayerWindow") #if (not f.mimetype in mimetypes.get_image_types()): self.emit_message(msgs.MEDIA_ACT_STOP) self.emit_message(msgs.MEDIA_ACT_LOAD, f) # update set of play files self.__current_file = f folder = self.__browser.get_current_folder() if (is_manual and folder != self.__play_folder): self.__play_folder = folder self.__random_files = [] self.__invalidate_play_files() logging.profile(stopwatch, "[navigator] loaded file") def __go_previous(self): now = time.time() if (not self.__play_files): self.__invalidate_play_files() try: idx = self.__play_files.index(self.__current_file) except ValueError: return False if (idx > 0): next_item = self.__play_files[idx - 1] self.__load_file(next_item, False) logging.profile(now, "[navigator] loaded previous item") def __go_next(self): stopwatch = logging.stopwatch() if (not self.__play_files): self.__invalidate_play_files() repeat_mode = mb_config.repeat_mode() shuffle_mode = mb_config.shuffle_mode() if (repeat_mode == mb_config.REPEAT_MODE_NONE): if (shuffle_mode == mb_config.SHUFFLE_MODE_NONE): self.__play_next(False) elif (shuffle_mode == mb_config.SHUFFLE_MODE_ONE): self.__play_shuffled(False) elif (shuffle_mode == mb_config.SHUFFLE_MODE_ALL): self.__play_shuffled(True) elif (repeat_mode == mb_config.REPEAT_MODE_ONE): if (self.__current_file): self.__play_same() else: self.__play_next(True) elif (repeat_mode == mb_config.REPEAT_MODE_ALL): if (shuffle_mode == mb_config.SHUFFLE_MODE_NONE): self.__play_next(True) elif (shuffle_mode == mb_config.SHUFFLE_MODE_ONE): self.__play_shuffled(False) elif (shuffle_mode == mb_config.SHUFFLE_MODE_ALL): self.__play_shuffled(True) logging.profile(stopwatch, "[navigator] loaded next item") def __play_same(self): self.__load_file(self.__current_file, False) return True def __play_next(self, wraparound): try: idx = self.__play_files.index(self.__current_file) except: idx = -1 if (idx + 1 < len(self.__play_files)): next_item = self.__play_files[idx + 1] self.__load_file(next_item, False) return True elif (wraparound): next_item = self.__play_files[0] self.__load_file(next_item, False) return True else: return False """ self.__play_folder = self.__browser.get_current_folder() self.__invalidate_play_files() if (self.__play_files): next_item = self.__play_files[0] self.__load_file(next_item, False) return True else: return False """ def __play_shuffled(self, from_all): if (from_all): # TODO... pass if (not self.__random_files): self.__random_files = self.__play_files[:] idx = random.randint(0, len(self.__random_files) - 1) next_item = self.__random_files.pop(idx) logging.debug("[navigator] picking random item %d of %d: %s", idx, len(self.__random_files), str(next_item)) self.__load_file(next_item, False) return True def __invalidate_play_files(self): """ Invalidates the play files and random files and rebuilds them. """ profile_now = time.time() prev_play_files = self.__play_files self.__play_files = [ f for f in self.__play_folder.get_children() if not f.mimetype.endswith("-folder") ] size = len(self.__play_files) img_size = len([ f for f in self.__play_files if f.mimetype in mimetypes.get_image_types() ]) ratio = img_size / float(size) if (ratio < 0.5): self.__play_files = [ f for f in self.__play_files if not f.mimetype in mimetypes.get_image_types() ] new_files = [f for f in self.__play_files if not f in prev_play_files] self.__random_files = [ f for f in self.__random_files if f in self.__play_files ] + new_files logging.profile(profile_now, "[navigator] invalidated list of files " \ "to play") def __filter_play_files(self): """ Filters the list of playfiles to see if there's cover art to remove from the list. """ if (not self.__play_files): return now = time.time() size = len(self.__play_files) img_size = len([ f for f in self.__play_files if f.mimetype in mimetypes.get_image_types() ]) ratio = img_size / float(size) if (ratio < 0.5): self.__play_files = [ f for f in self.__play_files if not f.mimetype in mimetypes.get_image_types() ] self.__random_files = [ f for f in self.__random_files if f in self.__play_files ] logging.profile(now, "[navigator] filtered items to play " \ "(removed cover art)") def __show_dialog(self, name): """ Shows the dialog with the given name. """ #print name, self.__dialogs dialogs = [d for d in self.__dialogs if repr(d) == name] if (dialogs): dlg = dialogs[0] dlg.set_visible(True) #end if def __save_state(self): # save state for next start path = [f.full_path for f in self.__browser.get_path_stack()] play_files = [f.full_path for f in self.__play_files] state.save(_STATEFILE, path, play_files, self.__play_folder and self.__play_folder.full_path or "", self.__current_file and self.__current_file.full_path or "") def render_this(self): w, h = self.get_size() if ((w, h) != self.__window_size): self.__update_items_per_row(self.__browser.get_current_folder()) self.__window_size = (w, h) if (self.__arr.is_visible()): Window.render_this(self) elif (self.__is_shutdown): x, y = self.get_screen_pos() screen = self.get_screen() screen.fill_area(x, y, w, h, theme.color_mb_background) screen.draw_centered_text(values.NAME + " " + values.VERSION, theme.font_mb_headline, x, h / 2 - 30, w, 30, theme.color_mb_text) screen.draw_centered_text(values.COPYRIGHT, theme.font_mb_plain, x, h / 2, w, 30, theme.color_mb_text) screen.draw_centered_text("Exiting...", theme.font_mb_plain, x, h - 80, w, 20, theme.color_mb_text) screen.fit_pixbuf(theme.mb_logo, w - 120, h - 120, 120, 120) else: x, y = self.get_screen_pos() screen = self.get_screen() screen.fill_area(x, y, w, h, theme.color_mb_background) screen.draw_centered_text(values.NAME + " " + values.VERSION, theme.font_mb_headline, x, h / 2 - 30, w, 30, theme.color_mb_text) screen.draw_centered_text(values.COPYRIGHT, theme.font_mb_plain, x, h / 2, w, 30, theme.color_mb_text) screen.draw_centered_text("Loading... Please Wait", theme.font_mb_plain, x, h - 80, w, 20, theme.color_mb_text) screen.fit_pixbuf(theme.mb_logo, w - 120, h - 120, 120, 120) def handle_COM_EV_COMPONENT_LOADED(self, component): if (isinstance(component, Dialog)): if (repr(component) in [repr(d) for d in self.__dialogs]): logging.error("a dialog with ID '%s' exists already.", repr(component)) else: self.__dialogs.append(component) #component.set_parent_window(self) elif (isinstance(component, Widget)): if (repr(component) in [repr(d) for d in self.__widgets]): pass else: self.__widgets.append(component) def handle_COM_EV_APP_STARTED(self): logging.profile(values.START_TIME, "[app] startup complete") # load state try: path, play_files, play_folder, current_file = state.load( _STATEFILE) path_stack = [] for p in path: f = self.call_service(msgs.CORE_SVC_GET_FILE, p) if (f): path_stack.append(f) self.emit_message(msgs.CORE_EV_FOLDER_VISITED, f) #end if #end for self.__browser.set_path_stack(path_stack) #self.__play_files = [ self.call_service(msgs.CORE_SVC_GET_FILE, p) # for p in play_files # if self.call_service(msgs.CORE_SVC_GET_FILE, p) ] self.__play_folder = self.call_service(msgs.CORE_SVC_GET_FILE, play_folder) self.__current_file = self.call_service(msgs.CORE_SVC_GET_FILE, current_file) except: logging.warning("could not restore navigator state:\n%s", logging.stacktrace()) self.__arr.set_visible(True) self.render() if (values.uri and (values.uri.startswith("http://") or os.path.exists(values.uri))): ext = os.path.splitext(values.uri)[1] mimetype = mimetypes.ext_to_mimetype(ext) f = self.call_service( msgs.CORE_SVC_GET_FILE, "adhoc://" + File.pack_path("/", values.uri, mimetype)) self.__load_file(f, True) #end if def handle_COM_EV_APP_SHUTDOWN(self): self.__is_shutdown = True #self.render() #while (gtk.events_pending()): gtk.main_iteration(True) self.__save_state() def handle_CORE_EV_THEME_CHANGED(self): self.render() def handle_CORE_EV_DEVICE_ADDED(self, ident, device): if (repr(device) == "navigator.RootDevice"): self.__browser.set_root_device(device) def handle_UI_ACT_SHOW_INFO(self, msg): dlg = InfoDialog(msg, self) dlg.run() def handle_UI_ACT_SHOW_DIALOG(self, name): self.__show_dialog(name) def handle_CORE_EV_FOLDER_INVALIDATED(self, folder): logging.debug("[navigator] invalidating folder %s", str(folder)) if (self.is_visible()): self.__browser.invalidate_folder(folder) if (folder and folder == self.__play_folder): self.__invalidate_play_files() """ prev_play_files = self.__play_files[:] self.__play_files = [ fl for fl in folder.get_children() if not fl.mimetype.endswith("-folder") ] # remove from random files what's no longer there and add to random # files what's new in play files logging.debug("[navigator] updating random items after folder " \ "invalidation") l = len(self.__random_files) self.__random_files = [ f for f in self.__play_files if f in self.__random_files or f not in prev_play_files ] logging.debug("[navigator] previously %d random items, now %d", l, len(self.__random_files)) """ def handle_CORE_EV_DEVICE_REMOVED(self, dev_id): folder = self.__browser.get_current_folder() if (folder.device_id == dev_id): self.__browser.go_root() def handle_ASR_ACT_ENABLE(self, value): self.set_flag(windowflags.ASR, value) def handle_ASR_EV_PORTRAIT(self): self.set_flag(windowflags.PORTRAIT, True) #self.__update_items_per_row(self.__browser.get_current_folder()) def handle_ASR_EV_LANDSCAPE(self): self.set_flag(windowflags.PORTRAIT, False) #self.__update_items_per_row(self.__browser.get_current_folder()) def handle_MEDIA_EV_LOADED(self, player, f): if (not self.__now_playing.is_visible()): self.__update_layout() self.__browser.hilight_file(f) self.__browser.render() def handle_MEDIA_ACT_LOAD_URI(self, uri, mimetype): self.__load_uri(uri, mimetype) def handle_MEDIA_ACT_CHANGE_PLAY_FOLDER(self, folder): self.__play_folder = folder self.__play_files = [ fl for fl in self.__browser.get_files() if not fl.mimetype.endswith("-folder") ] logging.debug("[navigator] clearing random items") self.__random_files = [] def handle_MEDIA_ACT_PREVIOUS(self): self.__go_previous() def handle_MEDIA_ACT_NEXT(self): self.__go_next() def handle_INPUT_EV_UP(self, pressed): if (self.is_visible()): self.__browser.move(0, -80) def handle_INPUT_EV_DOWN(self, pressed): if (self.is_visible()): self.__browser.move(0, 80) def handle_INPUT_EV_KEY(self, key, pressed): if (self.is_visible()): print "GOT KEY", key
class ImageViewer(Player): """ Player component for viewing images. """ def __init__(self): self.__is_fullscreen = False self.__zoom_handler = None # whether the slideshow is playing self.__is_playing = False # slideshow handler self.__slideshow_handler = None # slideshow timeout in milliseconds self.__slideshow_timeout = 3000 Player.__init__(self) self.__image = Image() self.__image.set_background(theme.color_image_viewer_background) #self.add(self.__image) kscr = KineticScroller(self.__image) gestures = Gestures(self.__image) gestures.connect_twirl(self.__on_twirl_gesture, kscr) gestures.connect_release(self.__on_release, kscr) #gestures.connect_hold(self.__on_hold) #gestures.connect_tap_hold(self.__on_tap_hold) gestures.connect_tap_tap(self.__on_tap_tap) gestures.connect_swipe(self.__on_swipe) # toolbar self.__btn_play = ToolbarButton(theme.mb_btn_play_1) self.__btn_play.connect_clicked(self.__on_btn_play) btn_previous = ToolbarButton(theme.mb_btn_previous_1) btn_previous.connect_clicked(self.__on_btn_previous) btn_next = ToolbarButton(theme.mb_btn_next_1) btn_next.connect_clicked(self.__on_btn_next) self.__toolbar = Toolbar() self.__toolbar.set_toolbar(btn_previous, self.__btn_play, btn_next) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__image, "image") self.__arr.add(self.__toolbar, "toolbar") #self.__arr.add(self.__volume_slider, "slider") self.add(self.__arr) def __update_layout(self): w, h = self.get_size() if (w < h): self.__arr.set_xml(_PORTRAIT_ARRANGEMENT) else: self.__arr.set_xml(_LANDSCAPE_ARRANGEMENT) def __slideshow_timer(self): gtk.main_iteration(False) if (self.__is_playing and self.may_render()): self.__image.slide_from_right() self.emit_message(msgs.MEDIA_ACT_NEXT) return True else: self.__btn_play.set_icon(theme.mb_btn_play_1) self.__slideshow_handler = None self.__is_playing = False self.emit_message(msgs.MEDIA_EV_PAUSE) return False def __on_btn_play(self): self.__is_playing = not self.__is_playing if (self.__is_playing): dlg = InputDialog("Slideshow Settings") dlg.add_range("Seconds between slides:", 1, _SLIDESHOW_MAX_TIMEOUT, 3) ret = dlg.run() if (ret != dlg.RETURN_OK): return secs = dlg.get_values()[0] self.__slideshow_timeout = int(secs * 1000) self.__btn_play.set_icon(theme.mb_btn_pause_1) self.emit_message(msgs.MEDIA_EV_PLAY) if (self.__slideshow_handler): gobject.source_remove(self.__slideshow_handler) self.__slideshow_handler = gobject.timeout_add( self.__slideshow_timeout, self.__slideshow_timer) else: self.__btn_play.set_icon(theme.mb_btn_play_1) def __on_btn_previous(self): self.__image.slide_from_left() self.emit_message(msgs.MEDIA_ACT_PREVIOUS) def __on_btn_next(self): self.__image.slide_from_right() self.emit_message(msgs.MEDIA_ACT_NEXT) def __on_twirl_gesture(self, direction, kscr): kscr.set_enabled(False) if (direction > 0): self.__image.zoom_in() else: self.__image.zoom_out() def __on_release(self, px, py, kscr): kscr.set_enabled(True) if (self.__zoom_handler): gobject.source_remove(self.__zoom_handler) def __on_hold(self, px, py): if (self.__zoom_handler): gobject.source_remove(self.__zoom_handler) self.__zoom_handler = gobject.timeout_add(50, self.__on_zoom_gesture, 1) def __on_tap_hold(self, px, py): if (self.__zoom_handler): gobject.source_remove(self.__zoom_handler) self.__zoom_handler = gobject.timeout_add(50, self.__on_zoom_gesture, -1) def __on_zoom_gesture(self, direction): if (direction < 0): self.__image.zoom_out(False) elif (direction > 0): self.__image.zoom_in(False) return True def __on_tap_tap(self, px, py): self.__toggle_fullscreen() def __on_swipe(self, direction): if (self.__image.is_image_fitting()): if (direction > 0): self.__image.slide_from_left() self.emit_message(msgs.MEDIA_ACT_PREVIOUS) else: self.__image.slide_from_right() self.emit_message(msgs.MEDIA_ACT_NEXT) def __toggle_fullscreen(self): self.__is_fullscreen = not self.__is_fullscreen if (self.__is_fullscreen): self.__toolbar.set_visible(False) self.__image.set_background( theme.color_image_viewer_background_fullscreen) else: self.__toolbar.set_visible(True) self.__image.set_background(theme.color_image_viewer_background) self.emit_message(msgs.UI_ACT_FULLSCREEN, self.__is_fullscreen) self.__update_layout() self.render() def render_this(self): x, y = self.get_screen_pos() w, h = self.get_size() screen = self.get_screen() #screen.fill_area(x, y, w, h, theme.color_mb_background) self.__arr.set_geometry(0, 0, w, h) def get_mime_types(self): return ["image/*"] def load(self, f): self.__image.load(f) self.emit_message(msgs.MEDIA_EV_LOADED, self, f) self.render() def handle_MEDIA_ACT_PAUSE(self): if (self.is_player_active()): self.__on_btn_play() def handle_INPUT_EV_VOLUME_UP(self, pressed): if (self.is_visible() and self.__image): self.__image.zoom_in(False) def handle_INPUT_EV_VOLUME_DOWN(self, pressed): if (self.is_visible() and self.__image): self.__image.zoom_out(False)
def __init__(self): # cover pixbuf self.__cover = None self.__cover_scaled = None self.__have_cover = False # lyrics text with hilights formatting self.__lyrics = "" self.__player = None self.__context_id = 0 self.__volume = 0 self.__offscreen_buffer = None # the currently playing file object (e.g. used for bookmarking) self.__current_file = None Player.__init__(self) self.set_visible(False) self.__trackinfo = InfoBox() # volume slider self.__volume_slider = Slider(theme.mb_list_slider) self.__volume_slider.set_mode(Slider.VERTICAL) self.__volume_slider.connect_value_changed(self.__on_change_volume) # progress bar self.__progress = MediaProgressBar(MediaProgressBar.DOWN) self.__progress.connect_changed(self.__on_seek) self.__progress.connect_bookmark_changed(self.__on_change_bookmark) # star button for bookmarks #self.__btn_star = ImageButton(theme.mb_btn_bookmark_1, # theme.mb_btn_bookmark_2) #self.__btn_star.connect_clicked(self.__on_btn_star) # toolbar elements self.__btn_play = ToolbarButton(theme.mb_btn_play_1) self.__btn_play.connect_clicked(self.__on_btn_play) btn_previous = ToolbarButton(theme.mb_btn_previous_1) btn_previous.connect_clicked(self.__on_btn_previous) btn_next = ToolbarButton(theme.mb_btn_next_1) btn_next.connect_clicked(self.__on_btn_next) # toolbar self.__toolbar = Toolbar() self.__toolbar.set_toolbar(btn_previous, self.__btn_play, btn_next) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__toolbar, "toolbar") self.__arr.add(self.__progress, "progress") #self.__arr.add(self.__btn_star, "btn_star") self.__arr.add(self.__volume_slider, "slider") self.__arr.add(self.__trackinfo, "trackinfo") self.add(self.__arr)
class AudioPlayer(Player): """ Player component for playing audio files. """ def __init__(self): # cover pixbuf self.__cover = None self.__cover_scaled = None self.__have_cover = False # lyrics text with hilights formatting self.__lyrics = "" self.__player = None self.__context_id = 0 self.__volume = 0 self.__offscreen_buffer = None # the currently playing file object (e.g. used for bookmarking) self.__current_file = None Player.__init__(self) self.set_visible(False) self.__trackinfo = InfoBox() # volume slider self.__volume_slider = Slider(theme.mb_list_slider) self.__volume_slider.set_mode(Slider.VERTICAL) self.__volume_slider.connect_value_changed(self.__on_change_volume) # progress bar self.__progress = MediaProgressBar(MediaProgressBar.DOWN) self.__progress.connect_changed(self.__on_seek) self.__progress.connect_bookmark_changed(self.__on_change_bookmark) # star button for bookmarks #self.__btn_star = ImageButton(theme.mb_btn_bookmark_1, # theme.mb_btn_bookmark_2) #self.__btn_star.connect_clicked(self.__on_btn_star) # toolbar elements self.__btn_play = ToolbarButton(theme.mb_btn_play_1) self.__btn_play.connect_clicked(self.__on_btn_play) btn_previous = ToolbarButton(theme.mb_btn_previous_1) btn_previous.connect_clicked(self.__on_btn_previous) btn_next = ToolbarButton(theme.mb_btn_next_1) btn_next.connect_clicked(self.__on_btn_next) # toolbar self.__toolbar = Toolbar() self.__toolbar.set_toolbar(btn_previous, self.__btn_play, btn_next) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__toolbar, "toolbar") self.__arr.add(self.__progress, "progress") #self.__arr.add(self.__btn_star, "btn_star") self.__arr.add(self.__volume_slider, "slider") self.__arr.add(self.__trackinfo, "trackinfo") self.add(self.__arr) def _reload(self): theme.color_mb_background.reload() def set_size(self, w, h): if ((w, h) != self.get_size()): self.__offscreen_buffer = Pixmap(None, w, h) self.__cover_scaled = None Player.set_size(self, w, h) def __update_layout(self): w, h = self.get_size() if (w < h): #self.__btn_star.set_visible(False) self.__arr.set_xml(_PORTRAIT_ARRANGEMENT) else: #self.__btn_star.set_visible(True) self.__arr.set_xml(_LANDSCAPE_ARRANGEMENT) def __set_cover(self, pbuf): if (not self.__cover): self.__cover = pbuf self.__cover_scaled = None def __set_lyrics(self, words, hi_from, hi_to): # reset cover buffer because we'll draw it tinted now if (not self.__lyrics): self.__cover_scaled = None if (hi_from > 0 or hi_to < len(words) - 1): self.__lyrics = "%s<span color='red'>%s</span>%s" \ % (textutils.escape_xml(words[:hi_from]), textutils.escape_xml(words[hi_from:hi_to]), textutils.escape_xml(words[hi_to:])) else: self.__lyrics = textutils.escape_xml(words) def get_mime_types(self): return ["application/ogg", "audio/*"] def __on_btn_play(self): if (self.__player): self.__player.pause() def __on_btn_previous(self): self.emit_message(msgs.MEDIA_ACT_PREVIOUS) def __on_btn_next(self): self.emit_message(msgs.MEDIA_ACT_NEXT) def __on_change_player_status(self, ctx_id, status): if (ctx_id == self.__context_id): if (status == self.__player.STATUS_PLAYING): self.__btn_play.set_icon(theme.mb_btn_pause_1) self.emit_message(msgs.MEDIA_EV_PLAY) elif (status == self.__player.STATUS_STOPPED): self.__btn_play.set_icon(theme.mb_btn_play_1) self.emit_message(msgs.MEDIA_EV_PAUSE) elif (status == self.__player.STATUS_EOF): self.__btn_play.set_icon(theme.mb_btn_play_1) self.emit_message(msgs.MEDIA_EV_EOF) self.emit_message(msgs.MEDIA_ACT_NEXT) elif (status == self.__player.STATUS_CONNECTING): self.__progress.set_message("Connecting") elif (status == self.__player.STATUS_BUFFERING): self.__progress.set_message("Buffering") def __on_change_bookmark(self): media_bookmarks.set_bookmarks(self.__current_file, self.__progress.get_bookmarks()) def __on_error(self, ctx_id, err): if (ctx_id == self.__context_id and self.__player): self.emit_message(msgs.UI_ACT_SHOW_INFO, self.__player.ERRORS[err]) def __on_seek(self, progress): if (self.__player): self.__player.seek_percent(progress) def __on_update_position(self, ctx_id, pos, total): if (ctx_id == self.__context_id): self.__progress.set_position(pos, total) self.__progress.set_message("%s / %s" \ % (self.seconds_to_hms(pos), self.seconds_to_hms(total))) self.emit_message(msgs.MEDIA_EV_POSITION, pos, total) def __on_discovered_tags(self, ctx_id, tags): if (ctx_id == self.__context_id): title = tags.get("TITLE") album = tags.get("ALBUM") artist = tags.get("ARTIST") cover = tags.get("PICTURE") if (title): self.__trackinfo.set_title(title) self.emit_message(msgs.MEDIA_EV_TAG, "TITLE", title) if (album): self.__trackinfo.set_album(album) self.emit_message(msgs.MEDIA_EV_TAG, "ALBUM", album) if (artist): self.__trackinfo.set_artist(artist) self.emit_message(msgs.MEDIA_EV_TAG, "ARTIST", artist) if (cover and not self.__have_cover): imageloader.load_data(cover, self.__on_loaded_cover, self.__context_id, time.time()) self.__have_cover = True #end if def __on_change_volume(self, v): if (self.__player): vol = int(v * 100) self.__player.set_volume(vol) self.__volume = vol def __on_change_player_volume(self, v): if (v != self.__volume): self.__volume_slider.set_value(v / 100.0) self.__volume = v def __on_loaded_cover(self, pbuf, ctx_id, stopwatch): if (ctx_id == self.__context_id and not self.__have_cover): self.__cover = None if (pbuf): self.__set_cover(pbuf) self.emit_message(msgs.MEDIA_EV_TAG, "PICTURE", pbuf) self.__have_cover = True else: self.__cover = None self.__cover_scaled = None self.emit_message(msgs.MEDIA_EV_TAG, "PICTURE", None) if (self.__offscreen_buffer): self.render_buffered(self.__offscreen_buffer) #end if logging.profile(stopwatch, "[audioplayer] loaded cover art") def __load_track_info(self, item): stopwatch = logging.stopwatch() tags = tagreader.get_tags(item) logging.profile(stopwatch, "[audioplayer] retrieved audio tags") gobject.timeout_add(0, self.__on_track_info, item, tags) def __on_track_info(self, item, tags): logging.debug("[audioplayer] processing track info") title = tags.get("TITLE") or item.name artist = tags.get("ARTIST") or "-" album = tags.get("ALBUM") or "-" self.__trackinfo.set_title(title) self.__trackinfo.set_album(album) self.__trackinfo.set_artist(artist) if (self.__offscreen_buffer): self.render_buffered(self.__offscreen_buffer) # load cover art self.call_service(msgs.COVERSTORE_SVC_GET_COVER, item, self.__on_loaded_cover, self.__context_id, logging.stopwatch()) stopwatch = logging.stopwatch() self.emit_message(msgs.MEDIA_EV_TAG, "TITLE", title) self.emit_message(msgs.MEDIA_EV_TAG, "ARTIST", artist) self.emit_message(msgs.MEDIA_EV_TAG, "ALBUM", album) logging.profile(stopwatch, "[audioplayer] propagated audio tags") def __scale_cover(self, is_tinted): w, h = self.get_size() if (w < h): h -= (100 + 100) else: w -= 100 h -= 100 p_w = self.__cover.get_width() p_h = self.__cover.get_height() factor1 = w / float(p_w) factor2 = h / float(p_h) #print (p_w, p_h), (w, h), factor1, factor2 if (p_h * factor1 < h): factor = factor2 else: factor = factor1 s_w = int(w / factor) s_h = int(h / factor) crop_x = (p_w - s_w) / 2 crop_y = (p_h - s_h) / 3 crop_w = s_w crop_h = s_h #print "CROP", (crop_x, crop_y), (crop_w, crop_h), "->", (w, h) self.__cover_scaled = self.__cover.subpixbuf(crop_x, crop_y, crop_w, crop_h) \ .scale_simple(w, h, gtk.gdk.INTERP_BILINEAR) if (is_tinted): self.__cover_scaled = self.__cover_scaled.composite_color_simple( w, h, gtk.gdk.INTERP_NEAREST, 0x60, w, 0, 0) def __render_lyrics(self): x, y = self.get_screen_pos() w, h = self.get_size() screen = self.get_screen() if (self.__lyrics): #self.__buffer.draw_frame(theme.mb_lyrics_box, bx, by, bw, bh, True) #screen.fill_area(x + 8, y + 8, w - 16, 200, "#000000a0") screen.draw_formatted_text(self.__lyrics, theme.font_mb_headline, x + 50, y + 8, w - 100, 200, theme.color_audio_player_lyrics, screen.LEFT, True) def __render_background(self): x, y = self.get_screen_pos() w, h = self.get_size() screen = self.get_screen() if (w < h): h -= (100 + 100) else: w -= 100 h -= 100 if (self.__cover): if (not self.__cover_scaled): self.__scale_cover((self.__lyrics != "")) screen.draw_pixbuf(self.__cover_scaled, x, y) #screen.fill_area(x, y, w, h, "#000000a0") self.__volume_slider.set_background( self.__cover_scaled.subpixbuf(0, 0, 40, h - 48)) self.__progress.set_background( self.__cover_scaled.subpixbuf(0, h - 48, w, 48)) else: screen.fill_area(x, y, w, h, theme.color_mb_background) p_w = theme.mb_unknown_album.get_width() p_h = theme.mb_unknown_album.get_height() screen.draw_pixbuf(theme.mb_unknown_album, x + (w - p_w) / 2, y + (h - p_h) / 2) self.__volume_slider.set_background(None) self.__progress.set_background(None) def render_this(self): x, y = self.get_screen_pos() w, h = self.get_size() screen = self.get_screen() self.__render_background() self.__render_lyrics() self.__arr.set_geometry(0, 0, w, h) #x, y = self.__progress.get_screen_pos() #w, h = self.__progress.get_size() #self.__progress.set_background(screen.subpixmap(x, y, w, h)) def load(self, f): self.__lyrics = "" self.__have_cover = False stopwatch = logging.stopwatch() self.__player = self.call_service(msgs.MEDIA_SVC_GET_OUTPUT) self.__player.connect_status_changed(self.__on_change_player_status) self.__player.connect_volume_changed(self.__on_change_player_volume) self.__player.connect_position_changed(self.__on_update_position) self.__player.connect_tag_discovered(self.__on_discovered_tags) self.__player.connect_error(self.__on_error) logging.profile(stopwatch, "[audioplayer] connected audio output") try: stopwatch = logging.stopwatch() self.__context_id = self.__player.load_audio(f) logging.profile(stopwatch, "[audioplayer] loaded media file: %s", f) except: logging.error("error loading media file: %s\n%s", f, logging.stacktrace()) stopwatch = logging.stopwatch() self.__current_file = f logging.profile(stopwatch, "[audioplayer] loaded track info") # load bookmarks self.__progress.set_bookmarks(media_bookmarks.get_bookmarks(f)) self.emit_message(msgs.MEDIA_EV_LOADED, self, f) t = threading.Thread(target = self.__load_track_info, args = [f]) t.setDaemon(True) gobject.idle_add(lambda *x:t.start() and False) if (self.__offscreen_buffer): self.render_buffered(self.__offscreen_buffer) def set_bookmark(self): self.__progress.add_bookmark() def handle_MEDIA_EV_LYRICS(self, words, hi_from, hi_to): self.__set_lyrics(words, hi_from, hi_to) if (self.__offscreen_buffer): self.render_buffered(self.__offscreen_buffer) def handle_MEDIA_ACT_PLAY(self): if (self.__player and self.is_player_active()): self.__player.play() def handle_MEDIA_ACT_PAUSE(self): if (self.__player and self.is_player_active()): self.__player.pause() def handle_MEDIA_ACT_STOP(self): if (self.__player and self.is_player_active()): self.__player.stop() def handle_MEDIA_ACT_SEEK(self, pos): if (self.__player and self.is_player_active()): self.__player.seek(pos) def handle_INPUT_EV_VOLUME_UP(self, pressed): self.__volume = min(100, self.__volume + 5) self.__volume_slider.set_value(self.__volume / 100.0) if (self.__player): self.__player.set_volume(self.__volume) def handle_INPUT_EV_VOLUME_DOWN(self, pressed): self.__volume = max(0, self.__volume - 5) self.__volume_slider.set_value(self.__volume / 100.0) if (self.__player): self.__player.set_volume(self.__volume) def handle_INPUT_EV_PLAY(self, pressed): if (self.is_visible() and self.__player): self.__player.pause() def handle_COM_EV_APP_SHUTDOWN(self): if (self.__player): self.__player.close()
def __init__(self): self.__is_fullscreen = False self.__volume = 50 self.__player = None self.__context_id = 0 self.__is_playing = False self.__blanking_handler = None self.__load_failed_handler = None # the currently playing file object (e.g. used for bookmarking) self.__current_file = None Player.__init__(self) # video screen self.__screen = VideoScreen() gestures = Gestures(self.__screen) gestures.connect_tap(self.__on_tap) gestures.connect_tap_tap(self.__on_tap_tap) gestures.connect_swipe(self.__on_swipe) # volume slider self.__volume_slider = Slider(theme.mb_list_slider) self.__volume_slider.set_mode(Slider.VERTICAL) self.__volume_slider.connect_value_changed(self.__on_change_volume) # progress bar self.__progress = MediaProgressBar(MediaProgressBar.UP) self.__progress.connect_changed(self.__on_seek) self.__progress.connect_bookmark_changed(self.__on_change_bookmark) # star button for bookmarks #self.__btn_star = ImageButton(theme.mb_btn_bookmark_1, # theme.mb_btn_bookmark_2) #self.__btn_star.connect_clicked(self.__on_btn_star) # toolbar elements self.__btn_play = ToolbarButton(theme.mb_btn_play_1) self.__btn_play.connect_clicked(self.__on_btn_play) btn_previous = ToolbarButton(theme.mb_btn_previous_1) btn_previous.connect_clicked(self.__on_btn_previous) btn_next = ToolbarButton(theme.mb_btn_next_1) btn_next.connect_clicked(self.__on_btn_next) # toolbar self.__toolbar = Toolbar() self.__toolbar.set_toolbar(btn_previous, self.__btn_play, btn_next) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__screen, "screen") self.__arr.add(self.__toolbar, "toolbar") self.__arr.add(self.__progress, "progress") #self.__arr.add(self.__btn_star, "btn_star") self.__arr.add(self.__volume_slider, "slider") self.add(self.__arr)
class VideoPlayer(Player): """ Player component for playing videos. """ def __init__(self): self.__is_fullscreen = False self.__volume = 50 self.__player = None self.__context_id = 0 self.__is_playing = False self.__blanking_handler = None self.__load_failed_handler = None # the currently playing file object (e.g. used for bookmarking) self.__current_file = None Player.__init__(self) # video screen self.__screen = VideoScreen() gestures = Gestures(self.__screen) gestures.connect_tap(self.__on_tap) gestures.connect_tap_tap(self.__on_tap_tap) gestures.connect_swipe(self.__on_swipe) # volume slider self.__volume_slider = Slider(theme.mb_list_slider) self.__volume_slider.set_mode(Slider.VERTICAL) self.__volume_slider.connect_value_changed(self.__on_change_volume) # progress bar self.__progress = MediaProgressBar(MediaProgressBar.UP) self.__progress.connect_changed(self.__on_seek) self.__progress.connect_bookmark_changed(self.__on_change_bookmark) # star button for bookmarks #self.__btn_star = ImageButton(theme.mb_btn_bookmark_1, # theme.mb_btn_bookmark_2) #self.__btn_star.connect_clicked(self.__on_btn_star) # toolbar elements self.__btn_play = ToolbarButton(theme.mb_btn_play_1) self.__btn_play.connect_clicked(self.__on_btn_play) btn_previous = ToolbarButton(theme.mb_btn_previous_1) btn_previous.connect_clicked(self.__on_btn_previous) btn_next = ToolbarButton(theme.mb_btn_next_1) btn_next.connect_clicked(self.__on_btn_next) # toolbar self.__toolbar = Toolbar() self.__toolbar.set_toolbar(btn_previous, self.__btn_play, btn_next) # arrangement self.__arr = Arrangement() self.__arr.connect_resized(self.__update_layout) self.__arr.add(self.__screen, "screen") self.__arr.add(self.__toolbar, "toolbar") self.__arr.add(self.__progress, "progress") #self.__arr.add(self.__btn_star, "btn_star") self.__arr.add(self.__volume_slider, "slider") self.add(self.__arr) def __update_layout(self): w, h = self.get_size() #if (self.__is_fullscreen): # self.__btn_star.set_visible(False) #else: # self.__btn_star.set_visible(True) if (w < h): self.__arr.set_xml(_PORTRAIT_ARRANGEMENT) else: self.__arr.set_xml(_LANDSCAPE_ARRANGEMENT) def __on_btn_play(self): if (self.__player): if (not self.__is_playing): self.__wait_for_dsp() self.__player.pause() def __on_btn_previous(self): self.emit_message(msgs.MEDIA_ACT_PREVIOUS) def __on_btn_next(self): self.emit_message(msgs.MEDIA_ACT_NEXT) def __on_tap(self, px, py): self.__toggle_fullscreen() def __on_tap_tap(self, px, py): self.__toggle_fullscreen() def __on_swipe(self, direction): if (self.__player): if (direction < 0): self.__player.rewind() elif (direction > 0): self.__player.forward() #end if def __on_status_changed(self, ctx_id, status): if (ctx_id == self.__context_id): if (status == self.__player.STATUS_PLAYING): self.__btn_play.set_icon(theme.mb_btn_pause_1) if (self.__load_failed_handler): gobject.source_remove(self.__load_failed_handler) self.__is_playing = True self.__progress.set_message("") self.emit_message(msgs.MEDIA_EV_PLAY) # we need manual unblanking on Maemo5 for videos if (not self.__blanking_handler and platforms.PLATFORM == platforms.MAEMO5): self.__blanking_handler = gobject.timeout_add( 23000, self.__inhibit_blanking) #end if elif (status == self.__player.STATUS_STOPPED): self.__btn_play.set_icon(theme.mb_btn_play_1) self.__is_playing = False self.call_service(msgs.VIDEOPLAYER_SVC_RELEASE_DSP) self.emit_message(msgs.MEDIA_EV_PAUSE) elif (status == self.__player.STATUS_EOF): self.__btn_play.set_icon(theme.mb_btn_play_1) self.__is_playing = False self.call_service(msgs.VIDEOPLAYER_SVC_RELEASE_DSP) self.emit_message(msgs.MEDIA_EV_EOF) self.emit_message(msgs.MEDIA_ACT_NEXT) elif (status == self.__player.STATUS_CONNECTING): self.__progress.set_message("Connecting") elif (status == self.__player.STATUS_BUFFERING): self.__progress.set_message("Buffering") def __on_update_position(self, ctx_id, pos, total): if (ctx_id == self.__context_id): self.__progress.set_position(pos, total) self.__progress.set_message("%s / %s" \ % (self.seconds_to_hms(pos), self.seconds_to_hms(total))) self.emit_message(msgs.MEDIA_EV_POSITION, pos, total) def __on_change_volume(self, v): if (self.__player): vol = int(v * 100) self.__player.set_volume(vol) self.__volume = vol def __on_change_player_volume(self, v): if (v != self.__volume): self.__volume_slider.set_value(v / 100.0) self.__volume = v def __on_change_player_aspect_ratio(self, ctx_id, r): if (ctx_id == self.__context_id and self.__player): self.__screen.set_aspect_ratio(r) def __on_change_bookmark(self): media_bookmarks.set_bookmarks(self.__current_file, self.__progress.get_bookmarks()) def __on_error(self, ctx_id, err): if (ctx_id == self.__context_id and self.__player): self.emit_message(msgs.UI_ACT_SHOW_INFO, self.__player.ERRORS[err]) def __on_seek(self, progress): if (self.__player): self.__player.seek_percent(progress) def __inhibit_blanking(self): if (self.__is_playing): platforms.inhibit_screen_blanking() return True else: self.__blanking_handler = None return False def __toggle_fullscreen(self): self.__is_fullscreen = not self.__is_fullscreen if (self.__is_fullscreen): self.__progress.set_visible(False) self.__volume_slider.set_visible(False) self.__toolbar.set_visible(False) #self.__btn_star.set_visible(False) else: self.__progress.set_visible(True) self.__volume_slider.set_visible(True) self.__toolbar.set_visible(True) #self.__btn_star.set_visible(True) self.__update_layout() self.emit_message(msgs.UI_ACT_FULLSCREEN, self.__is_fullscreen) #self.render() def _visibility_changed(self): # force video to landscape mode on Maemo win = self.get_window() if (win): # and platforms.MAEMO5): if (self.is_visible()): print "show video" logging.debug("[videoplayer] forcing landscape mode") self.emit_message(msgs.ASR_ACT_ENABLE, False) self.emit_message(msgs.ASR_EV_LANDSCAPE) else: print "hide video" self.emit_message(msgs.ASR_ACT_RESTORE) #end if self.__screen.render() #set_visible(self.is_visible()) def render_this(self): x, y = self.get_screen_pos() w, h = self.get_size() screen = self.get_screen() if (w == 0 or h == 0): return if (self.__is_fullscreen): screen.fill_area(x, y, w, h, "#000000") else: screen.fill_area(x, y, w, h, theme.color_mb_background) self.__arr.set_geometry(0, 0, w, h) if (w < h): self.__screen.set_visible(False) if (platforms.MAEMO4): screen.draw_centered_text("Video cannot be displayed in\n" \ "portrait mode.", theme.font_mb_plain, 0, h / 2 - 80, w, 0, theme.color_mb_text) else: self.__screen.set_visible(True) def get_mime_types(self): return ["video/*"] def __wait_for_dsp(self): self.__progress.set_message("Waiting for DSP") self.call_service(msgs.VIDEOPLAYER_SVC_LOCK_DSP) self.__progress.set_message("") def __on_load_failed(self): self.__load_failed_handler = None self.call_service(msgs.VIDEOPLAYER_SVC_RELEASE_DSP) def load(self, f): self.render() self.__wait_for_dsp() self.__player = self.call_service(msgs.MEDIA_SVC_GET_OUTPUT) self.__player.connect_status_changed(self.__on_status_changed) self.__player.connect_position_changed(self.__on_update_position) self.__player.connect_volume_changed(self.__on_change_player_volume) self.__player.connect_aspect_changed( self.__on_change_player_aspect_ratio) self.__player.connect_error(self.__on_error) self.__player.set_window(self.__screen.get_xid()) # loading may fail, so we need to setup a handler that frees the DSP # semaphore after some time if (self.__load_failed_handler): gobject.source_remove(self.__load_failed_handler) self.__load_failed_handler = gobject.timeout_add( 30000, self.__on_load_failed) try: self.__progress.set_message("Loading") self.__context_id = self.__player.load_video(f) self.__current_file = f # load bookmarks self.__progress.set_bookmarks(media_bookmarks.get_bookmarks(f)) self.emit_message(msgs.MEDIA_EV_LOADED, self, f) except: self.__progress.set_message("Error") logging.error("[videoplayer] error loading media file: %s\n%s", f, logging.stacktrace()) def set_bookmark(self): self.__progress.add_bookmark() def handle_MEDIA_ACT_PLAY(self): if (self.__player and self.is_player_active()): if (not self.__is_playing): self.__wait_for_dsp() self.__player.play() def handle_MEDIA_ACT_PAUSE(self): if (self.__player and self.is_player_active()): if (not self.__is_playing): self.__wait_for_dsp() self.__player.pause() def handle_MEDIA_ACT_STOP(self): if (self.__player and self.is_player_active()): self.__player.stop() def handle_MEDIA_ACT_SEEK(self, pos): if (self.__player and self.is_player_active()): self.__player.seek(pos) def handle_INPUT_EV_FULLSCREEN(self, pressed): if (self.is_visible()): self.__toggle_fullscreen() def handle_INPUT_EV_VOLUME_UP(self, pressed): self.__volume = min(100, self.__volume + 5) self.__volume_slider.set_value(self.__volume / 100.0) if (self.__player): self.__player.set_volume(self.__volume) def handle_INPUT_EV_VOLUME_DOWN(self, pressed): self.__volume = max(0, self.__volume - 5) self.__volume_slider.set_value(self.__volume / 100.0) if (self.__player): self.__player.set_volume(self.__volume) def handle_COM_EV_APP_SHUTDOWN(self): if (self.__player): self.__player.close()