Ejemplo n.º 1
0
    def open_url(self, url):
        # It looks like the maximum URL length is about 2k. I can't
        # seem to find the exact value
        if len(url) > 2047:
            url = url[:2047]
        try:
            webbrowser.get("windows-default").open_new(url)
        except:
            logging.warn("Error opening URL: %r\n%s", url,
                    traceback.format_exc())
            recommendURL = app.config.get(prefs.RECOMMEND_URL)

            if url.startswith(app.config.get(prefs.VIDEOBOMB_URL)):
                title = _('Error Bombing Item')
            elif url.startswith(recommendURL):
                title = _('Error Recommending Item')
            else:
                title = _("Error Opening Website")

            scheme, host, path, params, query, fragment = urlparse(url)
            shortURL = '%s:%s%s' % (scheme, host, path)
            msg = _(
                "There was an error opening %(url)s.  Please try again in a few "
                "seconds",
                {"url": shortURL}
            )
            dialogs.show_message(title, msg, dialogs.WARNING_MESSAGE)
Ejemplo n.º 2
0
Archivo: opml.py Proyecto: cool-RR/Miro
 def show_xml_error(self):
     title = _("OPML Import failed")
     message = _(
         "The selected OPML file appears to be invalid.  "
         "Import was interrupted.")
     dialog = dialogs.MessageBoxDialog(title, message)
     dialog.run()
Ejemplo n.º 3
0
Archivo: startup.py Proyecto: ndim/miro
def startup_for_frontend(obj, thread):
    """Run the startup code needed to get the frontend started

    This function should be kept as small as possible to ensure good startup
    times.
    """
    threadcheck.set_eventloop_thread(thread)
    logging.info("Installing deleted file checker...")
    item.setup_deleted_checker()
    logging.info("Restoring database...")
    start = time.time()
    app.db = storedatabase.LiveStorage()
    try:
        app.db.upgrade_database()
    except databaseupgrade.DatabaseTooNewError:
        summary = _("Database too new")
        description = _(
            "You have a database that was saved with a newer version of "
            "%(appname)s. You must download the latest version of "
            "%(appname)s and run that.",
            {"appname": app.config.get(prefs.SHORT_APP_NAME)},
        )
        raise StartupError(summary, description)
    except storedatabase.UpgradeErrorSendCrashReport, e:
        send_startup_crash_report(e.report)
        return
Ejemplo n.º 4
0
    def _run_downloader(self, url, content_type=None, title=None):
        if not self.id_exists():
            # we got deleted while we were doing the flash scraping
            return
        if content_type is not None:
            self.content_type = content_type
        if url is not None:
            if title is not None:
                for mem in self.item_list:
                    if not mem.title:
                        mem.title = title

            self.url = url
            logging.debug("downloading url %s", self.url)
            args = dict(url=self.url, content_type=self.content_type,
                        channel_name=self.channel_name)
            app.download_state_manager.add_download(self.dlid, self)
            app.download_state_manager.queue(self.dlid,
                                             app.download_state_manager.RESUME,
                                             args)
            self.state = u'downloading'
        else:
            self.state = u'failed'
            self.short_reason_failed = _('File not found')
            self.reason_failed = _('Flash URL Scraping Error')
        self.signal_change()
Ejemplo n.º 5
0
    def _run_downloader(self, url, content_type=None, title=None):
        if not self.id_exists():
            # we got deleted while we were doing the flash scraping
            return
        if content_type is not None:
            self.content_type = content_type
        if url is not None:
            if title is not None:
                # abuse the torrent_title attribute for this.  Since the file
                # comes from a flash site, we can be pretty sure that it's not
                # going to need it.
                for mem in self.item_list:
                    mem.set_torrent_title(title)

            self.url = url
            logging.debug("downloading url %s", self.url)
            args = dict(url=self.url, content_type=self.content_type,
                        channel_name=self.channel_name)
            app.download_state_manager.add_download(self.dlid, self)
            app.download_state_manager.queue(self.dlid,
                                             app.download_state_manager.RESUME,
                                             args)
            self.state = u'downloading'
        else:
            self.state = u'failed'
            self.short_reason_failed = _('File not found')
            self.reason_failed = _('Flash URL Scraping Error')
        self.signal_change()
Ejemplo n.º 6
0
 def _calc_retry_time(self):
     if self.retry_time > datetime.datetime.now():
         retry_delta = self.retry_time - datetime.datetime.now()
         time_str = displaytext.time_string(retry_delta.seconds)
         return _('no connection - retrying in %(time)s', {"time": time_str})
     else:
         return _('no connection - retrying soon')
Ejemplo n.º 7
0
    def build_widget(self):
        vbox = widgetset.VBox()

        grid = dialogwidgets.ControlGrid()
        
        count = get_logical_cpu_count()
        max_concurrent = []
        for i in range(0, count):
            max_concurrent.append((i+1, str(i+1)))
        max_concurrent_menu = widgetset.OptionMenu([op[1] for op in max_concurrent])
        attach_combo(max_concurrent_menu, prefs.MAX_CONCURRENT_CONVERSIONS, 
            [op[0] for op in max_concurrent])

        if count == 1:
            max_concurrent_menu.disable()

        grid.pack(dialogwidgets.label_with_note(
            _("Allow this many concurrent conversions:"),
            _("(changing this will not apply to currently running conversions)")),
            dialogwidgets.ControlGrid.ALIGN_RIGHT)
        grid.pack(max_concurrent_menu)
        grid.end_line(spacing=4)
        vbox.pack_start(widgetutil.align_left(grid.make_table()))

        pack_extras(vbox, "conversions")

        return vbox
