예제 #1
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    parser.add_option('--chanid', action='store', type='int', dest='chanid',
                      help='Use chanid for manual operation')
    parser.add_option('--starttime', action='store', type='int', 
                      dest='starttime',
                      help='Use starttime for manual operation')
    #MythLog.loadOptParse(parser)
    #MythLog._optparseinput()
    MythLog._setpath('/tmp')

    opts, args = parser.parse_args()

    j = TranscodeJob()
    try:
        if len(args) == 1:
            j.run(jobid=args[0])
        elif opts.chanid and opts.starttime:
            j.run(chanid=opts.chanid, starttime=opts.starttime)
        else:
            print 'Script must be provided jobid, or chanid and starttime.'
            sys.exit(1)
    except:
        j.logTB()
        sys.exit(1)
예제 #2
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    parser.add_option('--chanid', action='store', type='int', dest='chanid',
            help='Use chanid with both starttime and tzoffset for manual operation')
    parser.add_option('--starttime', action='store', type='string', dest='starttime',
            help='Use starttime with both chanid and tzoffset for manual operation')
    parser.add_option('--tzoffset', action='store', type='int', dest='tzoffset',
            help='Use tzoffset with both chanid and starttime for manual operation')
    parser.add_option('-v', '--verbose', action='store', type='string', dest='verbose',
            help='Verbosity level')

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if len(args) == 1:
        runjob(jobid=args[0])
    elif opts.chanid and opts.starttime and opts.tzoffset is not None:
        runjob(chanid=opts.chanid, starttime=opts.starttime, tzoffset=opts.tzoffset)
    else:
        print 'Script must be provided jobid, or chanid, starttime and timezone offset.'
        sys.exit(1)
예제 #3
0
 def initializeMythDB(self):
     ''' Import the MythTV database bindings
     return nothing
     '''
     try:
         from MythTV import MythDB, MythLog, MythError
         try:
             '''Create an instance of each: MythDB
             '''
             MythLog._setlevel(
                 'none'
             )  # Some non option -M cannot have any logging on stdout
             self.mythdb = MythDB()
         except MythError as e:
             sys.stderr.write('\n! Error - %s\n' % e.args[0])
             filename = os.path.expanduser("~") + '/.mythtv/config.xml'
             if not os.path.isfile(filename):
                 sys.stderr.write(
                     '\n! Error - A correctly configured (%s) file must exist\n'
                     % filename)
             else:
                 sys.stderr.write(
                     '\n! Error - Check that (%s) is correctly configured\n'
                     % filename)
             sys.exit(1)
         except Exception as e:
             sys.stderr.write(
                 "\n! Error - Creating an instance caused an error for one of: MythDB. error(%s)\n"
                 % e)
             sys.exit(1)
     except Exception as e:
         sys.stderr.write(
             "\n! Error - MythTV python bindings could not be imported. error(%s)\n"
             % e)
         sys.exit(1)
예제 #4
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    parser.add_option('--chanid', action='store', type='int', dest='chanid',
            help='Use chanid for manual operation')
    parser.add_option('--starttime', action='store', type='int', dest='starttime',
            help='Use starttime for manual operation')
    parser.add_option('-v', '--verbose', action='store', type='string', dest='verbose',
            help='Verbosity level')

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if len(args) == 1:
        runjob(jobid=args[0])
    elif opts.chanid and opts.starttime:
        runjob(chanid=opts.chanid, starttime=opts.starttime)
    else:
        print 'Script must be provided jobid, or chanid and starttime.'
        sys.exit(1)
예제 #5
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    parser.add_option("-f", "--helpformat", action="store_true", default=False, dest="fmthelp",
            help="Print explination of file format string.")
    parser.add_option("-p", "--printformat", action="store_true", default=False, dest="fmtprint",
            help="Print current file format string.")
    parser.add_option("--tformat", action="store", type="string", dest="tformat",
            help="Use TV format for current task. If no task, store in database.")
    parser.add_option("--mformat", action="store", type="string", dest="mformat",
            help="Use Movie format for current task. If no task, store in database.")
    parser.add_option("--gformat", action="store", type="string", dest="gformat",
            help="Use Generic format for current task. If no task, store in database.")
    parser.add_option("--chanid", action="store", type="int", dest="chanid",
            help="Use chanid for manual operation")
    parser.add_option("--starttime", action="store", type="int", dest="starttime",
            help="Use starttime for manual operation")
    parser.add_option("--listingonly", action="store_true", default=False, dest="listingonly",
            help="Use data from listing provider, rather than grabber")
    parser.add_option("--seekdata", action="store_true", default=False, dest="seekdata",
            help="Copy seekdata from source recording.")
    parser.add_option("--skiplist", action="store_true", default=False, dest="skiplist",
            help="Copy commercial detection from source recording.")
    parser.add_option("--cutlist", action="store_true", default=False, dest="cutlist",
            help="Copy manual commercial cuts from source recording.")
    parser.add_option('-v', '--verbose', action='store', type='string', dest='verbose',
            help='Verbosity level')

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if opts.fmthelp:
        usage_format()
        sys.exit(0)

    if opts.fmtprint:
        print_format()
        sys.exit(0)

    if opts.chanid and opts.starttime:
        export = VIDEO(opts)
    elif len(args) == 1:
        try:
            export = VIDEO(opts, int(args[0]))
        except Exception, e:
            Job(int(args[0])).update({'status':304,
                                      'comment':'ERROR: ' + e.args[0]})
            MythLog(module='mythvidexport.py').logTB(MythLog.IMPORTANT)
            sys.exit(1)
예제 #6
0
    def test_Logging_Basic_002_01(self):
        """Test if options can be modified from MythTV.MythLog."""

        m = MythLog('simple_test')

        m._setmask("most")
        # check the modified mask:
        self.assertEqual(m._MASK, LOGMASK.MOST)
        # check the default level:
        self.assertEqual(m._LEVEL, LOGLEVEL.INFO)
        # check the default file:
        self.assertTrue('stdout' in repr(m._LOGFILE))

        m._setlevel("notice")
        # check the modified mask:
        self.assertEqual(m._MASK, LOGMASK.MOST)
        # check the modified level:
        self.assertEqual(m._LEVEL, LOGLEVEL.NOTICE)
        # check the default file:
        self.assertTrue('stdout' in repr(m._LOGFILE))

        m._setfile("/tmp/my_logfile")
        # check the modified mask:
        self.assertEqual(m._MASK, LOGMASK.MOST)
        # check the modified level:
        self.assertEqual(m._LEVEL, LOGLEVEL.NOTICE)
        # check the modified file:
        self.assertTrue(os.path.exists("/tmp/my_logfile"))
예제 #7
0
def main():
    """Startup function."""
    parser = OptionParser(usage="usage: %prog [options]")
    parser.add_option(
        "--verbose",
        action="store_true",
        default=False,
        help="enable verbose output of MythTV API")
    parser.add_option(
        '-f',
        "--force",
        action="store_true",
        default=False,
        help="non-interactive mode, answer 'yes' to all questions")
    parser.add_option(
        '-t',
        "--title",
        action="store",
        type="string",
        help="limit recordings that match title")

    opts, _ = parser.parse_args()
    MythLog._setlevel('unknown' if opts.verbose else 'err')  # pylint:disable=protected-access

    try:
        backend = MythBE()
        recs = [
            r for r in list(backend.getRecordings()) if r.recgroup == 'Deleted'
        ]
        if opts.title:
            recs = [
                r for r in recs
                if re.findall(opts.title, r.title, re.IGNORECASE)
            ]
        if len(recs) == 0:
            print('no matching recordings found')
            sys.exit(0)
        if opts.force:
            undelete_all(backend, recs)
        else:
            interactive_undelete(backend, recs)
    except MythDBError as e:
        if e.name == 'DB_CREDENTIALS':
            print("ERROR: Could not find MythDB host:port OR correct login "
                  "credentials!")
            sys.exit(-1)
        else:
            raise
    sys.exit(0)
