Exemple #1
0
 def __playing_seconds_left(self, event, menuw):
     if self.player.paused:
         self.player.resume()
         dialog.show_message(_('Out of buffer space, playback resumed'))
     else:
         logger.debug('while playing ~%d seconds left in buffer before overwrite', event.arg)
     return True
Exemple #2
0
 def __playing_reader_overtaken(self, event, menuw):
     if self.player.paused:
         self.player.resume()
         dialog.show_message(_('Out of buffer space, playback resumed'))
     else:
         dialog.show_message(_('Out of buffer space'))
         logger.debug('Out of buffer space while playing!')
     return True
 def reschedule_favorites(self, arg=None, menuw=None):
     """
     Force rescheduling of favorites
     """
     logger.log( 9, 'resched_favs(arg=%r, menuw=%r)', arg, menuw)
     dialog.show_message(_('Rescheduling Favorites...'))
     self.recordclient.updateFavoritesScheduleCo().connect(self.reschedule_favorites_complete)
     if menuw:
         menuw.delete_submenu()
Exemple #4
0
    def imdb_search(self, arg=None, menuw=None):
        """
        search imdb for this item
        """

        items = []
        dlg = dialog.show_working_indicator(_('Searching IMDB...'))

        if self.disc_set:
            self.searchstring = self.item.media.label
        else:
            self.searchstring = self.item['title']

        try:
            #guess the title from the filename
            lock = kaa.ThreadCallable(self.fxd.guessImdb, self.searchstring,
                                      self.disc_set)()
            lock.wait()
            results = lock.result

            # loop through the results and create menu
            # should not use imdbpy objects here as imdbpy should be encapsulated by FxdImdb
            # but for now it's to much work to do this the right way.
            # It works so let's deal with it later.
            for movie in results:
                try:
                    # OK, we have a regular movie here, no nested episodes
                    items.append(menu.MenuItem('%s (%s) (%s)' % \
                                (movie['long imdb title'], movie['kind'], movie.movieID),
                                 self.imdb_create_fxd, (movie.movieID, movie['kind'])))
                except Unicode, e:
                    print e

        except (FxdImdb_Error) as error:
            logger.warning('%s', error)
            dlg.hide()
            dialog.show_message(_('Connection to IMDB failed'))
            return

        dlg.hide()

        if config.IMDB_AUTOACCEPT_SINGLE_HIT and len(items) == 1:
            self.imdb_create_fxd(arg=items[0].arg, menuw=menuw)
            return

        if items:
            moviemenu = menu.Menu(_('IMDB Query'),
                                  items,
                                  self.item.skin_fxd,
                                  item_types='%s default' % self.item.type)
            # we see if the item has individual skin and load it if so
            menuw.pushmenu(moviemenu)
            return

        dialog.show_message(_('No information available from IMDB'))
        return
Exemple #5
0
    def display_info(self, info_function):
        info_dict = info_function()

        info_message = '%s ' % info_dict['channel']
        info_message += time.strftime('%H:%M', time.localtime(info_dict['start_time']))
        info_message += '<-'
        info_message += time.strftime('%H:%M', time.localtime(info_dict['current_time']))
        info_message += '->'
        info_message += time.strftime('%H:%M', time.localtime(info_dict['end_time']))
        dialog.show_message(info_message)
Exemple #6
0
 def reschedule_favorites(self, arg=None, menuw=None):
     """
     Force rescheduling of favorites
     """
     logger.log(9, 'resched_favs(arg=%r, menuw=%r)', arg, menuw)
     dialog.show_message(_('Rescheduling Favorites...'))
     self.recordclient.updateFavoritesScheduleCo().connect(
         self.reschedule_favorites_complete)
     if menuw:
         menuw.delete_submenu()
Exemple #7
0
    def imdb_search(self, arg=None, menuw=None):
        """
        search imdb for this item
        """

        items = []
        dlg = dialog.show_working_indicator(_('Searching IMDB...'))

        if self.disc_set:
            self.searchstring = self.item.media.label
        else:
            self.searchstring = self.item['title']
    
        try:
            #guess the title from the filename
            lock = kaa.ThreadCallable(self.fxd.guessImdb, 
                                      self.searchstring, 
                                      self.disc_set)()
            lock.wait()
            results = lock.result            

            # loop through the results and create menu
            # should not use imdbpy objects here as imdbpy should be encapsulated by FxdImdb
            # but for now it's to much work to do this the right way. 
            # It works so let's deal with it later.
            for movie in results:
                try:
                    # OK, we have a regular movie here, no nested episodes
                    items.append(menu.MenuItem('%s (%s) (%s)' % \
                                (movie['long imdb title'], movie['kind'], movie.movieID), 
                                 self.imdb_create_fxd, (movie.movieID, movie['kind'])))
                except Unicode, e:
                    print e

        except (FxdImdb_Error) as error:
            logger.warning('%s', error)
            dlg.hide()
            dialog.show_message(_('Connection to IMDB failed'))
            return

        dlg.hide()

        if config.IMDB_AUTOACCEPT_SINGLE_HIT and len(items) == 1:
            self.imdb_create_fxd(arg=items[0].arg, menuw=menuw)
            return

        if items:
            moviemenu = menu.Menu(_('IMDB Query'), items, 
                self.item.skin_fxd, item_types = '%s default' % self.item.type)
            # we see if the item has individual skin and load it if so 
            menuw.pushmenu(moviemenu)
            return

        dialog.show_message(_('No information available from IMDB'))
        return
