Esempio n. 1
0
    def __init__(self):
        logger.log(9, 'encoding.PluginInterface.__init__(self)')
        plugin.DaemonPlugin.__init__(self)
        #IdleBarPlugin.__init__(self)
        self.poll_interval = 1
        self.draw_interval = self.poll_interval
        self.last_interval = self.poll_interval
        self.lastdraw = 0
        self.lastpoll = 0
        self.plugin_name = 'video.encodingstatus'
        self.server = EncodingClientActions()

        self.skin = skin.get_singleton()
        self.barimg = os.path.join(config.ICON_DIR, 'status/encoding_bar.png')
        self.boximg = os.path.join(config.ICON_DIR, 'status/encoding_box.png')
        self.boxborder = 3
        self.padding = 5  # internal padding for box vs text
        self.image = None
        self.cacheimg = {}
        self.muted = False
        self.encoding = -1
        self.progress = 0
        self.jobname = ''
        self.calculate = True
        self.jobs = ''
        self.mode = 'Not Running'
        self.text = []
        self.percent = 0.0
        self.running = False
        self.drawtime = 0
        self.polltime = 0
        self.state = 'noserver'
        self.laststate = None
        self.font = self.skin.get_font(config.ENCODING_IDLEBAR_FONT)
Esempio n. 2
0
 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
Esempio n. 3
0
    def __init__(self):
        """ Initialise the transcode idlebar plug-in """
        logger.log(9, 'transcode.PluginInterface.__init__()')
        IdleBarPlugin.__init__(self)
        self.plugin_name = 'idlebar.transcode'

        self.background = os.path.join(config.ICON_DIR,
                                       'status/enc_background.png')
        self.leftclamp = os.path.join(config.ICON_DIR,
                                      'status/enc_leftclamp.png')
        self.rightclamp = os.path.join(config.ICON_DIR,
                                       'status/enc_rightclamp.png')
        self.notrunning = os.path.join(config.ICON_DIR,
                                       'status/enc_notrunning.png')
        self.nojobs = os.path.join(config.ICON_DIR, 'status/enc_nojobs.png')
        self.audio = os.path.join(config.ICON_DIR, 'status/enc_audio.png')
        self.video = os.path.join(config.ICON_DIR, 'status/enc_video.png')
        self.video1 = os.path.join(config.ICON_DIR, 'status/enc_video1.png')
        self.video2 = os.path.join(config.ICON_DIR, 'status/enc_video2.png')
        self.video3 = os.path.join(config.ICON_DIR, 'status/enc_video3.png')
        self.multiplex = os.path.join(config.ICON_DIR,
                                      'status/enc_multiplex.png')

        self.cacheimg = {}
        self.background_w, self.background_h = (0, 0)
        self.leftclamp_w, self.leftclamp_h = (0, 0)
        self.rightclamp_w, self.rightclamp_h = (0, 0)
        self.remaining_min = re.compile('[0-9]*')
        self.remaining = ''
        self.progress = 0
        self.progress_x = None
        self.leftclamp_x = 0
        self.rightclamp_x = 0

        self.poll_interval = 1  # 1 sec should be same as most frequent
        self.draw_interval = 5.0  # 5 secs
        self.last_interval = self.poll_interval
        self.lastdraw = 0
        self.lastpoll = 0
        self.drawtime = 0
        self.server = EncodingClientActions()

        self.skin = skin.get_singleton()
        self.calculate = True
        self.jobs = ''
        self.mode = 'Not Running'
        self.state = 'noserver'
        self.laststate = None
        self.percent = 0.0
        self.running = False
        self.font = self.skin.get_font(config.OSD_IDLEBAR_FONT)
        self.timer = kaa.Timer(self._timerhandler)
        self.timer.start(self.poll_interval)
        logger.debug('transcode.PluginInterface.__init__() done.')
Esempio n. 4
0
    def __init__(self):
        logger.log( 9, 'encoding.PluginInterface.__init__(self)')
        plugin.DaemonPlugin.__init__(self)
        #IdleBarPlugin.__init__(self)
        self.poll_interval = 1
        self.draw_interval = self.poll_interval
        self.last_interval = self.poll_interval
        self.lastdraw  = 0
        self.lastpoll  = 0
        self.plugin_name = 'video.encodingstatus'
        self.server    = EncodingClientActions()

        self.skin      = skin.get_singleton()
        self.barimg    = os.path.join(config.ICON_DIR, 'status/encoding_bar.png')
        self.boximg    = os.path.join(config.ICON_DIR, 'status/encoding_box.png')
        self.boxborder = 3
        self.padding   = 5 # internal padding for box vs text
        self.image     = None
        self.cacheimg  = {}
        self.muted     = False
        self.encoding  = -1
        self.progress  = 0
        self.jobname   = ''
        self.calculate = True
        self.jobs      = ''
        self.mode      = 'Not Running'
        self.text      = []
        self.percent   = 0.0
        self.running   = False
        self.drawtime  = 0
        self.polltime  = 0
        self.state     = 'noserver'
        self.laststate = None
        self.font      = self.skin.get_font(config.ENCODING_IDLEBAR_FONT)
Esempio n. 5
0
 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