예제 #8
0
def main():
    """Startup function."""
    parser = OptionParser(usage="usage: %prog [options]")
    parser.add_option("--verbose",
                      action="store_true",
                      default=False,
                      help="enable verbose output of MythTV API")
    parser.add_option(
        '-f',
        "--force",
        action="store_true",
        default=False,
        help="non-interactive mode, answer 'yes' to all questions")
    parser.add_option('-t',
                      "--title",
                      action="store",
                      type="string",
                      help="limit recordings that match title")

    opts, _ = parser.parse_args()
    MythLog._setlevel('unknown' if opts.verbose else 'err')  # pylint:disable=protected-access

    try:
        backend = MythBE()
        recs = [
            r for r in list(backend.getRecordings()) if r.recgroup == 'Deleted'
        ]
        if opts.title:
            recs = [
                r for r in recs
                if re.findall(opts.title, r.title, re.IGNORECASE)
            ]
        if len(recs) == 0:
            print('no matching recordings found')
            sys.exit(0)
        if opts.force:
            undelete_all(backend, recs)
        else:
            interactive_undelete(backend, recs)
    except MythDBError as e:
        if e.name == 'DB_CREDENTIALS':
            print("ERROR: Could not find MythDB host:port OR correct login "
                  "credentials!")
            sys.exit(-1)
        else:
            raise
    sys.exit(0)
예제 #9
0
class TranscodeJob:
    def __init__(self):
        self.l = MythLog('transcode.py', db=self.db())

    def db(self):
        return MythDB()

    def log(self, message, level=LOGLEVEL.INFO, detail=None):
        return self.l.log(LOGMASK.GENERAL, level, message, detail)
    
    def logTB(self):
        return self.l.logTB(LOGMASK.GENERAL)

    def run(self, jobid=None, chanid=None, starttime=None):
        if jobid:
            job = Job(jobid, db=self.db())
            chanid = job.chanid
            starttime = job.starttime
        rec = Recorded((chanid, starttime), db=self.db())

        sg = mythproto.findfile(rec.basename, rec.storagegroup, db=self.db())
        if sg is None:
            self.log('Local access to recording not found.', LOGLEVEL.ERR)
            sys.exit(1)

        infile = os.path.join(sg.dirname, rec.basename)
        #### list of segments to be cut
        # rec.markup.gencutlist()
        #### list of segments to keep
        # rec.markup.genuncutlist()
        del(rec)

        task = System(path=TRANSCODER, db=self.db())
        try:
            outfile = task(infile).strip()
            if not os.path.exists(outfile):
                raise OSError('output file %s not found' % repr(outfile))
        except MythError, e:
            self.log('Transcode failed with output:', LOGLEVEL.ERR,
                     task.stderr)
            sys.exit(task.returncode)
        except OSError, e:
            self.log('Transcode failed to produce an output file:',
                     LOGLEVEL.ERR, repr(e))
            sys.exit(1)
예제 #10
0
def run_debug():
    MythLog._setfile('/var/log/mythtv/mythfs.log')
    MythLog._setlevel('important,general,file')
    fs = DebugFS()
    fs.fsinit()
    banner = 'MythTV Python interactive shell.'
    import code
    try:
        import readline, rlcompleter
    except:
        pass
    else:
        readline.parse_and_bind("tab: complete")
        banner += ' TAB completion available.'
    namespace = globals().copy()
    namespace.update(locals())
    code.InteractiveConsole(namespace).interact(banner)
    sys.exit()
예제 #11
0
    def __init__(self, host=None):
        self.db = MythDB()
        self.db.searchRecorded.handler = Recorded
        self.be = MythBE(db=self.db)
        self.log = MythLog(db=self.db)

        self.set_host(host)
        self.load_backends()
        self.load_storagegroups()
예제 #12
0
def run_debug():
    MythLog._setfile('/var/log/mythtv/mythfs.log')
    MythLog._setlevel('important,general,file')
    fs = DebugFS()
    fs.fsinit()
    banner = 'MythTV Python interactive shell.'
    import code
    try:
        import readline, rlcompleter
    except:
        pass
    else:
        readline.parse_and_bind("tab: complete")
        banner += ' TAB completion available.'
    namespace = globals().copy()
    namespace.update(locals())
    code.InteractiveConsole(namespace).interact(banner)
    sys.exit()
예제 #13
0
    def __init__(self, opts, jobid=None):
        if jobid:
            self.job = Job(jobid)
            self.chanid = self.job.chanid
            self.starttime = self.job.starttime
            self.job.update(status=3)
        else:
            self.job = None
            self.chanid = opts.chanid
            self.starttime = opts.starttime

        self.opts = opts
        self.db = MythDB()
        self.log = MythLog(module='mythvidexport.py', db=self.db)

        # load setting strings
        self.get_format()

        # prep objects
        self.rec = Recorded((self.chanid, self.starttime), db=self.db)
        self.log(MythLog.IMPORTANT, 'Using recording',
                 '%s - %s' % (self.rec.title, self.rec.subtitle))
        self.vid = Video(db=self.db).create({
            'title': '',
            'filename': '',
            'host': gethostname()
        })

        # process data
        self.get_meta()
        self.get_dest()

        # save file
        self.copy()
        if opts.seekdata:
            self.copy_seek()
        if opts.skiplist:
            self.copy_markup(static.MARKUP.MARK_COMM_START,
                             static.MARKUP.MARK_COMM_END)
        if opts.cutlist:
            self.copy_markup(static.MARKUP.MARK_CUT_START,
                             static.MARKUP.MARK_CUT_END)
        self.vid.update()
예제 #14
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    parser.add_option('--jobid', action='store', type='int', dest='jobid')
    parser.add_option('--chanid', action='store', type='int', dest='chanid')
    parser.add_option('--starttime', action='store', type='int', dest='starttime')
    parser.add_option('-v', '--verbose', action='store', type='string', dest='verbose',
            help='Verbosity level')
    parser.add_option('--title', action='store', type='string', dest='title',
            help='Title of Show')
    parser.add_option('--limit', action='store', type='int', dest='limit', default=100,
            help='Limit of how many recordings to do')

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    title = None
    if opts.jobid:
        rec = getjob(jobid=opts.jobid)
        title = rec.title 
    elif opts.chanid and opts.starttime:
        rec = getjob(chanid=opts.chanid, starttime=opts.starttime)
        title = rec.title
    elif opts.title:
        title = opts.title

    if title is None:
        print 'Unable to determine title.'
        sys.exit(1)

    timestr = time.strftime("%m-%d-%y %H:%M:%S")
    title_san = re.sub("\s", ".", title)
    print title_san
    try:
        os.mkdir(log_dir)
    except OSError, e:
        pass
예제 #15
0
    def __init__(self, opts, jobid=None):
        if jobid:
            self.job = Job(jobid)
            self.chanid = self.job.chanid
            self.starttime = self.job.starttime
            self.job.update(status=Job.STARTING)
        else:
            self.job = None
            self.chanid = opts.chanid
            self.starttime = opts.starttime

        self.opts = opts
        self.db = MythDB()
        self.log = MythLog(module='mythvidexport.py', db=self.db)

        # load setting strings
        self.get_format()

        # prep objects
        self.rec = Recorded((self.chanid, self.starttime), db=self.db)
        self.log(
            MythLog.GENERAL, MythLog.INFO, 'Using recording',
            '%s - %s' % (self.rec.title.encode('utf-8'),
                         self.rec.subtitle.encode('utf-8')))
        self.vid = Video(db=self.db).create({
            'title': '',
            'filename': '',
            'host': gethostname()
        })

        # process data
        self.get_meta()
        self.get_dest()
        # bug fix to work around limitation in the bindings where DBDataRef classes
        # are mapped to the filename at time of Video element creation. since the
        # filename is specified as blank when the video is created, the markup
        # handler is not properly initialized
        self.vid.markup._refdat = (self.vid.filename, )

        # save file
        self.copy()
        if opts.seekdata:
            self.copy_seek()
        if opts.skiplist:
            self.copy_markup(static.MARKUP.MARK_COMM_START,
                             static.MARKUP.MARK_COMM_END)
        if opts.cutlist:
            self.copy_markup(static.MARKUP.MARK_CUT_START,
                             static.MARKUP.MARK_CUT_END)
        self.vid.update()

        # delete old file
        if opts.delete:
            self.rec.delete()
    def test_logging_OptParse_002_01(self):
        """Test if 'OptParse' works with MythLog."""

        # set default values acc. source code
        m_dblog = False
        m_loglevel = LOGLEVEL.INFO
        m_verbose = LOGMASK.GENERAL
        m_logfile = stdout

        with add_log_flags():
            m = MythLog('simple_test')

            #print ("m._LEVEL = %d" %m._LEVEL)
            #print ("m._MASK  = %d" %m._MASK)
            #print ("m._DBLOG = %s" %m._DBLOG)
            #print (sys.argv)
            parser = OptionParser(prog="simple_test")

            # silence warnings in unittest about missing '-v' option:
            parser.add_option('-v',
                              action='store_true',
                              dest='uv',
                              default=False,
                              help='Use to set verbosity in unittest')

            # load MYthTV's extension
            m.loadOptParse(parser)
            opts, args = parser.parse_args()

            # check the options provided by 'additional_args':
            m_dblog = opts.nodblog  # the option is named '--nodblog', stored in 'nodblog'
            m_loglevel = m._LEVEL
            m_verbose = m._MASK
            m_logfile = m._LOGFILE

        self.assertEqual(m_dblog, True)
        self.assertEqual(m_loglevel, LOGLEVEL.DEBUG)
        self.assertEqual(
            m_verbose,
            LOGMASK.ALL)  ### XXX RER '-v' from unittest collides with this
        self.assertTrue(os.path.exists("/tmp/my_logfile"))