Exemple #8
0
    def subs_search(self, arg=None, menuw=None):
        """
        Search subtitle website for subtitles for this item
        """
        self.subs = {}
        items     = []
        dlg       = None
    
        try:
            #get the subtitles from each active handler
            for handler in self.get_handlers().values():
                dlg = dialog.show_working_indicator(_('Searching %s...' % (handler['name'])))

                if self.item.subitems:
                    for i in range(len(self.item.subitems)):
                        lock = kaa.ThreadCallable(handler.get_subs, 
                                                  self.item.subitems[i].filename, 
                                                  config.SUBS_LANGS.keys())()
                        lock.wait()
                        self.subs.update(lock.result)
                else:
                    lock = kaa.ThreadCallable(handler.get_subs, 
                                              self.item.filename, 
                                              config.SUBS_LANGS.keys())()
                    lock.wait()
                    self.subs.update(lock.result)

                dlg.hide()

            for subs in sorted(self.subs.values(), key=attrgetter('handler.id', 'lang', 'vfile')):
                try:
                    lang = config.SUBS_LANGS[subs.lang]
                    if self.item.subitems:
                        items.append(menu.MenuItem(_('%s subtitles for "%s" (%s from %s)' % \
                                     (lang, trunc(os.path.basename(subs.vfile), 20), subs.fmt, subs.handler['name'])),
                                     self.subs_create_subs, (subs['id'])))
                    else:
                        items.append(menu.MenuItem(_('%s subtitles (%s from %s)' % \
                                     (lang, subs.fmt, subs.handler['name'])),
                                     self.subs_create_subs, (subs['id'])))
                    
                except (Unicode) as err:
                    logger.warning(err)

            # if we have more then 1 set of subs, we give user an option to save all
            if len(self.subs) > 1:
                items.insert(0, menu.MenuItem(_('Get all available subtitles listed below'),
                             self.subs_create_subs, ('all')))

        except (Exception), err:
            logger.error('%s' % (err))
            dialog.show_message(_('Connection to subtitle service failed'))
            return
Exemple #9
0
    def display_info(self, info_function):
        info_dict = info_function()

        info_message = '%s ' % info_dict['channel']
        info_message += time.strftime('%H:%M',
                                      time.localtime(info_dict['start_time']))
        info_message += '<-'
        info_message += time.strftime(
            '%H:%M', time.localtime(info_dict['current_time']))
        info_message += '->'
        info_message += time.strftime('%H:%M',
                                      time.localtime(info_dict['end_time']))
        dialog.show_message(info_message)
Exemple #10
0
def show_channel_banner(channel=None, channel_number=None):
    global _channel_banner_dialog
    if dialog.is_dialog_supported():
        if channel is None and channel_number is None:
            raise RuntimeException('Either channel or channel_number must be specified!')
        if _channel_banner_dialog is None:
            _channel_banner_dialog = ChannelBannerDialog()
        _channel_banner_dialog.set_channel(channel, channel_number)
        _channel_banner_dialog.show()
    else:
        if channel:
            dialog.show_message(channel)
        else:
            dialog.show_message(channel_number)
Exemple #11
0
def show_channel_banner(channel=None, channel_number=None):
    global _channel_banner_dialog
    if dialog.is_dialog_supported():
        if channel is None and channel_number is None:
            raise RuntimeException(
                'Either channel or channel_number must be specified!')
        if _channel_banner_dialog is None:
            _channel_banner_dialog = ChannelBannerDialog()
        _channel_banner_dialog.set_channel(channel, channel_number)
        _channel_banner_dialog.show()
    else:
        if channel:
            dialog.show_message(channel)
        else:
            dialog.show_message(channel_number)
