Пример #1
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_Dataheap_Video_005_01(self):
        """Test creation of a Video with an existing file and host entry.
        """

        # check the result of the file creation
        self.assertTrue(self.result == 0)

        host = self.mydb.getMasterBackend()

        v = Video(db=self.mydb)
        v.host = host
        v.filename = self.frfilename
        v.create({
            'title': self.frtitle,
            'filename': self.frfilename,
            'host': host
        })

        # check if hash is in hex:
        hex_set = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
            'd', 'e', 'f'
        }
        self.assertTrue(set(v.hash.lower()).issubset(hex_set))

        #remove video entry
        v.delete()
Пример #3
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)
Пример #4
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()
    def test_Dataheap_Video_004_01(self):
        """Test creation of a Video and
           writing/reading to the videocategory table.
           This test assumes, that there are no entries
           in the videocategory table! All entries in that
           table will be deleted!
        """
        class VideoCategory(DBDataWrite):
            """
            VideoCategory(data=None, db=None) --> VideoCategory object to
            database table 'videocategory', data is a `videocategory` string.

            - get information about the table:
              $ mysql -h <master-backend-ip> -u mythtv -p<password-from-config.xml> mythconverg

              MariaDB [mythconverg]> describe videocategory;
                +-------------+-------------+------+-----+---------+----------------+
                | Field       | Type        | Null | Key | Default | Extra          |
                +-------------+-------------+------+-----+---------+----------------+
                | intid       | int(10)     | NO   | PRI | NULL    | auto_increment |
                | category    | varchar(128)| NO   |     |         |                |
                +-------------+-------------+------+-----+---------+----------------+
                2 rows in set (0.00 sec)

            """
            _table = 'videocategory'
            _key = ['category']
            _defaults = {'category': ''}

            ### end class VideoCategory

        title = u"Le Dernier Métro"
        filename = title + u".mkv"

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

        vid.category = u"python_test"
        vid.update()

        # find this video and check it
        vids = self.mydb.searchVideos(title=title)
        vid_r = next(vids)
        # print(vid_r.category)
        self.assertEqual(vid.category, vid_r.category)
        print(repr(vid_r))
        print(str(vid_r))

        # delete the video previously created
        vid.delete()

        # delete the previously assigned category
        vid_category = VideoCategory(u"python_test", db=self.mydb)
        vid_category.delete()
    def test_Dataheap_Video_003_fromFilename_01(self):
        """Test 'fromFilename' classmethod from MythTV.Video.
           According wiki, this
           "Creates a new object with initial data parsed from the filename.
           Object is not stored to the database."
           Remark: What to do with this 'new object' ?
        """
        path = self.testenv['VIDPATH_DE']
        cast = self.testenv['VIDCAST_DE']

        vid = Video.fromFilename(os.path.basename(path), db=self.mydb)
        self.assertEqual(os.path.basename(path), vid.filename)
