def _addDirectory(self, current, tree):
        if not util.vfs.exists(current):
            util.DEBUG_LOG('Creating: {0}'.format(repr(current)))
            util.vfs.mkdirs(current)

        for branch in tree:
            if isinstance(branch, tuple):
                new = util.pathJoin(current, branch[0])
                self._addDirectory(new, branch[1])
            else:
                sub = util.pathJoin(current, branch)
                if util.vfs.exists(sub):
                    continue
                util.DEBUG_LOG('Creating: {0}'.format(util.strRepr(sub)))
                util.vfs.mkdirs(sub)
    def addSongs(self, base, file, sub=None):
        path = util.pathJoin(base, file)

        if util.isDir(path):
            paths = util.vfs.listdir(path)
            sub = sub and (sub + ':' + file) or file
            for p in paths:
                self.addSongs(path, p, sub)
            return

        name, ext = os.path.splitext(file)
        if ext.lower() in util.musicExtensions:
            if sub:
                name = sub + ':' + name

            try:
                DB.Song.get(DB.Song.path == path)
                self.owner.log('Loading Song (exists): [ {0} ]'.format(util.strRepr(name)))
            except DB.peewee.DoesNotExist:
                data = None
                try:
                    data = mutagen.File(path)
                except:
                    util.ERROR()

                if data:
                    duration = data.info.length
                    self.owner.log('Loading Song (new): [ {0} ({1}) ]'.format(util.strRepr(name), data.info.pprint()))
                else:
                    duration = 0
                DB.Song.create(
                    path=path,
                    name=name,
                    duration=duration
                )
    def getSlide(self, path, c, pack=''):
        name, ext = os.path.splitext(c)
        duration = 0
        path = util.pathJoin(path, c)

        try:
            DB.Trivia.get(DB.Trivia.answerPath == path)
            self._callback('Loading Trivia (exists): [ {0} ]'.format(util.strRepr(name)))
        except DB.peewee.DoesNotExist:
            if ext.lower() in util.videoExtensions:
                ttype = 'video'
                parser = hachoir.hachoir_parser.createParser(path)
                metadata = hachoir.hachoir_metadata.extractMetadata(parser)
                durationDT = None
                if metadata:
                    durationDT = metadata.get('duration')
                    duration = durationDT and util.datetimeTotalSeconds(durationDT) or 0
                self._callback('Loading Trivia (video): [ {0} ({1}) ]'.format(util.strRepr(name), durationDT))

            elif ext.lower() in util.imageExtensions:
                ttype = 'fact'
                self._callback('Loading Trivia (single): [ {0} ]'.format(util.strRepr(name)))
            else:
                return

            DB.Trivia.get_or_create(
                    answerPath=path,
                    defaults={
                        'type': ttype,
                        'TID': u'{0}:{1}'.format(pack, name),
                        'name': name,
                        'duration': duration
                    }
                )
    def _fixTriviaSlidesDir(self):
        ts = util.pathJoin(self._contentDirectory, 'Trivia Slides' + util.getSep(self._contentDirectory))
        util.DEBUG_LOG('Checking for the existence of {0}'.format(util.strRepr(ts)))
        if not util.vfs.exists(ts):
            util.DEBUG_LOG("No 'Trivia Slides' directory exists")
            return
        t = util.pathJoin(self._contentDirectory, 'Trivia')
        success = True
        if util.vfs.exists(t):
            success = util.vfs.rmdir(t)

        if success:
            success = util.vfs.rename(ts, t)
        else:
            util.DEBUG_LOG("Failed to remove existing 'Trivia' directory")

        if success:
            util.DEBUG_LOG("Renamed 'Trivia Slides' to 'Trivia'")
        else:
            util.DEBUG_LOG('Failed to rename {0} to {1}'.format(util.strRepr(ts), util.strRepr(t)))
    def createBumpers(self, basePath, model, type_name, sub_name, pct_start, sub_default=''):
        paths = util.vfs.listdir(basePath)
        total = float(len(paths))

        for ct, sub in enumerate(paths):
            pct = pct_start + int((ct/total)*20)
            if not self._callback(pct=pct):
                break

            path = util.pathJoin(basePath, sub)
            if not util.isDir(path):
                continue

            if sub.startswith('_Exclude'):
                util.DEBUG_LOG('SKIPPING EXCLUDED DIR: {0}'.format(util.strRepr(sub)))
                continue

            if util.vfs.exists(util.pathJoin(path, 'system.xml')):  # For ratings
                self.loadRatingSystem(util.pathJoin(path, 'system.xml'))

            type_ = sub.replace(' Bumpers', '')
            self.addBumper(model, sub, path, type_name, sub_name, type_, sub_default)
    def dir(self, sItem):
        if not sItem.dir:
            return []

        try:
            files = util.vfs.listdir(sItem.dir)
            if sItem.random:
                files = random.sample(files, min((sItem.count, len(files))))
            else:
                files = files[:sItem.count]

            return [Video(util.pathJoin(sItem.dir, p), volume=sItem.getLive('volume')).fromModule(sItem) for p in files]
        except:
            util.ERROR()
            return []
    def addBumper(self, model, sub, path, type_name, sub_name, type_, sub_default, sub_val=None, prefix=None):
        for v in util.vfs.listdir(path):
            vpath = util.pathJoin(path, v)

            if util.isDir(vpath):
                if sub_name:
                    if not sub_val:
                        self.addBumper(model, sub, vpath, type_name, sub_name, type_, sub_default, v)
                else:
                    self.addBumper(model, sub, vpath, type_name, sub_name, type_, sub_default, prefix=v)

                continue

            name, ext = os.path.splitext(v)
            is3D = '3D' in name
            if is3D and type_name == 'system':  # Remove tags from rating bumpers
                name = re.sub(CONTENT_3D_RE, '', name).strip()

            isImage = False
            if ext in util.videoExtensions:
                isImage = False
            elif ext in util.imageExtensions:
                isImage = True
            else:
                continue

            name = prefix and (prefix + ':' + name) or name

            defaults = {
                type_name: TYPE_IDS.get(type_, type_),
                'name': name,
                'is3D': is3D,
                'isImage': isImage
            }

            if sub_name:
                sub_val = sub_val or sub_default
                defaults[sub_name] = sub_val
                self.log('Loading {0} ({1} - {2}): [ {3}{4} ]'.format(model.__name__, util.strRepr(sub), sub_val, util.strRepr(name), is3D and ': 3D' or ''))
            else:
                self.log('Loading {0} ({1}): [ {2}{3} ]'.format(model.__name__, util.strRepr(sub), util.strRepr(name), is3D and ': 3D' or ''))

            model.get_or_create(
                path=vpath,
                defaults=defaults
            )
    def dirHandler(self, sItem):
        count = sItem.getLive('count')

        path = sItem.getLive('dir')
        util.DEBUG_LOG('[{0}] Directory x {1}'.format(sItem.typeChar, count))

        if not path:
            util.DEBUG_LOG('    - Empty path!')
            return []

        try:
            files = [f for f in util.vfs.listdir(path) if os.path.splitext(f)[-1].lower() in util.videoExtensions]
            if self.sItem.getLive('filter3D'):
                files = [f for f in files if self.caller.nextQueuedFeature.is3D == util.pathIs3D(f)]
            files = random.sample(files, min((count, len(files))))
            [util.DEBUG_LOG('    - Using: {0}'.format(repr(f))) for f in files] or util.DEBUG_LOG('    - No matching files')
            return [Video(util.pathJoin(path, p), volume=sItem.getLive('volume')).fromModule(sItem) for p in files]
        except:
            util.ERROR()
            return []
    def loadTrivia(self):
        self.logHeading('LOADING TRIVIA')

        basePath = util.pathJoin(self._contentDirectory, 'Trivia')
        paths = util.vfs.listdir(basePath)

        total = float(len(paths))
        for ct, sub in enumerate(paths):
            pct = 20 + int((ct/total)*20)
            if not self._callback(pct=pct):
                break
            path = os.path.join(basePath, sub)
            if util.isDir(path):
                if sub.startswith('_Exclude'):
                    util.DEBUG_LOG('SKIPPING EXCLUDED DIR: {0}'.format(util.strRepr(sub)))
                    continue
            else:
                continue

            self.log('Processing trivia: {0}'.format(util.strRepr(os.path.basename(path))))
            self.triviaDirectoryHandler(path, prefix=sub)
    def __call__(self, basePath, prefix=None):
        hasSlidesXML = False
        slideXML = util.pathJoin(basePath, self._formatXML)
        if util.vfs.exists(slideXML):
            hasSlidesXML = True

        # pack = os.path.basename(basePath.rstrip('\\/'))

        xml = None
        slide = None

        if hasSlidesXML:
            try:
                f = util.vfs.File(slideXML, 'r')
                xml = f.read()
            finally:
                f.close()

            try:
                slides = ET.fromstring(xml)
                slide = slides.find('slide')
            except ET.ParseError:
                util.DEBUG_LOG('Bad slides.xml')
            except:
                util.ERROR()
                slide = None

        if slide:
            rating = self.getNodeAttribute(slide, self._ratingNA[0], self._ratingNA[1]) or ''
            questionRE = (self.getNodeAttribute(slide, self._questionNA[0], self._questionNA[1]) or '').replace('N/A', '')
            clueRE = self.getNodeAttribute(slide, self._clueNA[0], self._clueNA[1]) or ''.replace('N/A', '')
            answerRE = self.getNodeAttribute(slide, self._answerNA[0], self._answerNA[1]) or ''.replace('N/A', '')
        else:
            rating = ''
            questionRE = self._defaultQRegEx
            clueRE = self._defaultCRegEx
            answerRE = self._defaultARegEx

        contents = util.vfs.listdir(basePath)

        trivia = {}

        for c in contents:
            path = util.pathJoin(basePath, c)

            if util.isDir(path):
                self(path, prefix=prefix and (prefix + ':' + c) or c)
                continue

            base, ext = os.path.splitext(c)

            if not ext.lower() in util.imageExtensions:
                if ext.lower() in util.videoExtensions:
                    self.getSlide(basePath, c, prefix)
                continue

            ttype = ''
            clueCount = 0

            if re.search(questionRE, c):
                name = re.split(questionRE, c)[0]
                ttype = 'q'
            elif re.search(answerRE, c):
                name = re.split(answerRE, c)[0]
                ttype = 'a'
            elif re.search(clueRE, c):
                name = re.split(clueRE, c)[0]

                try:
                    clueCount = re.search(clueRE, c).group(1)
                except:
                    pass

                ttype = 'c'
            else:  # A still
                name, ext = os.path.splitext(c)
                # name = re.split(clueRE, c)[0]
                ttype = 'a'

            if name not in trivia:
                trivia[name] = {'q': None, 'c': {}, 'a': None}

            if ttype == 'q' or ttype == 'a':
                trivia[name][ttype] = path
            elif ttype == 'c':
                trivia[name]['c'][clueCount] = path

        for name, data in trivia.items():
            questionPath = data['q']
            answerPath = data['a']

            if not answerPath:
                continue

            if questionPath:
                ttype = 'QA'
                self._callback('Loading Trivia(QA): [ {0} ]'.format(util.strRepr(name)))
            else:
                ttype = 'fact'
                self._callback('Loading Trivia(single): [ {0} ]'.format(util.strRepr(name)))

            defaults = {
                    'type': ttype,
                    'TID': u'{0}:{1}'.format(prefix, name),
                    'name': name,
                    'rating': rating,
                    'questionPath': questionPath
            }

            for ct, key in enumerate(sorted(data['c'].keys())):
                defaults['cluePath{0}'.format(ct)] = data['c'][key]
            try:
                DB.Trivia.get_or_create(
                    answerPath=answerPath,
                    defaults=defaults
                )
            except:
                print repr(data)
                util.ERROR()
    def loadRatingsBumpers(self):
        self.logHeading('LOADING RATINGS BUMPERS')

        basePath = util.pathJoin(self._contentDirectory, 'Ratings Bumpers')

        self.createBumpers(basePath, DB.RatingsBumpers, 'system', 'style', 80, sub_default='Classic')
    def loadVideoBumpers(self):
        self.logHeading('LOADING VIDEO BUMPERS')

        basePath = util.pathJoin(self._contentDirectory, 'Video Bumpers')

        self.createBumpers(basePath, DB.VideoBumpers, 'type', None, 60)
    def loadMusic(self):
        self.logHeading('LOADING MUSIC')

        self.musicHandler(util.pathJoin(self._contentDirectory, 'Music'))