Esempio n. 6
0
    def __init__(self):
        """ Initialise the transcode idlebar plug-in """
        logger.log( 9, 'transcode.PluginInterface.__init__()')
        IdleBarPlugin.__init__(self)
        self.plugin_name = 'idlebar.transcode'

        self.background = os.path.join(config.ICON_DIR, 'status/enc_background.png')
        self.leftclamp  = os.path.join(config.ICON_DIR, 'status/enc_leftclamp.png')
        self.rightclamp = os.path.join(config.ICON_DIR, 'status/enc_rightclamp.png')
        self.notrunning = os.path.join(config.ICON_DIR, 'status/enc_notrunning.png')
        self.nojobs     = os.path.join(config.ICON_DIR, 'status/enc_nojobs.png')
        self.audio      = os.path.join(config.ICON_DIR, 'status/enc_audio.png')
        self.video      = os.path.join(config.ICON_DIR, 'status/enc_video.png')
        self.video1     = os.path.join(config.ICON_DIR, 'status/enc_video1.png')
        self.video2     = os.path.join(config.ICON_DIR, 'status/enc_video2.png')
        self.video3     = os.path.join(config.ICON_DIR, 'status/enc_video3.png')
        self.multiplex  = os.path.join(config.ICON_DIR, 'status/enc_multiplex.png')

        self.cacheimg = {}
        self.background_w, self.background_h = (0, 0)
        self.leftclamp_w, self.leftclamp_h = (0, 0)
        self.rightclamp_w, self.rightclamp_h = (0, 0)
        self.remaining_min = re.compile('[0-9]*')
        self.remaining = ''
        self.progress  = 0
        self.progress_x = None
        self.leftclamp_x = 0
        self.rightclamp_x = 0

        self.poll_interval = 1 # 1 sec should be same as most frequent
        self.draw_interval = 5.0 # 5 secs
        self.last_interval = self.poll_interval
        self.lastdraw  = 0
        self.lastpoll  = 0
        self.drawtime  = 0
        self.server    = EncodingClientActions()

        self.skin      = skin.get_singleton()
        self.calculate = True
        self.jobs      = ''
        self.mode      = 'Not Running'
        self.state     = 'noserver'
        self.laststate = None
        self.percent   = 0.0
        self.running   = False
        self.font      = self.skin.get_font(config.OSD_IDLEBAR_FONT)
        self.timer     = kaa.Timer(self._timerhandler)
        self.timer.start(self.poll_interval)
        logger.debug('transcode.PluginInterface.__init__() done.')
Esempio n. 7
0
 def __init__(self):
     logger.debug('reencode-old.PluginInterface.__init__(self)')
     plugin.ItemPlugin.__init__(self)
     self.server = EncodingClientActions()
Esempio n. 8
0
 def __init__(self):
     plugin.ItemPlugin.__init__(self)
     self.server = EncodingClientActions()