Пример #7
0
 def test_Dataheap_Video_002_parseFilename_02(self):
     """Test 'parseFilename' method from MythTV.Video
        according 'https://www.mythtv.org/wiki/MythVideo_File_Parsing'.
     """
     files = [  # (path,                                         result: (title, season, episode, subtitle ))
         (u"A_Title/Season 1/02 Subtitle1.mpg", (u"A Title", 1, 2,
                                                 u"Subtitle1")),
         (u"B_Title/Season 3/s03e04 Subtitle2.mpg", (u"B Title", 3, 4,
                                                     u"Subtitle2")),
         (u"C_Title/Season 5/5x06 Subtitle3.mpg", (u"C Title", 5, 6,
                                                   u"Subtitle3")),
         (u"D_Title/Season 7/D Title s07e08 Subtitle4.mpg",
          (u"D Title", 7, 8, u"Subtitle4")),
         (u"E Title/Season 9/E Title 9x10 Subtitle5.mpg",
          (u"E Title", 9, 10, u"Subtitle5")),
         (u"F Title/Season 11/Episode 12 Subtitle6.mpg",
          (u"F Title", 11, 12, u"Subtitle6")),
         (u"G Title/Season 13/Season 13 Episode 14 Subtitle7.mpg",
          (u"G Title", 13, 14, u"Subtitle7")),
         (u"H Title Season 15/16 Subtitle8.mpg", (u"H Title", 15, 16,
                                                  u"Subtitle8")),
         (u"I_Title Season 17/s17e18 Subtitle9.mpg", (u"I Title", 17, 18,
                                                      u"Subtitle9")),
         (u"J_Title Season 19/19x20 Subtitle10.mpg", (u"J Title", 19, 20,
                                                      u"Subtitle10")),
         (u"K_Title Season 21/K Title s21e22 Subtitle11.mpg",
          (u"K Title", 21, 22, u"Subtitle11")),
         (u"L_Title Season 23/L Title 23x024 Subtitle12.mpg",
          (u"L Title", 23, 24, u"Subtitle12")),
         (u"M_Title Season 25/Episode 26 Subtitle13.avi",
          (u"M Title", 25, 26, u"Subtitle13")),
         (u"N_Title Season 27/Season 27 Episode 28 Subtitle14.mkv",
          (u"N Title", 27, 28, u"Subtitle14"))
     ]
     v = Video(db=self.mydb)
     for (path, result) in files:
         v.filename = path
         (title, season, episode, subtitle) = v.parseFilename()
         #print(title, season, episode, subtitle)
         self.assertEqual((title, season, episode, subtitle), result)
Пример #8
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 FindDuplicates(dodelete):
    dupvids = []
    vids = sorted(Video.getAllEntries(), key=lambda v: v.hash)

    for i in range(len(vids)-1):
        if vids[i].hash == 'NULL':
            continue
        if vids[i].hash == vids[i+1].hash:
            dupvids.append(vids[i+1])

    if dodelete:
        for vid in dupvids:
            vid.delete()

    return dupvids
Пример #10
0
def FindDuplicates(dodelete):
    dupvids = []
    vids = sorted(Video.getAllEntries(), key=lambda v: v.hash)

    for i in range(len(vids)-1):
        if vids[i].hash == 'NULL':
            continue
        if vids[i].hash == vids[i+1].hash:
            dupvids.append(vids[i+1])

    if dodelete:
        for vid in dupvids:
            vid.delete()

    return dupvids
Пример #11
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)
Пример #12
0
    def test_Dataheap_Video_002_parseFilename_01(self):
        """Test 'parseFilename' method from MythTV.Video
           according 'https://www.mythtv.org/wiki/MythVideo_File_Parsing'.
        """

        files = [  # (path,                          result: (title,            season, episode, subtitle     ))
            (u"A Movie Title.mpg", (u"A Movie Title", None, None, None)),
            (u"A Movie Title 2019.mpg", (u"A Movie Title 2019", None, None,
                                         None)),
            (u"Title s01e02 Subtitle2.mpg", (u"Title", 1, 2, u"Subtitle2")),
            (u"Title 3x04 Subtitle4.mpg", (u"Title", 3, 4, u"Subtitle4")),
            (u"Title Season 5 Episode 6 Subtitle6.mpg", (u"Title", 5, 6,
                                                         u"Subtitle6")),
            (u"TV/Indiana Jones/Indiana Jones und das Königreich des Kristallschädels.mkv",
             (u"Indiana Jones und das Königreich des Kristallschädels", None,
              None, None))
        ]

        v = Video(db=self.mydb)
        for (path, result) in files:
            v.filename = path
            (title, season, episode, subtitle) = v.parseFilename()
            #print(title, season, episode, subtitle)
            self.assertEqual((title, season, episode, subtitle), result)
Пример #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()
        # 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()
Пример #14
0
    def handleUpdate(self, event=None):
        if event is None:
            self._reUp = re.compile(
                    re.escape(static.BACKEND_SEP).\
                        join(['BACKEND_MESSAGE',
                              'VIDEO_LIST_CHANGE',
                              'empty']))
            return self._reUp
        with self.db as cursor:
            cursor.execute("""SELECT intid FROM videometadata""")
            newids = [id[0] for id in cursor.fetchall()]

        oldids = self.vids.keys()
        for id in list(oldids):
            if id in newids:
                oldids.remove(id)
                newids.remove(id)

        for id in oldids:
            self._deleteCallback(self.vids[id])
        for id in newids:
            self.add(Video(id, db=self.db))