Exemple #12
0
 def check_reminders(self):
     """
     Check to see if we should show a dialog if a program is about to start.
     """
     now = time.time()
     for prog in self.progs.values():
         if prog.start <= now:
             channel_name = tv.channels.map_channel_id_to_name(prog.channel_id)
             if prog.start == now:
                 dialog.show_message(_('%s is starting now on %s') % (prog.name, channel_name))
             elif prog.start >= now + config.REMIND_MINUTES_BEFORE:
                 minutes = (prog.start - now) / 60
                 dialog.show_message(_('%s is about to start in %d minutes on %s') % (prog.name, minutes,channel_name))
         if now > prog.start:
             del self.progs[get_prog_key(prog)]
Exemple #13
0
 def remove_program(self, arg=None, menuw=None):
     """ Remove a program from schedule """
     logger.log( 9, 'remove_program(arg=%r, menuw=%r)', arg, menuw)
     # remove the program
     (status, reason) = self.recordclient.removeScheduledRecordingNow(self.prog)
     if status:
         self.scheduled = False
         menuw.delete_submenu(refresh=False)
         if hasattr(self.parent, 'update'):
             self.parent.update(force=True)
         else:
             menuw.refresh(reload=True)
         msgtext = _('"%s" has been removed from schedule') % self.name
     else:
         # something went wrong
         msgtext = _('Remove failed')+(':\n%s' % reason)
     dialog.show_message(msgtext)
Exemple #14
0
 def remove_program(self, arg=None, menuw=None):
     """ Remove a program from schedule """
     logger.log(9, 'remove_program(arg=%r, menuw=%r)', arg, menuw)
     # remove the program
     (status,
      reason) = self.recordclient.removeScheduledRecordingNow(self.prog)
     if status:
         self.scheduled = False
         menuw.delete_submenu(refresh=False)
         if hasattr(self.parent, 'update'):
             self.parent.update(force=True)
         else:
             menuw.refresh(reload=True)
         msgtext = _('"%s" has been removed from schedule') % self.name
     else:
         # something went wrong
         msgtext = _('Remove failed') + (':\n%s' % reason)
     dialog.show_message(msgtext)
Exemple #15
0
 def priority_mod(self, adjust, menuw=None):
     """
     Move current item in the priority list and refresh menu to
     show new position
     """
     name = self.origname
     result = self.recordclient.adjustPriorityNow(name, adjust)
     if result:
         # if this is successfull
         if menuw:
             menuw.delete_submenu()
             menuw.refresh(reload=1)
         else:
             event.Event('MENU_RELOAD').post()
     else:
         # if all fails then we should show an error
         msgtext = _('Priority adjustment failed')+(':\n%s' % msg)
         dialog.show_message(msgtext)
Exemple #16
0
 def priority_mod(self, adjust, menuw=None):
     """
     Move current item in the priority list and refresh menu to
     show new position
     """
     name = self.origname
     result = self.recordclient.adjustPriorityNow(name, adjust)
     if result:
         # if this is successfull
         if menuw:
             menuw.delete_submenu()
             menuw.refresh(reload=1)
         else:
             event.Event('MENU_RELOAD').post()
     else:
         # if all fails then we should show an error
         msgtext = _('Priority adjustment failed') + (':\n%s' % msg)
         dialog.show_message(msgtext)
Exemple #17
0
 def check_reminders(self):
     """
     Check to see if we should show a dialog if a program is about to start.
     """
     now = time.time()
     for prog in self.progs.values():
         if prog.start <= now:
             channel_name = tv.channels.map_channel_id_to_name(
                 prog.channel_id)
             if prog.start == now:
                 dialog.show_message(
                     _('%s is starting now on %s') %
                     (prog.name, channel_name))
             elif prog.start >= now + config.REMIND_MINUTES_BEFORE:
                 minutes = (prog.start - now) / 60
                 dialog.show_message(
                     _('%s is about to start in %d minutes on %s') %
                     (prog.name, minutes, channel_name))
         if now > prog.start:
             del self.progs[get_prog_key(prog)]
Exemple #18
0
    def subs_delete_subs(self, arg=None, menuw=None):
        """
        delete subtitle file(s) for the item
        """
        dlg = dialog.show_working_indicator(_('Deleting subtitles...'))

        try:
            if arg == None or arg == 'all':
                # we delete all available subtitle files
                for subs in self.subfiles:
                    os.remove(subs)

            else:
                # we delete only chosen subtitle file
                logger.debug('Deleting subtitle file %s', arg)
                os.remove(arg)

        except (Exception), error:
            logger.error('%s' % (err))
            dialog.show_message(_('Error while deleting subtitles'))