Esempio n. 9
0
class PluginInterface(IdleBarPlugin):
    """
    Shows the status of the current encoding job

    Activate with::

        | plugin.activate('idlebar.transcode')
    """

    def __init__(self):
        """ Initialise the transcode idlebar plug-in """
        logger.log( 9, 'transcode.PluginInterface.__init__()')
        IdleBarPlugin.__init__(self)
        self.plugin_name = 'idlebar.transcode'

        self.background = os.path.join(config.ICON_DIR, 'status/enc_background.png')
        self.leftclamp  = os.path.join(config.ICON_DIR, 'status/enc_leftclamp.png')
        self.rightclamp = os.path.join(config.ICON_DIR, 'status/enc_rightclamp.png')
        self.notrunning = os.path.join(config.ICON_DIR, 'status/enc_notrunning.png')
        self.nojobs     = os.path.join(config.ICON_DIR, 'status/enc_nojobs.png')
        self.audio      = os.path.join(config.ICON_DIR, 'status/enc_audio.png')
        self.video      = os.path.join(config.ICON_DIR, 'status/enc_video.png')
        self.video1     = os.path.join(config.ICON_DIR, 'status/enc_video1.png')
        self.video2     = os.path.join(config.ICON_DIR, 'status/enc_video2.png')
        self.video3     = os.path.join(config.ICON_DIR, 'status/enc_video3.png')
        self.multiplex  = os.path.join(config.ICON_DIR, 'status/enc_multiplex.png')

        self.cacheimg = {}
        self.background_w, self.background_h = (0, 0)
        self.leftclamp_w, self.leftclamp_h = (0, 0)
        self.rightclamp_w, self.rightclamp_h = (0, 0)
        self.remaining_min = re.compile('[0-9]*')
        self.remaining = ''
        self.progress  = 0
        self.progress_x = None
        self.leftclamp_x = 0
        self.rightclamp_x = 0

        self.poll_interval = 1 # 1 sec should be same as most frequent
        self.draw_interval = 5.0 # 5 secs
        self.last_interval = self.poll_interval
        self.lastdraw  = 0
        self.lastpoll  = 0
        self.drawtime  = 0
        self.server    = EncodingClientActions()

        self.skin      = skin.get_singleton()
        self.calculate = True
        self.jobs      = ''
        self.mode      = 'Not Running'
        self.state     = 'noserver'
        self.laststate = None
        self.percent   = 0.0
        self.running   = False
        self.font      = self.skin.get_font(config.OSD_IDLEBAR_FONT)
        self.timer     = kaa.Timer(self._timerhandler)
        self.timer.start(self.poll_interval)
        logger.debug('transcode.PluginInterface.__init__() done.')


    def config(self):
        logger.log( 9, 'config()')
        return [
        ]


    def getimage(self, image, osd, cache=False):
        """
        Load the image from the cache when available otherwise load the image and save
        in the cache.
        """
        logger.log( 9, 'getimage(image=%r, osd=%r, cache=%s)', image, osd, cache)
        if image.find(config.ICON_DIR) == 0 and image.find(osd.settings.icon_dir) == -1:
            new_image = os.path.join(osd.settings.icon_dir, image[len(config.ICON_DIR)+1:])
            if os.path.isfile(new_image):
                image = new_image
        if cache:
            if image not in self.cacheimg.keys():
                self.cacheimg[image] = pygame.image.load(image)
            return self.cacheimg[image]

        return pygame.image.load(image)


    def set_sprite(self):
        """ set the sprite image name and the drawing interval """
        logger.log( 9, 'set_sprite()')
        (status, jobs) = self.server.listJobs()
        if not status:
            self.sprite = self.notrunning
            self.state = 'noserver'
            self.jobs = _('encoding server not running')
            self.draw_interval = 5.0
            self.running = False
            return (self.background_w, self.background_h);
        if not jobs:
            self.sprite = self.nojobs
            self.state = 'nojobs'
            self.jobs = _('encoding server has no jobs')
            self.draw_interval = 5.0
            self.running = False
            return (self.background_w, self.background_h);
        self.state = 'active'
        (idnr, jobname, jobstate) = jobs[0]
        joblist = jobname
        for job in jobs[1:]:
            (idnr, jobname, jobstate) = job
            joblist += ', ' + jobname
        self.jobs = joblist
        self.running = True

        (status, progress) = self.server.getProgress();
        if status:
            if progress[1] == 0:
                self.sprite = self.nojobs
                self.mode = 'Not started'
                self.state = 'active'
                self.draw_interval = 5.0
            elif progress[1] == 1:
                self.sprite = self.audio
                self.mode = 'Audio'
                self.state = 'audio'
                self.draw_interval = 0.2
            elif progress[1] == 2:
                self.sprite = self.video1
                self.mode = 'Video-1'
                self.state = 'video'
                self.draw_interval = 1.0
            elif progress[1] == 3:
                self.sprite = self.video2
                self.mode = 'Video-2'
                self.state = 'video'
                self.draw_interval = 1.0
            elif progress[1] == 4:
                self.sprite = self.multiplex
                self.mode = 'Multiplexing'
                self.state = 'multiplexing'
                self.draw_interval = 1.0
            if isinstance(progress[3], basestring):
                remaining = self.remaining_min.search(progress[3])
            else:
                remaining = 0
            self.remaining = remaining and remaining.group() or ''
            self.progress = progress[2]
            self.percent = progress[2] / 100.0
            return (self.background_w, self.background_h);


    def calculatesizes(self, osd, font):
        """size calcs is not necessery on every pass
        There are some shortcuts here, the left and right clamps are the same with
        all sprites are the same size and the background
        return true when the progress has changed, false otherwise
        """
        logger.log( 9, 'calculatesizes(osd, font)')
        if self.progress_x == None:
            background = self.getimage(self.background, osd)
            rightclamp = self.getimage(self.rightclamp, osd, True)
            leftclamp = self.getimage(self.leftclamp, osd, True)
            self.background_w, self.background_h = background.get_size()
            self.leftclamp_w, self.leftclamp_h = leftclamp.get_size()
            self.rightclamp_w, self.rightclamp_h = rightclamp.get_size()
            logger.log( 9, 'background: w=%s, h=%s', self.background_w, self.background_h)
            logger.log( 9, 'leftclamp: w=%s, h=%s', self.leftclamp_w, self.leftclamp_h)
            logger.log( 9, 'rightclamp: w=%s, h=%s', self.rightclamp_w, self.rightclamp_h)

        progress_x = ((self.background_w - (2 * self.leftclamp_w)) * self.progress) / 200
        logger.log( 8, 'progress_x=%s, background_w=%s, leftclamp_w=%s, progress=%s', progress_x, self.background_w, self.leftclamp_w, self.progress)


        if self.progress_x != progress_x:
            self.progress_x = progress_x
            self.leftclamp_x = self.progress_x
            self.rightclamp_x = self.background_w - self.rightclamp_w - self.progress_x
            logger.log( 9, 'progress_x=%s, leftclamp_x=%s, rightclamp_x=%s', self.progress_x, self.leftclamp_x, self.rightclamp_x)

            return True
        return False


    def draw(self, (type, object), x, osd):
        """ Build the image by blitting sub images on the background and draw the background """
        logger.log( 8, 'draw((type=%r, object=), x=%r, osd=)', type, x)
        now = time.time()
        duration = now - self.drawtime
        logger.log( 9, "draw=%.2f, interval=%s, state=%s", duration, self.draw_interval, self.state)
        self.drawtime = now
        self.lastdraw = now

        (sprite_w, sprite_h) = self.set_sprite()
        self.calculatesizes(osd, self.font)

        background = self.getimage(self.background, osd)
        if self.sprite:
            sprite = self.getimage(self.sprite, osd)
            background.blit(sprite, (0, 0), (0, 0, self.background_w, self.background_h))
        leftclamp = self.getimage(self.leftclamp, osd, True)
        rightclamp = self.getimage(self.rightclamp, osd, True)
        background.blit(leftclamp, (self.leftclamp_x, 1), (0, 0, self.leftclamp_w, self.leftclamp_h))
        background.blit(rightclamp, (self.rightclamp_x, 1), (0, 0, self.rightclamp_w, self.rightclamp_h))
        osd.drawimage(background, (x, osd.y, -1, -1) )[0]
        if self.remaining:
            font = osd.get_font(config.OSD_IDLEBAR_FONT)
            widthdf = font.stringsize(self.remaining)
            remaining_x = x + ((self.background_w - widthdf) / 2)
            remaining_y = osd.y + self.background_h - font.h + 10
            logger.debug('remaining=%r x=%s y=%s widthdf=%s font.h=%s', self.remaining, remaining_x, remaining_y, widthdf, font.h)

            osd.write_text(self.remaining, font, None, remaining_x, remaining_y, widthdf, font.h, 'center', 'top')

        return self.background_w
