class PluginInterface(plugin.ItemPlugin): """ Make DVD backups (aka dvdrips) using EncodingServer This plugin NEEDS a running encodingserver to work properly. You can start an encodingserver with "freevo encodingserver start". Don't forget that you need some free diskspace in order to use this plugin, and don't forget a dvdrip eats quite a bit of space :) """ def __init__(self): plugin.ItemPlugin.__init__(self) self.server = EncodingClientActions() def config(self): return [ ('DVD_BACKUP_MENU', None, 'A customized menu of encoding parameters'), ] def actions(self, item): if config.DEBUG >= 2: #testing stuff if hasattr(item, 'type'): logger.debug('item.type=\"%s\"', item.type) if hasattr(item, 'mode'): logger.debug('item.mode=\"%s\"', item.mode) if hasattr(item, 'info_type'): logger.debug('item.info_type=\"%s\"', item.info_type) if hasattr(item, 'name'): logger.debug('item.name=\"%s\"', item.name) if hasattr(item, 'filename'): logger.debug('item.filename=\"%s\"', item.filename) if hasattr(item, 'parentname'): logger.debug('item.parentname=\"%s\"', item.parentname) if hasattr(item, 'media') and hasattr(item.media, 'devicename'): logger.debug('item.media.devicename=\"%s\"', item.media.devicename) if item.type == 'video' and item.mode == 'dvd' and hasattr( item, 'info_type'): if item.info_type == "track": #and item.media and item.media.devicename: #for dvd on disc self.dvdsource = item.filename self.title = int(split(item.url)[-1]) if hasattr(item, 'media') and hasattr(item.media, 'devicename'): #we have a "real" dvd disc self.dvdsource = item.media.devicename self.title = int(item.url[6:]) self.item = item return [(self.encoding_profile_menu, _('Backup this dvd title...'))] return [] def encoding_profile_menu(self, menuw=None, arg=None): if config.DVD_BACKUP_MENU: menu_items = [] for menu_item in config.DVD_BACKUP_MENU: menu_items.append( menu.MenuItem(menu_item[0], self.create_job, menu_item[1])) else: #create a menu with a few encoding options (1cd, 2cd, xvid, mpeg4) #args : tuple, (videocodec, size, multipass, bitrate, audiocodec, container) menu_items = [ menu.MenuItem("XviD, 700mb", self.create_job, (2, 700, False, 0, 0, 0)) ] menu_items.append( menu.MenuItem("XviD, 700mb, High Quality", self.create_job, (2, 700, True, 0, 0, 0))) menu_items.append( menu.MenuItem("XviD, 1400mb", self.create_job, (2, 1400, False, 0, 0, 0, 0, 0))) menu_items.append( menu.MenuItem("XviD, 1400mb, High Quality", self.create_job, (2, 1400, True, 0, 0, 0))) menu_items.append( menu.MenuItem("MPEG4, 700mb", self.create_job, (0, 700, False, 0, 0, 0))) menu_items.append( menu.MenuItem("MPEG4, 700mb, High Quality", self.create_job, (0, 700, True, 0, 0, 0))) menu_items.append( menu.MenuItem("MPEG4, 1400mb", self.create_job, (0, 1400, False, 0, 0, 0))) menu_items.append( menu.MenuItem("MPEG4, 1400mb, High Quality", self.create_job, (0, 1400, True, 0, 0, 0))) menu_items.append( menu.MenuItem("h.264, 700mb", self.create_job, (3, 700, False, 0, 0, 0))) menu_items.append( menu.MenuItem("h.264, 700mb, High Quality", self.create_job, (3, 700, True, 0, 0, 0))) menu_items.append( menu.MenuItem("h.264, 1400mb", self.create_job, (3, 1400, False, 0, 0, 0))) menu_items.append( menu.MenuItem("h.264, 1400mb, High Quality", self.create_job, (3, 1400, True, 0, 0, 0))) encoding_menu = menu.Menu(_('Choose your encoding profile'), menu_items) menuw.pushmenu(encoding_menu) def create_job(self, menuw=None, arg=None): """ """ #create a filename for the to-be-encoded dvd title #title = int(self.item.url[6:]) fname = join(config.VIDEO_ITEMS[0][1], "%s_%s" % (self.item.parent.name, self.title)) #_debug_('title=%s, fname=%s' % (title, fname)) logger.debug('arg=%r', arg) #unwrap settings tupple vcodecnr, tgtsize, mpass, vbitrate, acodecnr, contnr = 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() try: (status, resp) = self.server.initEncodingJob(self.dvdsource, fname, self.item.parent.name, self.title) if not status: self.error(resp) return finally: box.destroy() idnr = resp #ask for possible containers and set the first one (should be avi), we will get a list (status, resp) = self.server.getContainerCAP() if not status: self.error(resp) return container = resp[contnr] (status, resp) = self.server.setContainer(idnr, container) 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() if not status: self.error(resp) return vcodec = resp[vcodecnr] (status, resp) = self.server.setVideoCodec(idnr, vcodec, tgtsize, mpass, vbitrate) 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() if not status: self.error(resp) return acodec = resp[acodecnr] (status, resp) = self.server.setAudioCodec(idnr, acodec, 128) if not status: self.error(resp) return #And finally, qeue and start the job (status, resp) = self.server.queueIt(idnr, True) if not status: self.error(resp) return self.menuw = menuw AlertBox(width=400, height=200, text=_("Encoding started"), handler=self.mopup).show() logger.debug("boe") #menuw.delete_menu() #menuw.delete_menu() def error(self, text=""): AlertBox(width=400, height=200, text="ERROR: %s" % text).show() def mopup(self): self.menuw.delete_menu() self.menuw.back_one_menu()
class PluginInterface(plugin.ItemPlugin): """ Make DVD backups (aka dvdrips) using EncodingServer This plugin NEEDS a running encodingserver to work properly. You can start an encodingserver with "freevo encodingserver start". Don't forget that you need some free diskspace in order to use this plugin, and don't forget a dvdrip eats quite a bit of space :) """ def __init__(self): plugin.ItemPlugin.__init__(self) self.server = EncodingClientActions() def config(self): return [ ('DVD_BACKUP_MENU', None, 'A customized menu of encoding parameters'), ] def actions(self, item): if config.DEBUG >= 2: #testing stuff if hasattr(item, 'type'): logger.debug('item.type=\"%s\"', item.type) if hasattr(item, 'mode'): logger.debug('item.mode=\"%s\"', item.mode) if hasattr(item, 'info_type'): logger.debug('item.info_type=\"%s\"', item.info_type) if hasattr(item, 'name'): logger.debug('item.name=\"%s\"', item.name) if hasattr(item, 'filename'): logger.debug('item.filename=\"%s\"', item.filename) if hasattr(item, 'parentname'): logger.debug('item.parentname=\"%s\"', item.parentname) if hasattr(item, 'media') and hasattr(item.media, 'devicename'): logger.debug('item.media.devicename=\"%s\"', item.media.devicename) if item.type == 'video' and item.mode == 'dvd' and hasattr(item, 'info_type'): if item.info_type == "track": #and item.media and item.media.devicename: #for dvd on disc self.dvdsource = item.filename self.title = int(split(item.url)[-1]) if hasattr(item, 'media') and hasattr(item.media, 'devicename'): #we have a "real" dvd disc self.dvdsource = item.media.devicename self.title = int(item.url[6:]) self.item = item return [ (self.encoding_profile_menu, _('Backup this dvd title...')) ] return [] def encoding_profile_menu(self, menuw=None, arg=None): if config.DVD_BACKUP_MENU: menu_items = [] for menu_item in config.DVD_BACKUP_MENU: menu_items.append(menu.MenuItem(menu_item[0], self.create_job, menu_item[1])) else: #create a menu with a few encoding options (1cd, 2cd, xvid, mpeg4) #args : tuple, (videocodec, size, multipass, bitrate, audiocodec, container) menu_items = [ menu.MenuItem("XviD, 700mb", self.create_job, (2, 700, False, 0, 0, 0)) ] menu_items.append( menu.MenuItem("XviD, 700mb, High Quality", self.create_job, (2, 700, True, 0, 0, 0)) ) menu_items.append( menu.MenuItem("XviD, 1400mb", self.create_job, (2, 1400, False, 0, 0, 0, 0, 0)) ) menu_items.append( menu.MenuItem("XviD, 1400mb, High Quality", self.create_job, (2, 1400, True, 0, 0, 0)) ) menu_items.append( menu.MenuItem("MPEG4, 700mb", self.create_job, (0, 700, False, 0, 0, 0)) ) menu_items.append( menu.MenuItem("MPEG4, 700mb, High Quality", self.create_job, (0, 700, True, 0, 0, 0)) ) menu_items.append( menu.MenuItem("MPEG4, 1400mb", self.create_job, (0, 1400, False, 0, 0, 0)) ) menu_items.append( menu.MenuItem("MPEG4, 1400mb, High Quality", self.create_job, (0, 1400, True, 0, 0, 0)) ) menu_items.append( menu.MenuItem("h.264, 700mb", self.create_job, (3, 700, False, 0, 0, 0)) ) menu_items.append( menu.MenuItem("h.264, 700mb, High Quality", self.create_job, (3, 700, True, 0, 0, 0)) ) menu_items.append( menu.MenuItem("h.264, 1400mb", self.create_job, (3, 1400, False, 0, 0, 0)) ) menu_items.append( menu.MenuItem("h.264, 1400mb, High Quality", self.create_job, (3, 1400, True, 0, 0, 0)) ) encoding_menu = menu.Menu(_('Choose your encoding profile'), menu_items) menuw.pushmenu(encoding_menu) def create_job(self, menuw=None, arg=None): """ """ #create a filename for the to-be-encoded dvd title #title = int(self.item.url[6:]) fname = join(config.VIDEO_ITEMS[0][1], "%s_%s" % (self.item.parent.name, self.title)) #_debug_('title=%s, fname=%s' % (title, fname)) logger.debug('arg=%r', arg) #unwrap settings tupple vcodecnr, tgtsize, mpass, vbitrate, acodecnr, contnr = 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() try: (status, resp) = self.server.initEncodingJob(self.dvdsource, fname, self.item.parent.name, self.title) if not status: self.error(resp) return finally: box.destroy() idnr = resp #ask for possible containers and set the first one (should be avi), we will get a list (status, resp) = self.server.getContainerCAP() if not status: self.error(resp) return container = resp[contnr] (status, resp) = self.server.setContainer(idnr, container) 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() if not status: self.error(resp) return vcodec = resp[vcodecnr] (status, resp) = self.server.setVideoCodec(idnr, vcodec, tgtsize, mpass, vbitrate) 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() if not status: self.error(resp) return acodec = resp[acodecnr] (status, resp) = self.server.setAudioCodec(idnr, acodec, 128) if not status: self.error(resp) return #And finally, qeue and start the job (status, resp) = self.server.queueIt(idnr, True) if not status: self.error(resp) return self.menuw = menuw AlertBox(width=400, height=200, text=_("Encoding started"), handler=self.mopup).show() logger.debug("boe") #menuw.delete_menu() #menuw.delete_menu() def error(self, text=""): AlertBox(width=400, height=200, text="ERROR: %s" % text).show() def 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): """ 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()