Exemple #19
0
    def subs_create_subs(self, arg=None, menuw=None):
        """
        create subs for the item
        """
        dlg = dialog.show_working_indicator(_('Saving subtitles...'))
 
        try:
            if arg == None or arg == 'all':
                # we write all available subs
                for subs in self.subs.values():
                    subs.save()

            else:
                # we write only chosen subs
                subs = self.subs[arg]
                logger.debug('Writing subs from %s for lang %s', subs.handler['name'], subs.lang)
                subs.save()
                        
        except (Exception), err:
            logger.error('%s' % (err))
            dialog.show_message(_('Error while saving subtitles'))
Exemple #20
0
    def schedule_program(self, arg=None, menuw=None):
        """ Add a program to schedule """
        logger.log( 9, 'schedule_program(arg=%r, menuw=%r)', arg, menuw)
        # schedule the program
        (status, reason) = self.recordclient.scheduleRecordingNow(self.prog)
        if status == 'ok':
            self.scheduled = True
            menuw.delete_submenu(refresh=False)
            if hasattr(self.parent, 'update'):
                self.parent.update(force=True)
            else:
                menuw.refresh(reload=True)
            msgtext= _('"%s" has been scheduled for recording') % self.name
        elif status == 'conflict':
            msgtext=_('Conflict detected!')
            self.resolve_conflict(menuw, reason)
            return
        else:
            # something went wrong
            msgtext = _('Scheduling failed: ')+ _(reason)

        dialog.show_message(msgtext)
Exemple #21
0
    def schedule_program(self, arg=None, menuw=None):
        """ Add a program to schedule """
        logger.log(9, 'schedule_program(arg=%r, menuw=%r)', arg, menuw)
        # schedule the program
        (status, reason) = self.recordclient.scheduleRecordingNow(self.prog)
        if status == 'ok':
            self.scheduled = True
            menuw.delete_submenu(refresh=False)
            if hasattr(self.parent, 'update'):
                self.parent.update(force=True)
            else:
                menuw.refresh(reload=True)
            msgtext = _('"%s" has been scheduled for recording') % self.name
        elif status == 'conflict':
            msgtext = _('Conflict detected!')
            self.resolve_conflict(menuw, reason)
            return
        else:
            # something went wrong
            msgtext = _('Scheduling failed: ') + _(reason)

        dialog.show_message(msgtext)
Exemple #22
0
    def __playing_toggle_subtitles(self, event, menuw):
        # Enable/Disable subtitles
        if self.subtitles:
            self.subtitle_index += 1

        else:
            self.subtitles = self.player.get_subtitles()
            self.subtitle_index = 0

        if self.subtitles:
            if self.subtitle_index >= len(self.subtitles):
                self.subtitle_index = -1

            self.player.set_subtitles(self.subtitle_index)
            if self.subtitle_index == -1:
                subtitle_text = _('Disabled')
            else:
                subtitle_text = self.subtitles[self.subtitle_index]
            dialog.show_message(_('Subtitles: %s') % subtitle_text)
        else:
            dialog.show_message(_('Subtitles not supported'))

        return True
Exemple #23
0
    def __playing_toggle_audio_lang(self, event, menuw):
        if self.audio_langs:
            self.audio_lang_index += 1

        else:
            self.audio_langs = self.player.get_audio_langs()
            self.audio_lang_index = 0

        if self.audio_langs:
            if self.audio_lang_index >= len(self.audio_langs):
                self.audio_lang_index = -1

            self.player.set_audio_lang(self.audio_lang_index)
            if self.audio_lang_index == -1:
                audio_lang_text = _('Default')
            else:
                audio_lang_text = self.subtitles[self.subtitle_index]

            dialog.show_message(_('Audio language: %s') % audio_lang_text)
        else:
            dialog.show_message(_('Audio language selection not supported'))

        return True
Exemple #24
0
 def reschedule_favorites_complete(self, result):
     if result:
         dialog.show_message(_('Favorites rescheduled'))
     else:
         dialog.show_alert(_('Reschedule failed'))
Exemple #25
0
 def __playing_tv_record_stop(self, event, menuw):
     if self.state == State.PLAYING:
         dialog.show_message(_('Recording stopped'))
     self.recording = False
Exemple #26
0
 def __playing_tv_record_start(self, event, menuw):
     dialog.show_message(_('Recording started'))
Exemple #27
0
 def reschedule_favorites_complete(self, result):
     if result:
         dialog.show_message(_('Favorites rescheduled'))
     else:
         dialog.show_alert(_('Reschedule failed'))
Exemple #28
0
 def display_channel_number(self, channel):
     dialog.show_message(_('Channel #: %s') % channel)
Exemple #29
0
 def display_channel_number(self, channel):
     dialog.show_message(_('Channel #: %s') % channel)