Пример #15
0
    def test_Dataheap_VideoGrabber_002_importMetadata_01(self):
        """Test 'VideoGrabber.grabInetref' method and 'Video.importMetadata'
           methods using predefined values. See 'mythvidexport.py' as well.
           See MythtTV trac tickets #12243 and #12245.
           Note: Use a video with French accents in title and cast.
        """
        from MythTV import MythDB, Video, VideoGrabber

        with add_log_flags():

            title      = u"Le Dernier Métro"
            castlist   = [u"Catherine Deneuve", u"Gérard Depardieu", u"Andréa Ferréol"]
            inetstr    = "tmdb3.py_1716"
            lang       = "fr"
            filename   = title + u".mkv"

            # create a new Video instance
            self.mydb = MythDB()
            vid  = Video(db=self.mydb).create ({'title'   : title,
                                                'filename': filename,
                                                'host'    : self.mydb.getMasterBackend()})
            # grab details from www.themoviedb.org
            grab = VideoGrabber('MOVIE', lang=lang, db=self.mydb)
            metadata = grab.grabInetref(inetstr)
            #print(type(metadata))   -->   <class 'MythTV.system.VideoMetadata'>
            # import metadata into Video instance
            vid.importMetadata(metadata)
            #print(vid.cast[1].cast)   ### --->  Gérard Depardieu
            # create a list of cast members from metadata
            vidcastmembers = [c.cast for c in vid.cast]
            # check for members in cast list
            self.assertTrue(self.is_sublist(castlist, vidcastmembers))
            # delete previously created Video object in database
            vid.delete()
            #print(metadata.inetref)   # --> 1716
            self.assertEqual(metadata.inetref, inetstr.split('_')[-1])
            # run the grabber again, but based on a 'VideoMetadata' object
            new_metadata = grab.grabInetref(metadata)
            # check if collected metadata are the equal
            self.assertEqual(new_metadata, metadata)
Пример #16
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)
Пример #17
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=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 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.inetref:
            # good data is available, use it
            if self.rec.season > 0 or self.rec.episode > 0:
                self.log(self.log.GENERAL, self.log.INFO,
                         'Performing TV export with local data.')
                self.type = 'TV'
                grab = VideoGrabber(self.type)
                metadata = grab.grabInetref(self.rec.inetref, self.rec.season,
                                            self.rec.episode)
            else:
                self.log(self.log.GENERAL, self.log.INFO,
                         'Performing Movie export with local data.')
                self.type = 'MOVIE'
                grab = VideoGrabber(self.type)
                metadata = grab.grabInetref(self.rec.inetref)
        elif self.opts.listingonly:
            # force use of local data
            if self.rec.subtitle:
                self.log(self.log.GENERAL, self.log.INFO,
                         'Forcing TV export with local data.')
                self.type = 'TV'
            else:
                self.log(self.log.GENERAL, self.log.INFO,
                         'Forcing Movie export with local data.')
                self.type = 'MOVIE'
            metadata = self.rec.exportMetadata()
        else:
            if self.rec.subtitle:
                # subtitle exists, assume tv show
                self.type = 'TV'
                self.log(self.log.GENERAL, self.log.INFO,
                         'Attempting TV export.')
                grab = VideoGrabber(self.type)
                match = grab.sortedSearch(self.rec.title, self.rec.subtitle)
            else:  # assume movie
                self.type = 'MOVIE'
                self.log(self.log.GENERAL, self.log.INFO,
                         'Attempting Movie export.')
                grab = VideoGrabber(self.type)
                match = grab.sortedSearch(self.rec.title)

            if len(match) == 0:
                # no match found
                self.log(self.log.GENERAL, self.log.INFO,
                         'Falling back to generic export.')
                self.type = 'GENERIC'
                metadata = self.rec.exportMetadata()
            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.GENERAL, self.log.INFO,
                         'Importing content from', match[0].inetref)
                metadata = grab.grabInetref(match[0])

        self.vid.importMetadata(metadata)
        self.log(self.log.GENERAL, self.log.INFO, 'Import complete')

    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(MythLog.GENERAL|MythLog.FILE, MythLog.INFO, "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', nooverwrite=True)

        if self.job:
            self.job.setStatus(Job.RUNNING)
        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.GENERAL | MythLog.FILE, MythLog.INFO,
                 "Transfer Complete",
                 "%d seconds elapsed" % int(time.time() - stime))

        if self.opts.reallysafe:
            if self.job:
                self.job.setComment("Checking file hashes")
            self.log(MythLog.GENERAL | MythLog.FILE, MythLog.INFO,
                     "Checking file hashes.")
            srchash = hashfile(self.rec.open('r'))
            dsthash = hashfile(self.vid.open('r'))
            if srchash != dsthash:
                raise MythError('Source hash (%s) does not match destination hash (%s)' \
                            % (srchash, dsthash))
        elif self.opts.safe:
            self.log(MythLog.GENERAL | MythLog.FILE, MythLog.INFO,
                     "Checking file sizes.")
            be = MythBE(db=self.vid._db)
            try:
                srcsize = be.getSGFile(self.rec.hostname, self.rec.storagegroup, \
                                       self.rec.basename)[1]
                dstsize = be.getSGFile(self.vid.host, 'Videos',
                                       self.vid.filename)[1]
            except:
                raise MythError('Could not query file size from backend')
            if srcsize != dstsize:
                raise MythError('Source size (%d) does not match destination size (%d)' \
                            % (srcsize, dstsize))

        if self.job:
            self.job.setComment("Complete - %d seconds elapsed" % \
                            (int(time.time()-stime)))
            self.job.setStatus(Job.FINISHED)

    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)