Ejemplo n.º 8
0
    def adjustContent(self, videoWindow, animate):
        if videoWindow.is_fullscreen:
            self.popInOutButton.setHidden_(YES)
            self.popInOutLabel.setHidden_(YES)
            self.fsButton.setImage_(NSImage.imageNamed_('fs-button-exitfullscreen'))
            self.fsButton.setAlternateImage_(NSImage.imageNamed_('fs-button-exitfullscreen-alt'))
        else:
            if app.playback_manager.detached_window is None:
                image_path = resources.path('images/popout.png')
                label = _('Pop Out')
            else:
                image_path = resources.path('images/popin.png')
                label = _('Pop In')
            self.popInOutButton.setImage_(NSImage.alloc().initWithContentsOfFile_(image_path))
            self.popInOutButton.setHidden_(NO)
            self.popInOutLabel.setHidden_(NO)
            self.popInOutLabel.setStringValue_(label)
            self.fsButton.setImage_(NSImage.imageNamed_('fs-button-enterfullscreen'))
            self.fsButton.setAlternateImage_(NSImage.imageNamed_('fs-button-enterfullscreen-alt'))

        newFrame = self.window().frame() 
        if videoWindow.is_fullscreen or app.playback_manager.detached_window is not None: 
            self.titleLabel.setHidden_(NO)
            self.feedLabel.setHidden_(NO)
            newFrame.size.height = 198 
        else: 
            self.titleLabel.setHidden_(YES)
            self.feedLabel.setHidden_(YES)
            newFrame.size.height = 144
        newFrame.origin.x = self.getHorizontalPosition(videoWindow, newFrame.size.width)
        self.window().setFrame_display_animate_(newFrame, YES, animate)
        self.playbackControls.setNeedsDisplay_(YES)
Ejemplo n.º 9
0
 def _calc_retry_time(self):
     if self.status['retryTime'] > datetime.datetime.now():
         retry_delta = self.status['retryTime'] - datetime.datetime.now()
         time_str = displaytext.time_string(retry_delta.seconds)
         return _('no connection - retrying in %s') % time_str
     else:
         return _('no connection - retrying soon')
Ejemplo n.º 10
0
    def _run_downloader(self, url, contentType=None, title=None):
        if not self.id_exists():
            # we got deleted while we were doing the flash scraping
            return
        if contentType is not None:
            self.contentType = contentType
        if url is not None:
            if title is not None:
                for mem in self.item_list:
                    if not mem.title:
                        mem.title = title

            self.url = url
            logging.debug("downloading url %s", self.url)
            c = command.StartNewDownloadCommand(RemoteDownloader.dldaemon,
                                                self.url, self.dlid,
                                                self.contentType,
                                                self.channelName)
            c.send()
            _downloads[self.dlid] = self
        else:
            self.status["state"] = u'failed'
            self.status["shortReasonFailed"] = _('File not found')
            self.status["reasonFailed"] = _('Flash URL Scraping Error')
        self.signal_change()
Ejemplo n.º 11
0
 def _run_db_error_dialog(self):
     if self._db_retry_callback_pending:
         return
     gettext_values = {"appname": app.config.get(prefs.SHORT_APP_NAME)}
     title = _("%(appname)s database query failed", gettext_values)
     description = _("%(appname)s was unable to read from its database.", gettext_values)
     app.db_error_handler.run_dialog(title, description, self._retry_after_db_error)
Ejemplo n.º 12
0
def run_dialog():
    """Creates and launches the New Feed dialog.  This dialog waits for
    the user to press "Create Podcast" or "Cancel".

    Returns the URL, or None.
    """
    text = app.widgetapp.get_clipboard_text()
    if text and feed.validate_feed_url(text):
        text = feed.normalize_feed_url(text)
    else:
        text = ""

    title = _('Add Podcast')
    description = _('Enter the URL of the podcast to add')

    while 1:
        text = _run_dialog(title, description, initial_text=text)
        if text == None:
            return None

        normalized_url = feed.normalize_feed_url(text)
        if feed.validate_feed_url(normalized_url):
            return normalized_url

        title = _('Add Podcast - Invalid URL')
        description = _(
            'The address you entered is not a valid url.  '
            'Please check the URL and try again.'
            '\n\n'
            'Enter the URL of the podcast to add')
Ejemplo n.º 13
0
def add_subtitle_encoding_menu(menubar, category_label, *encodings):
    """Helper method to set up the subtitles encoding menu.

    This method should be called for each category of subtitle encodings (East
    Asian, Western European, Unicode, etc).  Pass it the list of encodings for
    that category.

    :param category_label: human-readable name for the category
    :param encodings: list of (label, encoding) tuples.  label is a
        human-readable name, and encoding is a value that we can pass to
        VideoDisplay.select_subtitle_encoding()
    """
    subtitles_menu = menubar.get("PlaybackMenu").get("SubtitlesMenu")
    try:
        encoding_menu = subtitles_menu.get("SubtitleEncodingMenu")
    except ValueError:
        # first time calling this function, we need to set up the menu.
        encoding_menu = Menu(_("_Encoding"), "SubtitleEncodingMenu", [], groups=["PlayingVideo"])
        subtitles_menu.append(encoding_menu)
        default_item = RadioMenuItem(
            _("Default (UTF-8)"), "SubtitleEncoding-Default", "subtitle-encoding", groups=["PlayingVideo"]
        )
        encoding_menu.append(default_item)
        app.menu_manager.subtitle_encoding_enabled = True

    category_menu = Menu(category_label, "SubtitleEncodingCat%s" % encoding_menu.count(), [], groups=["PlayingVideo"])
    encoding_menu.append(category_menu)

    for encoding, name in encodings:
        label = "%s (%s)" % (name, encoding)
        category_menu.append(
            RadioMenuItem(label, "SubtitleEncoding-%s" % encoding, "subtitle-encoding", groups=["PlayingVideo"])
        )
Ejemplo n.º 14
0
Archivo: style.py Proyecto: codito/miro
    def _calc_status_text(self):
        """Calculate the text/color for our status line.

        :returns: (text, color) tuple
        """
        if self.info.downloaded:
            if self.info.is_playable:
                if not self.info.video_watched:
                    return (_('Unplayed'), UNPLAYED_COLOR)
                elif self.info.expiration_date:
                    text = displaytext.expiration_date_short(
                            self.info.expiration_date)
                    return (text, EXPIRING_TEXT_COLOR)
        elif (self.info.download_info and
                self.info.download_info.rate == 0):
            if self.info.download_info.state == 'paused':
                return (_('paused'), DOWNLOADING_COLOR)
            elif self.info.download_info.state == 'pending':
                return (_('queued'), DOWNLOADING_COLOR)
            elif self.info.download_info.state == 'failed':
                return (self.info.download_info.short_reason_failed,
                        ERROR_COLOR)
            else:
                return (self.info.download_info.startup_activity,
                        DOWNLOADING_COLOR)
        elif not self.info.item_viewed:
            return (_('Newly Available'), AVAILABLE_COLOR)
        return ('', self.default_text_color)
