Exemple #1
0
class PhonePrefs(Configurator):
    """
    Configurator for setting the phone behavior.
    """

    ICON = theme.prefs_icon_phone
    TITLE = "Phone Behavior"
    DESCRIPTION = "Configure the phone behavior"

    def __init__(self):

        Configurator.__init__(self)

        self.__list = ThumbableGridView()
        self.add(self.__list)

        lbl = LabelItem("Behavior after a phone call:")
        self.__list.append_item(lbl)

        chbox = OptionItem("Resume playing", config.RESUME_AUTOMATIC,
                           "Stay paused", config.RESUME_MANUAL)
        chbox.connect_changed(self.__on_select_phonecall_resume)
        self.__list.append_item(chbox)

        self.__label_info = LabelItem("")
        self.__list.append_item(self.__label_info)
        chbox.select_by_value(config.get_phonecall_resume())

    def __on_select_phonecall_resume(self, value):

        config.set_phonecall_resume(value)
        self.__label_info.set_text(_DESCRIPTIONS[value])
        self.__list.invalidate()
        self.__list.render()
Exemple #2
0
class DisplayLightPrefs(Configurator):
    """
    Configurator for setting the display light behavior.
    """

    ICON = theme.prefs_icon_displaylight
    TITLE = "Display Light"
    DESCRIPTION = "Configure the display light"

    def __init__(self):

        Configurator.__init__(self)

        self.__list = ThumbableGridView()
        self.add(self.__list)

        lbl = LabelItem("Keep display lit:")
        #lbl.set_font(theme.font_mb_headline)
        self.__list.append_item(lbl)

        chbox = OptionItem("never", "no", "while playing", "playing")
        #"yes", "yes")
        chbox.connect_changed(self.__on_select_display_lit)
        self.__list.append_item(chbox)

        self.__label_lit = LabelItem("")
        self.__list.append_item(self.__label_lit)
        chbox.select_by_value(config.get_display_lit())

    def __on_select_display_lit(self, value):

        config.set_display_lit(value)
        self.__label_lit.set_text(_DESCRIPTIONS[value])
        self.__list.invalidate()
        self.__list.render()
Exemple #3
0
class DownloadManager(Dialog):
    """
    Dialog for managing active downloads.
    """
    def __init__(self):

        # table: download ID -> item
        self.__items = {}

        Dialog.__init__(self)
        self.set_title("Active Downloads")

        self.__list = ThumbableGridView()
        self.add(self.__list)

    def __on_click_item(self, download_id):

        dlg = OptionDialog("Abort this download?")
        dlg.add_option(None, "Yes, abort")
        dlg.add_option(None, "No, continue")

        if (dlg.run() == dlg.RETURN_OK):
            choice = dlg.get_choice()
            if (choice == 0):
                self.emit_message(msgs.DOWNLOADER_ACT_ABORT, download_id)
        #end if

    def handle_DOWNLOADER_EV_STARTED(self, download_id, url, destination):

        item = DownloadItem(url, destination)
        self.__items[download_id] = item
        self.__list.append_item(item)

        item.connect_clicked(self.__on_click_item, download_id)

    def handle_DOWNLOADER_EV_FINISHED(self, download_id):

        item = self.__items.get(download_id)
        if (item):
            del self.__items[download_id]
            pos = self.__list.get_items().index(item)
            self.__list.remove_item(pos)
            self.__list.invalidate()
            self.__list.render()

    def handle_DOWNLOADER_EV_ABORTED(self, download_id):

        item = self.__items.get(download_id)
        if (item):
            del self.__items[download_id]
            pos = self.__list.get_items().index(item)
            self.__list.remove_item(pos)
            self.__list.invalidate()
            self.__list.render()

    def handle_DOWNLOADER_EV_PROGRESS(self, download_id, name, amount, total):

        item = self.__items.get(download_id)
        if (item):
            item.set_amount(amount, total)
            item.set_destination(name)
            idx = self.__list.get_items().index(item)
            self.__list.invalidate_item(idx)