def initialize(path=None, callback=None):
    callback = callback or dummyCallback

    callback(None, 'Creating/updating database...')

    global DB
    global W_DB
    global DBVersion
    global Song
    global Trivia
    global AudioFormatBumpers
    global RatingsBumpers
    global VideoBumpers
    global RatingSystem
    global Rating
    global Trailers
    global WatchedTrivia

    ###########################################################################################
    # Version
    ###########################################################################################
    dbDir = path or util.STORAGE_PATH
    if not util.vfs.exists(dbDir):
        util.vfs.mkdirs(dbDir)

    dbPath = util.pathJoin(dbDir, 'content.db')
    dbExists = util.vfs.exists(dbPath)

    DB = peewee.SqliteDatabase(dbPath)
    W_DB = peewee.SqliteDatabase(util.pathJoin(path or util.STORAGE_PATH, 'watched.db'))

    DB.connect()

    class DBVersion(peewee.Model):
        version = peewee.IntegerField(default=0)

        class Meta:
            database = DB

    DBVersion.create_table(fail_silently=True)

    if dbExists:  # Only check version if we had a DB, otherwise we're creating it fresh
        checkDBVersion(DB)

    ###########################################################################################
    # Content
    ###########################################################################################
    class ContentBase(peewee.Model):
        name = peewee.CharField()
        accessed = peewee.DateTimeField(null=True)
        pack = peewee.TextField(null=True)

        class Meta:
            database = DB

    callback(' - Music')

    class Song(ContentBase):
        rating = peewee.CharField(null=True)
        genre = peewee.CharField(null=True)
        year = peewee.CharField(null=True)

        path = peewee.CharField(unique=True)
        duration = peewee.FloatField(default=0)

    Song.create_table(fail_silently=True)

    callback(' - Tivia')

    class Trivia(ContentBase):
        type = peewee.CharField()

        TID = peewee.CharField(unique=True)

        rating = peewee.CharField(null=True)
        genre = peewee.CharField(null=True)
        year = peewee.CharField(null=True)
        duration = peewee.FloatField(default=0)

        questionPath = peewee.CharField(unique=True, null=True)
        cluePath0 = peewee.CharField(unique=True, null=True)
        cluePath1 = peewee.CharField(unique=True, null=True)
        cluePath2 = peewee.CharField(unique=True, null=True)
        cluePath3 = peewee.CharField(unique=True, null=True)
        cluePath4 = peewee.CharField(unique=True, null=True)
        cluePath5 = peewee.CharField(unique=True, null=True)
        cluePath6 = peewee.CharField(unique=True, null=True)
        cluePath7 = peewee.CharField(unique=True, null=True)
        cluePath8 = peewee.CharField(unique=True, null=True)
        cluePath9 = peewee.CharField(unique=True, null=True)
        answerPath = peewee.CharField(unique=True, null=True)

    Trivia.create_table(fail_silently=True)

    callback(' - AudioFormatBumpers')

    class BumperBase(ContentBase):
        is3D = peewee.BooleanField(default=False)
        isImage = peewee.BooleanField(default=False)
        path = peewee.CharField(unique=True)

    class AudioFormatBumpers(BumperBase):
        format = peewee.CharField()

    AudioFormatBumpers.create_table(fail_silently=True)

    callback(' - RatingsBumpers')

    class RatingsBumpers(BumperBase):
        system = peewee.CharField(default='MPAA')
        style = peewee.CharField(default='Classic')

    RatingsBumpers.create_table(fail_silently=True)

    callback(' - VideoBumpers')

    class VideoBumpers(BumperBase):
        type = peewee.CharField()

        rating = peewee.CharField(null=True)
        genre = peewee.CharField(null=True)
        year = peewee.CharField(null=True)

    VideoBumpers.create_table(fail_silently=True)

    ###########################################################################################
    # Ratings
    ###########################################################################################
    class RatingSystem(peewee.Model):
        name = peewee.CharField()
        context = peewee.CharField(null=True)
        regEx = peewee.CharField()
        regions = peewee.CharField(null=True)

        class Meta:
            database = DB

    RatingSystem.create_table(fail_silently=True)

    class Rating(peewee.Model):
        name = peewee.CharField(unique=True)
        internal = peewee.CharField()
        value = peewee.IntegerField(default=0)
        system = peewee.CharField()

        class Meta:
            database = DB

    Rating.create_table(fail_silently=True)

    ###########################################################################################
    # Watched Database
    ###########################################################################################
    class WatchedBase(peewee.Model):
        WID = peewee.CharField(unique=True)
        watched = peewee.BooleanField(default=False)
        date = peewee.DateTimeField(default=datetime.date(1900, 1, 1))

        class Meta:
            database = W_DB

    class Trailers(WatchedBase):
        source = peewee.CharField()
        rating = peewee.CharField(null=True)
        genres = peewee.CharField(null=True)
        title = peewee.CharField()
        release = peewee.DateTimeField(default=datetime.date(1900, 1, 1))
        url = peewee.CharField(null=True)
        userAgent = peewee.CharField(null=True)
        thumb = peewee.CharField(null=True)
        broken = peewee.BooleanField(default=False)
        is3D = peewee.BooleanField(default=False)
        verified = peewee.BooleanField(default=True)

    Trailers.create_table(fail_silently=True)

    callback(' - Trailers')

    class WatchedTrivia(WatchedBase):
        pass

    WatchedTrivia.create_table(fail_silently=True)

    callback(' - Trivia (watched status)')

    callback(None, 'Database created')

    DB.close()
    def __call__(self, basePath, prefix=None):
        hasSlidesXML = False
        slideXML = util.pathJoin(basePath, self._formatXML)
        if util.vfs.exists(slideXML):
            hasSlidesXML = True

        # pack = os.path.basename(basePath.rstrip('\\/'))

        xml = None
        slide = None

        if hasSlidesXML:
            try:
                f = util.vfs.File(slideXML, 'r')
                xml = f.read()
            finally:
                f.close()

            try:
                slides = ET.fromstring(xml)
                slide = slides.find('slide')
            except ET.ParseError:
                util.DEBUG_LOG('Bad slides.xml')
            except:
                util.ERROR()
                slide = None

        if slide:
            rating = self.getNodeAttribute(slide, self._ratingNA[0],
                                           self._ratingNA[1]) or ''
            questionRE = (self.getNodeAttribute(slide, self._questionNA[0],
                                                self._questionNA[1])
                          or '').replace('N/A', '')
            clueRE = self.getNodeAttribute(slide, self._clueNA[0],
                                           self._clueNA[1]) or ''.replace(
                                               'N/A', '')
            answerRE = self.getNodeAttribute(slide, self._answerNA[0],
                                             self._answerNA[1]) or ''.replace(
                                                 'N/A', '')
        else:
            rating = ''
            questionRE = self._defaultQRegEx
            clueRE = self._defaultCRegEx
            answerRE = self._defaultARegEx

        contents = util.vfs.listdir(basePath)

        trivia = {}

        for c in contents:
            path = util.pathJoin(basePath, c)

            if util.isDir(path):
                self(path, prefix=prefix and (prefix + ':' + c) or c)
                continue

            base, ext = os.path.splitext(c)

            if not ext.lower() in util.imageExtensions:
                if ext.lower() in util.videoExtensions:
                    self.getSlide(basePath, c, prefix)
                continue

            ttype = ''
            clueCount = 0

            if re.search(questionRE, c):
                name = re.split(questionRE, c)[0]
                ttype = 'q'
            elif re.search(answerRE, c):
                name = re.split(answerRE, c)[0]
                ttype = 'a'
            elif re.search(clueRE, c):
                name = re.split(clueRE, c)[0]

                try:
                    clueCount = re.search(clueRE, c).group(1)
                except:
                    pass

                ttype = 'c'
            else:  # A still
                name, ext = os.path.splitext(c)
                # name = re.split(clueRE, c)[0]
                ttype = 'a'

            if name not in trivia:
                trivia[name] = {'q': None, 'c': {}, 'a': None}

            if ttype == 'q' or ttype == 'a':
                trivia[name][ttype] = path
            elif ttype == 'c':
                trivia[name]['c'][clueCount] = path

        for name, data in trivia.items():
            questionPath = data['q']
            answerPath = data['a']

            if not answerPath:
                continue

            if questionPath:
                ttype = 'QA'
                self._callback('Loading Trivia(QA): [ {0} ]'.format(
                    util.strRepr(name)))
            else:
                ttype = 'fact'
                self._callback('Loading Trivia(single): [ {0} ]'.format(
                    util.strRepr(name)))

            defaults = {
                'type': ttype,
                'TID': u'{0}:{1}'.format(prefix, name),
                'name': name,
                'rating': rating,
                'questionPath': questionPath
            }

            for ct, key in enumerate(sorted(data['c'].keys())):
                defaults['cluePath{0}'.format(ct)] = data['c'][key]
            try:
                DB.Trivia.get_or_create(answerPath=answerPath,
                                        defaults=defaults)
            except:
                print repr(data)
                util.ERROR()
    def addBumper(self,
                  model,
                  sub,
                  path,
                  type_name,
                  sub_name,
                  type_,
                  sub_default,
                  sub_val=None,
                  prefix=None):
        for v in util.vfs.listdir(path):
            vpath = util.pathJoin(path, v)

            if util.isDir(vpath):
                if sub_name:
                    if not sub_val:
                        self.addBumper(model, sub, vpath, type_name, sub_name,
                                       type_, sub_default, v)
                else:
                    self.addBumper(model,
                                   sub,
                                   vpath,
                                   type_name,
                                   sub_name,
                                   type_,
                                   sub_default,
                                   prefix=v)

                continue

            name, ext = os.path.splitext(v)
            is3D = '3D' in name
            if is3D and type_name == 'system':  # Remove tags from rating bumpers
                name = re.sub(CONTENT_3D_RE, '', name).strip()

            isImage = False
            if ext in util.videoExtensions:
                isImage = False
            elif ext in util.imageExtensions:
                isImage = True
            else:
                continue

            name = prefix and (prefix + ':' + name) or name

            defaults = {
                type_name: TYPE_IDS.get(type_, type_),
                'name': name,
                'is3D': is3D,
                'isImage': isImage
            }

            if sub_name:
                sub_val = sub_val or sub_default
                defaults[sub_name] = sub_val
                self.log('Loading {0} ({1} - {2}): [ {3}{4} ]'.format(
                    model.__name__, util.strRepr(sub), sub_val,
                    util.strRepr(name), is3D and ': 3D' or ''))
            else:
                self.log('Loading {0} ({1}): [ {2}{3} ]'.format(
                    model.__name__, util.strRepr(sub), util.strRepr(name),
                    is3D and ': 3D' or ''))

            model.get_or_create(path=vpath, defaults=defaults)