Esempio n. 10
0
 def __init__(self):
     plugin.ItemPlugin.__init__(self)
     self.server = EncodingClientActions()
Esempio n. 11
0
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()
Esempio n. 12
0
class PluginInterface(IdleBarPlugin):
    """
    Shows the status of the current encoding job

    Activate with::

        | plugin.activate('idlebar.transcode')
    """
    def __init__(self):
        """ Initialise the transcode idlebar plug-in """
        logger.log(9, 'transcode.PluginInterface.__init__()')
        IdleBarPlugin.__init__(self)
        self.plugin_name = 'idlebar.transcode'

        self.background = os.path.join(config.ICON_DIR,
                                       'status/enc_background.png')
        self.leftclamp = os.path.join(config.ICON_DIR,
                                      'status/enc_leftclamp.png')
        self.rightclamp = os.path.join(config.ICON_DIR,
                                       'status/enc_rightclamp.png')
        self.notrunning = os.path.join(config.ICON_DIR,
                                       'status/enc_notrunning.png')
        self.nojobs = os.path.join(config.ICON_DIR, 'status/enc_nojobs.png')
        self.audio = os.path.join(config.ICON_DIR, 'status/enc_audio.png')
        self.video = os.path.join(config.ICON_DIR, 'status/enc_video.png')
        self.video1 = os.path.join(config.ICON_DIR, 'status/enc_video1.png')
        self.video2 = os.path.join(config.ICON_DIR, 'status/enc_video2.png')
        self.video3 = os.path.join(config.ICON_DIR, 'status/enc_video3.png')
        self.multiplex = os.path.join(config.ICON_DIR,
                                      'status/enc_multiplex.png')

        self.cacheimg = {}
        self.background_w, self.background_h = (0, 0)
        self.leftclamp_w, self.leftclamp_h = (0, 0)
        self.rightclamp_w, self.rightclamp_h = (0, 0)
        self.remaining_min = re.compile('[0-9]*')
        self.remaining = ''
        self.progress = 0
        self.progress_x = None
        self.leftclamp_x = 0
        self.rightclamp_x = 0

        self.poll_interval = 1  # 1 sec should be same as most frequent
        self.draw_interval = 5.0  # 5 secs
        self.last_interval = self.poll_interval
        self.lastdraw = 0
        self.lastpoll = 0
        self.drawtime = 0
        self.server = EncodingClientActions()

        self.skin = skin.get_singleton()
        self.calculate = True
        self.jobs = ''
        self.mode = 'Not Running'
        self.state = 'noserver'
        self.laststate = None
        self.percent = 0.0
        self.running = False
        self.font = self.skin.get_font(config.OSD_IDLEBAR_FONT)
        self.timer = kaa.Timer(self._timerhandler)
        self.timer.start(self.poll_interval)
        logger.debug('transcode.PluginInterface.__init__() done.')

    def config(self):
        logger.log(9, 'config()')
        return []

    def getimage(self, image, osd, cache=False):
        """
        Load the image from the cache when available otherwise load the image and save
        in the cache.
        """
        logger.log(9, 'getimage(image=%r, osd=%r, cache=%s)', image, osd,
                   cache)
        if image.find(config.ICON_DIR) == 0 and image.find(
                osd.settings.icon_dir) == -1:
            new_image = os.path.join(osd.settings.icon_dir,
                                     image[len(config.ICON_DIR) + 1:])
            if os.path.isfile(new_image):
                image = new_image
        if cache:
            if image not in self.cacheimg.keys():
                self.cacheimg[image] = pygame.image.load(image)
            return self.cacheimg[image]

        return pygame.image.load(image)

    def set_sprite(self):
        """ set the sprite image name and the drawing interval """
        logger.log(9, 'set_sprite()')
        (status, jobs) = self.server.listJobs()
        if not status:
            self.sprite = self.notrunning
            self.state = 'noserver'
            self.jobs = _('encoding server not running')
            self.draw_interval = 5.0
            self.running = False
            return (self.background_w, self.background_h)
        if not jobs:
            self.sprite = self.nojobs
            self.state = 'nojobs'
            self.jobs = _('encoding server has no jobs')
            self.draw_interval = 5.0
            self.running = False
            return (self.background_w, self.background_h)
        self.state = 'active'
        (idnr, jobname, jobstate) = jobs[0]
        joblist = jobname
        for job in jobs[1:]:
            (idnr, jobname, jobstate) = job
            joblist += ', ' + jobname
        self.jobs = joblist
        self.running = True

        (status, progress) = self.server.getProgress()
        if status:
            if progress[1] == 0:
                self.sprite = self.nojobs
                self.mode = 'Not started'
                self.state = 'active'
                self.draw_interval = 5.0
            elif progress[1] == 1:
                self.sprite = self.audio
                self.mode = 'Audio'
                self.state = 'audio'
                self.draw_interval = 0.2
            elif progress[1] == 2:
                self.sprite = self.video1
                self.mode = 'Video-1'
                self.state = 'video'
                self.draw_interval = 1.0
            elif progress[1] == 3:
                self.sprite = self.video2
                self.mode = 'Video-2'
                self.state = 'video'
                self.draw_interval = 1.0
            elif progress[1] == 4:
                self.sprite = self.multiplex
                self.mode = 'Multiplexing'
                self.state = 'multiplexing'
                self.draw_interval = 1.0
            if isinstance(progress[3], basestring):
                remaining = self.remaining_min.search(progress[3])
            else:
                remaining = 0
            self.remaining = remaining and remaining.group() or ''
            self.progress = progress[2]
            self.percent = progress[2] / 100.0
            return (self.background_w, self.background_h)

    def calculatesizes(self, osd, font):
        """size calcs is not necessery on every pass
        There are some shortcuts here, the left and right clamps are the same with
        all sprites are the same size and the background
        return true when the progress has changed, false otherwise
        """
        logger.log(9, 'calculatesizes(osd, font)')
        if self.progress_x == None:
            background = self.getimage(self.background, osd)
            rightclamp = self.getimage(self.rightclamp, osd, True)
            leftclamp = self.getimage(self.leftclamp, osd, True)
            self.background_w, self.background_h = background.get_size()
            self.leftclamp_w, self.leftclamp_h = leftclamp.get_size()
            self.rightclamp_w, self.rightclamp_h = rightclamp.get_size()
            logger.log(9, 'background: w=%s, h=%s', self.background_w,
                       self.background_h)
            logger.log(9, 'leftclamp: w=%s, h=%s', self.leftclamp_w,
                       self.leftclamp_h)
            logger.log(9, 'rightclamp: w=%s, h=%s', self.rightclamp_w,
                       self.rightclamp_h)

        progress_x = ((self.background_w -
                       (2 * self.leftclamp_w)) * self.progress) / 200
        logger.log(
            8, 'progress_x=%s, background_w=%s, leftclamp_w=%s, progress=%s',
            progress_x, self.background_w, self.leftclamp_w, self.progress)

        if self.progress_x != progress_x:
            self.progress_x = progress_x
            self.leftclamp_x = self.progress_x
            self.rightclamp_x = self.background_w - self.rightclamp_w - self.progress_x
            logger.log(9, 'progress_x=%s, leftclamp_x=%s, rightclamp_x=%s',
                       self.progress_x, self.leftclamp_x, self.rightclamp_x)

            return True
        return False

    def draw(self, (type, object), x, osd):
        """ Build the image by blitting sub images on the background and draw the background """
        logger.log(8, 'draw((type=%r, object=), x=%r, osd=)', type, x)
        now = time.time()
        duration = now - self.drawtime
        logger.log(9, "draw=%.2f, interval=%s, state=%s", duration,
                   self.draw_interval, self.state)
        self.drawtime = now
        self.lastdraw = now

        (sprite_w, sprite_h) = self.set_sprite()
        self.calculatesizes(osd, self.font)

        background = self.getimage(self.background, osd)
        if self.sprite:
            sprite = self.getimage(self.sprite, osd)
            background.blit(sprite, (0, 0),
                            (0, 0, self.background_w, self.background_h))
        leftclamp = self.getimage(self.leftclamp, osd, True)
        rightclamp = self.getimage(self.rightclamp, osd, True)
        background.blit(leftclamp, (self.leftclamp_x, 1),
                        (0, 0, self.leftclamp_w, self.leftclamp_h))
        background.blit(rightclamp, (self.rightclamp_x, 1),
                        (0, 0, self.rightclamp_w, self.rightclamp_h))
        osd.drawimage(background, (x, osd.y, -1, -1))[0]
        if self.remaining:
            font = osd.get_font(config.OSD_IDLEBAR_FONT)
            widthdf = font.stringsize(self.remaining)
            remaining_x = x + ((self.background_w - widthdf) / 2)
            remaining_y = osd.y + self.background_h - font.h + 10
            logger.debug('remaining=%r x=%s y=%s widthdf=%s font.h=%s',
                         self.remaining, remaining_x, remaining_y, widthdf,
                         font.h)

            osd.write_text(self.remaining, font, None, remaining_x,
                           remaining_y, widthdf, font.h, 'center', 'top')

        return self.background_w
