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
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()
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
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)
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()
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
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
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)
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)
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)
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)]
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)
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)
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)
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)
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)]
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'))
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'))
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)
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)
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
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
def reschedule_favorites_complete(self, result): if result: dialog.show_message(_('Favorites rescheduled')) else: dialog.show_alert(_('Reschedule failed'))
def __playing_tv_record_stop(self, event, menuw): if self.state == State.PLAYING: dialog.show_message(_('Recording stopped')) self.recording = False
def __playing_tv_record_start(self, event, menuw): dialog.show_message(_('Recording started'))
def display_channel_number(self, channel): dialog.show_message(_('Channel #: %s') % channel)
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)
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
# 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
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)