예제 #17
0
    def test_Logging_Basic_004_01(self):
        """"Test if setting options works without a MythLog instance."""

        MythLog._setmask("most")
        # check the modified mask:
        self.assertEqual(MythLog._MASK, LOGMASK.MOST)
        # check the default level:
        self.assertEqual(MythLog._LEVEL, LOGLEVEL.INFO)
        # check the default file:
        self.assertTrue('stdout' in repr(MythLog._LOGFILE))

        MythLog._setlevel("notice")
        # check the modified mask:
        self.assertEqual(MythLog._MASK, LOGMASK.MOST)
        # check the modified level:
        self.assertEqual(MythLog._LEVEL, LOGLEVEL.NOTICE)
        # check the default file:
        self.assertTrue('stdout' in repr(MythLog._LOGFILE))

        MythLog._setfile("/tmp/my_logfile")
        # check the modified mask:
        self.assertEqual(MythLog._MASK, LOGMASK.MOST)
        # check the modified level:
        self.assertEqual(MythLog._LEVEL, LOGLEVEL.NOTICE)
        # check the modified file:
        self.assertTrue(os.path.exists("/tmp/my_logfile"))
    def test_Logging_argparse_001_01(self):
        """Test if 'argparse' works with MythLog."""

        m = MythLog('simple_test')

        parser = argparse.ArgumentParser(prog="simple_test")

        # Add arbitrary option:
        parser.add_argument('--chanid',
                            action='store',
                            dest='chanid',
                            default=0,
                            help='Use chanid for manual operation')

        # load MYthTV's extension
        m.loadArgParse(parser)

        # unittest : first arguements are the test class or the verbosity flag
        test_args = []
        args_found = False
        for a in argv:
            if not args_found:
                args_found = a.startswith('test')
            else:
                test_args.append(a)

        args = parser.parse_args(test_args)

        # check the default mask:
        self.assertEqual(m._MASK, LOGMASK.GENERAL)

        # check if helptext contains 'siparser'
        h = m.helptext
        found = False
        for line in h.split("\n"):
            match = re.findall(r'siparser', line)
            if match:
                found = True
        self.assertEqual(found, True)
    def test_Logging_argparse_002_01(self):
        """Test if 'argparse' works with MythLog."""

        # set default values acc. source code
        m_dblog = True
        m_loglevel = LOGLEVEL.INFO
        m_verbose = LOGMASK.GENERAL
        m_logfile = stdout

        with add_log_flags():
            m = MythLog('simple_test')
            parser = argparse.ArgumentParser(prog="simple_test")

            # load MYthTV's extension
            m.loadArgParse(parser)

            # unittest : first arguements are the test class or the verbosity flag
            # filter out arguements for unittesting:
            test_args = add_log_flags.additional_args

            # according 'add_log_flags', test_args should be:
            #  ['--nodblog', '--loglevel', 'debug', '--verbose', 'all', '--logfile', '/tmp/my_logfile']

            args = parser.parse_args(test_args)
            #print(test_args)
            #print(args)

            # check the options provided by 'additional_args':
            m_dblog = m._DBLOG
            m_loglevel = m._LEVEL
            m_verbose = m._MASK
            m_logfile = m._LOGFILE

        self.assertEqual(m_dblog, False)
        self.assertEqual(m_loglevel, LOGLEVEL.DEBUG)
        self.assertEqual(m_verbose, LOGMASK.ALL)
        self.assertTrue(os.path.exists("/tmp/my_logfile"))
예제 #20
0
    def test_Logging_Basic_001_01(self):
        """Test if default options works with MythLog."""

        m = MythLog('simple_test')

        # check the default mask:
        self.assertEqual(m._MASK, LOGMASK.GENERAL)
        # check the default level:
        self.assertEqual(m._LEVEL, LOGLEVEL.INFO)
        # check the default file:
        self.assertTrue('stdout' in repr(m._LOGFILE))

        # test '__repr__' and '__str__'
        print()
        print(repr(m))
        print(str(m))
예제 #21
0
    def __init__(self, opts, jobid=None):
        if jobid:
            self.job = Job(jobid)
            self.chanid = self.job.chanid
            self.starttime = self.job.starttime
            self.job.update(status=3)
        else:
            self.job = None
            self.chanid = opts.chanid
            self.starttime = opts.starttime

        self.opts = opts
        self.db = MythDB()
        self.log = MythLog(module='mythvidexport.py', db=self.db)

        # load setting strings
        self.get_format()

        # prep objects
        self.rec = Recorded((self.chanid, self.starttime), db=self.db)
        self.log(MythLog.IMPORTANT, 'Using recording',
                        '%s - %s' % (self.rec.title, self.rec.subtitle))
        self.vid = Video(db=self.db).create({'title':'', 'filename':'', 'host':gethostname()})

        # process data
        self.get_meta()
        self.get_dest()
        # kludgy fix for issue with altered filenames in the bindings
        self.vid.markup._refdat = (self.vid.filename,)

        # save file
        self.copy()
        if opts.seekdata:
            self.copy_seek()
        if opts.skiplist:
            self.copy_markup(static.MARKUP.MARK_COMM_START,
                             static.MARKUP.MARK_COMM_END)
        if opts.cutlist:
            self.copy_markup(static.MARKUP.MARK_CUT_START,
                             static.MARKUP.MARK_CUT_END)
        self.vid.update()
예제 #22
0
    def __init__(self, opts, jobid=None):

        # Setup for the job to run
        if jobid:
            self.thisJob = Job(jobid)
            self.chanID = self.thisJob.chanid
            self.startTime = self.thisJob.starttime
            self.thisJob.update(status=Job.STARTING)

        # If no job ID given, must be a command line run
        else:
            self.thisJob = jobid
            self.chanID = opts.chanid
            self.startTime = opts.startdate + " " + opts.starttime + opts.offset
        self.opts = opts
        self.type = "none"
        self.db = MythDB()
        self.log = MythLog(module='Myth-Rec-to-Vid.py', db=self.db)

        # Capture the backend host name
        self.host = self.db.gethostname()

        # prep objects
        self.rec = Recorded((self.chanID, self.startTime), db=self.db)
        self.log(
            MythLog.GENERAL, MythLog.INFO, 'Using recording',
            '%s - %s' % (self.rec.title.encode('utf-8'),
                         self.rec.subtitle.encode('utf-8')))

        self.vid = Video(db=self.db).create({
            'title': '',
            'filename': '',
            'host': self.host
        })

        self.bend = MythBE(db=self.db)
예제 #23
0
        a = a[2:]
        if '=' in a:
            a = a.split('=', 1)
            param[a[0]] = a[1]
        else:
            if len(temp):
                b = temp.pop(0)
                if (b[:2] == '--') or (b[:1] == '-'):
                    temp.insert(0, b)
                    param[a] = ''
                else:
                    param[a] = b
            else:
                param[a] = ''

MythLog._setlevel(param.get('verbose', 'none'))
try:
    param.pop('verbose')
except:
    pass

force = False
if 'force' in param:
    force = True
    param.pop('force')

if len(a) == 0:
    sys.exit(0)