def initialize(path=None, callback=None):
    callback = callback or dummyCallback

    callback(None, 'Creating/updating database...')

    global DB
    global W_DB
    global DBVersion
    global Song
    global Trivia
    global AudioFormatBumpers
    global RatingsBumpers
    global VideoBumpers
    global RatingSystem
    global Rating
    global Trailers
    global WatchedTrivia

    ###########################################################################################
    # Version
    ###########################################################################################
    dbDir = path or util.STORAGE_PATH
    if not util.vfs.exists(dbDir):
        util.vfs.mkdirs(dbDir)

    dbPath = util.pathJoin(dbDir, 'content.db')
    dbExists = util.vfs.exists(dbPath)

    DB = peewee.SqliteDatabase(dbPath)
    W_DB = peewee.SqliteDatabase(util.pathJoin(path or util.STORAGE_PATH, 'watched.db'))

    DB.connect()

    class DBVersion(peewee.Model):
        version = peewee.IntegerField(default=0)

        class Meta:
            database = DB

    DBVersion.create_table(fail_silently=True)

    if dbExists:  # Only check version if we had a DB, otherwise we're creating it fresh
        checkDBVersion(DB)

    ###########################################################################################
    # Content
    ###########################################################################################
    class ContentBase(peewee.Model):
        name = peewee.CharField()
        accessed = peewee.DateTimeField(null=True)
        pack = peewee.TextField(null=True)

        class Meta:
            database = DB

    callback(' - Music')

    class Song(ContentBase):
        rating = peewee.CharField(null=True)
        genre = peewee.CharField(null=True)
        year = peewee.CharField(null=True)

        path = peewee.CharField(unique=True)
        duration = peewee.FloatField(default=0)

    Song.create_table(fail_silently=True)

    callback(' - Tivia')

    class Trivia(ContentBase):
        type = peewee.CharField()

        TID = peewee.CharField(unique=True)

        rating = peewee.CharField(null=True)
        genre = peewee.CharField(null=True)
        year = peewee.CharField(null=True)
        duration = peewee.FloatField(default=0)

        questionPath = peewee.CharField(unique=True, null=True)
        cluePath0 = peewee.CharField(unique=True, null=True)
        cluePath1 = peewee.CharField(unique=True, null=True)
        cluePath2 = peewee.CharField(unique=True, null=True)
        cluePath3 = peewee.CharField(unique=True, null=True)
        cluePath4 = peewee.CharField(unique=True, null=True)
        cluePath5 = peewee.CharField(unique=True, null=True)
        cluePath6 = peewee.CharField(unique=True, null=True)
        cluePath7 = peewee.CharField(unique=True, null=True)
        cluePath8 = peewee.CharField(unique=True, null=True)
        cluePath9 = peewee.CharField(unique=True, null=True)
        answerPath = peewee.CharField(unique=True, null=True)

    Trivia.create_table(fail_silently=True)

    callback(' - AudioFormatBumpers')

    class BumperBase(ContentBase):
        is3D = peewee.BooleanField(default=False)
        isImage = peewee.BooleanField(default=False)
        path = peewee.CharField(unique=True)

    class AudioFormatBumpers(BumperBase):
        format = peewee.CharField()

    AudioFormatBumpers.create_table(fail_silently=True)

    callback(' - RatingsBumpers')

    class RatingsBumpers(BumperBase):
        system = peewee.CharField(default='MPAA')
        style = peewee.CharField(default='Classic')

    RatingsBumpers.create_table(fail_silently=True)

    callback(' - VideoBumpers')

    class VideoBumpers(BumperBase):
        type = peewee.CharField()

        rating = peewee.CharField(null=True)
        genre = peewee.CharField(null=True)
        year = peewee.CharField(null=True)

    VideoBumpers.create_table(fail_silently=True)

    ###########################################################################################
    # Ratings
    ###########################################################################################
    class RatingSystem(peewee.Model):
        name = peewee.CharField()
        context = peewee.CharField(null=True)
        regEx = peewee.CharField()
        regions = peewee.CharField(null=True)

        class Meta:
            database = DB

    RatingSystem.create_table(fail_silently=True)

    class Rating(peewee.Model):
        name = peewee.CharField(unique=True)
        internal = peewee.CharField()
        value = peewee.IntegerField(default=0)
        system = peewee.CharField()

        class Meta:
            database = DB

    Rating.create_table(fail_silently=True)

    ###########################################################################################
    # Watched Database
    ###########################################################################################
    class WatchedBase(peewee.Model):
        WID = peewee.CharField(unique=True)
        watched = peewee.BooleanField(default=False)
        date = peewee.DateTimeField(default=datetime.date(1900, 1, 1))

        class Meta:
            database = W_DB

    class Trailers(WatchedBase):
        source = peewee.CharField()
        rating = peewee.CharField(null=True)
        genres = peewee.CharField(null=True)
        title = peewee.CharField()
        release = peewee.DateTimeField(default=datetime.date(1900, 1, 1))
        url = peewee.CharField(null=True)
        userAgent = peewee.CharField(null=True)
        thumb = peewee.CharField(null=True)
        broken = peewee.BooleanField(default=False)
        is3D = peewee.BooleanField(default=False)
        verified = peewee.BooleanField(default=True)

    Trailers.create_table(fail_silently=True)

    callback(' - Trailers')

    class WatchedTrivia(WatchedBase):
        pass

    WatchedTrivia.create_table(fail_silently=True)

    callback(' - Trivia (watched status)')

    callback(None, 'Database created')

    DB.close()
    def loadAudioFormatBumpers(self):
        self.logHeading('LOADING AUDIO FORMAT BUMPERS')

        basePath = util.pathJoin(self._contentDirectory, 'Audio Format Bumpers')

        self.createBumpers(basePath, DB.AudioFormatBumpers, 'format', None, 40)
    def loadVideoBumpers(self):
        self.logHeading('LOADING VIDEO BUMPERS')

        basePath = util.pathJoin(self._contentDirectory, 'Video Bumpers')

        self.createBumpers(basePath, DB.VideoBumpers, 'type', None, 60)
    def loadMusic(self):
        self.logHeading('LOADING MUSIC')

        self.musicHandler(util.pathJoin(self._contentDirectory, 'Music'))