Esempio n. 1
0
    def __init__(self):

        self.__current_page = 0
        self.__pages = []

        data = open(os.path.join(_PATH, "tour_C.dat")).read()
        self.__parse_tour(data)

        Configurator.__init__(self)

        self.__tour_box = Widget()

        # toolbar elements
        btn_toc = ToolbarButton(theme.mb_btn_toc_1)
        btn_toc.connect_clicked(self.__on_btn_toc)

        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, btn_toc, btn_next)

        # arrangement
        self.__arr = Arrangement()
        self.__arr.connect_resized(self.__update_layout)
        self.__arr.add(self.__tour_box, "content")
        self.__arr.add(self.__toolbar, "toolbar")
        self.add(self.__arr)
Esempio n. 2
0
    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)
Esempio n. 3
0
    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)
Esempio n. 4
0
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
Esempio n. 5
0
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)
Esempio n. 6
0
    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)
Esempio n. 7
0
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()
Esempio n. 8
0
    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)
Esempio n. 9
0
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()
Esempio n. 10
0
class Tour(Configurator):
    """
    Configurator providing a short tour through the application.
    """

    ICON = theme.prefs_icon_get_started
    TITLE = "Get Started"
    DESCRIPTION = "Learn how to use MediaBox"

    def __init__(self):

        self.__current_page = 0
        self.__pages = []

        data = open(os.path.join(_PATH, "tour_C.dat")).read()
        self.__parse_tour(data)

        Configurator.__init__(self)

        self.__tour_box = Widget()

        # toolbar elements
        btn_toc = ToolbarButton(theme.mb_btn_toc_1)
        btn_toc.connect_clicked(self.__on_btn_toc)

        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, btn_toc, btn_next)

        # arrangement
        self.__arr = Arrangement()
        self.__arr.connect_resized(self.__update_layout)
        self.__arr.add(self.__tour_box, "content")
        self.__arr.add(self.__toolbar, "toolbar")
        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 __on_btn_previous(self):

        self.__go_back()

    def __on_btn_toc(self):

        dlg = ListDialog("Table of Contents")
        cnt = 0
        for title, image, text in self.__pages:
            item = LabelItem(title)
            item.set_payload(cnt)
            dlg.add_item(item)
            cnt += 1
        #end for

        dlg.run()
        item = dlg.get_choice()
        if (item):
            idx = item.get_payload()
            self.__go_page(idx)

    def __on_btn_next(self):

        self.__go_forward()

    def __on_click(self, px, py):

        w, h = self.get_size()
        if (px < w / 2):
            self.__go_back()
        else:
            self.__go_forward()

    def __go_back(self):

        self.__go_page(self.__current_page - 1)

    def __go_forward(self):

        self.__go_page(self.__current_page + 1)

    def __go_page(self, idx):

        if (0 <= idx < len(self.__pages)):
            if (idx < self.__current_page):
                slide_mode = self.SLIDE_RIGHT
            else:
                slide_mode = self.SLIDE_LEFT

            self.__current_page = idx

            title, image, text = self.__pages[self.__current_page]
            self.set_title(title.strip())

            w, h = self.get_size()
            buf = Pixmap(None, w, h)
            self.render_at(buf)

            box_x, box_y = self.__tour_box.get_screen_pos()
            box_w, box_h = self.__tour_box.get_size()
            self.fx_slide_horizontal(buf, box_x, box_y, box_w, box_h,
                                     slide_mode)
        #end if

    def __parse_tour(self, data):

        self.__pages = []
        title = ""
        image = ""
        text = ""

        section = 0
        subsection = 0
        for line in data.splitlines():
            if (line.startswith("#")):
                continue

            elif (line.startswith("BEGIN")):
                section += 1
                subsection = 0
                title = "%d. %s" % (section, line[6:].strip())
                image = ""
                text = ""

            elif (line.startswith("SUBBEGIN")):
                subsection += 1
                title = "%d.%d %s" % (section, subsection, line[9:].strip())
                image = ""
                text = ""

            elif (line.startswith("IMAGE ")):
                image = line[6:].strip()

            elif (line.startswith("END")):
                self.__pages.append((title, image, text))

            else:
                text += line + "\n"
        #end for

    def _visibility_changed(self):

        self.__current_page = 0
        Configurator._visibility_changed(self)

    def render_this(self):

        Configurator.render_this(self)
        self.__render_tour()

    def __render_tour(self):

        self.__arr.render()
        x, y = self.__tour_box.get_screen_pos()
        w, h = self.__tour_box.get_size()
        screen = self.__tour_box.get_screen()

        title, image, text = self.__pages[self.__current_page]
        self.set_title(title.strip())

        screen.fill_area(x, y, w, h, theme.color_mb_background)

        #screen.draw_text("%d/%d" % (self.__current_page + 1, len(self.__pages)),
        #                 theme.font_mb_tiny,
        #                 x + w - 42, y + 4,
        #                 theme.color_mb_text)

        if (w < h):
            # portrait mode
            title_x, title_y = 4, 4
            image_x, image_y = 90, 4
            if (image):
                text_x, text_y = 4, 320
                text_w, text_h = w - 8, 240
            else:
                text_x, text_y = 4, 4
                text_w, text_h = w - 8, 540

        else:
            # landscape mode
            title_x, title_y = 4, 4
            image_x, image_y = 40, 4
            if (image):
                text_x, text_y = 380, 4
                text_w, text_h = 320, 320
            else:
                text_x, text_y = 4, 4
                text_w, text_h = w - 88, 320

        if (image):
            pbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(_PATH, image))
            img_w, img_h = pbuf.get_width(), pbuf.get_height()
            image_x += (300 - img_w) / 2
            image_y += (300 - img_h) / 2
            screen.draw_pixbuf(pbuf, x + image_x, y + image_y)

        if (text):
            screen.draw_formatted_text(text, theme.font_mb_plain, x + text_x,
                                       y + text_y, text_w, text_h,
                                       theme.color_mb_text)