Ejemplo n.º 15
0
    def get_metainfo(self):
        if self.metainfo is None:
            if self.url.startswith('file://'):
                path = get_file_url_path(self.url)
                try:
                    metainfoFile = open(path, 'rb')
                except IOError:
                    self.handle_error(
                        _("Torrent file deleted"),
                        _("The torrent file for this item was deleted "
                          "outside of %(appname)s.",
                          {"appname": app.config.get(prefs.SHORT_APP_NAME)}
                          ))

                    return
                try:
                    metainfo = metainfoFile.read()
                finally:
                    metainfoFile.close()

                self.handle_metainfo(metainfo)
            else:
                self.description_client = httpclient.grab_url(self.url,
                        self.on_metainfo_download,
                        self.on_metainfo_download_error,
                        content_check_callback=self.check_description)
        else:
            self.got_metainfo()
Ejemplo n.º 16
0
    def awakeFromNib(self):
        image_path = resources.path('images/subtitles_down.png')
        self.subtitlesButton.setImage_(NSImage.alloc().initWithContentsOfFile_(image_path))
        self.subtitlesLabel.setTitleWithMnemonic_(_("Subtitles"))
        self.fsLabel.setTitleWithMnemonic_(_("Fullscreen"))
        self.shareButton.setImage_(getOverlayButtonImage(self.shareButton.bounds().size))
        self.shareButton.setAlternateImage_(getOverlayButtonAlternateImage(self.shareButton.bounds().size))
        self.shareButton.setTitle_(_("Share"))

        self.keepButton.setImage_(getOverlayButtonImage(self.keepButton.bounds().size))
        self.keepButton.setAlternateImage_(getOverlayButtonAlternateImage(self.keepButton.bounds().size))
        self.keepButton.setTitle_(_("Keep"))

        self.deleteButton.setImage_(getOverlayButtonImage(self.deleteButton.bounds().size))
        self.deleteButton.setAlternateImage_(getOverlayButtonAlternateImage(self.deleteButton.bounds().size))
        self.deleteButton.setTitle_(_("Delete"))

        self.seekForwardButton.setCell_(SkipSeekButtonCell.cellFromButtonCell_direction_delay_(self.seekForwardButton.cell(), 1, 0.0))
        self.seekForwardButton.cell().setAllowsSkipping(False)
        self.seekBackwardButton.setCell_(SkipSeekButtonCell.cellFromButtonCell_direction_delay_(self.seekBackwardButton.cell(), -1, 0.0))
        self.seekBackwardButton.cell().setAllowsSkipping(False)

        self.progressSlider.cursor = NSImage.imageNamed_(u'fs-progress-slider')
        self.progressSlider.sliderWasClicked = self.progressSliderWasClicked
        self.progressSlider.sliderWasDragged = self.progressSliderWasDragged
        self.progressSlider.sliderWasReleased = self.progressSliderWasReleased
        self.progressSlider.setShowCursor_(True)

        self.volumeSlider.cursor = NSImage.imageNamed_(u'fs-volume-slider')
        self.volumeSlider.sliderWasClicked = self.volumeSliderWasClicked
        self.volumeSlider.sliderWasDragged = self.volumeSliderWasDragged
        self.volumeSlider.sliderWasReleased = self.volumeSliderWasReleased
        self.volumeSlider.setShowCursor_(True)
Ejemplo n.º 17
0
    def update_free_space(self):
        """Updates the free space text on the downloads tab.

        amount -- the total number of bytes free.
        """
        amount = get_available_bytes_for_movies()
        if app.config.get(prefs.PRESERVE_DISK_SPACE):
            available = (app.config.get(prefs.PRESERVE_X_GB_FREE) * 1024 * 1024 * 1024)
            available = amount - available

            if available < 0:
                available = available * -1.0
                text = _(
                    "%(available)s below downloads space limit (%(amount)s "
                    "free on disk)",
                    {"amount": displaytext.size_string(amount),
                     "available": displaytext.size_string(available)}
                )
            else:
                text = _(
                    "%(available)s free for downloads (%(amount)s free "
                    "on disk)",
                    {"amount": displaytext.size_string(amount),
                     "available": displaytext.size_string(available)}
                )
        else:
            text = _("%(amount)s free on disk",
                     {"amount": displaytext.size_string(amount)})
        self._free_disk_label.set_text(text)
Ejemplo n.º 18
0
    def make_subtitles_button(self):
        hbox = HBox(5)

        current_track = app.video_renderer.get_enabled_subtitle_track()

        # None, -1 and 0 all mean there is no current track.
        if current_track is not None and current_track > 0:
            ccimage = 'images/cc-on.png'
            cccolor = GREEN
            cctext = _("Subtitles On")

        else:
            tracks = app.video_renderer.get_subtitle_tracks()
            if tracks is not None and len(tracks) > 0:
                ccimage = 'images/cc-available.png'
                cctext = _("Subtitles Found")
                cccolor = WHITE
            else:
                ccimage = 'images/cc-available.png'
                cctext = _("Subtitles")
                cccolor = WHITE

        cc_image_button = make_image_button(ccimage, self.handle_subtitles)
        hbox.pack_start(_align_middle(cc_image_button))
        subtitles_link = make_label(cctext, self.handle_subtitles)
        subtitles_link.set_color(cccolor)
        hbox.pack_start(_align_middle(subtitles_link))

        subtitles_image = make_image_button(
            'images/subtitles_down.png', self.handle_subtitles)
        hbox.pack_start(_align_middle(subtitles_image))
        return hbox
Ejemplo n.º 19
0
 def _show_save_error_dialog(self, error_text):
     title = _("%(appname)s database save failed",
               {"appname": app.config.get(prefs.SHORT_APP_NAME)})
     description = _(
         "%(appname)s was unable to save its database.\n\n"
         "If your disk is full, we suggest freeing up some space and "
         "retrying.  If your disk is not full, it's possible that "
         "retrying will work.\n\n"
         "If retrying did not work, please quit %(appname)s and restart.  "
         "Recent changes may be lost.\n\n"
         "If you see this error often while downloading, we suggest "
         "you reduce the number of simultaneous downloads in the Options "
         "dialog in the Download tab.\n\n"
         "Error: %(error_text)s\n\n",
         {"appname": app.config.get(prefs.SHORT_APP_NAME),
          "error_text": error_text}
         )
     d = dialogs.ChoiceDialog(title, description,
             dialogs.BUTTON_RETRY, dialogs.BUTTON_QUIT)
     choice = d.run_blocking()
     if choice == dialogs.BUTTON_QUIT:
         self._quitting_from_operational_error = True
         messages.FrontendQuit().send_to_frontend()
     else:
         logging.warn("Re-running SQL statement")