Exemple #30
0
    def eventhandler(self, event, menuw=None):
        """
        eventhandler for mplayer control. If an event is not bound in this
        function it will be passed over to the items eventhandler
        """
        logger.debug('%s.eventhandler(event=%s)', self.__class__, event)
        if not self.app:
            return self.item.eventhandler(event)

        for p in self.plugins:
            if p.eventhandler(event):
                return True

        if event == VIDEO_MANUAL_SEEK:
            self.seek = 0
            rc.set_app_context(self, 'input')
            dialog.show_message("input")
            return True

        if event.context == 'input':
            if event in INPUT_ALL_NUMBERS:
                self.reset_seek_timeout()
                self.seek = self.seek * 10 + int(event);
                return True

            elif event == INPUT_ENTER:
                self.seek_timer.cancel()
                self.seek *= 60
                self.app.write('seek ' + str(self.seek) + ' 2\n')
                logger.debug("seek " + str(self.seek) + " 2\n")
                self.seek = 0
                rc.set_app_context(self, 'video')
                return True

            elif event == INPUT_EXIT:
                logger.debug('seek stopped')
                #self.app.write('seek stopped\n')
                self.seek_timer.cancel()
                self.seek = 0
                rc.set_app_context(self, 'video')
                return True

        if event == STOP:
            self.stop()
            return self.item.eventhandler(event)

        if event == 'AUDIO_ERROR_START_AGAIN':
            self.stop()
            self.play(self.options, self.item)
            return True

        if event in (PLAY_END, USER_END):
            self.stop()
            return self.item.eventhandler(event)

        if event == VIDEO_SEND_MPLAYER_CMD:
            self.app.write('%s\n' % event.arg)
            return True

        if event == TOGGLE_OSD:
            if dialog.is_dialog_supported():
                if self.play_state_dialog is None:
                    if self.paused:
                        self.play_state_dialog = dialog.show_play_state(dialog.PLAY_STATE_INFO, self.item, self.get_stored_time_info)
                    else:
                        self.play_state_dialog = dialog.show_play_state(dialog.PLAY_STATE_INFO, self.item, self.get_time_info)
                else:
                    self.play_state_dialog.hide()
                    self.play_state_dialog = None
            else:
                self.paused = False
                self.app.write('osd\n')
            return True

        if event == PAUSE or event == PLAY:
            self.paused = not self.paused
            # We have to store the current time before displaying the dialog
            # otherwise the act of requesting the current position resumes playback!
            if self.paused:
                self.stored_time_info = self.get_time_info()
                self.play_state_dialog = dialog.show_play_state(dialog.PLAY_STATE_PAUSE, self.item, self.get_stored_time_info)
                self.app.write('pause\n')
            else:
                self.app.write('speed_set 1.0\n')
                self.play_state_dialog = dialog.show_play_state(dialog.PLAY_STATE_PLAY, self.item, self.get_time_info)

            return True

        if event == SEEK:
            if event.arg > 0 and self.item_length != -1 and self.dynamic_seek_control:
                # check if the file is growing
                if self.item_info.get_endpos() == self.item_length:
                    # not growing, deactivate this
                    self.item_length = -1

                self.dynamic_seek_control = False

            if event.arg > 0 and self.item_length != -1:
                # safety time for bad mplayer seeking
                seek_safety_time = 20
                if self.item_info['type'] in ('MPEG-PES', 'MPEG-TS'):
                    seek_safety_time = 500

                # check if seek is allowed
                if self.item_length <= self.item.elapsed + event.arg + seek_safety_time:
                    # get new length
                    self.item_length = self.item_info.get_endpos()

                # check again if seek is allowed
                if self.item_length <= self.item.elapsed + event.arg + seek_safety_time:
                    logger.debug('unable to seek %s secs at time %s, length %s', event.arg, self.item.elapsed, self.item_length)
                    dialog.show_message(_('Seeking not possible'))
                    return False
            
            self.paused = False
            self.app.write('seek %s\n' % event.arg)
            if event.arg > 0:
                self.play_state_dialog = dialog.show_play_state(dialog.PLAY_STATE_SEEK_FORWARD, self.item, self.get_time_info)
            else:
                self.play_state_dialog = dialog.show_play_state(dialog.PLAY_STATE_SEEK_BACK, self.item, self.get_time_info)
            return True

        if event == VIDEO_AVSYNC:
            self.app.write('audio_delay %g\n' % float(event.arg));
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write('osd_show_property_text "Audio delay ${audio_delay}" 2000\n')
            return True

        if event == VIDEO_SUBSYNC:
            self.app.write('sub_delay %g\n' % float(event.arg));
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write('osd_show_property_text "Subtitles delay ${sub_delay}" 2000\n')
            return True

        if event == VIDEO_NEXT_AUDIOLANG:
            self.app.write('switch_audio\n')
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write('osd_show_property_text "Audio ${switch_audio}" 2000\n')
            return True

        if event == VIDEO_NEXT_SUBTITLE:
            self.app.write('sub_select\n')
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write('osd_show_property_text "Subtitles ${sub_file}" 2000\n')
            return True

        if event == OSD_MESSAGE:
            self.show_message(event.arg)
            return True

        if event == 'MPLAYER_VO':
            if config.OSD_SINGLE_WINDOW:
                w_ratio = float(config.CONF.width) / float(event.arg[0])
                h_ratio = float(config.CONF.height) / float(event.arg[1])
                ratio = min(w_ratio, h_ratio)
                w = int(event.arg[0] * ratio)
                h = int(event.arg[1] * ratio)
                x = (config.CONF.width - w) / 2
                y = (config.CONF.height - h) / 2
                osd.video_window.set_geometry((x,y), (w,h))
                osd.video_window.show()
            return True

        # nothing found? Try the eventhandler of the object who called us
        return self.item.eventhandler(event)