Esempio n. 13
0
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()
Esempio n. 14
0
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()
Esempio n. 15
0
class PluginInterface(plugin.DaemonPlugin):
    """
    This plugin shows the current encoding status
    Activate with:
    | plugin.activate('idlebar.encoding')
    """
    def __init__(self):
        logger.log(9, 'encoding.PluginInterface.__init__(self)')
        plugin.DaemonPlugin.__init__(self)
        #IdleBarPlugin.__init__(self)
        self.poll_interval = 1
        self.draw_interval = self.poll_interval
        self.last_interval = self.poll_interval
        self.lastdraw = 0
        self.lastpoll = 0
        self.plugin_name = 'video.encodingstatus'
        self.server = EncodingClientActions()

        self.skin = skin.get_singleton()
        self.barimg = os.path.join(config.ICON_DIR, 'status/encoding_bar.png')
        self.boximg = os.path.join(config.ICON_DIR, 'status/encoding_box.png')
        self.boxborder = 3
        self.padding = 5  # internal padding for box vs text
        self.image = None
        self.cacheimg = {}
        self.muted = False
        self.encoding = -1
        self.progress = 0
        self.jobname = ''
        self.calculate = True
        self.jobs = ''
        self.mode = 'Not Running'
        self.text = []
        self.percent = 0.0
        self.running = False
        self.drawtime = 0
        self.polltime = 0
        self.state = 'noserver'
        self.laststate = None
        self.font = self.skin.get_font(config.ENCODING_IDLEBAR_FONT)

    def config(self):
        return [
            ('ENCODING_IDLEBAR', True, 'Use the idlebar'),
            ('ENCODING_IDLEBAR_FONT', 'small0',
             'Font to use in the idlebar, tiny0 is another good choice'),
        ]

    def getimage(self, image, osd, cache=False):
        logger.log(9, 'getimage(self, image, osd, cache=False)')
        if image.find(config.ICON_DIR) == 0 and image.find(
                osd.settings.icon_dir) == -1:
            new_image = os.path.join(osd.settings.icon_dir,
                                     image[len(config.ICON_DIR) + 1:])
            if os.path.isfile(new_image):
                image = new_image
        if cache:
            if image not in self.cacheimg.keys():
                self.cacheimg[image] = pygame.image.load(image)
            return self.cacheimg[image]

        return pygame.image.load(image)

    def settext(self):
        logger.log(9, 'settext(self)')
        """
        set the text
        """
        (status, jobs) = self.server.listJobs()
        if not status:
            self.state = 'noserver'
            self.jobs = _('encoding server not running')
            self.draw_interval = 5000
            self.running = False
            return 0
        if not jobs:
            self.state = 'nojobs'
            self.jobs = _('encoding server has no jobs')
            self.draw_interval = 5000
            self.running = False
            return 0
        self.state = 'active'
        (idnr, jobname, jobstate) = jobs[0]
        joblist = jobname
        for job in jobs[1:]:
            (idnr, jobname, jobstate) = job
            joblist += ', ' + jobname
        self.jobs = joblist
        self.running = True

        self.text = []
        (status, progress) = self.server.getProgress()
        if status:
            if progress[1] == 0:
                self.mode = 'Not started'
                self.state = 'active'
                self.draw_interval = 5000
            elif progress[1] == 1:
                self.mode = 'Audio'
                self.state = 'audio'
                self.draw_interval = 200
            elif progress[1] == 2:
                self.mode = 'Video-1'
                self.state = 'video'
                self.draw_interval = 1000
            elif progress[1] == 3:
                self.mode = 'Video-2'
                self.state = 'video'
                self.draw_interval = 1000
            elif progress[1] == 4:
                self.mode = 'Multiplexing'
                self.state = 'multiplexing'
                self.draw_interval = 1000
            self.text.append("%s %s%% %s" %
                             (self.mode, progress[2], progress[3]))
            self.percent = progress[2] / 100.0

    def calculatesizes(self, osd, font):
        logger.log(9, 'calculatesizes(self, osd, font)')
        """
        sizecalcs is not necessery on every pass
        """
        if config.ENCODING_IDLEBAR:
            if not hasattr(self, 'idlebar'):
                self.idlebar = plugin.getbyname('idlebar')
                if self.idlebar:
                    self.idlebar_max = osd.width + osd.x
                    logger.log(9, 'idlebar_max=%s, free_space=%s',
                               self.idlebar_max, self.idlebar.free_space)
                    for p in plugin.get('idlebar'):
                        if hasattr(p, 'clock_left_position'):
                            self.idlebar_max = p.clock_left_position

                    if self.idlebar_max - self.idlebar.free_space < 250:
                        logger.debug(
                            'free space in idlebar to small, using normal detach'
                        )
                        self.idlebar = None
                    else:
                        # this doesn't work, but needs to for the detachbar
                        self.idlebar.take_space(250)
        else:
            self.idlebar = None

        if self.idlebar:
            self.boxborder = 0
            self.padding = 0

        if self.calculate:
            self.calculate = False
            self.font_h = font.font.height

            logger.log(9, 'osd.width=%s, osd.height=%s, osd.x=%s, osd.y=%s',
                       osd.width, osd.height, osd.x, osd.y)
            screen_width = osd.width + 2 * osd.x
            screen_height = osd.height + 2 * osd.y

            used_width = font.font.stringsize(self.jobs) - 1
            # ensure that the box width is between min and max
            used_width = max(used_width, 200)
            used_width = min(used_width, 280)
            used_height = self.font_h
            if self.running:
                w, h = self.getimage(self.boximg, osd).get_size()
                used_width = max(used_width, w)
                used_height += h
                for text in self.text:
                    used_width = max(used_width,
                                     font.font.stringsize(text)) - 1
                    used_height += self.font_h

            logger.log(
                9,
                'screen_width=%s, screen_height=%s, used_width=%s, used_height=%s, font_h=%s',
                screen_width, screen_height, used_width, used_height,
                self.font_h)

            self.boxw = used_width + (self.padding + self.boxborder) * 2
            self.boxh = used_height + (self.padding + self.boxborder) * 2
            self.bx = osd.x
            self.by = screen_height - osd.y - self.boxh
            self.textw = used_width
            self.texth = used_height
            self.tx = self.bx + self.boxborder + self.padding
            self.ty = self.by + self.boxborder + self.padding

        if self.idlebar:
            if self.image:
                self.bx = self.idlebar.free_space + 250 + 70
            else:
                self.bx = self.idlebar.free_space + 250
            self.by = osd.y
            self.tx = self.bx + self.boxborder + self.padding
            self.ty = self.by + self.boxborder + self.padding
            self.textw = min(self.textw, self.idlebar_max - self.bx - 30)

    def draw(self, (type, object), osd):
        logger.log(9, 'draw(self, (type, object), osd)')
        now = time.time()
        duration = now - self.drawtime
        logger.log(9, "draw=%.2f, interval=%s, state=%s", duration,
                   self.draw_interval, self.state)
        self.drawtime = now
        self.lastdraw = now

        self.calculate = True
        self.settext()
        self.calculatesizes(osd, self.font)

        logger.log(
            9, 'self:bx=%s, by=%s, boxh=%s, boxw=%s, border=%s, padding=%s',
            self.bx, self.by, self.boxh, self.boxw, self.boxborder,
            self.padding)

        if self.idlebar:
            osd.drawroundbox(self.bx, self.by, self.boxw, self.boxh,
                             (0xffffffffL, self.boxborder, 0x40ffff00L, 0))
            #  A R G B                      A R G B
            #  background border_width      border     border_radius
        else:
            osd.drawroundbox(
                self.bx, self.by, self.boxw, self.boxh,
                (0xf0ffffffL, self.boxborder, 0xb0000000L, self.boxborder))

        logger.log(9, 'self:tx=%s, ty=%s, texth=%s, textw=%s', self.tx,
                   self.ty, self.texth, self.textw)
        y = self.ty
        osd.write_text(self.jobs, self.font, None, self.tx, y, self.textw,
                       self.font_h, 'center', 'center')
        if self.running:
            y += self.font_h
            encbar = self.getimage(self.barimg, osd, True)
            encbox = self.getimage(self.boximg, osd)
            w, h = encbox.get_size()
            encbox.blit(encbar, (3, 3), (0, 0, (w * self.percent), h))
            x = (self.textw - w) / 2
            #osd.drawroundbox(self.tx+x-2, y-2, w+4, h+4,
            #    (0xf0ffffffL, 2, 0xb000ffffL, 0))
            osd.drawimage(encbox, (self.tx + x, y, -1, -1))[0]
            y += h
            for text in self.text:
                osd.write_text(text, self.font, None, self.tx, y, self.textw,
                               self.font_h, 'center', 'center')
                y += self.font_h

        return self.textw