recs = list(MythDB().searchRecorded(**param))
if len(recs) == 0:
예제 #24
0
class VIDEO:
    def __init__(self, opts, jobid=None):
        if jobid:
            self.job = Job(jobid)
            self.chanid = self.job.chanid
            self.starttime = self.job.starttime
            self.job.update(status=3)
        else:
            self.job = None
            self.chanid = opts.chanid
            self.starttime = opts.starttime

        self.opts = opts
        self.db = MythDB()
        self.log = MythLog(module='mythvidexport.py', db=self.db)

        # load setting strings
        self.get_format()

        # prep objects
        self.rec = Recorded((self.chanid, self.starttime), db=self.db)
        self.log(MythLog.IMPORTANT, 'Using recording',
                        '%s - %s' % (self.rec.title, self.rec.subtitle))
        self.vid = Video(db=self.db).create({'title':'', 'filename':'', 'host':gethostname()})

        # process data
        self.get_meta()
        self.get_dest()
        # kludgy fix for issue with altered filenames in the bindings
        self.vid.markup._refdat = (self.vid.filename,)

        # save file
        self.copy()
        if opts.seekdata:
            self.copy_seek()
        if opts.skiplist:
            self.copy_markup(static.MARKUP.MARK_COMM_START,
                             static.MARKUP.MARK_COMM_END)
        if opts.cutlist:
            self.copy_markup(static.MARKUP.MARK_CUT_START,
                             static.MARKUP.MARK_CUT_END)
        self.vid.update()

    def get_format(self):
        host = self.db.gethostname()
        # TV Format
        if self.opts.tformat:
            self.tfmt = self.opts.tformat
        elif self.db.settings[host]['mythvideo.TVexportfmt']:
            self.tfmt = self.db.settings[host]['mythvideo.TVexportfmt']
        else:
            self.tfmt = 'Television/%TITLE%/Season %SEASON%/' + \
                            '%TITLE% - S%SEASON%E%EPISODEPAD% - %SUBTITLE%'

        # Movie Format
        if self.opts.mformat:
            self.mfmt = self.opts.mformat
        elif self.db.settings[host]['mythvideo.MOVIEexportfmt']:
            self.mfmt = self.db.settings[host]['mythvideo.MOVIEexportfmt']
        else:
            self.mfmt = 'Movies/%TITLE%'

        # Generic Format
        if self.opts.gformat:
            self.gfmt = self.opts.gformat
        elif self.db.settings[host]['mythvideo.GENERICexportfmt']:
            self.gfmt = self.db.settings[host]['mythvideo.GENERICexportfmt']
        else:
            self.gfmt = 'Videos/%TITLE%'

    def get_meta(self):
        self.vid.hostname = self.db.gethostname()

        if self.rec.subtitle:  # subtitle exists, assume tv show
            self.type = 'TV'
            self.log(self.log.IMPORTANT, 'Attempting TV export.')
            if self.opts.listingonly:
                self.log(self.log.IMPORTANT, 'Forcing listing data only.')
                self.get_generic(False)
                return
            grab = VideoGrabber(self.type)
            match = grab.sortedSearch(self.rec.title, self.rec.subtitle)
        else:  # assume movie
            self.type = 'MOVIE'
            self.log(self.log.IMPORTANT, 'Attempting Movie export.')
            if self.opts.listingonly:
                self.log(self.log.IMPORTANT, 'Forcing listing data only.')
                self.get_generic(False)
                return
            grab = VideoGrabber(self.type)
            match = grab.sortedSearch(self.rec.title)

        if len(match) == 0:
            # no match found
            self.log(self.log.IMPORTANT, 'Falling back to generic export.')
            self.get_generic()
        elif (len(match) > 1) & (match[0].levenshtein > 0):
            # multiple matches found, and closest is not exact
            self.vid.delete()
            raise MythError('Multiple metadata matches found: '\
                                                   + self.rec.title)
        else:
            self.log(self.log.IMPORTANT, 'Importing content from', match[0].inetref)
            self.vid.importMetadata(grab.grabInetref(match[0]))

    def get_generic(self, name_as_generic=True):
        self.vid.title = self.rec.title
        if self.rec.subtitle:
            self.vid.subtitle = self.rec.subtitle
        if self.rec.description:
            self.vid.plot = self.rec.description
        if self.rec.originalairdate:
            self.vid.year = self.rec.originalairdate.year
            self.vid.releasedate = self.rec.originalairdate
        lsec = (self.rec.endtime - self.rec.starttime).seconds
        self.vid.length = str(lsec / 60)
        for member in self.rec.cast:
            if member.role == 'director':
                self.vid.director = member.name
            elif member.role == 'actor':
                self.vid.cast.append(member.name)
        if name_as_generic:
            self.type = 'GENERIC'

    def get_dest(self):
        if self.type == 'TV':
            self.vid.filename = self.process_fmt(self.tfmt)
        elif self.type == 'MOVIE':
            self.vid.filename = self.process_fmt(self.mfmt)
        elif self.type == 'GENERIC':
            self.vid.filename = self.process_fmt(self.gfmt)

    def process_fmt(self, fmt):
        # replace fields from viddata
        # print self.vid.data
        ext = '.' + self.rec.basename.rsplit('.', 1)[1]
        rep = (('%TITLE%', 'title', '%s'), ('%SUBTITLE%', 'subtitle', '%s'),
            ('%SEASON%', 'season', '%d'), ('%SEASONPAD%', 'season', '%02d'),
            ('%EPISODE%', 'episode', '%d'), ('%EPISODEPAD%', 'episode', '%02d'),
            ('%YEAR%', 'year', '%s'), ('%DIRECTOR%', 'director', '%s'))
        for tag, data, format in rep:
            if self.vid[data]:
                fmt = fmt.replace(tag, format % self.vid[data])
            else:
                fmt = fmt.replace(tag, '')

        # replace fields from program data
        rep = (('%HOSTNAME', 'hostname', '%s'), ('%STORAGEGROUP%', 'storagegroup', '%s'))
        for tag, data, format in rep:
            data = getattr(self.rec, data)
            fmt = fmt.replace(tag, format % data)

#       fmt = fmt.replace('%CARDID%',self.rec.cardid)
#       fmt = fmt.replace('%CARDNAME%',self.rec.cardid)
#       fmt = fmt.replace('%SOURCEID%',self.rec.cardid)
#       fmt = fmt.replace('%SOURCENAME%',self.rec.cardid)
#       fmt = fmt.replace('%CHANNUM%',self.rec.channum)
#       fmt = fmt.replace('%CHANNAME%',self.rec.cardid)

        if len(self.vid.genre):
            fmt = fmt.replace('%GENRE%', self.vid.genre[0].genre)
        else:
            fmt = fmt.replace('%GENRE%', '')
#       if len(self.country):
#           fmt = fmt.replace('%COUNTRY%',self.country[0])
#       else:
#           fmt = fmt.replace('%COUNTRY%','')
        return fmt + ext

    def copy(self):
        stime = time.time()
        srcsize = self.rec.filesize
        htime = [stime, stime, stime, stime]

        self.log.log(MythLog.IMPORTANT | MythLog.FILE, "Copying myth://%s@%s/%s"\
               % (self.rec.storagegroup, self.rec.hostname, self.rec.basename)\
                                                    + " to myth://Videos@%s/%s"\
                                          % (self.vid.host, self.vid.filename))
        srcfp = self.rec.open('r')
        dstfp = self.vid.open('w')

        if self.job:
            self.job.setStatus(4)
        tsize = 2 ** 24
        while tsize == 2 ** 24:
            tsize = min(tsize, srcsize - dstfp.tell())
            dstfp.write(srcfp.read(tsize))
            htime.append(time.time())
            rate = float(tsize * 4) / (time.time() - htime.pop(0))
            remt = (srcsize - dstfp.tell()) / rate
            if self.job:
                self.job.setComment("%02d%% complete - %d seconds remaining" % \
                            (dstfp.tell() * 100 / srcsize, remt))
        srcfp.close()
        dstfp.close()

        self.vid.hash = self.vid.getHash()

        self.log(MythLog.IMPORTANT | MythLog.FILE, "Transfer Complete",
                            "%d seconds elapsed" % int(time.time() - stime))
        if self.job:
            self.job.setComment("Complete - %d seconds elapsed" % \
                            (int(time.time() - stime)))
            self.job.setStatus(256)

    def copy_seek(self):
        for seek in self.rec.seek:
            self.vid.markup.add(seek.mark, seek.offset, seek.type)

    def copy_markup(self, start, stop):
        for mark in self.rec.markup:
            if mark.type in (start, stop):
                self.vid.markup.add(mark.mark, 0, mark.type)