Ejemplo n.º 20
0
def _playback_panel():
    extras = []

    lab = widgetset.Label(_("Renderer options:"))
    lab.set_bold(True)
    extras.append(align_left(lab))

    grid = dialogwidgets.ControlGrid()

    note = dialogwidgets.note(
        _("You must restart %(appname)s for renderer "
          "changes to take effect.",
          {"appname": app.config.get(prefs.SHORT_APP_NAME)}))
    grid.pack(align_left(note, bottom_pad=12), grid.ALIGN_LEFT, span=2)

    grid.end_line(spacing=12)

    rbg = widgetset.RadioButtonGroup()
    radio_map = {}
    for mem in renderers.get_renderer_list():
        radio_map[mem] = widgetset.RadioButton(mem, rbg)

    buttons = [(v, k) for k, v in radio_map.items()]
    attach_radio(buttons, options.USE_RENDERER)

    grid.pack_label(_("Video renderer:"), grid.ALIGN_RIGHT)
    grid.pack(dialogwidgets.radio_button_list(*radio_map.values()))

    grid.end_line(spacing=12)

    extras.append(align_left(grid.make_table()))

    return extras
Ejemplo n.º 21
0
    def get_subtitles(self):
        """Returns a dict of index -> (language, filename) for available
        tracks.
        """
        if not self.playbin or not self.supports_subtitles:
            return {}

        tracks = {}

        if self.playbin.get_property("suburi") is None:
            # Don't list subtitle tracks that we're getting from an SRT file
            for track_index in range(self.playbin.get_property("n-text")):
                track_name = self._get_subtitle_track_name(track_index)
                if track_name is None:
                    track_name = _("Track %(tracknumber)d",
                                   {"tracknumber": track_index})
                tracks[track_index] = (track_name, None)

        files = gather_subtitle_files(self.iteminfo.video_path)

        external_track_id = 100
        for i, mem in enumerate(files):
            track_name = self._get_subtitle_file_name(mem)
            if track_name is None:
                track_name = _("Subtitle file %(tracknumber)d",
                               {"tracknumber": i})
            tracks[external_track_id + i] = (track_name, mem)

        return tracks
Ejemplo n.º 22
0
 def _handle_upgrade_error(self):
     self._backup_failed_upgrade_db()
     title = _("%(appname)s database upgrade failed",
               {"appname": app.config.get(prefs.SHORT_APP_NAME)})
     description = _(
         "We're sorry, %(appname)s was unable to upgrade your database "
         "due to errors.\n\n"
         "Check to see if your disk is full.  If it is full, then quit "
         "%(appname)s, free up some space, and start %(appname)s "
         "again.\n\n"
         "If your disk is not full, help us understand the problem by "
         "reporting a bug to our crash database.\n\n"
         "Finally, you can start fresh and your damaged database will be "
         "removed, but you will have to re-add your podcasts and media "
         "files.", {"appname": app.config.get(prefs.SHORT_APP_NAME)}
         )
     d = dialogs.ThreeChoiceDialog(title, description,
             dialogs.BUTTON_QUIT, dialogs.BUTTON_SUBMIT_REPORT,
             dialogs.BUTTON_START_FRESH)
     choice = d.run_blocking()
     if choice == dialogs.BUTTON_START_FRESH:
         self._handle_load_error("Error upgrading database")
         self.startup_version = self.current_version = self._get_version()
     elif choice == dialogs.BUTTON_SUBMIT_REPORT:
         report = crashreport.format_crash_report("Upgrading Database",
                 exc_info=sys.exc_info(), details=None)
         raise UpgradeErrorSendCrashReport(report)
     else:
         raise UpgradeError()
Ejemplo n.º 23
0
 def init_info(self, info):
     info.type = u'sharing'
     info.unwatched = info.available = 0
     active = None
     if info.is_folder and info.playlist_id is None:
         thumb_path = resources.path('images/sharing.png')
     # Checking the name instead of a supposedly unique id is ok for now
     # because
     elif info.playlist_id == u'video':
         thumb_path = resources.path('images/icon-video.png')
         active = resources.path('images/icon-video_active.png')
         info.name = _('Video')
     elif info.playlist_id == u'audio':
         thumb_path = resources.path('images/icon-audio.png')
         active = resources.path('images/icon-audio_active.png')
         info.name = _('Music')
     elif info.playlist_id == u'playlist':
         thumb_path = resources.path('images/icon-playlist.png')
         active = resources.path('images/icon-playlist_active.png')
         info.name = _('Playlists')
     elif info.playlist_id == u'podcast':
         thumb_path = resources.path('images/icon-podcast.png')
         active = resources.path('images/icon-podcast_active.png')
         info.name = _('Podcasts')
     else:
         if info.podcast:
             thumb_path = resources.path('images/icon-podcast-small.png')
             active = resources.path('images/icon-podcast-small_active.png')
         else:
             thumb_path = resources.path('images/icon-playlist-small.png')
             active = resources.path('images/icon-playlist-small_active.png')
     info.icon = imagepool.get_surface(thumb_path)
     if active:
         info.active_icon = imagepool.get_surface(active)
Ejemplo n.º 24
0
def run_dialog():
    """Creates and launches the New Feed dialog.  This dialog waits for
    the user to press "Create Feed" or "Cancel".

    Returns a tuple of the (url, section).
    """
    text = app.widgetapp.get_clipboard_text()
    if text and feed.validate_feed_url(text):
        text = feed.normalize_feed_url(text)
    else:
        text = ""

    title = _('Add Feed')
    description = _('Enter the URL of the feed to add')

    while 1:
        text, section = _run_dialog(title, description, initial_text=text)
        if text == None:
            return (None, None)

        normalized_url = feed.normalize_feed_url(text)
        if feed.validate_feed_url(normalized_url):
            return (normalized_url, section)

        title = _('Add Feed - Invalid URL')
        description = _('The address you entered is not a valid url.\nPlease check the URL and try again.\n\nEnter the URL of the feed to add')
Ejemplo n.º 25
0
 def _set_play_pause(self):
     if ((not app.playback_manager.is_playing
          or app.playback_manager.is_paused)):
         label = _('Play')
     else:
         label = _('Pause')
     self.menu_item_fetcher['PlayPauseItem'].set_label(label)