Exemple #4
0
class WebAccess(Configurator):
    """
    Component for remote-access with a web browser.
    
    The web server accepts:
    
     - MediaBox media paths (e.g. media:///) in URL-safe form
     - theme graphics paths (e.g. theme.mb_btn_dir_up_1)
     
    The parameter 'clientid' is supplied to associate the client with a path
    history in the navigator. Stateless requests may omit this parameter.
    
    The parameter 'action' specifies how the server should react on a certain
    path:
    
     - open:            opens a directory (this is the default action)
     - load:            transfers the file's contents to the client
     - play:            plays media in MediaBox
     - nav-up:          moves to the parent folder
     - nav-shelf:       moves to the shelf
     - media-pause:     play/pause action on MediaBox
     - media-previous:  goes to the previous track
     - media-next:      goes to the next track
    """

    ICON = theme.mb_logo
    TITLE = "Web Access"
    DESCRIPTION = "Access and remote-control MediaBox"

    __client_cnt = 0

    def __init__(self):

        # table: clientid -> path_stack
        self.__path_stacks = {}

        self.__current_file = None
        self.__artist = ""
        self.__title = ""

        Configurator.__init__(self)

        self.__list = ThumbableGridView()
        self.add(self.__list)

        lbl = LabelItem("MediaBox WebAccess lets you access your media and " \
                        "remote-control MediaBox with a web browser.")
        self.__list.append_item(lbl)

        lbl = LabelItem("This is still an experimental feature and not " \
                        "fully working yet!")
        self.__list.append_item(lbl)

        chbox = OptionItem("WebAccess is Off", "off", "WebAccess is On", "on")
        chbox.select_by_value("off")
        chbox.connect_changed(self.__on_toggle_webaccess)
        self.__list.append_item(chbox)

        self.__lbl_info = LabelItem("")
        self.__list.append_item(self.__lbl_info)

    def __on_toggle_webaccess(self, value):
        """
        Reacts on toggling the WebAccess in the configurator.
        """

        ip = network.get_ip()
        if (value == "on"):
            error = self.call_service(msgs.HTTPSERVER_SVC_BIND, self, ip,
                                      _PORT)
            if (error):
                self.__lbl_info.set_text("Error: %s" % error)
            else:
                self.__lbl_info.set_text("WebAccess-URL: http://%s:%d" %
                                         (ip, _PORT))
            self.__list.render()
        else:
            self.call_service(msgs.HTTPSERVER_SVC_UNBIND, self, ip, _PORT)
            self.__lbl_info.set_text("")

        self.__list.invalidate()
        self.__list.render()

    def __send_contents(self, request, clientid, folder, contents):
        """
        Sends the list of contents to the client.
        """

        if (self.__title):
            now_playing = self.__title
            if (self.__artist):
                now_playing += " / " + self.__artist
        elif (self.__current_file):
            now_playing = self.__current_file.name + "   " + \
                          self.__current_file.info
        else:
            now_playing = ""

        html = pages.render_json_contents(clientid, contents)
        request.send_html(html)

    def handle_HTTPSERVER_EV_REQUEST(self, owner, request):
        def on_child(f, folder, contents):
            if (f):
                # look up thumbnail
                if (not f.icon):
                    icon, is_final = self.call_service(
                        msgs.THUMBNAIL_SVC_LOOKUP_THUMBNAIL, f)
                else:
                    icon = f.icon
                contents.append((f, icon))
            else:
                self.__send_contents(request, clientid, folder, contents)

            return True

        if (owner != self): return

        path = urlquote.unquote(request.get_path())
        #if (not path):
        #    path = "media:///"

        if (path.startswith("theme.")):
            path = getattr(theme, path[6:]).get_path()

        # get parameters
        params = request.get_query()
        action = params.get("action", ["open"])[0]
        clientid = params.get("clientid", [""])[0]
        if (not clientid):
            clientid = str(self.__client_cnt)
            self.__client_cnt += 1

        # prepare path stack for client
        if (not clientid in self.__path_stacks):
            self.__path_stacks[clientid] = []
        path_stack = self.__path_stacks[clientid]

        print "requesting", clientid, path, action

        if (path == "/"):
            request.send_html(pages.render_page_browser(clientid))

        elif (path == "/nav-home"):
            f = self.call_service(msgs.CORE_SVC_GET_FILE, "media:///")
            path_stack[:] = [f]
            f.get_contents(0, 0, on_child, f, [])

        elif (path == "/nav-up"):
            if (len(path_stack) > 1):
                path_stack.pop()
                f = path_stack.pop()
            else:
                f = self.call_service(msgs.CORE_SVC_GET_FILE, "media:///")
                path_stack[:] = []

            path_stack.append(f)
            f.get_contents(0, 0, on_child, f, [])

        elif (path == "/open"):
            filepath = urlquote.unquote(params["path"][0])
            f = self.call_service(msgs.CORE_SVC_GET_FILE, filepath)

            if (f and f.mimetype.endswith("-folder")):
                path_stack.append(f)
                f.get_contents(0, 0, on_child, f, [])

            elif (f):
                parent = path_stack[-1]
                self.emit_message(msgs.MEDIA_ACT_LOAD, f)
                self.emit_message(msgs.MEDIA_ACT_CHANGE_PLAY_FOLDER, parent)
                request.send_html("<html><body>OK</body></html>")

            else:
                request.send_not_found("MediaBox WebAccess", filepath)

        elif (path == "/file"):
            filepath = urlquote.unquote(params["path"][0])
            f = self.call_service(msgs.CORE_SVC_GET_FILE, filepath)
            print "FILE", f, f.is_local
            if (f and f.is_local):
                request.send_file(open(f.get_resource(), "r"), f.name,
                                  f.mimetype)

        elif (path == "/theme"):
            filepath = urlquote.unquote(params["path"][0])
            pbuf = getattr(theme, filepath)
            request.send_file(open(pbuf.get_path(), "r"), filepath,
                              "image/x-png")

        elif (action == "volume-down"):
            self.emit_message(msgs.INPUT_EV_VOLUME_DOWN, True)
            request.send_html("<html><body>OK</body></html>")

        elif (action == "volume-up"):
            self.emit_message(msgs.INPUT_EV_VOLUME_UP, True)
            request.send_html("<html><body>OK</body></html>")

        elif (action == "media-previous"):
            self.emit_message(msgs.MEDIA_ACT_PREVIOUS)
            request.send_html("<html><body>OK</body></html>")

        elif (action == "media-next"):
            self.emit_message(msgs.MEDIA_ACT_NEXT)
            request.send_html("<html><body>OK</body></html>")

        elif (action == "media-pause"):
            self.emit_message(msgs.MEDIA_ACT_PAUSE)
            request.send_html("<html><body>OK</body></html>")

        elif (action == "ui-fullscreen"):
            self.emit_message(msgs.INPUT_EV_FULLSCREEN, True)
            request.send_html("<html><body>OK</body></html>")

        elif (action == "nav-up"):
            if (len(path_stack) > 1):
                path_stack.pop()
                f = path_stack.pop()
            else:
                f = self.call_service(msgs.CORE_SVC_GET_FILE, "media:///")
                path_stack[:] = []

            path_stack.append(f)
            f.get_contents(0, 0, on_child, f, [])

        elif (action == "nav-shelf"):
            f = self.call_service(msgs.CORE_SVC_GET_FILE, "media:///")
            path_stack[:] = [f]
            f.get_contents(0, 0, on_child, f, [])

        elif (action == "open"):
            f = self.call_service(msgs.CORE_SVC_GET_FILE, path)
            if (f):
                path_stack.append(f)
                print "opening", f.name
                f.get_contents(0, 0, on_child, f, [])
            else:
                request.send_not_found("MediaBox WebAccess", path)

        elif (action == "play"):
            f = self.call_service(msgs.CORE_SVC_GET_FILE, path)
            if (f):
                print "loading"
                parent = path_stack[-1]
                self.emit_message(msgs.MEDIA_ACT_LOAD, f)
                self.emit_message(msgs.MEDIA_ACT_CHANGE_PLAY_FOLDER, parent)
                request.send_html("<html><body>OK</body></html>")

            else:
                request.send_not_found("MediaBox WebAccess", path)

        else:
            f = self.call_service(msgs.CORE_SVC_GET_FILE, path)
            if (f and f.is_local):
                request.send_file(open(f.get_resource(), "r"), f.name,
                                  f.mimetype)

            elif (f and not f.is_local):
                request.send_redirect(f.get_resource())

            else:
                request.send_not_found("MediaBox WebAccess", path)

        #end if

    def handle_MEDIA_EV_LOADED(self, player, f):

        self.__current_file = f
        self.__artist = ""
        self.__title = ""

    def handle_MEDIA_EV_TAG(self, tag, value):

        if (tag == "ARTIST"):
            self.__artist = value
        elif (tag == "TITLE"):
            self.__title = value