예제 #25
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    parser.add_option("-f",
                      "--helpformat",
                      action="store_true",
                      default=False,
                      dest="fmthelp",
                      help="Print explination of file format string.")
    parser.add_option("-p",
                      "--printformat",
                      action="store_true",
                      default=False,
                      dest="fmtprint",
                      help="Print current file format string.")
    parser.add_option(
        "--tformat",
        action="store",
        type="string",
        dest="tformat",
        help="Use TV format for current task. If no task, store in database.")
    parser.add_option(
        "--mformat",
        action="store",
        type="string",
        dest="mformat",
        help="Use Movie format for current task. If no task, store in database."
    )
    parser.add_option(
        "--gformat",
        action="store",
        type="string",
        dest="gformat",
        help=
        "Use Generic format for current task. If no task, store in database.")
    parser.add_option("--chanid",
                      action="store",
                      type="int",
                      dest="chanid",
                      help="Use chanid for manual operation")
    parser.add_option("--starttime",
                      action="store",
                      type="int",
                      dest="starttime",
                      help="Use starttime for manual operation")
    parser.add_option(
        "--listingonly",
        action="store_true",
        default=False,
        dest="listingonly",
        help="Use data from listing provider, rather than grabber")
    parser.add_option("--seekdata",
                      action="store_true",
                      default=False,
                      dest="seekdata",
                      help="Copy seekdata from source recording.")
    parser.add_option("--skiplist",
                      action="store_true",
                      default=False,
                      dest="skiplist",
                      help="Copy commercial detection from source recording.")
    parser.add_option(
        "--cutlist",
        action="store_true",
        default=False,
        dest="cutlist",
        help="Copy manual commercial cuts from source recording.")
    parser.add_option('-v',
                      '--verbose',
                      action='store',
                      type='string',
                      dest='verbose',
                      help='Verbosity level')

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if opts.fmthelp:
        usage_format()
        sys.exit(0)

    if opts.fmtprint:
        print_format()
        sys.exit(0)

    if opts.chanid and opts.starttime:
        export = VIDEO(opts)
    elif len(args) == 1:
        try:
            export = VIDEO(opts, int(args[0]))
        except Exception, e:
            Job(int(args[0])).update({
                'status': 304,
                'comment': 'ERROR: ' + e.args[0]
            })
            MythLog(module='mythvidexport.py').logTB(MythLog.IMPORTANT)
            sys.exit(1)
예제 #26
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    sourcegroup = OptionGroup(parser, "Source Definition",
                    "These options can be used to manually specify a recording to operate on "+\
                    "in place of the job id.")
    sourcegroup.add_option("--chanid", action="store", type="int", dest="chanid",
            help="Use chanid for manual operation, format interger")
    sourcegroup.add_option("--startdate", action="store", type="string", dest="startdate",
            help="Use startdate for manual operation, format is year-mm-dd")
    sourcegroup.add_option("--starttime", action="store", type="string", dest="starttime",
            help="Use starttime for manual operation, format is hh:mm:ss in UTC")
    sourcegroup.add_option("--offset", action="store", type="string", dest="offset",
            help="Use offset(timezone) for manual operation, format is [+/-]hh:mm. Do not adjust for DST")
    parser.add_option_group(sourcegroup)

    actiongroup = OptionGroup(parser, "Additional Actions",
                    "These options perform additional actions after the recording has been migrated. "+\
                    "A safe copy is always performed in that the file is checked to match the "+\
                    "MythBE hash. The safe copy option will abort the entire process if selected "+\
                    "along with Other Data and an exception occurs in the process")
    actiongroup.add_option('--safe', action='store_true', default=False, dest='safe',
            help='If other data is copied and a failure occurs this will abort the whole process.')
    actiongroup.add_option("--delete", action="store_true", default=False,
            help="Delete source recording after successful export. Enforces use of --safe.")
    parser.add_option_group(actiongroup)

    othergroup = OptionGroup(parser, "Other Data",
                    "These options copy additional information from the source recording.")
    othergroup.add_option("--seekdata", action="store_true", default=False, dest="seekdata",
            help="Copy seekdata from source recording.")
    othergroup.add_option("--skiplist", action="store_true", default=False, dest="skiplist",
            help="Copy commercial detection from source recording.")
    othergroup.add_option("--cutlist", action="store_true", default=False, dest="cutlist",
            help="Copy manual commercial cuts from source recording.")
    parser.add_option_group(othergroup)

    MythLog.loadOptParse(parser)

    opts, args = parser.parse_args()

    def error_out():
        export.delete_vid()
        if export.thisJob:        
            export.set_job_status(Job.ERRORED)
        sys.exit(1)
        
    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if opts.delete:
        opts.safe = True

    # if a manual channel and time entry then setup the export with opts
    if opts.chanid and opts.startdate and opts.starttime and opts.offset:
        try:
            export = VIDEO(opts)

        except Exception, e:
            sys.exit(1)
예제 #27
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    formatgroup = OptionGroup(parser, "Formatting Options",
                    "These options are used to display and manipulate the output file formats.")
    formatgroup.add_option("-f", "--helpformat", action="store_true", default=False, dest="fmthelp",
            help="Print explination of file format string.")
    formatgroup.add_option("-p", "--printformat", action="store_true", default=False, dest="fmtprint",
            help="Print current file format string.")
    formatgroup.add_option("--tformat", action="store", type="string", dest="tformat",
            help="Use TV format for current task. If no task, store in database.")
    formatgroup.add_option("--mformat", action="store", type="string", dest="mformat",
            help="Use Movie format for current task. If no task, store in database.")
    formatgroup.add_option("--gformat", action="store", type="string", dest="gformat",
            help="Use Generic format for current task. If no task, store in database.")
    formatgroup.add_option("--listingonly", action="store_true", default=False, dest="listingonly",
            help="Use data from listing provider, rather than grabber")
    parser.add_option_group(formatgroup)

    sourcegroup = OptionGroup(parser, "Source Definition",
                    "These options can be used to manually specify a recording to operate on "+\
                    "in place of the job id.")
    sourcegroup.add_option("--chanid", action="store", type="int", dest="chanid",
            help="Use chanid for manual operation")
    sourcegroup.add_option("--starttime", action="store", type="int", dest="starttime",
            help="Use starttime for manual operation")
    parser.add_option_group(sourcegroup)

    actiongroup = OptionGroup(parser, "Additional Actions",
                    "These options perform additional actions after the recording has been exported.")
    actiongroup.add_option('--safe', action='store_true', default=False, dest='safe',
            help='Perform quick sanity check of exported file using file size.')
    actiongroup.add_option('--really-safe', action='store_true', default=False, dest='reallysafe',
            help='Perform slow sanity check of exported file using SHA1 hash.')
    actiongroup.add_option("--delete", action="store_true", default=False,
            help="Delete source recording after successful export. Enforces use of --safe.")
    parser.add_option_group(actiongroup)

    othergroup = OptionGroup(parser, "Other Data",
                    "These options copy additional information from the source recording.")
    othergroup.add_option("--seekdata", action="store_true", default=False, dest="seekdata",
            help="Copy seekdata from source recording.")
    othergroup.add_option("--skiplist", action="store_true", default=False, dest="skiplist",
            help="Copy commercial detection from source recording.")
    othergroup.add_option("--cutlist", action="store_true", default=False, dest="cutlist",
            help="Copy manual commercial cuts from source recording.")
    parser.add_option_group(othergroup)

    MythLog.loadOptParse(parser)

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if opts.fmthelp:
        usage_format()
        sys.exit(0)

    if opts.fmtprint:
        print_format()
        sys.exit(0)

    if opts.delete:
        opts.safe = True

    if opts.chanid and opts.starttime:
        export = VIDEO(opts)
    elif len(args) == 1:
        try:
            export = VIDEO(opts,int(args[0]))
        except Exception, e:
            Job(int(args[0])).update({'status':Job.ERRORED,
                                      'comment':'ERROR: '+e.args[0]})
            MythLog(module='mythvidexport.py').logTB(MythLog.GENERAL)
            sys.exit(1)