Пример #18
0
 def getAll(self):
     for vid in Video.getAllEntries(db=self.db):
         self.add(vid)
Пример #19
0
class VIDEO:
    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)
        
        
    def check_hash(self):
        self.log(self.log.GENERAL, self.log.INFO,
                 'Performing copy validation.')
        srchash = self.bend.getHash(self.rec.basename, self.rec.storagegroup)
        dsthash = self.bend.getHash(self.vid.filename, 'Videos')
        if srchash != dsthash:
            return False
        else:
            return True
               
    def copy(self):
        stime = time.time()
        srcsize = self.rec.filesize
        htime = [stime,stime,stime,stime]

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

        if self.thisJob:
            self.set_job_status(Job.RUNNING)
        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.thisJob:
                self.thisJob.setComment("%02d%% complete - %d seconds remaining" %\
                                      (dstfp.tell()*100/srcsize, remt))
        srcfp.close()
        dstfp.close()
        
        self.vid.hash = self.vid.getHash()
        
        self.log(MythLog.GENERAL|MythLog.FILE, MythLog.INFO, "Transfer Complete",
        			      "%d seconds elapsed" % int(time.time()-stime))

        if self.thisJob:
            self.thisJob.setComment("Complete - %d seconds elapsed" % \
        	      (int(time.time()-stime)))

    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)

    def copy_seek(self):
        for seek in self.rec.seek:
            self.vid.markup.add(seek.mark, seek.offset, seek.type)
                
    def delete_vid(self):
        self.vid.delete()
        
    def delete_rec(self):
        self.rec.delete()
        
    def dup_check(self):
        self.log(MythLog.GENERAL, MythLog.INFO, 'Processing new file name ',
                    '%s' % (self.vid.filename))
        self.log(MythLog.GENERAL, MythLog.INFO, 'Checking for duplication of ',
                    '%s - %s' % (self.rec.title.encode('utf-8'), 
                                 self.rec.subtitle.encode('utf-8')))
        if self.bend.fileExists(self.vid.filename, 'Videos'):
            self.log(MythLog.GENERAL, MythLog.INFO, 'Recording already exists in Myth Videos')
            if self.thisJob:
                self.thisJob.setComment("Action would result in duplicate entry" )
            return True
          
        else:
            self.log(MythLog.GENERAL, MythLog.INFO, 'No duplication found for ',
                    '%s - %s' % (self.rec.title.encode('utf-8'), 
                                 self.rec.subtitle.encode('utf-8')))
            return False 

    def get_dest(self):
        if self.type == 'TV':
            self.vid.filename = self.process_fmt(TVFMT)
        elif self.type == 'MOVIE':
            self.vid.filename = self.process_fmt(MVFMT)
        
        self.vid.markup._refdat = (self.vid.filename,)

    def get_meta(self):
        import_info = 'Listing only MetaData import complete'
        metadata = self.rec.exportMetadata()
        yrInfo = self.rec.getProgram()
        metadata['year'] = yrInfo.get('year')
        self.vid.importMetadata(metadata)
        if self.type == 'MOVIE':
            grab = VideoGrabber('Movie')
            results = grab.sortedSearch(self.rec.title)
            if len(results) > 0:
                for i in results:
                    if i.year == yrInfo.get('year') and i.title == self.rec.get('title'):
                        self.vid.importMetadata(i)
                        match = grab.grabInetref(i.get('inetref'))
                        length = len(match.people)
                        for p in range(length-2):
                            self.vid.cast.add(match.people[p].get('name'))
                        self.vid.director = match.people[length - 1].get('name')
                        import_info = 'Full MetaData Import complete'
        else:
            grab = VideoGrabber('TV')
            results = grab.sortedSearch(self.rec.title, self.rec.subtitle)
            if len(results) > 0:
                for i in results:
                    if  i.title == self.rec.get('title') and i.subtitle == self.rec.get('subtitle'):
                        self.vid.importMetadata(i)
                        match = grab.grabInetref(grab.grabInetref(i.get('inetref'), \
                                season=i.get('season'),episode=i.get('episode')))
                        length = len(match.people)
                        for p in range(length-2):
                            self.vid.cast.add(match.people[p].get('name'))
                        self.vid.director = match.people[length - 1].get('name')
                        import_info = 'Full MetaData Import complete'
            
        
        self.vid.category = self.rec.get('category')

        self.log(self.log.GENERAL, self.log.INFO, import_info)

    def get_type(self):
        if self.rec.seriesid != None and self.rec.programid[:2] != 'MV':
            self.type = 'TV'
            self.log(self.log.GENERAL, self.log.INFO,
                    'Performing TV type migration.')
        else:
            self.type = 'MOVIE'
            self.log(self.log.GENERAL, self.log.INFO,
                    'Performing Movie type migration.')

    def process_fmt(self, fmt):
        # replace fields from viddata

        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)


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

    def set_job_status(self, status):
        self.thisJob.setStatus(status)
        
    def set_vid_hash(self):
        self.vid.hash = self.vid.getHash()
    
    def update_vid(self):
        self.vid.update()