Ejemplo n.º 26
0
def _conversions_panel():
    extras = []

    lab = widgetset.Label(_("Binaries to use:"))
    lab.set_bold(True)
    extras.append(align_left(lab))

    grid = dialogwidgets.ControlGrid()

    grid.pack_label(_("ffmpeg binary path:"), grid.ALIGN_RIGHT)
    ffmpeg_binary = widgetset.TextEntry()
    attach_text(ffmpeg_binary, options.FFMPEG_BINARY)
    grid.pack(ffmpeg_binary)

    grid.end_line(spacing=4)

    grid.pack_label(_("ffmpeg2theora binary path:"), grid.ALIGN_RIGHT)
    ffmpeg2theora_binary = widgetset.TextEntry()
    attach_text(ffmpeg2theora_binary, options.FFMPEG2THEORA_BINARY)
    grid.pack(ffmpeg2theora_binary)

    grid.end_line(spacing=4)

    extras.append(align_left(grid.make_table()))

    return extras
Ejemplo n.º 27
0
 def make_folder_context_menu(self, obj):
     return [
         (_('Update Podcasts In Folder'),
          app.widgetapp.update_selected_feeds),
         (_('Rename Podcast Folder'), app.widgetapp.rename_something),
         (_('Remove'), app.widgetapp.remove_something)
     ]
Ejemplo n.º 28
0
    def build_widget(self):
        grid = dialogwidgets.ControlGrid()

        cbx = widgetset.Checkbox(_('Keep at least this much free space on my drive:'))
        limit = widgetset.TextEntry()
        limit.set_width(6)
        note = widgetset.Label(_('GB'))
        attach_boolean(cbx, prefs.PRESERVE_DISK_SPACE, (limit,))

        def set_library_filter(self, typ, filter):
            self.library[typ] = filter
        attach_float(limit, prefs.PRESERVE_X_GB_FREE, create_float_checker(min=0.0))

        grid.pack(cbx)
        grid.pack(limit)
        grid.pack_label(_('GB'))
        grid.end_line(spacing=4)

        expire_ops = [(1, _('1 day')),
                (3, _('3 days')),
                (6, _('6 days')),
                (10, _('10 days')),
                (30, _('1 month')),
                (-1, _('never'))]
        expire_menu = widgetset.OptionMenu([op[1] for op in expire_ops])
        attach_combo(expire_menu, prefs.EXPIRE_AFTER_X_DAYS,
                [op[0] for op in expire_ops])

        grid.pack_label(_('By default, video and audio items expire after:'), extra_space=dialogwidgets.ControlGrid.ALIGN_RIGHT)
        grid.pack(expire_menu, extra_space=dialogwidgets.ControlGrid.ALIGN_LEFT)

        return grid.make_table()
Ejemplo n.º 29
0
    def awakeFromNib(self):
        self.shareButton.setImage_(getOverlayButtonImage(self.shareButton.bounds().size))
        self.shareButton.setAlternateImage_(getOverlayButtonAlternateImage(self.shareButton.bounds().size))
        self.shareButton.setTitle_(_("Share"))

        self.keepButton.setImage_(getOverlayButtonImage(self.keepButton.bounds().size))
        self.keepButton.setAlternateImage_(getOverlayButtonAlternateImage(self.keepButton.bounds().size))
        self.keepButton.setTitle_(_("Keep"))

        self.deleteButton.setImage_(getOverlayButtonImage(self.deleteButton.bounds().size))
        self.deleteButton.setAlternateImage_(getOverlayButtonAlternateImage(self.deleteButton.bounds().size))
        self.deleteButton.setTitle_(_("Delete"))

        self.seekForwardButton.setCell_(SkipSeekButtonCell.cellFromButtonCell_direction_delay_(self.seekForwardButton.cell(), 1, 0.0))
        self.seekForwardButton.cell().setAllowsSkipping(False)
        self.seekBackwardButton.setCell_(SkipSeekButtonCell.cellFromButtonCell_direction_delay_(self.seekBackwardButton.cell(), -1, 0.0))
        self.seekBackwardButton.cell().setAllowsSkipping(False)

        self.progressSlider.cursor = NSImage.imageNamed_(u'fs-progress-slider')
        self.progressSlider.sliderWasClicked = self.progressSliderWasClicked
        self.progressSlider.sliderWasDragged = self.progressSliderWasDragged
        self.progressSlider.sliderWasReleased = self.progressSliderWasReleased
        self.progressSlider.setShowCursor_(True)

        self.volumeSlider.cursor = NSImage.imageNamed_(u'fs-volume-slider')
        self.volumeSlider.sliderWasClicked = self.volumeSliderWasClicked
        self.volumeSlider.sliderWasDragged = self.volumeSliderWasDragged
        self.volumeSlider.sliderWasReleased = self.volumeSliderWasReleased
        self.volumeSlider.setShowCursor_(True)
Ejemplo n.º 30
0
    def __init__(self):
        widgetset.VBox.__init__(self)
        label = widgetset.Label()
        label.set_text(
            _("Your device isn't telling us its exact model number."))
        self.pack_start(widgetutil.align_center(label, left_pad=20, top_pad=50,
                                              bottom_pad=20))
        label = widgetset.Label()
        label.set_text(
            _('For optimal video conversion, select the device model.'))
        label.set_bold(True)
        self.pack_start(widgetutil.align_center(label, left_pad=20,
                                                bottom_pad=20)),

        self.device_choices = widgetset.VBox()
        self.pack_start(widgetutil.align_center(self.device_choices,
                                                left_pad=20, top_pad=20,
                                                bottom_pad=20))

        image = widgetset.ImageDisplay(
            imagepool.get(resources.path('images/sync-unknown.png')))
        self.pack_start(widgetutil.align_center(image, left_pad=20,
                                                bottom_pad=20))

        label = widgetset.Label()
        label.set_text(_("If you don't know the model or it doesn't appear "
                         "in the list, it's fine to choose the 'Generic' "
                         "device option."))
        label.set_bold(True)
        self.pack_start(widgetutil.align_center(label, left_pad=20,
                                                bottom_pad=20))
Ejemplo n.º 31
0
 def __init__(self, title):
     FileDialogBase.__init__(self)
     self._files = None
     choose_str =_('Choose').encode('utf-8')
     fcd = gtk.FileChooserDialog(
         title,
         action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
         buttons=(gtk.STOCK_CANCEL,
                  gtk.RESPONSE_CANCEL,
                  choose_str, gtk.RESPONSE_OK))
     self.set_window(fcd)