예제 #28
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    formatgroup = OptionGroup(
        parser, "Formatting Options",
        "These options are used to display and manipulate the output file formats."
    )
    formatgroup.add_option("-f",
                           "--helpformat",
                           action="store_true",
                           default=False,
                           dest="fmthelp",
                           help="Print explination of file format string.")
    formatgroup.add_option("-p",
                           "--printformat",
                           action="store_true",
                           default=False,
                           dest="fmtprint",
                           help="Print current file format string.")
    formatgroup.add_option(
        "--tformat",
        action="store",
        type="string",
        dest="tformat",
        help="Use TV format for current task. If no task, store in database.")
    formatgroup.add_option(
        "--mformat",
        action="store",
        type="string",
        dest="mformat",
        help="Use Movie format for current task. If no task, store in database."
    )
    formatgroup.add_option(
        "--gformat",
        action="store",
        type="string",
        dest="gformat",
        help=
        "Use Generic format for current task. If no task, store in database.")
    formatgroup.add_option(
        "--listingonly",
        action="store_true",
        default=False,
        dest="listingonly",
        help="Use data from listing provider, rather than grabber")
    parser.add_option_group(formatgroup)

    sourcegroup = OptionGroup(parser, "Source Definition",
                    "These options can be used to manually specify a recording to operate on "+\
                    "in place of the job id.")
    sourcegroup.add_option("--chanid",
                           action="store",
                           type="int",
                           dest="chanid",
                           help="Use chanid for manual operation")
    sourcegroup.add_option("--starttime",
                           action="store",
                           type="string",
                           dest="starttime",
                           help="Use starttime for manual operation")
    parser.add_option_group(sourcegroup)

    actiongroup = OptionGroup(
        parser, "Additional Actions",
        "These options perform additional actions after the recording has been exported."
    )
    actiongroup.add_option(
        '--safe',
        action='store_true',
        default=False,
        dest='safe',
        help='Perform quick sanity check of exported file using file size.')
    actiongroup.add_option(
        '--really-safe',
        action='store_true',
        default=False,
        dest='reallysafe',
        help='Perform slow sanity check of exported file using SHA1 hash.')
    actiongroup.add_option(
        "--delete",
        action="store_true",
        default=False,
        help=
        "Delete source recording after successful export. Enforces use of --safe."
    )
    parser.add_option_group(actiongroup)

    othergroup = OptionGroup(
        parser, "Other Data",
        "These options copy additional information from the source recording.")
    othergroup.add_option("--seekdata",
                          action="store_true",
                          default=False,
                          dest="seekdata",
                          help="Copy seekdata from source recording.")
    othergroup.add_option(
        "--skiplist",
        action="store_true",
        default=False,
        dest="skiplist",
        help="Copy commercial detection from source recording.")
    othergroup.add_option(
        "--cutlist",
        action="store_true",
        default=False,
        dest="cutlist",
        help="Copy manual commercial cuts from source recording.")
    parser.add_option_group(othergroup)

    MythLog.loadOptParse(parser)

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if opts.fmthelp:
        usage_format()
        sys.exit(0)

    if opts.fmtprint:
        print_format()
        sys.exit(0)

    if opts.delete:
        opts.safe = True

    if opts.chanid and opts.starttime:
        export = VIDEO(opts)
    elif len(args) == 1:
        try:
            export = VIDEO(opts, int(args[0]))
        except Exception, e:
            Job(int(args[0])).update({
                'status': Job.ERRORED,
                'comment': 'ERROR: ' + e.args[0]
            })
            MythLog(module='mythvidexport.py').logTB(MythLog.GENERAL)
            sys.exit(1)
예제 #29
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    sourcegroup = OptionGroup(parser, "Source Definition",
                    "These options can be used to manually specify a recording to operate on "+\
                    "in place of the job id.")
    sourcegroup.add_option(
        "--chanid",
        action="store",
        type="int",
        dest="chanid",
        help="Use chanid for manual operation, format interger")
    sourcegroup.add_option(
        "--startdate",
        action="store",
        type="string",
        dest="startdate",
        help="Use startdate for manual operation, format is year-mm-dd")
    sourcegroup.add_option(
        "--starttime",
        action="store",
        type="string",
        dest="starttime",
        help="Use starttime for manual operation, format is hh:mm:ss in UTC")
    sourcegroup.add_option(
        "--offset",
        action="store",
        type="string",
        dest="offset",
        help=
        "Use offset(timezone) for manual operation, format is [+/-]hh:mm. Do not adjust for DST"
    )
    parser.add_option_group(sourcegroup)

    actiongroup = OptionGroup(parser, "Additional Actions",
                    "These options perform additional actions after the recording has been migrated. "+\
                    "A safe copy is always performed in that the file is checked to match the "+\
                    "MythBE hash. The safe copy option will abort the entire process if selected "+\
                    "along with Other Data and an exception occurs in the process")
    actiongroup.add_option(
        '--safe',
        action='store_true',
        default=False,
        dest='safe',
        help=
        'If other data is copied and a failure occurs this will abort the whole process.'
    )
    actiongroup.add_option(
        "--delete",
        action="store_true",
        default=False,
        help=
        "Delete source recording after successful export. Enforces use of --safe."
    )
    parser.add_option_group(actiongroup)

    othergroup = OptionGroup(
        parser, "Other Data",
        "These options copy additional information from the source recording.")
    othergroup.add_option("--seekdata",
                          action="store_true",
                          default=False,
                          dest="seekdata",
                          help="Copy seekdata from source recording.")
    othergroup.add_option(
        "--skiplist",
        action="store_true",
        default=False,
        dest="skiplist",
        help="Copy commercial detection from source recording.")
    othergroup.add_option(
        "--cutlist",
        action="store_true",
        default=False,
        dest="cutlist",
        help="Copy manual commercial cuts from source recording.")
    parser.add_option_group(othergroup)

    MythLog.loadOptParse(parser)

    opts, args = parser.parse_args()

    def error_out():
        export.delete_vid()
        if export.thisJob:
            export.set_job_status(Job.ERRORED)
        sys.exit(1)

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if opts.delete:
        opts.safe = True

    # if a manual channel and time entry then setup the export with opts
    if opts.chanid and opts.startdate and opts.starttime and opts.offset:
        try:
            export = VIDEO(opts)

        except Exception, e:
            sys.exit(1)
예제 #30
0
#!/usr/bin/env python

import os
import sys
try:
    from MythTV import MythVideo, VideoGrabber, MythLog
except:
    print 'ERROR: The python bindings are not installed'
    sys.exit(-1)

LOG = MythLog('MythVideo Scanner', lstr='general')
mvid = MythVideo()


def format_name(vid):
    # returns a string in the format 'TITLE[ - SEASONxEPISODE][ - SUBTITLE]'
    s = vid.title
    if vid.season:
        s += ' - %dx%02d' % (vid.season, vid.episode)
    if vid.subtitle:
        s += ' - ' + vid.subtitle
    return s.encode('utf-8', 'replace')


# Load TV Grabber
try:
    TVgrab = VideoGrabber('TV', db=mvid)
except:
    print 'ERROR: Cannot find MythVideo TV grabber'
    sys.exit(-1)
예제 #31
0
#!/usr/bin/env python
from MythTV import MythDB, MythError, MythLog, Frontend

from datetime import datetime, timedelta
from curses   import wrapper, ascii
from time     import sleep
import sys, socket, curses, re

#note for ticket, on-screen-keyboard remotely does not have focus

MythLog._setlevel('none')
frontend = None

rplaytype = re.compile('Playback ([a-zA-Z]+)')
rrecorded = re.compile('Playback ([a-zA-Z]+) ([\d:]+) of ([\d:]+) ([-0-9\.]+x) (\d*) ([0-9-T:]+)')
rlivetv   = rrecorded
rvideo    = re.compile('Playback [a-zA-Z]+ ([\d:]+) ([-0-9\.]+x) .*/(.*) \d+ [\.\d]+')
rrname    = re.compile('\d+ [0-9-T:]+ (.*)')
rlname    = re.compile('\d+ [0-9-T: ]+ (.*)')