Exemple #31
0
class PluginInterface(plugin.ItemPlugin):
    """
    You can add subtitles for video items with the plugin.

    Activate with:
    | plugin.activate('video.subtitles')
    Make sure the suitable subtitles handler plugin is activated too:
    | plugin.activate('video.subtitles.napiprojekt')
    and/or
    | plugin.activate('video.subtitles.opensubtitles')
    etc.

    You can also set subs_search on a key (e.g. 't') by setting
    | EVENTS['menu']['t'] = Event(MENU_CALL_ITEM_ACTION, arg='subs_search')
    """

    def __init__(self):
        if not config.SYS_USE_NETWORK:
            self.reason = 'SYS_USE_NETWORK not enabled'
            return
        
        self.handlers = {}
        self.subs     = {}
        self.subfiles = []

        plugin.ItemPlugin.__init__(self)
        
        self.handlers = self.get_handlers()


    def config(self):
        """
        Returns the config variables used by this plugin
        """
        return [
            ('SUBS_LANGS',          { 'eng': ('English') },
                'Subtitles to download'),
            ('SUBS_EXTS',           [ '.srt', '.sub', '.txt', '.ssa', '.smi', '.ass', '.mpl'], 
                'Known subtitles file extensions'),
            ('SUBS_AUTOACCEPT',     False, 
                'Autoaccept all found subtitles, language coded filenames'),
            ('SUBS_FORCE_UPDATE',   True,  
                'Force update of existing subtitles'),
            ('SUBS_FORCE_BACKUP',   True,  
                'Force backup of existing subtitles'),
            ('SUBS_FORCE_LANG_EXT', True,
                'Force use of the subtitle lagnguage code in the filename i.e. xxx.eng.txt'),
        ]


    def actions(self, item):
        """
        Actions this item supports
        """
        self.item = item
        subs      = False

        if hasattr(self.item, 'subitems') and self.item.subitems:
            for i in range(len(self.item.subitems)):
                subs = self.check_existing_subs(self.item.subitems[i].filename)
        else:
            subs = self.check_existing_subs(self.item.filename)

        if item.type == 'video' and item.mode == 'file':
            if subs and not config.SUBS_FORCE_BACKUP:
                return [ ( self.subs_delete , _('Delete Subtitles'),   'subs_delete') ]
            elif subs and config.SUBS_FORCE_BACKUP:
                return [ ( self.subs_delete , _('Delete Subtitles'),   'subs_delete'),
                         ( self.subs_search , _('Download Subtitles'), 'subs_search') ]
            else:
                return [ ( self.subs_search , _('Download Subtitles'), 'subs_search') ]
      
        return []

    
    def check_existing_subs(self, file):
        """
        Check if any existing subitle files that match the pattern 
        """
        return len(self.get_existing_subs(file))



    def get_existing_subs(self, file):
        """
        Get all existing subitle files that match the pattern 
        into the collection and return it.
        """
        # if there are literal chars like '[' or ']' in the filename then glob will 
        # not match filenames. Need to replace them with '?'. Most likely it confuses
        # regex inside glob
        base = re.sub('[\]\[]+', '?', os.path.splitext(file)[0])

        return [n for n in glob.glob(base + '*') \
            if os.path.splitext(n)[1] in config.SUBS_EXTS]


    def get_handlers(self):
        """
        Get all regitered subtitle plugins into the local dictionary
        @return:    Hanlders dictionary keyed by the handler ID.
        """
        if self.handlers is None or len(self.handlers) < 1:
            handlers = plugin.get('subtitles')
            logger.info('Available subtitles handlers : %s', handlers)

            for handler in handlers:
                self.handlers[handler['id']] = handler
                logger.info('Successfuly loaded subtitle handler %s', handler.name)

        return self.handlers             
        
        

    def subs_search(self, arg=None, menuw=None):
        """
        Search subtitle website for subtitles for this item
        """
        self.subs = {}
        items     = []
        dlg       = None
    
        try:
            #get the subtitles from each active handler
            for handler in self.get_handlers().values():
                dlg = dialog.show_working_indicator(_('Searching %s...' % (handler['name'])))

                if self.item.subitems:
                    for i in range(len(self.item.subitems)):
                        lock = kaa.ThreadCallable(handler.get_subs, 
                                                  self.item.subitems[i].filename, 
                                                  config.SUBS_LANGS.keys())()
                        lock.wait()
                        self.subs.update(lock.result)
                else:
                    lock = kaa.ThreadCallable(handler.get_subs, 
                                              self.item.filename, 
                                              config.SUBS_LANGS.keys())()
                    lock.wait()
                    self.subs.update(lock.result)

                dlg.hide()

            for subs in sorted(self.subs.values(), key=attrgetter('handler.id', 'lang', 'vfile')):
                try:
                    lang = config.SUBS_LANGS[subs.lang]
                    if self.item.subitems:
                        items.append(menu.MenuItem(_('%s subtitles for "%s" (%s from %s)' % \
                                     (lang, trunc(os.path.basename(subs.vfile), 20), subs.fmt, subs.handler['name'])),
                                     self.subs_create_subs, (subs['id'])))
                    else:
                        items.append(menu.MenuItem(_('%s subtitles (%s from %s)' % \
                                     (lang, subs.fmt, subs.handler['name'])),
                                     self.subs_create_subs, (subs['id'])))
                    
                except (Unicode) as err:
                    logger.warning(err)

            # if we have more then 1 set of subs, we give user an option to save all
            if len(self.subs) > 1:
                items.insert(0, menu.MenuItem(_('Get all available subtitles listed below'),
                             self.subs_create_subs, ('all')))

        except (Exception), err:
            logger.error('%s' % (err))
            dialog.show_message(_('Connection to subtitle service failed'))
            return

        if config.SUBS_AUTOACCEPT and len(items) > 0:
            self.subs_create_subs(arg=('all'), menuw=menuw)
            return

        if items:
            moviemenu = menu.Menu(_('Subtitles Query'), items)
            menuw.pushmenu(moviemenu)
            return

        dialog.show_message(_('No subtitles available'))
        return