Пример #20
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)
Пример #21
0
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#---------------------------
# Name: hash_videos.py
# Python Script
# Author: Raymond Wagner
# Purpose
#   This script will regenerate the hash values associated with
#   videos in the MythVideo database.
#---------------------------

from MythTV import Video

QUIET = True

def print_aligned(left, right):
    indent = 100 - len(left)
    print left, indent*' ', right

for vid in Video.getAllEntries():
    if vid.hash in ('NULL', '', 'UNKNOWN_COMMAND'):
        vid.hash = vid.getHash()
        vid.update()
        print_aligned(vid.filename, vid.hash)
    elif not QUIET:
        print_aligned(vid.filename, 'skipped')

Пример #22
0
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#---------------------------
# Name: hash_videos.py
# Python Script
# Author: Raymond Wagner
# Purpose
#   This script will regenerate the hash values associated with
#   videos in the MythVideo database.
#---------------------------

from MythTV import Video

QUIET = True


def print_aligned(left, right):
    indent = 100 - len(left)
    print left, indent * ' ', right


for vid in Video.getAllEntries():
    if vid.hash in ('NULL', '', 'UNKNOWN_COMMAND'):
        vid.hash = vid.getHash()
        vid.update()
        print_aligned(vid.filename, vid.hash)
    elif not QUIET:
        print_aligned(vid.filename, 'skipped')