Esempio n. 16
0
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()
Esempio n. 17
0
 def __init__(self):
     logger.debug('reencode-old.PluginInterface.__init__(self)')
     plugin.ItemPlugin.__init__(self)
     self.server = EncodingClientActions()
Esempio n. 18
0
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()
Esempio n. 19
0
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()
Esempio n. 20
0
class PluginInterface(plugin.DaemonPlugin):
    """
    This plugin shows the current encoding status
    Activate with:
    | plugin.activate('idlebar.encoding')
    """

    def __init__(self):
        logger.log( 9, 'encoding.PluginInterface.__init__(self)')
        plugin.DaemonPlugin.__init__(self)
        #IdleBarPlugin.__init__(self)
        self.poll_interval = 1
        self.draw_interval = self.poll_interval
        self.last_interval = self.poll_interval
        self.lastdraw  = 0
        self.lastpoll  = 0
        self.plugin_name = 'video.encodingstatus'
        self.server    = EncodingClientActions()

        self.skin      = skin.get_singleton()
        self.barimg    = os.path.join(config.ICON_DIR, 'status/encoding_bar.png')
        self.boximg    = os.path.join(config.ICON_DIR, 'status/encoding_box.png')
        self.boxborder = 3
        self.padding   = 5 # internal padding for box vs text
        self.image     = None
        self.cacheimg  = {}
        self.muted     = False
        self.encoding  = -1
        self.progress  = 0
        self.jobname   = ''
        self.calculate = True
        self.jobs      = ''
        self.mode      = 'Not Running'
        self.text      = []
        self.percent   = 0.0
        self.running   = False
        self.drawtime  = 0
        self.polltime  = 0
        self.state     = 'noserver'
        self.laststate = None
        self.font      = self.skin.get_font(config.ENCODING_IDLEBAR_FONT)


    def config(self):
        return [
            ('ENCODING_IDLEBAR', True, 'Use the idlebar'),
            ('ENCODING_IDLEBAR_FONT', 'small0', 'Font to use in the idlebar, tiny0 is another good choice'),
        ]


    def getimage(self, image, osd, cache=False):
        logger.log( 9, 'getimage(self, image, osd, cache=False)')
        if image.find(config.ICON_DIR) == 0 and image.find(osd.settings.icon_dir) == -1:
            new_image = os.path.join(osd.settings.icon_dir, image[len(config.ICON_DIR)+1:])
            if os.path.isfile(new_image):
                image = new_image
        if cache:
            if image not in self.cacheimg.keys():
                self.cacheimg[image] = pygame.image.load(image)
            return self.cacheimg[image]

        return pygame.image.load(image)


    def settext(self):
        logger.log( 9, 'settext(self)')
        """
        set the text
        """
        (status, jobs) = self.server.listJobs()
        if not status:
            self.state = 'noserver'
            self.jobs = _('encoding server not running')
            self.draw_interval = 5000
            self.running = False
            return 0;
        if not jobs:
            self.state = 'nojobs'
            self.jobs = _('encoding server has no jobs')
            self.draw_interval = 5000
            self.running = False
            return 0;
        self.state = 'active'
        (idnr, jobname, jobstate) = jobs[0]
        joblist = jobname
        for job in jobs[1:]:
            (idnr, jobname, jobstate) = job
            joblist += ', ' + jobname
        self.jobs = joblist
        self.running = True

        self.text = []
        (status, progress) = self.server.getProgress();
        if status:
            if progress[1] == 0:
                self.mode = 'Not started'
                self.state = 'active'
                self.draw_interval = 5000
            elif progress[1] == 1:
                self.mode = 'Audio'
                self.state = 'audio'
                self.draw_interval = 200
            elif progress[1] == 2:
                self.mode = 'Video-1'
                self.state = 'video'
                self.draw_interval = 1000
            elif progress[1] == 3:
                self.mode = 'Video-2'
                self.state = 'video'
                self.draw_interval = 1000
            elif progress[1] == 4:
                self.mode = 'Multiplexing'
                self.state = 'multiplexing'
                self.draw_interval = 1000
            self.text.append("%s %s%% %s" % (self.mode, progress[2], progress[3]))
            self.percent = progress[2] / 100.0


    def calculatesizes(self, osd, font):
        logger.log( 9, 'calculatesizes(self, osd, font)')
        """
        sizecalcs is not necessery on every pass
        """
        if config.ENCODING_IDLEBAR:
            if not hasattr(self, 'idlebar'):
                self.idlebar = plugin.getbyname('idlebar')
                if self.idlebar:
                    self.idlebar_max = osd.width + osd.x
                    logger.log( 9, 'idlebar_max=%s, free_space=%s', self.idlebar_max, self.idlebar.free_space)
                    for p in plugin.get('idlebar'):
                        if hasattr(p, 'clock_left_position'):
                            self.idlebar_max = p.clock_left_position

                    if self.idlebar_max - self.idlebar.free_space < 250:
                        logger.debug('free space in idlebar to small, using normal detach')
                        self.idlebar = None
                    else:
                        # this doesn't work, but needs to for the detachbar
                        self.idlebar.take_space(250)
        else:
            self.idlebar = None

        if self.idlebar:
            self.boxborder = 0
            self.padding = 0

        if self.calculate:
            self.calculate = False
            self.font_h = font.font.height

            logger.log( 9, 'osd.width=%s, osd.height=%s, osd.x=%s, osd.y=%s', osd.width, osd.height, osd.x, osd.y)
            screen_width = osd.width + 2*osd.x
            screen_height = osd.height + 2*osd.y

            used_width = font.font.stringsize(self.jobs) - 1
            # ensure that the box width is between min and max
            used_width = max(used_width, 200)
            used_width = min(used_width, 280)
            used_height = self.font_h
            if self.running:
                w, h = self.getimage(self.boximg, osd).get_size()
                used_width = max(used_width, w)
                used_height += h
                for text in self.text:
                    used_width = max(used_width, font.font.stringsize(text)) - 1
                    used_height += self.font_h

            logger.log( 9, 'screen_width=%s, screen_height=%s, used_width=%s, used_height=%s, font_h=%s', screen_width, screen_height, used_width, used_height, self.font_h)

            self.boxw = used_width + (self.padding + self.boxborder) * 2
            self.boxh = used_height + (self.padding + self.boxborder) * 2
            self.bx = osd.x
            self.by = screen_height - osd.y - self.boxh
            self.textw = used_width
            self.texth = used_height
            self.tx = self.bx + self.boxborder + self.padding
            self.ty = self.by + self.boxborder + self.padding

        if self.idlebar:
            if self.image:
                self.bx = self.idlebar.free_space + 250 + 70
            else:
                self.bx = self.idlebar.free_space + 250
            self.by = osd.y
            self.tx = self.bx + self.boxborder + self.padding
            self.ty = self.by + self.boxborder + self.padding
            self.textw = min(self.textw, self.idlebar_max - self.bx - 30)


    def draw(self, (type, object), osd):
        logger.log( 9, 'draw(self, (type, object), osd)')
        now = time.time()
        duration = now - self.drawtime
        logger.log( 9, "draw=%.2f, interval=%s, state=%s", duration, self.draw_interval, self.state)
        self.drawtime = now
        self.lastdraw = now

        self.calculate = True
        self.settext()
        self.calculatesizes(osd, self.font)

        logger.log( 9, 'self:bx=%s, by=%s, boxh=%s, boxw=%s, border=%s, padding=%s', self.bx, self.by, self.boxh, self.boxw, self.boxborder, self.padding)

        if self.idlebar:
            osd.drawroundbox(self.bx, self.by, self.boxw, self.boxh,
                (0xffffffffL, self.boxborder, 0x40ffff00L, 0))
                #  A R G B                      A R G B
                #  background border_width      border     border_radius
        else:
            osd.drawroundbox(self.bx, self.by, self.boxw, self.boxh,
                (0xf0ffffffL, self.boxborder, 0xb0000000L, self.boxborder))

        logger.log( 9, 'self:tx=%s, ty=%s, texth=%s, textw=%s', self.tx, self.ty, self.texth, self.textw)
        y = self.ty
        osd.write_text(self.jobs, self.font, None, self.tx, y, self.textw, self.font_h, 'center', 'center')
        if self.running:
            y += self.font_h
            encbar = self.getimage(self.barimg, osd, True)
            encbox = self.getimage(self.boximg, osd)
            w, h = encbox.get_size()
            encbox.blit(encbar, (3, 3), (0, 0, (w * self.percent), h))
            x = (self.textw - w) / 2
            #osd.drawroundbox(self.tx+x-2, y-2, w+4, h+4,
            #    (0xf0ffffffL, 2, 0xb000ffffL, 0))
            osd.drawimage(encbox, (self.tx+x, y, -1, -1) )[0]
            y += h
            for text in self.text:
                osd.write_text(text, self.font, None, self.tx, y, self.textw, self.font_h, 'center', 'center')
                y += self.font_h

        return self.textw