Exemple #5
0
class RotationPrefs(Configurator):
    """
    Configurator for display rotation.
    """

    ICON = theme.prefs_icon_asr
    TITLE = "Display Orientation"
    DESCRIPTION = "Configure the display orientation"


    def __init__(self):
    
        self.__have_unapplied_changes = False
    
        Configurator.__init__(self)
        
        self.__list = ThumbableGridView()
        self.add(self.__list)
        
        #lbl = LabelItem("Orientation:")
        #self.__list.append_item(lbl)
        
        if (platforms.MAEMO5):
            chbox = OptionItem("Landscape Mode", config.ORIENTATION_LANDSCAPE,
                               "Portrait Mode", config.ORIENTATION_PORTRAIT,
                               "Automatic", config.ORIENTATION_AUTOMATIC)
        else:
            chbox = OptionItem("Landscape Mode", config.ORIENTATION_LANDSCAPE,
                               "Portrait Mode", config.ORIENTATION_PORTRAIT)
        
        chbox.connect_changed(self.__on_select_orientation)
        chbox.select_by_value(config.orientation())
        self.__list.append_item(chbox)

        # abusing empty label for space... TODO: implement space item :)
        #lbl = LabelItem("")
        #self.__list.append_item(lbl)

        chk = CheckBoxItem("Swap volume/zoom keys in portrait mode",
                           config.portrait_swap_volume())
        chk.connect_checked(self.__on_check_swap)
        self.__list.append_item(chk)


    def _visibility_changed(self):
    
        Configurator._visibility_changed(self)
        
        if (not self.is_visible() and self.__have_unapplied_changes):
            self.__have_unapplied_changed = False
            
            orientation = config.orientation()
            self.__set_orientation(orientation)


    def __on_select_orientation(self, value):
    
        self.__have_unapplied_changes = True

        self.__list.invalidate()
        self.__list.render()

        config.set_orientation(value)
        

    def __set_orientation(self, value):
    
        if (value == config.ORIENTATION_LANDSCAPE):
            self.emit_message(msgs.ASR_ACT_ENABLE, False)
            self.emit_message(msgs.ASR_EV_LANDSCAPE)
            logging.info("[rotation] landscape orientation")

        elif (value == config.ORIENTATION_PORTRAIT):
            self.emit_message(msgs.ASR_ACT_ENABLE, False)
            self.emit_message(msgs.ASR_EV_PORTRAIT)
            logging.info("[rotation] portrait orientation")

        else:
            self.emit_message(msgs.ASR_ACT_ENABLE, True)
            self.emit_message(msgs.ASR_EV_LANDSCAPE)
            logging.info("[rotation] automatic orientation")


    def __on_check_swap(self, v):
    
        config.set_portrait_swap_volume(v)
        self.__list.invalidate()
        self.__list.render()


    def __restore_orientation(self):

        o = config.orientation()
        self.__set_orientation(o)
        #if (o == config.ORIENTATION_PORTRAIT):
        #    self.emit_message(msgs.ASR_EV_PORTRAIT)
        #elif (o == config.ORIENTATION_AUTOMATIC):
        #    self.emit_message(msgs.ASR_ACT_ENABLE, True)
        #    self.emit_message(msgs.ASR_EV_LANDSCAPE)
            

    def handle_COM_EV_APP_STARTED(self):
    
        self.__restore_orientation()


    def handle_ASR_ACT_RESTORE(self):
    
        self.__restore_orientation()