Пример #23
0
class VIDEO:
    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)

    def check_hash(self):
        self.log(self.log.GENERAL, self.log.INFO,
                 'Performing copy validation.')
        srchash = self.bend.getHash(self.rec.basename, self.rec.storagegroup)
        dsthash = self.bend.getHash(self.vid.filename, 'Videos')
        if srchash != dsthash:
            return False
        else:
            return True

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

        self.log(MythLog.GENERAL|MythLog.FILE, MythLog.INFO, "Copying myth://%s@%s/%s"\
               % (self.rec.storagegroup, self.rec.hostname, self.rec.basename)\
                                                    +" to myth://Videos@%s/%s"\
                                          % (self.host, self.vid.filename))

        srcfp = self.rec.open('r')
        dstfp = self.vid.open('w')

        if self.thisJob:
            self.set_job_status(Job.RUNNING)
        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.thisJob:
                self.thisJob.setComment("%02d%% complete - %d seconds remaining" %\
                                      (dstfp.tell()*100/srcsize, remt))
        srcfp.close()
        dstfp.close()

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

        self.log(MythLog.GENERAL | MythLog.FILE, MythLog.INFO,
                 "Transfer Complete",
                 "%d seconds elapsed" % int(time.time() - stime))

        if self.thisJob:
            self.thisJob.setComment("Complete - %d seconds elapsed" % \
               (int(time.time()-stime)))

    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)

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

    def delete_vid(self):
        self.vid.delete()

    def delete_rec(self):
        self.rec.delete()

    def dup_check(self):
        self.log(MythLog.GENERAL, MythLog.INFO, 'Processing new file name ',
                 '%s' % (self.vid.filename))
        self.log(
            MythLog.GENERAL, MythLog.INFO, 'Checking for duplication of ',
            '%s - %s' % (self.rec.title.encode('utf-8'),
                         self.rec.subtitle.encode('utf-8')))
        if self.bend.fileExists(self.vid.filename, 'Videos'):
            self.log(MythLog.GENERAL, MythLog.INFO,
                     'Recording already exists in Myth Videos')
            if self.thisJob:
                self.thisJob.setComment(
                    "Action would result in duplicate entry")
            return True

        else:
            self.log(
                MythLog.GENERAL, MythLog.INFO, 'No duplication found for ',
                '%s - %s' % (self.rec.title.encode('utf-8'),
                             self.rec.subtitle.encode('utf-8')))
            return False

    def get_dest(self):
        if self.type == 'TV':
            self.vid.filename = self.process_fmt(TVFMT)
        elif self.type == 'MOVIE':
            self.vid.filename = self.process_fmt(MVFMT)

        self.vid.markup._refdat = (self.vid.filename, )

    def get_meta(self):
        import_info = 'Listing only MetaData import complete'
        metadata = self.rec.exportMetadata()
        yrInfo = self.rec.getProgram()
        metadata['year'] = yrInfo.get('year')
        self.vid.importMetadata(metadata)
        if self.type == 'MOVIE':
            grab = VideoGrabber('Movie')
            results = grab.sortedSearch(self.rec.title)
            if len(results) > 0:
                for i in results:
                    if i.year == yrInfo.get(
                            'year') and i.title == self.rec.get('title'):
                        self.vid.importMetadata(i)
                        match = grab.grabInetref(i.get('inetref'))
                        length = len(match.people)
                        for p in range(length - 2):
                            self.vid.cast.add(match.people[p].get('name'))
                        self.vid.director = match.people[length -
                                                         1].get('name')
                        import_info = 'Full MetaData Import complete'
        else:
            grab = VideoGrabber('TV')
            results = grab.sortedSearch(self.rec.title, self.rec.subtitle)
            if len(results) > 0:
                for i in results:
                    if i.title == self.rec.get(
                            'title') and i.subtitle == self.rec.get(
                                'subtitle'):
                        self.vid.importMetadata(i)
                        match = grab.grabInetref(grab.grabInetref(i.get('inetref'), \
                                season=i.get('season'),episode=i.get('episode')))
                        length = len(match.people)
                        for p in range(length - 2):
                            self.vid.cast.add(match.people[p].get('name'))
                        self.vid.director = match.people[length -
                                                         1].get('name')
                        import_info = 'Full MetaData Import complete'

        self.vid.category = self.rec.get('category')

        self.log(self.log.GENERAL, self.log.INFO, import_info)

    def get_type(self):
        if self.rec.seriesid != None and self.rec.programid[:2] != 'MV':
            self.type = 'TV'
            self.log(self.log.GENERAL, self.log.INFO,
                     'Performing TV type migration.')
        else:
            self.type = 'MOVIE'
            self.log(self.log.GENERAL, self.log.INFO,
                     'Performing Movie type migration.')

    def process_fmt(self, fmt):
        # replace fields from viddata

        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)

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

    def set_job_status(self, status):
        self.thisJob.setStatus(status)

    def set_vid_hash(self):
        self.vid.hash = self.vid.getHash()

    def update_vid(self):
        self.vid.update()