def align(side, window, y, string, flush=0):
    w = window.getmaxyx()[1]-1
    if len(string) > w:
        string = string[:w]
    if side == 0:
        x = 1
    elif side == 1:
        x = (w-len(string))/2+1
    elif side == 2:
        x = w-len(string)
    window.addstr(y,x,string)
예제 #32
0
        a = a[2:]
        if '=' in a:
            a = a.split('=',1)
            param[a[0]] = a[1]
        else:
            if len(temp):
                b = temp.pop(0)
                if (b[:2] == '--') or (b[:1] == '-'):
                    temp.insert(0,b)
                    param[a] = ''
                else:
                    param[a] = b
            else:
                param[a] = ''

MythLog._setlevel(param.get('verbose','none'))
try:
    param.pop('verbose')
except: pass

force = False
if 'force' in param:
    force = True
    param.pop('force')

if len(a) == 0:
    sys.exit(0)

recs = list(MythDB().searchRecorded(**param))
if len(recs) == 0:
    print 'no matching recordings found'
예제 #33
0
class VIDEO:
    def __init__(self, opts, jobid=None):
        if jobid:
            self.job = Job(jobid)
            self.chanid = self.job.chanid
            self.starttime = self.job.starttime
            self.job.update(status=3)
        else:
            self.job = None
            self.chanid = opts.chanid
            self.starttime = opts.starttime

        self.opts = opts
        self.db = MythDB()
        self.log = MythLog(module='mythvidexport.py', db=self.db)

        # load setting strings
        self.get_format()

        # prep objects
        self.rec = Recorded((self.chanid, self.starttime), db=self.db)
        self.log(MythLog.IMPORTANT, 'Using recording',
                 '%s - %s' % (self.rec.title, self.rec.subtitle))
        self.vid = Video(db=self.db).create({
            'title': '',
            'filename': '',
            'host': gethostname()
        })

        # process data
        self.get_meta()
        self.get_dest()

        # save file
        self.copy()
        if opts.seekdata:
            self.copy_seek()
        if opts.skiplist:
            self.copy_markup(static.MARKUP.MARK_COMM_START,
                             static.MARKUP.MARK_COMM_END)
        if opts.cutlist:
            self.copy_markup(static.MARKUP.MARK_CUT_START,
                             static.MARKUP.MARK_CUT_END)
        self.vid.update()

    def get_format(self):
        host = self.db.gethostname()
        # TV Format
        if self.opts.tformat:
            self.tfmt = self.opts.tformat
        elif self.db.settings[host]['mythvideo.TVexportfmt']:
            self.tfmt = self.db.settings[host]['mythvideo.TVexportfmt']
        else:
            self.tfmt = 'Television/%TITLE%/Season %SEASON%/'+\
                            '%TITLE% - S%SEASON%E%EPISODEPAD% - %SUBTITLE%'

        # Movie Format
        if self.opts.mformat:
            self.mfmt = self.opts.mformat
        elif self.db.settings[host]['mythvideo.MOVIEexportfmt']:
            self.mfmt = self.db.settings[host]['mythvideo.MOVIEexportfmt']
        else:
            self.mfmt = 'Movies/%TITLE%'

        # Generic Format
        if self.opts.gformat:
            self.gfmt = self.opts.gformat
        elif self.db.settings[host]['mythvideo.GENERICexportfmt']:
            self.gfmt = self.db.settings[host]['mythvideo.GENERICexportfmt']
        else:
            self.gfmt = 'Videos/%TITLE%'

    def get_meta(self):
        self.vid.hostname = self.db.gethostname()

        if self.rec.subtitle:  # subtitle exists, assume tv show
            self.type = 'TV'
            self.log(self.log.IMPORTANT, 'Attempting TV export.')
            if self.opts.listingonly:
                self.log(self.log.IMPORTANT, 'Forcing listing data only.')
                self.get_generic(False)
                return
            grab = VideoGrabber(self.type)
            match = grab.sortedSearch(self.rec.title, self.rec.subtitle)
        else:  # assume movie
            self.type = 'MOVIE'
            self.log(self.log.IMPORTANT, 'Attempting Movie export.')
            if self.opts.listingonly:
                self.log(self.log.IMPORTANT, 'Forcing listing data only.')
                self.get_generic(False)
                return
            grab = VideoGrabber(self.type)
            match = grab.sortedSearch(self.rec.title)

        if len(match) == 0:
            # no match found
            self.log(self.log.IMPORTANT, 'Falling back to generic export.')
            self.get_generic()
        elif (len(match) > 1) & (match[0].levenshtein > 0):
            # multiple matches found, and closest is not exact
            self.vid.delete()
            raise MythError('Multiple metadata matches found: '\
                                                   +self.rec.title)
        else:
            self.log(self.log.IMPORTANT, 'Importing content from',
                     match[0].inetref)
            self.vid.importMetadata(grab.grabInetref(match[0]))

    def get_generic(self, name_as_generic=True):
        self.vid.title = self.rec.title
        if self.rec.subtitle:
            self.vid.subtitle = self.rec.subtitle
        if self.rec.description:
            self.vid.plot = self.rec.description
        if self.rec.originalairdate:
            self.vid.year = self.rec.originalairdate.year
            self.vid.releasedate = self.rec.originalairdate
        lsec = (self.rec.endtime - self.rec.starttime).seconds
        self.vid.length = str(lsec / 60)
        for member in self.rec.cast:
            if member.role == 'director':
                self.vid.director = member.name
            elif member.role == 'actor':
                self.vid.cast.append(member.name)
        if name_as_generic:
            self.type = 'GENERIC'

    def get_dest(self):
        if self.type == 'TV':
            self.vid.filename = self.process_fmt(self.tfmt)
        elif self.type == 'MOVIE':
            self.vid.filename = self.process_fmt(self.mfmt)
        elif self.type == 'GENERIC':
            self.vid.filename = self.process_fmt(self.gfmt)

    def process_fmt(self, fmt):
        # replace fields from viddata
        #print self.vid.data
        ext = '.' + self.rec.basename.rsplit('.', 1)[1]
        rep = (('%TITLE%', 'title', '%s'), ('%SUBTITLE%', 'subtitle', '%s'),
               ('%SEASON%', 'season', '%d'), ('%SEASONPAD%', 'season', '%02d'),
               ('%EPISODE%', 'episode', '%d'), ('%EPISODEPAD%', 'episode',
                                                '%02d'),
               ('%YEAR%', 'year', '%s'), ('%DIRECTOR%', 'director', '%s'))
        for tag, data, format in rep:
            if self.vid[data]:
                fmt = fmt.replace(tag, format % self.vid[data])
            else:
                fmt = fmt.replace(tag, '')

        # replace fields from program data
        rep = (('%HOSTNAME', 'hostname', '%s'), ('%STORAGEGROUP%',
                                                 'storagegroup', '%s'))
        for tag, data, format in rep:
            data = getattr(self.rec, data)
            fmt = fmt.replace(tag, format % data)

#       fmt = fmt.replace('%CARDID%',self.rec.cardid)
#       fmt = fmt.replace('%CARDNAME%',self.rec.cardid)
#       fmt = fmt.replace('%SOURCEID%',self.rec.cardid)
#       fmt = fmt.replace('%SOURCENAME%',self.rec.cardid)
#       fmt = fmt.replace('%CHANNUM%',self.rec.channum)
#       fmt = fmt.replace('%CHANNAME%',self.rec.cardid)

        if len(self.vid.genre):
            fmt = fmt.replace('%GENRE%', self.vid.genre[0].genre)
        else:
            fmt = fmt.replace('%GENRE%', '')


