class PluginInterface(plugin.ItemPlugin): """ Archive recorded TV programmes using EncodingServer This plugin needs a running encodingserver to work properly. You can start an encodingserver with 'freevo encodingserver start'. To activate, put the following line in local_conf.py: | plugin.activate('video.reencode') """ def __init__(self): logger.debug('reencode.PluginInterface.__init__(self)') plugin.ItemPlugin.__init__(self) self.server = EncodingClientActions() self.title = '' self.source = '' self.output = '' self.resetprofile() self.timeslice = [ None, None ] self.warn_once_savedir = True def resetprofile(self): self.profile = {} self.timeslice = [ None, None ] self.profile['container'] = config.REENCODE_CONTAINER self.profile['resolution'] = config.REENCODE_RESOLUTION self.profile['videocodec'] = config.REENCODE_VIDEOCODEC self.profile['altprofile'] = config.REENCODE_ALTPROFILE self.profile['audiocodec'] = config.REENCODE_AUDIOCODEC self.profile['numpasses'] = config.REENCODE_NUMPASSES self.profile['numthreads'] = config.REENCODE_NUMTHREADS self.profile['videobitrate'] = config.REENCODE_VIDEOBITRATE self.profile['audiobitrate'] = config.REENCODE_AUDIOBITRATE self.profile['videofilter'] = config.REENCODE_VIDEOFILTER def config(self): '''config is called automatically, for default settings run: freevo plugins -i video.reencode ''' logger.log( 9, 'config(self)') return [ ('REENCODE_CONTAINER', 'avi', 'Container type'), ('REENCODE_RESOLUTION', 'Optimal', 'Resolution'), ('REENCODE_VIDEOCODEC', 'XviD', 'Video codec'), ('REENCODE_ALTPROFILE', None, 'Alternate Encoding Profile'), ('REENCODE_VIDEOBITRATE', '800', 'Video bit rate'), ('REENCODE_AUDIOCODEC', 'MPEG 1 Layer 3 (mp3)', 'Audio codec'), ('REENCODE_AUDIOBITRATE', '128', 'Audio bit rate'), ('REENCODE_NUMPASSES', '2', 'Number of passes'), ('REENCODE_VIDEOFILTER', 'None', 'Video Filter'), ('REENCODE_NUMTHREADS','1','Number of Encoding Threads'), ] #def eventhandler(self, event, menuw=None, arg=None): # _debug_('eventhandler(self, event=%r, menuw=%r, arg=%r)' % (event, menuw, arg), 2) # return self.item.eventhandler(event, menuw=menuw, arg=arg) def prepare_output(self, source): """Prepare the output file path. Note that we strip the extension from the output file name""" output = os.path.splitext(source)[0] directory = os.path.dirname(output) #can we write in that directory? If so, the reencoded file will go there if directory and os.path.isabs(output) and os.path.isdir(directory) and \ os.access(directory, os.R_OK | os.W_OK | os.X_OK): return output basename = os.path.basename(output) if basename == '': basename = 'reencoded_video' # check that we have a default place where we can write the resulting # reencoded file (it is up to the user to create the dir with correct # permission) directory = config.ENCODINGSERVER_SAVEDIR if directory and os.path.isdir(directory) and os.access(directory, os.R_OK | os.W_OK | os.X_OK): return os.path.join(directory, basename) else: #in this case, it all ends into a temporary file return os.path.join('.', basename) def actions(self, item): logger.log( 9, 'actions(self, item)') if item.type == 'video' and item.mode == 'file': self.item = item self.title = item.name self.source = item.filename #this is temporarily set , since it is called too often #(even when browsing a directory ot TV recordings) self.output = '(to be set later)' # logger.log( 8, 'item.__dict__:', item.__dict__) return [ (self.encoding_profile_menu, _('Transcode this program...')) ] return [] def getattr(self, attr): '''callback function from the skin fxd file to get the display format of an item, the attr represents the expression in the skin ''' logger.log( 9, 'getattr(self, attr=%r)', attr) if attr == 'disp_title': return '%s' % (self.title) if attr == 'disp_filename': # note that this may be changed by the encodingserver # by calling the uniquify_filename() # in particular if many jobs are encoded in short sequence self.output = self.prepare_output(self.source) return uniquify_filename(self.output + '.' +self.profile['container']) elif attr == 'disp_container': return '%s' % (self.profile['container']) elif attr == 'disp_resolution': return '%s' % (self.profile['resolution']) elif attr == 'disp_videocodec': return '%s' % (self.profile['videocodec']) elif attr == 'altprofile': return '%s' % (self.profile['altprofile']) elif attr == 'disp_videobitrate': return '%s' % (self.profile['videobitrate']) elif attr == 'disp_audiocodec': return '%s' % (self.profile['audiocodec']) elif attr == 'disp_audiobitrate': return '%s' % (self.profile['audiobitrate']) elif attr == 'disp_numpasses': return '%s' % (self.profile['numpasses']) elif attr == 'disp_numthreads': return '%s' % (self.profile['numthreads']) elif attr == 'disp_videofilter': return '%s' % (self.profile['videofilter']) return '"%s" not defined' % (attr) def encoding_profile_menu(self, menuw=None, arg=None): logger.log( 9, 'encoding_profile_menu(self, menuw=%r, arg=%r)', menuw, arg) menu_items = [] menu_items += [ menu.MenuItem(_('Start Encoding'), self.create_job, self.profile) ] menu_items += [ menu.MenuItem(_('Select Encoding Profile'), action=self.select_profile) ] menu_items += [ menu.MenuItem(_('Modify Container'), action=self.mod_container) ] menu_items += [ menu.MenuItem(_('Modify Start Time'), action=self.mod_start_time) ] menu_items += [ menu.MenuItem(_('Modify End Time'), action=self.mod_end_time) ] menu_items += [ menu.MenuItem(_('Modify Resolution'), action=self.mod_resolution) ] menu_items += [ menu.MenuItem(_('Modify Video Codec'), action=self.mod_videocodec) ] menu_items += [ menu.MenuItem(_('Modify Video Bit Rate'), action=self.mod_videobitrate) ] menu_items += [ menu.MenuItem(_('Modify Audio Codec'), action=self.mod_audiocodec) ] menu_items += [ menu.MenuItem(_('Modify Audio Bit Rate'), action=self.mod_audiobitrate) ] menu_items += [ menu.MenuItem(_('Modify Number of passes'), action=self.mod_numpasses) ] menu_items += [ menu.MenuItem(_('Modify Number of Encoder Threads'), action=self.mod_numthreads) ] menu_items += [ menu.MenuItem(_('Modify Video Filter (not implemented)'), action=self.mod_videofilter) ] encoding_menu = menu.Menu(_('Choose your encoding profile'), menu_items, item_types = 'video encoding menu') encoding_menu.infoitem = self menuw.pushmenu(encoding_menu) menuw.refresh() def select_profile(self, arg=None, menuw=None): logger.log( 9, 'select_profile(self, arg=None, menuw=None)') menu_items = [] menu_items += [ menu.MenuItem(_('Xvid Low Quality'), action=self.select_encoding_profile, arg='xvid_low') ] menu_items += [ menu.MenuItem(_('Xvid High Quality'), action=self.select_encoding_profile, arg='xvid_high') ] menu_items += [ menu.MenuItem(_('iPod'), action=self.select_encoding_profile, arg='ipod') ] menu_items += [ menu.MenuItem(_('DVD'), action=self.select_encoding_profile, arg='MPEG 2 (lavc)') ] encoding_menu = menu.Menu(_('Select Profile'), menu_items, item_types = 'video encoding menu') encoding_menu.infoitem = self menuw.pushmenu(encoding_menu) menuw.refresh() def set_start_time(self, arg=None, menuw=None): self.timeslice[0] = arg if menuw: menuw.back_one_menu(arg='reload') def set_end_time(self, arg=None, menuw=None): self.timeslice[1] = arg if menuw: menuw.back_one_menu(arg='reload') def _select_time(self, arg=None, menuw=None, which=None): bookmarkfile = util.get_bookmarkfile(self.item.filename) if not os.path.exists(bookmarkfile): self.error(_('No bookmarks are set for this video')) return menu_items = [] menu_items = [ menu.MenuItem(_('Do not set'), action=which, arg=None),] for line in util.readfile(bookmarkfile): sec = int(line) hour = int(sec/3600) min = int((sec-(hour*3600))/60) time = '%0.2d:%0.2d:%0.2d' % (hour,min,sec % 60) menu_items.append(menu.MenuItem(time, action=which, arg=sec)) encoding_menu = menu.Menu(_('Select Time'), menu_items, item_types = 'video encoding menu') encoding_menu.infoitem = self menuw.pushmenu(encoding_menu) menuw.refresh() def mod_start_time(self, arg=None, menuw=None): self._select_time(arg, menuw, self.set_start_time) def mod_end_time(self, arg=None, menuw=None): self._select_time(arg, menuw, self.set_end_time) def mod_container(self, arg=None, menuw=None): logger.log( 9, 'mod_container(self, arg=%r, menuw=%r)', arg, menuw) items = [] for container in self.server.getContainerCAP()[1]: items.append(menu.MenuItem(container, action=self.alter_prop, arg=('container', container))) container_menu = menu.Menu(_('Modify Container'), items, item_types = 'video encoding menu') container_menu.infoitem = self menuw.pushmenu(container_menu) menuw.refresh() def mod_resolution(self, arg=None, menuw=None): logger.log( 9, 'mod_resolution(self, arg=%r, menuw=%r)', arg, menuw) items = [] for resolution in ('Optimal', '1920:1080', '1280:720', '852:480', '720:576', '720:480', '320:240'): items.append(menu.MenuItem(resolution, action=self.alter_prop, arg=('resolution', resolution))) resolution_menu = menu.Menu(_('Modify Resolution'), items, item_types = 'video encoding menu') resolution_menu.infoitem = self menuw.pushmenu(resolution_menu) menuw.refresh() def mod_videocodec(self, arg=None, menuw=None): logger.log( 9, 'mod_videocodec(self, arg=%r, menuw=%r)', arg, menuw) items = [] for videocodec in self.server.getVideoCodecCAP()[1]: items.append(menu.MenuItem(videocodec, action=self.alter_prop, arg=('videocodec', videocodec))) videocodec_menu = menu.Menu(_('Modify Video Codec'), items, item_types = 'video encoding menu') videocodec_menu.infoitem = self menuw.pushmenu(videocodec_menu) menuw.refresh() def mod_videobitrate(self, arg=None, menuw=None): logger.log( 9, 'mod_videobitrate(self, arg=%r, menuw=%r)', arg, menuw) items = [] for videobitrate in range(400, 2001, 200): items.append(menu.MenuItem(videobitrate, action=self.alter_prop, arg=('videobitrate', videobitrate))) videobitrate_menu = menu.Menu(_('Modify Video Bitrate'), items, item_types = 'video encoding menu') videobitrate_menu.infoitem = self menuw.pushmenu(videobitrate_menu) menuw.refresh() def mod_audiocodec(self, arg=None, menuw=None): logger.log( 9, 'mod_audiocodec(self, arg=%r, menuw=%r)', arg, menuw) items = [] for audiocodec in self.server.getAudioCodecCAP()[1]: items.append(menu.MenuItem(audiocodec, action=self.alter_prop, arg=('audiocodec', audiocodec))) audiocodec_menu = menu.Menu(_('Modify Video Codec'), items, item_types = 'video encoding menu') audiocodec_menu.infoitem = self menuw.pushmenu(audiocodec_menu) menuw.refresh() def mod_audiobitrate(self, arg=None, menuw=None): logger.log( 9, 'mod_audiobitrate(self, arg=%r, menuw=%r)', arg, menuw) items = [] for audiobitrate in (64, 128, 192, 224): items.append(menu.MenuItem(audiobitrate, action=self.alter_prop, arg=('audiobitrate', audiobitrate))) audiobitrate_menu = menu.Menu(_('Modify Audio Bitrate'), items, item_types = 'video encoding menu') audiobitrate_menu.infoitem = self menuw.pushmenu(audiobitrate_menu) menuw.refresh() def mod_numpasses(self, arg=None, menuw=None): logger.log( 9, 'mod_numpasses(self, arg=%r, menuw=%r)', arg, menuw) items = [] for numpasses in (1, 2): items.append(menu.MenuItem(numpasses, action=self.alter_prop, arg=('numpasses', numpasses))) numpasses_menu = menu.Menu(_('Modify Number of Passes'), items, item_types = 'video encoding menu') numpasses_menu.infoitem = self menuw.pushmenu(numpasses_menu) menuw.refresh() def mod_numthreads(self, arg=None, menuw=None): logger.log( 9, 'mod_numthreads(self, arg=%r, menuw=%r)', arg, menuw) items = [] for numthreads in (1, 2, 3, 4, 5, 6, 7, 8): items.append(menu.MenuItem(numthreads, action=self.alter_prop, arg=('numthreads', numthreads))) numthreads_menu = menu.Menu(_('Modify Number of Encoding threads'), items, item_types = 'video encoding menu') numthreads_menu.infoitem = self menuw.pushmenu(numthreads_menu) menuw.refresh() def mod_videofilter(self, arg=None, menuw=None): logger.log( 9, 'mod_videofilter(self, arg=%r, menuw=%r)', arg, menuw) items = [] for videofilter in self.server.getVideoFiltersCAP()[1]: items.append(menu.MenuItem(videofilter, action=self.alter_prop, arg=('videofilter', videofilter))) videofilter_menu = menu.Menu(_('Modify Video Filter'), items, item_types = 'video encoding menu') videofilter_menu.infoitem = self menuw.pushmenu(videofilter_menu) menuw.refresh() def select_encoding_profile(self, arg=None, menuw=None): logger.log( 9, 'select_encoding_profile(self, arg=%r, menuw=%r)', arg, menuw) if arg == 'xvid_low': self.profile['container'] = 'avi' self.profile['resolution'] = 'Optimal' self.profile['videocodec'] = 'XviD' self.profile['altprofile'] = None self.profile['videobitrate'] = 800 self.profile['audiocodec'] = 'MPEG 1 Layer 3 (mp3)' self.profile['audiobitrate'] = 128 self.profile['numpasses'] = 1 self.profile['videofilter'] = 'None' elif arg == 'xvid_high': self.profile['container'] = 'avi' self.profile['resolution'] = 'Optimal' self.profile['videocodec'] = 'XviD' self.profile['altprofile'] = None self.profile['videobitrate'] = 1200 self.profile['audiocodec'] = 'MPEG 1 Layer 3 (mp3)' self.profile['audiobitrate'] = 128 self.profile['numpasses'] = 2 self.profile['videofilter'] = 'None' elif arg == 'ipod': self.profile['container'] = 'mp4' self.profile['resolution'] = '320:240' self.profile['videocodec'] = 'MPEG 4 (lavc)' self.profile['altprofile'] = 'vcodec=mpeg4:mbd=2:cmp=2:subcmp=2:trell=yes:v4mv=yes:vglobal=1' self.profile['videobitrate'] = 1200 self.profile['audiocodec'] = 'AAC (iPod)' self.profile['audiobitrate'] = 192 self.profile['numpasses'] = 2 self.profile['videofilter'] = 'ipod' elif arg == 'MPEG 2 (lavc)': self.profile['container'] = 'mpeg' self.profile['resolution'] = '720:480' self.profile['videocodec'] = 'MPEG 2 (lavc)' self.profile['altprofile'] = None self.profile['videobitrate'] = 5200 self.profile['audiocodec'] = 'AC3' self.profile['audiobitrate'] = 224 self.profile['numpasses'] = 1 self.profile['videofilter'] = 'None' else: logger.error('Unknown Profile "%s"', arg) self.error(_('Unknown Profile')+(' "%s"' % (arg))) return if menuw: menuw.back_one_menu(arg='reload') def alter_prop(self, arg=(None, None), menuw=None): logger.log( 9, 'alter_prop(self, arg=%r, menuw=%r)', arg, menuw) (prop, val) = arg if prop == 'container': self.profile['container'] = val elif prop == 'resolution': self.profile['resolution'] = val elif prop == 'videocodec': self.profile['videocodec'] = val elif prop == 'altprofile': self.profile['altprofile'] = val elif prop == 'videobitrate': self.profile['videobitrate'] = val elif prop == 'audiocodec': self.profile['audiocodec'] = val elif prop == 'audiobitrate': self.profile['audiobitrate'] = val elif prop == 'numpasses': self.profile['numpasses'] = val elif prop == 'numthreads': self.profile['numthreads'] = val elif prop == 'videofilter': self.profile['videofilter'] = val else: logger.error('Unknown property "%s"', prop) self.error(_('Unknown Property')+(' "%s"' % (prop))) return if menuw: menuw.back_one_menu(arg='reload') def alter_name(self, name): '''alter_name is not used''' logger.log( 9, 'alter_name(self, name=%r)', name) self.menuw.refresh() def create_job(self, menuw=None, arg=None): logger.log( 9, 'create_job(self, arg=%r, menuw=%r)', arg, menuw) profile = arg # note that this may later be changed by the uniquify_filename() self.output = self.prepare_output(self.source) if self.output[:2] == './' and self.warn_once_savedir : #it will go into the encodingserver temporary dir, and we cant tell it from # this process self.warn_once_savedir = False AlertBox(text=_('This encoding job will be written to a temporary ' 'directory. Please set the variable ENCODINGSERVER_SAVEDIR to a ' 'directory where the reencoded file can be written to.')).show() return #we are going to create a job and send it to the encoding server, this can take some time while analyzing box = PopupBox(text=_('Please wait, analyzing video...')) box.show() (status, resp) = self.server.initEncodingJob(self.source, self.output, self.title) idnr = resp logger.debug('initEncodingJob:status:%s resp:%s', status, resp) if not status: box.destroy() self.error(_('Failed to analyze video.')) return (status, resp) = self.server.setTimeslice(idnr, self.timeslice) logger.debug('setTimeslice:status:%s resp:%s', status, resp) if not status: box.destroy() self.error(resp) return (status, resp) = self.server.waitCropDetect(idnr) logger.debug('WaitCropDetect:status:%s resp:%s', status, resp) if not status: box.destroy() self.error(resp) return box.destroy() if not status: self.error(resp) return (status, resp) = self.server.setContainer(idnr, profile['container']) logger.debug('setContainer:status:%s resp:%s', status, resp) if not status: self.error(resp) return multipass = profile['numpasses'] > 1 (status, resp) = self.server.setVideoCodec(idnr, profile['videocodec'], 0, multipass, profile['videobitrate'], profile['altprofile']) logger.debug('setVideoCodec:status:%s resp:%s', status, resp) if not status: self.error(resp) return (status, resp) = self.server.setAudioCodec(idnr, profile['audiocodec'], profile['audiobitrate']) logger.debug('setAudioCodec:status:%s resp:%s', status, resp) if not status: self.error(resp) return (status, resp) = self.server.setNumThreads(idnr, profile['numthreads']) logger.debug('setNumThreads:status:%s resp:%s', status, resp) if not status: self.error(resp) return (status, resp) = self.server.setVideoRes(idnr, profile['resolution']) logger.debug('setVideoRes:status:%s resp:%s', status, resp) if not status: self.error(resp) return #(status, resp) = self.server.setVideoFilters(idnr, vfilters) #_debug_('setVideoFilters:status:%s resp:%s' % (status, resp)) #And finally, queue and start the job (status, resp) = self.server.queueIt(idnr, True) logger.debug('queueIt:status:%s resp:%s', status, resp) if not status: self.error(resp) return self.menuw = menuw AlertBox(width=400, height=200, text=_('Encoding started'), handler=self.mopup).show() self.resetprofile() logger.debug('boe') #menuw.delete_menu() #menuw.delete_menu() def error(self, text=''): logger.debug('error(self, text=%r)', text) AlertBox(width=400, height=200, text='ERROR: %s' % text).show() def mopup(self): logger.debug('mopup(self)') self.menuw.delete_menu() self.menuw.back_one_menu()
class PluginInterface(plugin.ItemPlugin): """ Archive recorded TV programmes using EncodingServer This plugin needs a running encodingserver to work properly. You can start an encodingserver with 'freevo encodingserver start'. To activate, put the following line in local_conf.py: | plugin.activate('video.reencode') """ def __init__(self): logger.debug('reencode.PluginInterface.__init__(self)') plugin.ItemPlugin.__init__(self) self.server = EncodingClientActions() self.title = '' self.source = '' self.output = '' self.resetprofile() self.timeslice = [None, None] self.warn_once_savedir = True def resetprofile(self): self.profile = {} self.timeslice = [None, None] self.profile['container'] = config.REENCODE_CONTAINER self.profile['resolution'] = config.REENCODE_RESOLUTION self.profile['videocodec'] = config.REENCODE_VIDEOCODEC self.profile['altprofile'] = config.REENCODE_ALTPROFILE self.profile['audiocodec'] = config.REENCODE_AUDIOCODEC self.profile['numpasses'] = config.REENCODE_NUMPASSES self.profile['numthreads'] = config.REENCODE_NUMTHREADS self.profile['videobitrate'] = config.REENCODE_VIDEOBITRATE self.profile['audiobitrate'] = config.REENCODE_AUDIOBITRATE self.profile['videofilter'] = config.REENCODE_VIDEOFILTER def config(self): '''config is called automatically, for default settings run: freevo plugins -i video.reencode ''' logger.log(9, 'config(self)') return [ ('REENCODE_CONTAINER', 'avi', 'Container type'), ('REENCODE_RESOLUTION', 'Optimal', 'Resolution'), ('REENCODE_VIDEOCODEC', 'XviD', 'Video codec'), ('REENCODE_ALTPROFILE', None, 'Alternate Encoding Profile'), ('REENCODE_VIDEOBITRATE', '800', 'Video bit rate'), ('REENCODE_AUDIOCODEC', 'MPEG 1 Layer 3 (mp3)', 'Audio codec'), ('REENCODE_AUDIOBITRATE', '128', 'Audio bit rate'), ('REENCODE_NUMPASSES', '2', 'Number of passes'), ('REENCODE_VIDEOFILTER', 'None', 'Video Filter'), ('REENCODE_NUMTHREADS', '1', 'Number of Encoding Threads'), ] #def eventhandler(self, event, menuw=None, arg=None): # _debug_('eventhandler(self, event=%r, menuw=%r, arg=%r)' % (event, menuw, arg), 2) # return self.item.eventhandler(event, menuw=menuw, arg=arg) def prepare_output(self, source): """Prepare the output file path. Note that we strip the extension from the output file name""" output = os.path.splitext(source)[0] directory = os.path.dirname(output) #can we write in that directory? If so, the reencoded file will go there if directory and os.path.isabs(output) and os.path.isdir(directory) and \ os.access(directory, os.R_OK | os.W_OK | os.X_OK): return output basename = os.path.basename(output) if basename == '': basename = 'reencoded_video' # check that we have a default place where we can write the resulting # reencoded file (it is up to the user to create the dir with correct # permission) directory = config.ENCODINGSERVER_SAVEDIR if directory and os.path.isdir(directory) and os.access( directory, os.R_OK | os.W_OK | os.X_OK): return os.path.join(directory, basename) else: #in this case, it all ends into a temporary file return os.path.join('.', basename) def actions(self, item): logger.log(9, 'actions(self, item)') if item.type == 'video' and item.mode == 'file': self.item = item self.title = item.name self.source = item.filename #this is temporarily set , since it is called too often #(even when browsing a directory ot TV recordings) self.output = '(to be set later)' # logger.log(8, 'item.__dict__:', item.__dict__) return [(self.encoding_profile_menu, _('Transcode this program...'))] return [] def getattr(self, attr): '''callback function from the skin fxd file to get the display format of an item, the attr represents the expression in the skin ''' logger.log(9, 'getattr(self, attr=%r)', attr) if attr == 'disp_title': return '%s' % (self.title) if attr == 'disp_filename': # note that this may be changed by the encodingserver # by calling the uniquify_filename() # in particular if many jobs are encoded in short sequence self.output = self.prepare_output(self.source) return uniquify_filename(self.output + '.' + self.profile['container']) elif attr == 'disp_container': return '%s' % (self.profile['container']) elif attr == 'disp_resolution': return '%s' % (self.profile['resolution']) elif attr == 'disp_videocodec': return '%s' % (self.profile['videocodec']) elif attr == 'altprofile': return '%s' % (self.profile['altprofile']) elif attr == 'disp_videobitrate': return '%s' % (self.profile['videobitrate']) elif attr == 'disp_audiocodec': return '%s' % (self.profile['audiocodec']) elif attr == 'disp_audiobitrate': return '%s' % (self.profile['audiobitrate']) elif attr == 'disp_numpasses': return '%s' % (self.profile['numpasses']) elif attr == 'disp_numthreads': return '%s' % (self.profile['numthreads']) elif attr == 'disp_videofilter': return '%s' % (self.profile['videofilter']) return '"%s" not defined' % (attr) def encoding_profile_menu(self, menuw=None, arg=None): logger.log(9, 'encoding_profile_menu(self, menuw=%r, arg=%r)', menuw, arg) menu_items = [] menu_items += [ menu.MenuItem(_('Start Encoding'), self.create_job, self.profile) ] menu_items += [ menu.MenuItem(_('Select Encoding Profile'), action=self.select_profile) ] menu_items += [ menu.MenuItem(_('Modify Container'), action=self.mod_container) ] menu_items += [ menu.MenuItem(_('Modify Start Time'), action=self.mod_start_time) ] menu_items += [ menu.MenuItem(_('Modify End Time'), action=self.mod_end_time) ] menu_items += [ menu.MenuItem(_('Modify Resolution'), action=self.mod_resolution) ] menu_items += [ menu.MenuItem(_('Modify Video Codec'), action=self.mod_videocodec) ] menu_items += [ menu.MenuItem(_('Modify Video Bit Rate'), action=self.mod_videobitrate) ] menu_items += [ menu.MenuItem(_('Modify Audio Codec'), action=self.mod_audiocodec) ] menu_items += [ menu.MenuItem(_('Modify Audio Bit Rate'), action=self.mod_audiobitrate) ] menu_items += [ menu.MenuItem(_('Modify Number of passes'), action=self.mod_numpasses) ] menu_items += [ menu.MenuItem(_('Modify Number of Encoder Threads'), action=self.mod_numthreads) ] menu_items += [ menu.MenuItem(_('Modify Video Filter (not implemented)'), action=self.mod_videofilter) ] encoding_menu = menu.Menu(_('Choose your encoding profile'), menu_items, item_types='video encoding menu') encoding_menu.infoitem = self menuw.pushmenu(encoding_menu) menuw.refresh() def select_profile(self, arg=None, menuw=None): logger.log(9, 'select_profile(self, arg=None, menuw=None)') menu_items = [] menu_items += [ menu.MenuItem(_('Xvid Low Quality'), action=self.select_encoding_profile, arg='xvid_low') ] menu_items += [ menu.MenuItem(_('Xvid High Quality'), action=self.select_encoding_profile, arg='xvid_high') ] menu_items += [ menu.MenuItem(_('iPod'), action=self.select_encoding_profile, arg='ipod') ] menu_items += [ menu.MenuItem(_('DVD'), action=self.select_encoding_profile, arg='MPEG 2 (lavc)') ] encoding_menu = menu.Menu(_('Select Profile'), menu_items, item_types='video encoding menu') encoding_menu.infoitem = self menuw.pushmenu(encoding_menu) menuw.refresh() def set_start_time(self, arg=None, menuw=None): self.timeslice[0] = arg if menuw: menuw.back_one_menu(arg='reload') def set_end_time(self, arg=None, menuw=None): self.timeslice[1] = arg if menuw: menuw.back_one_menu(arg='reload') def _select_time(self, arg=None, menuw=None, which=None): bookmarkfile = util.get_bookmarkfile(self.item.filename) if not os.path.exists(bookmarkfile): self.error(_('No bookmarks are set for this video')) return menu_items = [] menu_items = [ menu.MenuItem(_('Do not set'), action=which, arg=None), ] for line in util.readfile(bookmarkfile): sec = int(line) hour = int(sec / 3600) min = int((sec - (hour * 3600)) / 60) time = '%0.2d:%0.2d:%0.2d' % (hour, min, sec % 60) menu_items.append(menu.MenuItem(time, action=which, arg=sec)) encoding_menu = menu.Menu(_('Select Time'), menu_items, item_types='video encoding menu') encoding_menu.infoitem = self menuw.pushmenu(encoding_menu) menuw.refresh() def mod_start_time(self, arg=None, menuw=None): self._select_time(arg, menuw, self.set_start_time) def mod_end_time(self, arg=None, menuw=None): self._select_time(arg, menuw, self.set_end_time) def mod_container(self, arg=None, menuw=None): logger.log(9, 'mod_container(self, arg=%r, menuw=%r)', arg, menuw) items = [] for container in self.server.getContainerCAP()[1]: items.append( menu.MenuItem(container, action=self.alter_prop, arg=('container', container))) container_menu = menu.Menu(_('Modify Container'), items, item_types='video encoding menu') container_menu.infoitem = self menuw.pushmenu(container_menu) menuw.refresh() def mod_resolution(self, arg=None, menuw=None): logger.log(9, 'mod_resolution(self, arg=%r, menuw=%r)', arg, menuw) items = [] for resolution in ('Optimal', '1920:1080', '1280:720', '852:480', '720:576', '720:480', '320:240'): items.append( menu.MenuItem(resolution, action=self.alter_prop, arg=('resolution', resolution))) resolution_menu = menu.Menu(_('Modify Resolution'), items, item_types='video encoding menu') resolution_menu.infoitem = self menuw.pushmenu(resolution_menu) menuw.refresh() def mod_videocodec(self, arg=None, menuw=None): logger.log(9, 'mod_videocodec(self, arg=%r, menuw=%r)', arg, menuw) items = [] for videocodec in self.server.getVideoCodecCAP()[1]: items.append( menu.MenuItem(videocodec, action=self.alter_prop, arg=('videocodec', videocodec))) videocodec_menu = menu.Menu(_('Modify Video Codec'), items, item_types='video encoding menu') videocodec_menu.infoitem = self menuw.pushmenu(videocodec_menu) menuw.refresh() def mod_videobitrate(self, arg=None, menuw=None): logger.log(9, 'mod_videobitrate(self, arg=%r, menuw=%r)', arg, menuw) items = [] for videobitrate in range(400, 2001, 200): items.append( menu.MenuItem(videobitrate, action=self.alter_prop, arg=('videobitrate', videobitrate))) videobitrate_menu = menu.Menu(_('Modify Video Bitrate'), items, item_types='video encoding menu') videobitrate_menu.infoitem = self menuw.pushmenu(videobitrate_menu) menuw.refresh() def mod_audiocodec(self, arg=None, menuw=None): logger.log(9, 'mod_audiocodec(self, arg=%r, menuw=%r)', arg, menuw) items = [] for audiocodec in self.server.getAudioCodecCAP()[1]: items.append( menu.MenuItem(audiocodec, action=self.alter_prop, arg=('audiocodec', audiocodec))) audiocodec_menu = menu.Menu(_('Modify Video Codec'), items, item_types='video encoding menu') audiocodec_menu.infoitem = self menuw.pushmenu(audiocodec_menu) menuw.refresh() def mod_audiobitrate(self, arg=None, menuw=None): logger.log(9, 'mod_audiobitrate(self, arg=%r, menuw=%r)', arg, menuw) items = [] for audiobitrate in (64, 128, 192, 224): items.append( menu.MenuItem(audiobitrate, action=self.alter_prop, arg=('audiobitrate', audiobitrate))) audiobitrate_menu = menu.Menu(_('Modify Audio Bitrate'), items, item_types='video encoding menu') audiobitrate_menu.infoitem = self menuw.pushmenu(audiobitrate_menu) menuw.refresh() def mod_numpasses(self, arg=None, menuw=None): logger.log(9, 'mod_numpasses(self, arg=%r, menuw=%r)', arg, menuw) items = [] for numpasses in (1, 2): items.append( menu.MenuItem(numpasses, action=self.alter_prop, arg=('numpasses', numpasses))) numpasses_menu = menu.Menu(_('Modify Number of Passes'), items, item_types='video encoding menu') numpasses_menu.infoitem = self menuw.pushmenu(numpasses_menu) menuw.refresh() def mod_numthreads(self, arg=None, menuw=None): logger.log(9, 'mod_numthreads(self, arg=%r, menuw=%r)', arg, menuw) items = [] for numthreads in (1, 2, 3, 4, 5, 6, 7, 8): items.append( menu.MenuItem(numthreads, action=self.alter_prop, arg=('numthreads', numthreads))) numthreads_menu = menu.Menu(_('Modify Number of Encoding threads'), items, item_types='video encoding menu') numthreads_menu.infoitem = self menuw.pushmenu(numthreads_menu) menuw.refresh() def mod_videofilter(self, arg=None, menuw=None): logger.log(9, 'mod_videofilter(self, arg=%r, menuw=%r)', arg, menuw) items = [] for videofilter in self.server.getVideoFiltersCAP()[1]: items.append( menu.MenuItem(videofilter, action=self.alter_prop, arg=('videofilter', videofilter))) videofilter_menu = menu.Menu(_('Modify Video Filter'), items, item_types='video encoding menu') videofilter_menu.infoitem = self menuw.pushmenu(videofilter_menu) menuw.refresh() def select_encoding_profile(self, arg=None, menuw=None): logger.log(9, 'select_encoding_profile(self, arg=%r, menuw=%r)', arg, menuw) if arg == 'xvid_low': self.profile['container'] = 'avi' self.profile['resolution'] = 'Optimal' self.profile['videocodec'] = 'XviD' self.profile['altprofile'] = None self.profile['videobitrate'] = 800 self.profile['audiocodec'] = 'MPEG 1 Layer 3 (mp3)' self.profile['audiobitrate'] = 128 self.profile['numpasses'] = 1 self.profile['videofilter'] = 'None' elif arg == 'xvid_high': self.profile['container'] = 'avi' self.profile['resolution'] = 'Optimal' self.profile['videocodec'] = 'XviD' self.profile['altprofile'] = None self.profile['videobitrate'] = 1200 self.profile['audiocodec'] = 'MPEG 1 Layer 3 (mp3)' self.profile['audiobitrate'] = 128 self.profile['numpasses'] = 2 self.profile['videofilter'] = 'None' elif arg == 'ipod': self.profile['container'] = 'mp4' self.profile['resolution'] = '320:240' self.profile['videocodec'] = 'MPEG 4 (lavc)' self.profile[ 'altprofile'] = 'vcodec=mpeg4:mbd=2:cmp=2:subcmp=2:trell=yes:v4mv=yes:vglobal=1' self.profile['videobitrate'] = 1200 self.profile['audiocodec'] = 'AAC (iPod)' self.profile['audiobitrate'] = 192 self.profile['numpasses'] = 2 self.profile['videofilter'] = 'ipod' elif arg == 'MPEG 2 (lavc)': self.profile['container'] = 'mpeg' self.profile['resolution'] = '720:480' self.profile['videocodec'] = 'MPEG 2 (lavc)' self.profile['altprofile'] = None self.profile['videobitrate'] = 5200 self.profile['audiocodec'] = 'AC3' self.profile['audiobitrate'] = 224 self.profile['numpasses'] = 1 self.profile['videofilter'] = 'None' else: logger.error('Unknown Profile "%s"', arg) self.error(_('Unknown Profile') + (' "%s"' % (arg))) return if menuw: menuw.back_one_menu(arg='reload') def alter_prop(self, arg=(None, None), menuw=None): logger.log(9, 'alter_prop(self, arg=%r, menuw=%r)', arg, menuw) (prop, val) = arg if prop == 'container': self.profile['container'] = val elif prop == 'resolution': self.profile['resolution'] = val elif prop == 'videocodec': self.profile['videocodec'] = val elif prop == 'altprofile': self.profile['altprofile'] = val elif prop == 'videobitrate': self.profile['videobitrate'] = val elif prop == 'audiocodec': self.profile['audiocodec'] = val elif prop == 'audiobitrate': self.profile['audiobitrate'] = val elif prop == 'numpasses': self.profile['numpasses'] = val elif prop == 'numthreads': self.profile['numthreads'] = val elif prop == 'videofilter': self.profile['videofilter'] = val else: logger.error('Unknown property "%s"', prop) self.error(_('Unknown Property') + (' "%s"' % (prop))) return if menuw: menuw.back_one_menu(arg='reload') def alter_name(self, name): '''alter_name is not used''' logger.log(9, 'alter_name(self, name=%r)', name) self.menuw.refresh() def create_job(self, menuw=None, arg=None): logger.log(9, 'create_job(self, arg=%r, menuw=%r)', arg, menuw) profile = arg # note that this may later be changed by the uniquify_filename() self.output = self.prepare_output(self.source) if self.output[:2] == './' and self.warn_once_savedir: #it will go into the encodingserver temporary dir, and we cant tell it from # this process self.warn_once_savedir = False AlertBox(text=_( 'This encoding job will be written to a temporary ' 'directory. Please set the variable ENCODINGSERVER_SAVEDIR to a ' 'directory where the reencoded file can be written to.')).show( ) return #we are going to create a job and send it to the encoding server, this can take some time while analyzing box = PopupBox(text=_('Please wait, analyzing video...')) box.show() (status, resp) = self.server.initEncodingJob(self.source, self.output, self.title) idnr = resp logger.debug('initEncodingJob:status:%s resp:%s', status, resp) if not status: box.destroy() self.error(_('Failed to analyze video.')) return (status, resp) = self.server.setTimeslice(idnr, self.timeslice) logger.debug('setTimeslice:status:%s resp:%s', status, resp) if not status: box.destroy() self.error(resp) return (status, resp) = self.server.waitCropDetect(idnr) logger.debug('WaitCropDetect:status:%s resp:%s', status, resp) if not status: box.destroy() self.error(resp) return box.destroy() if not status: self.error(resp) return (status, resp) = self.server.setContainer(idnr, profile['container']) logger.debug('setContainer:status:%s resp:%s', status, resp) if not status: self.error(resp) return multipass = profile['numpasses'] > 1 (status, resp) = self.server.setVideoCodec(idnr, profile['videocodec'], 0, multipass, profile['videobitrate'], profile['altprofile']) logger.debug('setVideoCodec:status:%s resp:%s', status, resp) if not status: self.error(resp) return (status, resp) = self.server.setAudioCodec(idnr, profile['audiocodec'], profile['audiobitrate']) logger.debug('setAudioCodec:status:%s resp:%s', status, resp) if not status: self.error(resp) return (status, resp) = self.server.setNumThreads(idnr, profile['numthreads']) logger.debug('setNumThreads:status:%s resp:%s', status, resp) if not status: self.error(resp) return (status, resp) = self.server.setVideoRes(idnr, profile['resolution']) logger.debug('setVideoRes:status:%s resp:%s', status, resp) if not status: self.error(resp) return #(status, resp) = self.server.setVideoFilters(idnr, vfilters) #_debug_('setVideoFilters:status:%s resp:%s' % (status, resp)) #And finally, queue and start the job (status, resp) = self.server.queueIt(idnr, True) logger.debug('queueIt:status:%s resp:%s', status, resp) if not status: self.error(resp) return self.menuw = menuw AlertBox(width=400, height=200, text=_('Encoding started'), handler=self.mopup).show() self.resetprofile() logger.debug('boe') #menuw.delete_menu() #menuw.delete_menu() def error(self, text=''): logger.debug('error(self, text=%r)', text) AlertBox(width=400, height=200, text='ERROR: %s' % text).show() def mopup(self): logger.debug('mopup(self)') self.menuw.delete_menu() self.menuw.back_one_menu()
class PluginInterface(plugin.ItemPlugin): """ Plug-in to archive recorded TV programmes using EncodingServer This plugin NEEDS a running encodingserver to work properly. You can start an encodingserver with "freevo encodingserver start". """ def __init__(self): logger.debug('reencode-old.PluginInterface.__init__(self)') plugin.ItemPlugin.__init__(self) self.server = EncodingClientActions() def actions(self, item): logger.debug('actions(self, item)') if item.type == 'video' and item.mode == 'file': # TODO: use a config variable (filename, extn) = os.path.splitext(item.filename) if extn in ['.mpeg', '.mpg']: #for dvd on disc self.dvdsource = item.filename self.title = item.name self.source = item.filename self.filename = filename + '.avi' self.item = item return [(self.encoding_profile_menu, _('Re-encode this program...'))] return [] def encoding_profile_menu(self, menuw=None, arg=None): logger.debug('encoding_profile_menu(self, menuw=None, arg=None)') #create a menu with a few encoding options (1cd, 2cd, xvid, mpeg4) #args : tuple, (videocodec, size, multipass menu_items = [ menu.MenuItem("XviD, 800bps", self.create_job, (0, 0, 1, None, 700, False, 800)) ] menu_items.append( menu.MenuItem("XviD, 800bps, High Quality", self.create_job, (0, 0, 1, None, 700, True, 800))) menu_items.append( menu.MenuItem("XviD, 1200bps", self.create_job, (0, 0, 1, None, 1400, False, 1200))) menu_items.append( menu.MenuItem("XviD, 1200bps, High Quality", self.create_job, (0, 0, 1, None, 1400, True, 1200))) menu_items.append( menu.MenuItem("DivX, 800bps", self.create_job, (0, 0, 0, None, 700, False, 800))) menu_items.append( menu.MenuItem("DivX, 800bps, High Quality", self.create_job, (0, 0, 0, None, 700, True, 800))) menu_items.append( menu.MenuItem("DivX, 1200bps", self.create_job, (0, 0, 0, None, 1400, False, 1200))) menu_items.append( menu.MenuItem("DivX, 1200bps, High Quality", self.create_job, (0, 0, 0, None, 1400, True, 1200))) menu_items.append( menu.MenuItem("iPod", self.create_job, (2, 2, 2, None, None, False, 1200))) encoding_menu = menu.Menu(_('Choose your encoding profile'), menu_items) menuw.pushmenu(encoding_menu) def create_job(self, menuw=None, arg=None): logger.debug('create_job(self, menuw=None, arg=None)') print 'arg:', arg #unwrap settings tupple (contnr, audionr, vcodecnr, vfilter, tgtsize, mpass, vbitrate) = arg #we are going to create a job and send it to the encoding server, this can take some time while analyzing box = PopupBox(text=_('Please wait, analyzing video...')) box.show() (status, resp) = self.server.initEncodingJob(self.source, self.filename, self.title) print 'initEncodingJob:status:', status, ' resp:', resp box.destroy() if not status: self.error(resp) return idnr = resp #ask for possible containers and set the first one (should be avi), we will get a list (status, resp) = self.server.getContainerCAP(idnr) print 'getContainerCAP:status:', status, ' resp:', resp if not status: self.error(resp) return container = resp[contnr] (status, resp) = self.server.setContainer(idnr, container) print 'setContainer:status:', status, ' resp:', resp if not status: self.error(resp) return #ask for possible videocodec and set the first one (should be mpeg4), we will get a list (status, resp) = self.server.getVideoCodecCAP(idnr) print 'getVideoCodecCAP:status:', status, ' resp:', resp if not status: self.error(resp) return vcodec = resp[vcodecnr] (status, resp) = self.server.setVideoCodec(idnr, vcodec, tgtsize, mpass, vbitrate) print 'setVideoCodec:status:', status, ' resp:', resp if not status: self.error(resp) return #ask for possible audiocodec and set the first one (should be mp3), we will get a list #Audiocodec call isn't necessary atm, it defaults to 128 kbit mp3, but this might change in the future #so we play safe (status, resp) = self.server.getAudioCodecCAP(idnr) print 'getAudioCodecCAP:status:', status, ' resp:', resp if not status: self.error(resp) return acodec = resp[audionr] (status, resp) = self.server.setAudioCodec(idnr, acodec, 128) print 'setAudioCodec:status:', status, ' resp:', resp if not status: self.error(resp) return (status, resp) = self.server.getVideoFiltersCAP(idnr) print 'getVideoFiltersCAP:status:', status, ' resp:', resp if not status: self.error(resp) return #vfilters=resp[vfilter] #(status, resp) = self.server.setVideoFilters(idnr, vfilters) #print 'setVideoFilter:status:', status, ' resp:', resp #And finally, qeue and start the job (status, resp) = self.server.queueIt(idnr, True) print 'queueIt:status:', status, ' resp:', resp if not status: self.error(resp) return self.menuw = menuw AlertBox(width=400, height=200, text=_("Encoding started"), handler=self.mopup).show() print "boe" #menuw.delete_menu() #menuw.delete_menu() def error(self, text=""): logger.debug('error(self, text="")') AlertBox(width=400, height=200, text="ERROR: %s" % text).show() def mopup(self): logger.debug('mopup(self)') self.menuw.delete_menu() self.menuw.back_one_menu()
class PluginInterface(plugin.ItemPlugin): """ Plug-in to archive recorded TV programmes using EncodingServer This plugin NEEDS a running encodingserver to work properly. You can start an encodingserver with "freevo encodingserver start". """ def __init__(self): logger.debug('reencode-old.PluginInterface.__init__(self)') plugin.ItemPlugin.__init__(self) self.server = EncodingClientActions() def actions(self, item): logger.debug('actions(self, item)') if item.type == 'video' and item.mode == 'file': # TODO: use a config variable (filename, extn) = os.path.splitext(item.filename) if extn in ['.mpeg','.mpg']: #for dvd on disc self.dvdsource = item.filename self.title = item.name self.source = item.filename self.filename = filename+'.avi' self.item = item return [ (self.encoding_profile_menu, _('Re-encode this program...')) ] return [] def encoding_profile_menu(self, menuw=None, arg=None): logger.debug('encoding_profile_menu(self, menuw=None, arg=None)') #create a menu with a few encoding options (1cd, 2cd, xvid, mpeg4) #args : tuple, (videocodec, size, multipass menu_items = [ menu.MenuItem("XviD, 800bps", self.create_job, (0,0,1,None,700,False,800)) ] menu_items.append( menu.MenuItem("XviD, 800bps, High Quality", self.create_job, (0,0,1,None,700,True,800)) ) menu_items.append( menu.MenuItem("XviD, 1200bps", self.create_job, (0,0,1,None,1400,False,1200)) ) menu_items.append( menu.MenuItem("XviD, 1200bps, High Quality", self.create_job, (0,0,1,None,1400,True,1200)) ) menu_items.append( menu.MenuItem("DivX, 800bps", self.create_job, (0,0,0,None,700,False,800)) ) menu_items.append( menu.MenuItem("DivX, 800bps, High Quality", self.create_job, (0,0,0,None,700,True,800)) ) menu_items.append( menu.MenuItem("DivX, 1200bps", self.create_job, (0,0,0,None,1400,False,1200)) ) menu_items.append( menu.MenuItem("DivX, 1200bps, High Quality", self.create_job, (0,0,0,None,1400,True,1200)) ) menu_items.append( menu.MenuItem("iPod", self.create_job,(2,2,2,None,None,False,1200)) ) encoding_menu = menu.Menu(_('Choose your encoding profile'), menu_items) menuw.pushmenu(encoding_menu) def create_job(self, menuw=None, arg=None): logger.debug('create_job(self, menuw=None, arg=None)') print 'arg:', arg #unwrap settings tupple (contnr, audionr, vcodecnr, vfilter, tgtsize, mpass, vbitrate) = arg #we are going to create a job and send it to the encoding server, this can take some time while analyzing box = PopupBox(text=_('Please wait, analyzing video...')) box.show() (status, resp) = self.server.initEncodingJob(self.source, self.filename, self.title) print 'initEncodingJob:status:', status, ' resp:', resp box.destroy() if not status: self.error(resp) return idnr = resp #ask for possible containers and set the first one (should be avi), we will get a list (status, resp) = self.server.getContainerCAP(idnr) print 'getContainerCAP:status:', status, ' resp:', resp if not status: self.error(resp) return container = resp[contnr] (status, resp) = self.server.setContainer(idnr, container) print 'setContainer:status:', status, ' resp:', resp if not status: self.error(resp) return #ask for possible videocodec and set the first one (should be mpeg4), we will get a list (status, resp) = self.server.getVideoCodecCAP(idnr) print 'getVideoCodecCAP:status:', status, ' resp:', resp if not status: self.error(resp) return vcodec = resp[vcodecnr] (status, resp) = self.server.setVideoCodec(idnr, vcodec, tgtsize, mpass, vbitrate) print 'setVideoCodec:status:', status, ' resp:', resp if not status: self.error(resp) return #ask for possible audiocodec and set the first one (should be mp3), we will get a list #Audiocodec call isn't necessary atm, it defaults to 128 kbit mp3, but this might change in the future #so we play safe (status, resp) = self.server.getAudioCodecCAP(idnr) print 'getAudioCodecCAP:status:', status, ' resp:', resp if not status: self.error(resp) return acodec = resp[audionr] (status, resp) = self.server.setAudioCodec(idnr, acodec, 128) print 'setAudioCodec:status:', status, ' resp:', resp if not status: self.error(resp) return (status, resp) = self.server.getVideoFiltersCAP(idnr) print 'getVideoFiltersCAP:status:', status, ' resp:', resp if not status: self.error(resp) return #vfilters=resp[vfilter] #(status, resp) = self.server.setVideoFilters(idnr, vfilters) #print 'setVideoFilter:status:', status, ' resp:', resp #And finally, qeue and start the job (status, resp) = self.server.queueIt(idnr, True) print 'queueIt:status:', status, ' resp:', resp if not status: self.error(resp) return self.menuw = menuw AlertBox(width=400, height=200, text=_("Encoding started"), handler=self.mopup).show() print "boe" #menuw.delete_menu() #menuw.delete_menu() def error(self, text=""): logger.debug('error(self, text="")') AlertBox(width=400, height=200, text="ERROR: %s" % text).show() def mopup(self): logger.debug('mopup(self)') self.menuw.delete_menu() self.menuw.back_one_menu()