Ejemplo n.º 32
0
class ItemFilterPodcasts(ItemFilter):
    """Filter for podcast items.

    Not: this means the user flagged the item as a podcast somehow, not that
    we downloaded it from a feed
    """
    key = u'podcasts'
    user_label = _('Podcasts')

    def filter(self, item_info):
        return item_info.kind == 'podcast'
Ejemplo n.º 33
0
 def init_info(self, info):
     info.type = u'sharing'
     info.unwatched = info.available = 0
     info.video_playlist_id = unicode(
         md5(repr((u'video', info.host, info.port, u'video'))).hexdigest())
     info.audio_playlist_id = unicode(
         md5(repr((u'audio', info.host, info.port, u'audio'))).hexdigest())
     if info.is_folder:
         thumb_path = resources.path('images/sharing.png')
     # Checking the name instead of a supposedly unique id is ok for now
     # because
     elif info.playlist_id == u'video':
         thumb_path = resources.path('images/icon-video.png')
         info.name = _('Video')
     elif info.playlist_id == u'audio':
         thumb_path = resources.path('images/icon-audio.png')
         info.name = _('Music')
     else:
         thumb_path = resources.path('images/icon-playlist.png')
     info.icon = imagepool.get_surface(thumb_path)
Ejemplo n.º 34
0
def _general_panel():
    extras = []
    show_cbx = widgetset.Checkbox(_("Enable tray icon"))
    attach_boolean(show_cbx, options.SHOW_TRAYICON)
    extras.append(show_cbx)

    lab = widgetset.Label(_("When I click the red close button:"))
    extras.append(widgetutil.align_left(lab))
    rbg = widgetset.RadioButtonGroup()
    rad_close = widgetset.RadioButton(
        _("Close to tray so that downloads can continue."), rbg)
    rad_quit = widgetset.RadioButton(
        _("Quit %(appname)s completely.",
          {'appname': app.config.get(prefs.SHORT_APP_NAME)}), rbg)

    attach_radio([(rad_close, True), (rad_quit, False)],
                 prefs.MINIMIZE_TO_TRAY)
    extras.append(widgetutil.align_left(rad_close, left_pad=20))
    extras.append(widgetutil.align_left(rad_quit, left_pad=20))
    return extras
Ejemplo n.º 35
0
 def _build_android_section(self, bottom):
     hbox = widgetset.HBox()
     vbox = widgetset.VBox()
     label = self.build_header(_("Miro on Android"))
     vbox.pack_start(
         widgetutil.align_left(label, left_pad=20, bottom_pad=10))
     label = widgetset.Label(
         _("We don't yet have a Miro app for Android, but you can stream "
           "to your device using other DAAP apps."))
     label.set_size(self.TEXT_SIZE)
     label.set_color(self.TEXT_COLOR)
     label.set_wrap(True)
     label.set_size_request(550, -1)
     vbox.pack_start(
         widgetutil.align_left(label,
                               left_pad=20,
                               right_pad=10,
                               bottom_pad=20))
     hbox.pack_start(vbox)
     bottom.pack_start(hbox)
Ejemplo n.º 36
0
    def on_close(self):
        if app.config.get(prefs.MINIMIZE_TO_TRAY_ASK_ON_CLOSE):
            ret = dialogs.show_choice_dialog(
                _("Close to tray?"),
                _(
                    "When you click the red close button, would you like %(appname)s to "
                    "close to the system tray or quit?  You can change this "
                    "setting later in the Options.",
                    {"appname": app.config.get(prefs.SHORT_APP_NAME)}),
                (dialogs.BUTTON_QUIT, dialogs.BUTTON_CLOSE_TO_TRAY))
            app.config.set(prefs.MINIMIZE_TO_TRAY_ASK_ON_CLOSE, False)
            if ret == dialogs.BUTTON_CLOSE_TO_TRAY:
                app.config.set(prefs.MINIMIZE_TO_TRAY, True)
            else:
                app.config.set(prefs.MINIMIZE_TO_TRAY, False)

        if app.config.get(prefs.MINIMIZE_TO_TRAY):
            self.trayicon.on_click(None)
        else:
            self.quit()
Ejemplo n.º 37
0
 def __init__(self, name):
     self.name = self.device_name = name
     self.update({
         'generic': True,
         'mount_instructions': _("Your drive must be mounted."),
         'audio_conversion': 'copy',
         'audio_types': '',
         'audio_path': u'Miro',
         'video_conversion': 'copy',
         'video_path': u'Miro',
     })
Ejemplo n.º 38
0
    def draw(self, context, layout):
        self.background.draw(context, 0, 0, self.background.width,
                             self.background.height)
        if self.value:  # on
            text = _("On")
            left = self.background.width - self.on.width
            right = self.background.width
            self.on.draw(context, self.background.width - self.on.width, 0,
                         self.on.width, self.on.height)
        else:
            text = _("Off")
            left = 0
            right = self.off.width
            self.off.draw(context, 0, 0, self.off.width, self.off.height)

        textbox = layout.textbox(text.upper())
        layout.set_font(1)
        x = int(((right - left) - textbox.get_size()[0]) / 2) + left
        y = int((self.background.height - textbox.get_size()[1]) / 2)
        textbox.draw(context, x, y, *textbox.get_size())
Ejemplo n.º 39
0
class ItemFilterPodcasts(ItemFilter):
    """Filter for podcast items.

    Not: this means the user flagged the item as a podcast somehow, not that
    we downloaded it from a feed
    """
    key = u'podcasts'
    user_label = _('Podcasts')

    def add_to_query(self, query):
        query.add_condition('kind', '=', u'podcast')
Ejemplo n.º 40
0
class ItemFilterWatchedFolderAudio(ItemFilterWatchedFolderAudioVideo):
    """Filter for audio items in watch folders.

    This works like the Audio filter, but it doesn't automatically select
    other filters when selected
    """
    key = u'wf-audio'
    user_label = _('Audio')

    def add_to_query(self, query):
        query.add_condition('file_type', '=', 'audio')
Ejemplo n.º 41
0
class ConvertingTab(StaticTab):
    type = u'converting'
    id = u'converting'
    name = _('Converting')
    icon_name = 'icon-converting'

    def __init__(self):
        StaticTab.__init__(self)
        # FIXME - we redo the translation here so we're doing it at
        # instantiation time and NOT at import time which is stupid.
        ConvertingTab.name = _("Converting")