Пример #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=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, self.rec.subtitle))
        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 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.inetref:
            # good data is available, use it
            if self.rec.season is not None:
                self.log(self.log.GENERAL, self.log.INFO,
                        'Performing TV export with local data.')
                self.type = 'TV'
            else:
                self.log(self.log.GENERAL, self.log.INFO,
                        'Performing Movie export with local data.')
                self.type = 'MOVIE'
            metadata = self.rec.exportMetadata()
        elif self.opts.listingonly:
            # force use of local data
            if self.rec.subtitle:
                self.log(self.log.GENERAL, self.log.INFO,
                        'Forcing TV export with local data.')
                self.type = 'TV'
            else:
                self.log(self.log.GENERAL, self.log.INFO,
                        'Forcing Movie export with local data.')
                self.type = 'MOVIE'
            metadata = self.rec.exportMetadata()
        else:
            if self.rec.subtitle:
                # subtitle exists, assume tv show
                self.type = 'TV'
                self.log(self.log.GENERAL, self.log.INFO,
                        'Attempting TV export.')
                grab = VideoGrabber(self.type)
                match = grab.sortedSearch(self.rec.title, self.rec.subtitle)
            else:                   # assume movie
                self.type = 'MOVIE'
                self.log(self.log.GENERAL, self.log.INFO,
                        'Attempting Movie export.')
                grab = VideoGrabber(self.type)
                match = grab.sortedSearch(self.rec.title)

            if len(match) == 0:
                # no match found
                self.log(self.log.GENERAL, self.log.INFO,
                        'Falling back to generic export.')
                self.type = 'GENERIC'
                metadata = self.rec.exportMetadata()
            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.GENERAL, self.log.INFO,
                        'Importing content from', match[0].inetref)
                metadata = grab.grabInetref(match[0])

        self.vid.importMetadata(metadata)
        self.log(self.log.GENERAL, self.log.INFO, 'Import complete')

    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(MythLog.GENERAL|MythLog.FILE, MythLog.INFO, "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(Job.RUNNING)
        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.GENERAL|MythLog.FILE, MythLog.INFO, "Transfer Complete",
                            "%d seconds elapsed" % int(time.time()-stime))

        if self.opts.reallysafe:
            if self.job:
                self.job.setComment("Checking file hashes")
            self.log(MythLog.GENERAL|MythLog.FILE, MythLog.INFO, "Checking file hashes.")
            srchash = hashfile(self.rec.open('r'))
            dsthash = hashfile(self.rec.open('r'))
            if srchash != dsthash:
                raise MythError('Source hash (%s) does not match destination hash (%s)' \
                            % (srchash, dsthash))
        elif self.opts.safe:
            self.log(MythLog.GENERAL|MythLog.FILE, MythLog.INFO, "Checking file sizes.")
            be = MythBE(db=self.vid._db)
            try:
                srcsize = be.getSGFile(self.rec.hostname, self.rec.storagegroup, \
                                       self.rec.basename)[1]
                dstsize = be.getSGFile(self.vid.host, 'Videos', self.vid.filename)[1]
            except:
                raise MythError('Could not query file size from backend')
            if srcsize != dstsize:
                raise MythError('Source size (%d) does not match destination size (%d)' \
                            % (srcsize, dstsize))

        if self.job:
            self.job.setComment("Complete - %d seconds elapsed" % \
                            (int(time.time()-stime)))
            self.job.setStatus(Job.FINISHED)

    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 getAll(self):
     for vid in Video.getAllEntries(db=self.db):
         self.add(vid)