Exemple #32
0
        # if we have more then 1 set of subs, we give user an option to save all
        if len(self.subfiles) > 1:
            items.insert(0, menu.MenuItem(_('Delete all subtitle files listed below'),
                         self.subs_delete_subs, ('all')))

        if config.SUBS_AUTOACCEPT and len(items) > 0:
            self.subs_delete_subs(arg='all', menuw=menuw)
            return

        if items:
            moviemenu = menu.Menu(_('Subtitles Query'), items)
            menuw.pushmenu(moviemenu)
            return

        dialog.show_message(_('No subtitles to be deleted'))
        return


    def subs_menu_back(self, menuw):
        """
        check how many menus we have to go back to see the item
        """
        import directory

        # check if we have to go one menu back (called directly) or
        # two (called from the item menu)
        back = 1
        if menuw.menustack[-2].selected != self.item:
            back = 2
Exemple #33
0
    def eventhandler(self, event, menuw=None):
        """
        eventhandler for mplayer control. If an event is not bound in this
        function it will be passed over to the items eventhandler
        """
        logger.debug('%s.eventhandler(event=%s)', self.__class__, event)
        if not self.app:
            return self.item.eventhandler(event)

        for p in self.plugins:
            if p.eventhandler(event):
                return True

        if event == VIDEO_MANUAL_SEEK:
            self.seek = 0
            rc.set_app_context(self, 'input')
            dialog.show_message("input")
            return True

        if event.context == 'input':
            if event in INPUT_ALL_NUMBERS:
                self.reset_seek_timeout()
                self.seek = self.seek * 10 + int(event)
                return True

            elif event == INPUT_ENTER:
                self.seek_timer.cancel()
                self.seek *= 60
                self.app.write('seek ' + str(self.seek) + ' 2\n')
                logger.debug("seek " + str(self.seek) + " 2\n")
                self.seek = 0
                rc.set_app_context(self, 'video')
                return True

            elif event == INPUT_EXIT:
                logger.debug('seek stopped')
                #self.app.write('seek stopped\n')
                self.seek_timer.cancel()
                self.seek = 0
                rc.set_app_context(self, 'video')
                return True

        if event == STOP:
            self.stop()
            return self.item.eventhandler(event)

        if event == 'AUDIO_ERROR_START_AGAIN':
            self.stop()
            self.play(self.options, self.item)
            return True

        if event in (PLAY_END, USER_END):
            self.stop()
            return self.item.eventhandler(event)

        if event == VIDEO_SEND_MPLAYER_CMD:
            self.app.write('%s\n' % event.arg)
            return True

        if event == TOGGLE_OSD:
            if dialog.is_dialog_supported():
                if self.play_state_dialog is None:
                    if self.paused:
                        self.play_state_dialog = dialog.show_play_state(
                            dialog.PLAY_STATE_INFO, self.item,
                            self.get_stored_time_info)
                    else:
                        self.play_state_dialog = dialog.show_play_state(
                            dialog.PLAY_STATE_INFO, self.item,
                            self.get_time_info)
                else:
                    self.play_state_dialog.hide()
                    self.play_state_dialog = None
            else:
                self.paused = False
                self.app.write('osd\n')
            return True

        if event == PAUSE or event == PLAY:
            self.paused = not self.paused
            # We have to store the current time before displaying the dialog
            # otherwise the act of requesting the current position resumes playback!
            if self.paused:
                self.stored_time_info = self.get_time_info()
                self.play_state_dialog = dialog.show_play_state(
                    dialog.PLAY_STATE_PAUSE, self.item,
                    self.get_stored_time_info)
                self.app.write('pause\n')
            else:
                self.app.write('speed_set 1.0\n')
                self.play_state_dialog = dialog.show_play_state(
                    dialog.PLAY_STATE_PLAY, self.item, self.get_time_info)

            return True

        if event == SEEK:
            if event.arg > 0 and self.item_length != -1 and self.dynamic_seek_control:
                # check if the file is growing
                if self.item_info.get_endpos() == self.item_length:
                    # not growing, deactivate this
                    self.item_length = -1

                self.dynamic_seek_control = False

            if event.arg > 0 and self.item_length != -1:
                # safety time for bad mplayer seeking
                seek_safety_time = 20
                if self.item_info['type'] in ('MPEG-PES', 'MPEG-TS'):
                    seek_safety_time = 500

                # check if seek is allowed
                if self.item_length <= self.item.elapsed + event.arg + seek_safety_time:
                    # get new length
                    self.item_length = self.item_info.get_endpos()

                # check again if seek is allowed
                if self.item_length <= self.item.elapsed + event.arg + seek_safety_time:
                    logger.debug(
                        'unable to seek %s secs at time %s, length %s',
                        event.arg, self.item.elapsed, self.item_length)
                    dialog.show_message(_('Seeking not possible'))
                    return False

            self.paused = False
            self.app.write('seek %s\n' % event.arg)
            if event.arg > 0:
                self.play_state_dialog = dialog.show_play_state(
                    dialog.PLAY_STATE_SEEK_FORWARD, self.item,
                    self.get_time_info)
            else:
                self.play_state_dialog = dialog.show_play_state(
                    dialog.PLAY_STATE_SEEK_BACK, self.item, self.get_time_info)
            return True

        if event == VIDEO_AVSYNC:
            self.app.write('audio_delay %g\n' % float(event.arg))
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write(
                    'osd_show_property_text "Audio delay ${audio_delay}" 2000\n'
                )
            return True

        if event == VIDEO_SUBSYNC:
            self.app.write('sub_delay %g\n' % float(event.arg))
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write(
                    'osd_show_property_text "Subtitles delay ${sub_delay}" 2000\n'
                )
            return True

        if event == VIDEO_NEXT_AUDIOLANG:
            self.app.write('switch_audio\n')
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write(
                    'osd_show_property_text "Audio ${switch_audio}" 2000\n')
            return True

        if event == VIDEO_NEXT_SUBTITLE:
            self.app.write('sub_select\n')
            if config.MPLAYER_USE_OSD_SHOW_PROPS:
                self.app.write(
                    'osd_show_property_text "Subtitles ${sub_file}" 2000\n')
            return True

        if event == OSD_MESSAGE:
            self.show_message(event.arg)
            return True

        if event == 'MPLAYER_VO':
            if config.OSD_SINGLE_WINDOW:
                w_ratio = float(config.CONF.width) / float(event.arg[0])
                h_ratio = float(config.CONF.height) / float(event.arg[1])
                ratio = min(w_ratio, h_ratio)
                w = int(event.arg[0] * ratio)
                h = int(event.arg[1] * ratio)
                x = (config.CONF.width - w) / 2
                y = (config.CONF.height - h) / 2
                osd.video_window.set_geometry((x, y), (w, h))
                osd.video_window.show()
            return True

        # nothing found? Try the eventhandler of the object who called us
        return self.item.eventhandler(event)