Ejemplo n.º 42
0
    def _build_add_playlist_section(self, bottom):
        hbox = widgetset.HBox()
        label = widgetset.Label(_("Name"))
        hbox.pack_start(widgetutil.align_middle(label))

        self.name_entry = widgetset.TextEntry()
        self.name_entry.set_size_request(400, -1)
        self.name_entry.connect('activate', self._on_add_playlist)
        hbox.pack_start(widgetutil.align_middle(self.name_entry, left_pad=15))

        self.add_playlist_button = widgetutil.TitlebarButton(_("Add Playlist"))
        self.add_playlist_button.connect('clicked', self._on_add_playlist)
        hbox.pack_start(
            widgetutil.align_middle(self.add_playlist_button, left_pad=15))

        bg = widgetutil.RoundedSolidBackground(
            widgetutil.css_to_color('#e4e4e4'))
        bg.add(widgetutil.pad(hbox, 10, 10, 10, 10))

        bottom.pack_start(bg)
Ejemplo n.º 43
0
class SearchTab(StaticTab):
    type = u'search'
    id = u'search'
    name = _('Video Search')
    icon_name = 'icon-search'

    def __init__(self):
        StaticTab.__init__(self)
        # FIXME - we redo the translation here so we're doing it at
        # instantiation time and NOT at import time which is stupid.
        SearchTab.name = _("Video Search")
Ejemplo n.º 44
0
def install_bonjour(startup=False):
    title = _("Install Bonjour")
    if not startup:
        description = _(
            'For the best %(appname)s experience, we suggest you '
            'install Bonjour.  Installing Bonjour will '
            'allow you share your media library with other '
            '%(appname)s users on your network, as well as stream '
            'media from other %(appname)s users on your '
            'network.\n\n'
            '%(appname)s has determined that your system is most '
            'likely missing the Avahi mDNSResponder compatibility '
            'library.  Please refer to your operating system '
            'documentation on how you can install this library.',
            {"appname": app.config.get(prefs.SHORT_APP_NAME)})
    else:
        description = _(
            'For the best %(appname)s experience, we suggest you '
            'install Bonjour.  Installing Bonjour will '
            'allow you share your media library with other '
            '%(appname)s users on your network, as well as stream '
            'media from other %(appname)s users on your '
            'network.\n\n'
            '%(appname)s has determined that your system is most '
            'likely missing the Avahi mDNSResponder compatibility '
            'library.  Please refer to your operating system '
            'documentation on how you can install this '
            'library.\n\n'
            'Would you like %(appname)s to warn you on next '
            'startup?', {"appname": app.config.get(prefs.SHORT_APP_NAME)})
    if not startup:
        dialogs.show_message(title, description)
    else:
        # Buttons in this order because if the window is destroyed by the
        # "X" button it becomes -1 which is the last element of the list.
        ret = dialogs.show_choice_dialog(
            title, description, [dialogs.BUTTON_NO, dialogs.BUTTON_YES])
        if ret is None or ret == dialogs.BUTTON_YES:
            return
        else:
            app.config.set(prefs.BONJOUR_REQUEST_COUNT, 1)
Ejemplo n.º 45
0
    def add_filters(self, filters):
        for name, ext_list in filters:
            f = gtk.FileFilter()
            f.set_name(name)
            for mem in ext_list:
                f.add_pattern('*.%s' % mem)
            self._window.add_filter(f)

        f = gtk.FileFilter()
        f.set_name(_('All files'))
        f.add_pattern('*')
        self._window.add_filter(f)
Ejemplo n.º 46
0
 def get_startup_activity(self):
     self.confirm_db_thread()
     activity = self.status.get('activity')
     if ((activity is None and self.status.get('retryCount', -1) > -1
          and 'retryTime' in self.status)):
         activity = self._calc_retry_time()
         if self._update_retry_time_dc is None:
             self._update_retry_time_dc = eventloop.add_timeout(1,
                     self._update_retry_time, 'Updating retry time')
     if activity is None:
         return _("starting up")
     return activity
Ejemplo n.º 47
0
def size_string(nbytes):
    # when switching from the enclosure reported size to the
    # downloader reported size, it takes a while to get the new size
    # and the downloader returns -1.  the user sees the size go to -1B
    # which is weird....  better to return an empty string.
    if nbytes == -1 or nbytes == 0:
        return ""

    # FIXME this is a repeat of util.format_size_for_user ...  should
    # probably ditch one of them.
    if nbytes >= (1 << 30):
        value = "%.1f" % (nbytes / float(1 << 30))
        return _("%(size)s GB", {"size": value})
    elif nbytes >= (1 << 20):
        value = "%.1f" % (nbytes / float(1 << 20))
        return _("%(size)s MB", {"size": value})
    elif nbytes >= (1 << 10):
        value = "%.1f" % (nbytes / float(1 << 10))
        return _("%(size)s KB", {"size": value})
    else:
        return _("%(size)s B", {"size": nbytes})
Ejemplo n.º 48
0
 def callback(info):
     if info.get('content-type') == expected_content_type:
         subscription_list = autodiscover.parse_content(info['body'])
         if subscription_list is None:
             text = _(
                 "This %(appname)s podcast file has an invalid format: "
                 "%(url)s.  Please notify the publisher of this file.", {
                     "appname": app.config.get(prefs.SHORT_APP_NAME),
                     "url": real_url
                 })
             _complain_about_subscription_url(text)
         else:
             subscription.Subscriber().add_subscriptions(subscription_list)
     else:
         text = _(
             "This %(appname)s podcast file has the wrong content type: "
             "%(url)s. Please notify the publisher of this file.", {
                 "appname": app.config.get(prefs.SHORT_APP_NAME),
                 "url": real_url
             })
         _complain_about_subscription_url(text)
Ejemplo n.º 49
0
 def get_startup_activity(self):
     self.confirm_db_thread()
     activity = self.activity
     if (activity is None and self.retry_count is not None
             and self.retry_time is not None):
         activity = self._calc_retry_time()
         if self._update_retry_time_dc is None:
             self._update_retry_time_dc = eventloop.add_timeout(
                 1, self._update_retry_time, 'Updating retry time')
     if activity is None:
         return _("starting up")
     return activity
Ejemplo n.º 50
0
 def set_sync_state(self, count):
     if self.in_progress:
         # don't update sync state while we're syncing
         return
     if count:
         self.sync_button.set_text(
             ngettext('Sync 1 File', 'Sync %(count)i Files', count,
                      {'count': count}))
         self.sync_button.enable()
     else:
         self.sync_button.set_text(_("Up to date"))
         self.sync_button.disable()