Exemple #6
0
class FileScannerPrefs(Configurator):
    """
    Configurator for file indexing.
    """

    ICON = theme.prefs_icon_fileindex
    TITLE = "Media Indexing"
    DESCRIPTION = "Configure file indexing"

    def __init__(self):

        Configurator.__init__(self)

        self.__list = ThumbableGridView()
        self.add(self.__list)

        if (platforms.MAEMO4 or platforms.MAEMO5):
            if (platforms.MAEMO4): tracker = "Metalayer Crawler"
            elif (platforms.MAEMO5): tracker = "Tracker"
            lbl = LabelItem("Your device provides a tracker service (%s) for "
                            "discovering new media. MediaBox can use it for "
                            "scanning for new media." % tracker)
            self.__list.append_item(lbl)

            btn = ButtonItem("Look for new media now")
            btn.connect_clicked(self.__on_click_update)
            self.__list.append_item(btn)

            chk = CheckBoxItem("Look for new media at startup (recommended)",
                               mb_config.scan_at_startup())
            chk.connect_checked(self.__on_check_startup)
            self.__list.append_item(chk)

        else:
            lbl = LabelItem("Your device does not provide a tracker service for "
                            "discovering new media automatically. You can " \
                            "scan for new media manually by selecting " \
                            "'Scan for Media' from the item popup menu of a "\
                            "local folder.")
            self.__list.append_item(lbl)

            lbl = LabelItem("")
            self.__list.append_item(lbl)
        #end if

        lbl = LabelItem("By clearing the index, MediaBox forgets about all "
                        "media files until you have it scan for media again.")
        self.__list.append_item(lbl)

        btn = ButtonItem("Clear index now")
        btn.connect_clicked(self.__on_click_clear)
        self.__list.append_item(btn)


        lbl = LabelItem("At startup, MediaBox removes media that no longer "
                        "exists from the index. If necessary, you can trigger " \
                        "this manually anytime, too")
        self.__list.append_item(lbl)

        btn = ButtonItem("Remove dead entries from index")
        btn.connect_clicked(self.__on_click_bury)
        self.__list.append_item(btn)

    def __on_check_startup(self, value):

        mb_config.set_scan_at_startup(value)
        self.__list.invalidate()
        self.__list.render()

    def __on_click_update(self):

        self.emit_message(msgs.UI_ACT_SHOW_INFO, "Updating media index.")
        self.emit_message(msgs.FILEINDEX_ACT_SCAN)

    def __on_click_clear(self):

        self.emit_message(msgs.UI_ACT_SHOW_INFO, "Clearing media index.")
        self.emit_message(msgs.FILEINDEX_SVC_CLEAR)

    def __on_click_bury(self):

        self.emit_message(msgs.UI_ACT_SHOW_INFO,
                          "Removing dead entries from index.")
        self.emit_message(msgs.FILEINDEX_SVC_BURY)