#       if len(self.country):
#           fmt = fmt.replace('%COUNTRY%',self.country[0])
#       else:
#           fmt = fmt.replace('%COUNTRY%','')
        return fmt + ext

    def copy(self):
        stime = time.time()
        srcsize = self.rec.filesize
        htime = [stime, stime, stime, stime]

        self.log.log(MythLog.IMPORTANT|MythLog.FILE, "Copying myth://%s@%s/%s"\
               % (self.rec.storagegroup, self.rec.hostname, self.rec.basename)\
                                                    +" to myth://Videos@%s/%s"\
                                          % (self.vid.host, self.vid.filename))
        srcfp = self.rec.open('r')
        dstfp = self.vid.open('w')

        if self.job:
            self.job.setStatus(4)
        tsize = 2**24
        while tsize == 2**24:
            tsize = min(tsize, srcsize - dstfp.tell())
            dstfp.write(srcfp.read(tsize))
            htime.append(time.time())
            rate = float(tsize * 4) / (time.time() - htime.pop(0))
            remt = (srcsize - dstfp.tell()) / rate
            if self.job:
                self.job.setComment("%02d%% complete - %d seconds remaining" %\
                            (dstfp.tell()*100/srcsize, remt))
        srcfp.close()
        dstfp.close()

        self.vid.hash = self.vid.getHash()

        self.log(MythLog.IMPORTANT | MythLog.FILE, "Transfer Complete",
                 "%d seconds elapsed" % int(time.time() - stime))
        if self.job:
            self.job.setComment("Complete - %d seconds elapsed" % \
                            (int(time.time()-stime)))
            self.job.setStatus(256)

    def copy_seek(self):
        for seek in self.rec.seek:
            self.vid.markup.add(seek.mark, seek.offset, seek.type)

    def copy_markup(self, start, stop):
        for mark in self.rec.markup:
            if mark.type in (start, stop):
                self.vid.markup.add(mark.mark, 0, mark.type)
예제 #34
0
def LOG(msg):
    logger = MythLog(module='mythadder.py')
    logger(MythLog.GENERAL, MythLog.INFO, msg)
예제 #35
0
try:
    import MythTV
except:
    print 'Warning! MythTV Python bindings could not be found'
    sys.exit(1)
if MythTV.__version__ < (0,24,0,0):
    print 'Warning! Installed MythTV Python bindings are tool old. Please update'
    print '    to 0.23.0.18 or later.'
    sys.exit(1)
from MythTV import MythDB, MythVideo, ftopen, MythBE,\
                   Video, Recorded, MythLog, static

fuse.fuse_python_api = (0, 2)
LOG = MythLog(lstr='none')
MythLog._setfile('/dev/null')
BACKEND = None

def doNothing(*args, **kwargs):
    pass

def increment():
    res = 1
    while True:
        yield res
        res += 1

class Attr(fuse.Stat):
    def __init__(self):
        self.st_mode = 0
        self.st_ino = 0
예제 #36
0
 def __init__(self):
     self.l = MythLog('transcode.py', db=self.db())
예제 #37
0
    def __getattr__(self, attr):
        """Delegate everything but write to the stream"""
        return getattr(self.out, attr)
sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')


# Find out if the MythTV python bindings can be accessed and instances can created
try:
    '''If the MythTV python interface is found, required to access Netvision icon directory settings
    '''
    from MythTV import MythDB, MythLog
    try:
        '''Create an instance of each: MythDB
        '''
        MythLog._setlevel('none') # Some non option -M cannot have any logging on stdout
        mythdb = MythDB()
    except MythError, e:
        sys.stderr.write(u'\n! Error - %s\n' % e.args[0])
        filename = os.path.expanduser("~")+'/.mythtv/config.xml'
        if not os.path.isfile(filename):
            sys.stderr.write(u'\n! Error - A correctly configured (%s) file must exist\n' % filename)
        else:
            sys.stderr.write(u'\n! Error - Check that (%s) is correctly configured\n' % filename)
        sys.exit(1)
    except Exception, e:
        sys.stderr.write(u"\n! Error - Creating an instance caused an error for one of: MythDB. error(%s)\n" % e)
        sys.exit(1)
except Exception, e:
    sys.stderr.write(u"\n! Error - MythTV python bindings could not be imported. error(%s)\n" % e)
    sys.exit(1)
예제 #38
0
def main():
    parser = OptionParser(usage="usage: %prog [options] [jobid]")

    parser.add_option(
        '--chanid',
        action='store',
        type='int',
        dest='chanid',
        help='Use chanid with both starttime and tzoffset for manual operation'
    )
    parser.add_option(
        '--starttime',
        action='store',
        type='string',
        dest='starttime',
        help='Use starttime with both chanid and tzoffset for manual operation'
    )
    parser.add_option(
        '--tzoffset',
        action='store',
        type='int',
        dest='tzoffset',
        help='Use tzoffset with both chanid and starttime for manual operation'
    )
    parser.add_option(
        '--overwrite',
        action='store',
        type='int',
        default=1,
        dest='overwrite',
        help='Use overwrite to force the output to replace the original file')
    parser.add_option('--sd',
                      action='store',
                      type='int',
                      default=0,
                      dest='sdonly',
                      help='Use sd to force the output to be SD dimentions')
    parser.add_option('--burncc',
                      action='store',
                      type='int',
                      default=0,
                      dest='burncc',
                      help='Use burncc to burn the subtitle/cc into the video')
    parser.add_option('--mkv',
                      action='store',
                      type='int',
                      default=0,
                      dest='usemkv',
                      help='Use mkv instead of mp4')
    parser.add_option('-v',
                      '--verbose',
                      action='store',
                      type='string',
                      dest='verbose',
                      help='Verbosity level')

    opts, args = parser.parse_args()

    if opts.verbose:
        if opts.verbose == 'help':
            print MythLog.helptext
            sys.exit(0)
        MythLog._setlevel(opts.verbose)

    if len(args) == 1:
        runjob(jobid=args[0],
               overwrite=opts.overwrite,
               sdonly=opts.sdonly,
               burncc=opts.burncc,
               usemkv=opts.usemkv)
    elif opts.chanid and opts.starttime and opts.tzoffset is not None:
        runjob(chanid=opts.chanid,
               starttime=opts.starttime,
               tzoffset=opts.tzoffset,
               overwrite=opts.overwrite,
               sdonly=opts.sdonly,
               burncc=opts.burncc,
               usemkv=opts.usemkv)
    else:
        print 'Script must be provided jobid, or chanid, starttime and timezone offset.'
        sys.exit(1)
예제 #39
0
        """Delegate everything but write to the stream"""
        return getattr(self.out, attr)


sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')

# Find out if the MythTV python bindings can be accessed and instances can created
try:
    '''If the MythTV python interface is found, required to access Netvision icon directory settings
    '''
    from MythTV import MythDB, MythLog
    try:
        '''Create an instance of each: MythDB
        '''
        MythLog._setlevel(
            'none')  # Some non option -M cannot have any logging on stdout
        mythdb = MythDB()
    except MythError, e:
        sys.stderr.write(u'\n! Error - %s\n' % e.args[0])
        filename = os.path.expanduser("~") + '/.mythtv/config.xml'
        if not os.path.isfile(filename):
            sys.stderr.write(
                u'\n! Error - A correctly configured (%s) file must exist\n' %
                filename)
        else:
            sys.stderr.write(
                u'\n! Error - Check that (%s) is correctly configured\n' %
                filename)
        sys.exit(1)
    except Exception, e:
        sys.stderr.write(
예제 #40
0
from fuse import Fuse

try:
    import MythTV
except:
    print 'Warning! MythTV Python bindings could not be found'
    sys.exit(1)
if MythTV.__version__ < (0, 24, 0, 0):
    print 'Warning! Installed MythTV Python bindings are tool old. Please update'
    print '    to 0.23.0.18 or later.'
    sys.exit(1)
from MythTV import MythDB, MythVideo, ftopen, MythBE,\
                   Video, Recorded, MythLog, static

fuse.fuse_python_api = (0, 2)
LOG = MythLog(lstr='none')
MythLog._setfile('/dev/null')
BACKEND = None


def doNothing(*args, **kwargs):
    pass


def increment():
    res = 1
    while True:
        yield res
        res += 1

예제 #41
0
            export = VIDEO(opts)

        except Exception, e:
            sys.exit(1)

    # If an auto or manual job entry then setup the export with the jobID
    elif len(args) == 1:
        try:
            export = VIDEO(opts, int(args[0]))

        except Exception, e:
            Job(int(args[0])).update({
                'status': Job.ERRORED,
                'comment': 'ERROR: ' + e.args[0]
            })
            MythLog(module='Myth-Rec-to-Vid.py').logTB(MythLog.GENERAL)
            sys.exit(1)

    # else bomb the job and return an error code
    else:
        parser.print_help()
        sys.exit(2)

    # Export object created so process the job
    try:
        export.get_type()
        export.get_meta()
        export.get_dest()

    except Exception, e:
        export.log(MythLog.GENERAL | MythLog.FILE, MythLog.INFO,