Ejemplo n.º 51
0
 def _make_convert_menu(self):
     convert_menu = []
     sections = app.menu_manager.get_converters()
     for index, converter_list in enumerate(sections):
         for (identifier, title) in converter_list:
             func = functools.partial(app.widgetapp.convert_items,
                                      identifier)
             convert_menu.append((title, func))
         convert_menu.append(None)
     convert_menu.append((_("Show Conversion Folder"),
                          app.widgetapp.reveal_conversions_folder))
     return convert_menu
Ejemplo n.º 52
0
class OthersTab(StaticTab):
    type = u'others'
    id = u'others'
    name = _('Misc')
    icon_name = 'icon-other'
    media_type = u'other'

    def __init__(self):
        StaticTab.__init__(self)
        # FIXME - we redo the translation here so we're doing it at
        # instantiation time and NOT at import time which is stupid.
        OthersTab.name = _("Misc")
Ejemplo n.º 53
0
class AudioLibraryTab(StaticTab):
    type = u'music'
    id = u'music'
    name = _('Music')
    icon_name = 'icon-audio'
    media_type = u'audio'

    def __init__(self):
        StaticTab.__init__(self)
        # FIXME - we redo the translation here so we're doing it at
        # instantiation time and NOT at import time which is stupid.
        AudioLibraryTab.name = _("Music")
Ejemplo n.º 54
0
 def __init__(self, field, items, label, option_map):
     Field.__init__(self, field, items, label)
     labels = dict(option_map)
     labels['_mixed'] = _("(mixed)")
     self.options = [option[0] for option in option_map]
     if self.mixed_values:
         self.options.insert(0, '_mixed')
     option_labels = (labels[option] for option in self.options)
     self.widget = widgetset.OptionMenu(option_labels)
     self.widget.set_width(134)
     if self.common_value is not None:
         self.widget.set_selected(self.options.index(self.common_value))
Ejemplo n.º 55
0
def get_plat_media_player_name_path():
    music_path = specialfolders.get_special_folder("My Music")
    if music_path == None:
        # if specialfolders returns None, then My Music doesn't exist
        # so we return (None, None) indicating there's no media
        # player.

        # FIXME - can the iTunes folder be in another place?
        return (None, None)

    itunes_path = os.path.join(music_path, 'iTunes')
    return (_('iTunes'), import_itunes_path(itunes_path))
Ejemplo n.º 56
0
def finish_startup(obj, thread):
    database.set_thread(thread)
    logging.info("Installing deleted file checker...")
    item.setup_deleted_checker()
    logging.info("Restoring database...")
    start = time.time()
    app.db = storedatabase.LiveStorage()
    try:
        app.db.upgrade_database()
    except databaseupgrade.DatabaseTooNewError:
        summary = _("Database too new")
        description = _(
            "You have a database that was saved with a newer version of "
            "%(appname)s. You must download the latest version of "
            "%(appname)s and run that.",
            {"appname": app.config.get(prefs.SHORT_APP_NAME)},
        )
        raise StartupError(summary, description)
    except storedatabase.UpgradeErrorSendCrashReport, e:
        send_startup_crash_report(e.report)
        return
Ejemplo n.º 57
0
    def _build_note_section(self, bottom):
        label = widgetset.Label(
            _(
                "Sources are any websites that offer audio, video, or "
                "torrents for download that you would like to use "
                "within %(shortappname)s.",
                {'shortappname': app.config.get(prefs.SHORT_APP_NAME)}))
        label.set_size(widgetconst.SIZE_SMALL)
        label.set_wrap(True)
        label.set_size_request(550, -1)

        bottom.pack_start(widgetutil.align_left(label, bottom_pad=30))
Ejemplo n.º 58
0
 def test_404_error(self, write_file=None):
     self.expecting_errback = True
     url = self.httpserver.build_url('badfile.txt')
     self.grab_url(url, write_file=write_file)
     self.assert_(isinstance(self.grab_url_error,
         httpclient.UnexpectedStatusCode))
     # FIXME: It'd be nice if we could check a HTTP code rather than a
     # static message.
     self.assertEquals(self.grab_url_error.friendlyDescription,
             _("File not found"))
     if write_file:
         self.assertEquals(open(write_file).read(), '')
Ejemplo n.º 59
0
 def handle_change_clicked(widget):
     dir_ = dialogs.ask_for_directory(
         _("Choose directory to search for media files"),
         initial_directory=get_default_search_dir(),
         transient_for=self)
     if dir_:
         search_entry.set_text(filename_to_unicode(dir_))
         self.search_directory = dir_
     else:
         self.search_directory = get_default_search_dir()
     # reset the search results if they change the directory
     self.gathered_media_files = None
Ejemplo n.º 60
0
Archivo: menus.py Proyecto: kmshi/miro
def add_subtitle_encoding_menu(menubar, category_label, *encodings):
    """Helper method to set up the subtitles encoding menu.

    This method should be called for each category of subtitle encodings (East
    Asian, Western European, Unicode, etc).  Pass it the list of encodings for
    that category.

    :param category_label: human-readable name for the category
    :param encodings: list of (label, encoding) tuples.  label is a
        human-readable name, and encoding is a value that we can pass to
        VideoDisplay.select_subtitle_encoding()
    """
    subtitles_menu = menubar.get("PlaybackMenu").get("SubtitlesMenu")
    try:
        encoding_menu = subtitles_menu.get("SubtitleEncodingMenu")
    except ValueError:
        # first time calling this function, we need to set up the menu.
        encoding_menu = Menu(_("_Encoding"),
                             "SubtitleEncodingMenu", [],
                             groups=['PlayingVideo'])
        subtitles_menu.append(encoding_menu)
        default_item = RadioMenuItem(_('Default (UTF-8)'),
                                     "SubtitleEncoding-Default",
                                     'subtitle-encoding',
                                     groups=['PlayingVideo'])
        encoding_menu.append(default_item)
        app.menu_manager.subtitle_encoding_enabled = True

    category_menu = Menu(category_label,
                         "SubtitleEncodingCat%s" % encoding_menu.count(), [],
                         groups=['PlayingVideo'])
    encoding_menu.append(category_menu)

    for encoding, name in encodings:
        label = '%s (%s)' % (name, encoding)
        category_menu.append(
            RadioMenuItem(label,
                          'SubtitleEncoding-%s' % encoding,
                          'subtitle-encoding',
                          groups=["PlayingVideo"]))