Пример #1
0
def select_audiocodec(isQuery, inFile, tsn=""):
    if inFile[-5:].lower() == ".tivo":
        return "-acodec copy"
    vInfo = video_info(inFile)
    codectype = vInfo["vCodec"]
    codec = config.get_tsn("audio_codec", tsn)
    if not codec:
        # Default, compatible with all TiVo's
        codec = "ac3"
        if vInfo["aCodec"] in ("ac3", "liba52", "mp2"):
            aKbps = vInfo["aKbps"]
            if aKbps == None:
                if not isQuery:
                    aKbps = audio_check(inFile, tsn)
                else:
                    codec = "TBD"
            if aKbps != None and int(aKbps) <= config.getMaxAudioBR(tsn):
                # compatible codec and bitrate, do not reencode audio
                codec = "copy"
    copy_flag = config.get_tsn("copy_ts", tsn)
    copyts = " -copyts"
    if (codec == "copy" and codectype == "mpeg2video" and not copy_flag) or (
        copy_flag and copy_flag.lower() == "false"
    ):
        copyts = ""
    return "-acodec " + codec + copyts
Пример #2
0
def select_audiocodec(isQuery, inFile, tsn=''):
    if inFile[-5:].lower() == '.tivo':
        return '-acodec copy'
    vInfo = video_info(inFile)
    codectype = vInfo['vCodec']
    codec = config.get_tsn('audio_codec', tsn)
    if not codec:
        # Default, compatible with all TiVo's
        codec = 'ac3'
        if vInfo['aCodec'] in ('ac3', 'liba52', 'mp2'):
            aKbps = vInfo['aKbps']
            if aKbps == None:
                if not isQuery:
                    aKbps = audio_check(inFile, tsn)
                else:
                    codec = 'TBD'
            if aKbps != None and int(aKbps) <= config.getMaxAudioBR(tsn):
                # compatible codec and bitrate, do not reencode audio
                codec = 'copy'
    copy_flag = config.get_tsn('copy_ts', tsn)
    copyts = ' -copyts'
    if ((codec == 'copy' and codectype == 'mpeg2video' and not copy_flag) or
        (copy_flag and copy_flag.lower() == 'false')):
        copyts = ''
    return '-acodec ' + codec + copyts
Пример #3
0
def getMind(tsn=None):
    username = config.get_tsn('tivo_username', tsn)
    password = config.get_tsn('tivo_password', tsn)

    if not username or not password:
        raise Exception("tivo_username and tivo_password required")

    return Mind(username, password, tsn)
Пример #4
0
def getMind(tsn=None):
    username = config.get_tsn('tivo_username', tsn)
    password = config.get_tsn('tivo_password', tsn)

    if not username or not password:
        raise Exception("tivo_username and tivo_password required")

    return Mind(username, password, tsn)
Пример #5
0
def tivo_compatible_audio(vInfo, inFile, tsn, mime=''):
    message = (True, '')
    while True:
        codec = vInfo.get('aCodec', '')

        if codec == None:
            debug('No audio stream detected')
            break

        if mime == 'video/mp4':
            if codec not in ('mpeg4aac', 'libfaad', 'mp4a', 'aac',
                             'ac3', 'liba52'):
                message = (False, 'aCodec %s not compatible' % codec)
                break
            if vInfo['aCodec'] in ('mpeg4aac', 'libfaad', 'mp4a', 'aac') and (vInfo['aCh'] == None or vInfo['aCh'] > 2):
                message = (False, 'aCodec %s is only supported with 2 or less channels, the track has %s channels' % (codec, vInfo['aCh']))
                break

            audio_lang = config.get_tsn('audio_lang', tsn)
            if audio_lang:
                if vInfo['mapAudio'][0][0] != select_audiolang(inFile, tsn)[-3:]:
                    message = (False, '%s preferred audio track exists' %
                                      audio_lang)
            break

        if mime == 'video/bif':
            if codec != 'wmav2':
                message = (False, 'aCodec %s not compatible' % codec)

            break

        if inFile[-5:].lower() == '.tivo':
            break

        if mime == 'video/x-tivo-mpeg-ts':
            if codec not in ('ac3', 'liba52', 'mp2', 'aac_latm'):
                message = (False, 'aCodec %s not compatible' % codec)

            break

        if codec not in ('ac3', 'liba52', 'mp2'):
            message = (False, 'aCodec %s not compatible' % codec)
            break

        if (not vInfo['aKbps'] or
            int(vInfo['aKbps']) > config.getMaxAudioBR(tsn)):
            message = (False, '%s kbps exceeds max audio bitrate' %
                              vInfo['aKbps'])
            break

        audio_lang = config.get_tsn('audio_lang', tsn)
        if audio_lang:
            if vInfo['mapAudio'][0][0] != select_audiolang(inFile, tsn)[-3:]:
                message = (False, '%s preferred audio track exists' %
                                  audio_lang)
        break

    return message
Пример #6
0
def tivo_compatible_audio(vInfo, inFile, tsn, mime=""):
    message = (True, "")
    while True:
        codec = vInfo.get("aCodec", "")

        if codec == None:
            debug("No audio stream detected")
            break

        if mime == "video/mp4":
            if codec not in ("mpeg4aac", "libfaad", "mp4a", "aac", "ac3", "liba52"):
                message = (False, "aCodec %s not compatible" % codec)
                break
            if vInfo["aCodec"] in ("mpeg4aac", "libfaad", "mp4a", "aac") and (vInfo["aCh"] == None or vInfo["aCh"] > 2):
                message = (
                    False,
                    "aCodec %s is only supported with 2 or less channels, the track has %s channels"
                    % (codec, vInfo["aCh"]),
                )
                break

            audio_lang = config.get_tsn("audio_lang", tsn)
            if audio_lang:
                if vInfo["mapAudio"][0][0] != select_audiolang(inFile, tsn)[-3:]:
                    message = (False, "%s preferred audio track exists" % audio_lang)
            break

        if mime == "video/bif":
            if codec != "wmav2":
                message = (False, "aCodec %s not compatible" % codec)

            break

        if inFile[-5:].lower() == ".tivo":
            break

        if mime == "video/x-tivo-mpeg-ts":
            if codec not in ("ac3", "liba52", "mp2", "aac_latm"):
                message = (False, "aCodec %s not compatible" % codec)

            break

        if codec not in ("ac3", "liba52", "mp2"):
            message = (False, "aCodec %s not compatible" % codec)
            break

        if not vInfo["aKbps"] or int(vInfo["aKbps"]) > config.getMaxAudioBR(tsn):
            message = (False, "%s kbps exceeds max audio bitrate" % vInfo["aKbps"])
            break

        audio_lang = config.get_tsn("audio_lang", tsn)
        if audio_lang:
            if vInfo["mapAudio"][0][0] != select_audiolang(inFile, tsn)[-3:]:
                message = (False, "%s preferred audio track exists" % audio_lang)
        break

    return message
Пример #7
0
def tivo_compatible_audio(vInfo, inFile, tsn, mime=""):
    message = (True, "")
    while True:
        codec = vInfo["aCodec"]
        if mime == "video/mp4":
            if codec not in ("mpeg4aac", "libfaad", "mp4a", "aac", "ac3", "liba52"):
                message = (False, "aCodec %s not compatible" % codec)

            break

        if mime == "video/bif":
            if codec != "wmav2":
                message = (False, "aCodec %s not compatible" % codec)

            break

        if inFile[-5:].lower() == ".tivo":
            break

        if codec not in ("ac3", "liba52", "mp2"):
            message = (False, "aCodec %s not compatible" % codec)
            break

        if not vInfo["aKbps"] or int(vInfo["aKbps"]) > config.getMaxAudioBR(tsn):
            message = (False, "%s kbps exceeds max audio bitrate" % vInfo["aKbps"])
            break

        audio_lang = config.get_tsn("audio_lang", tsn)
        if audio_lang:
            if vInfo["mapAudio"][0][0] != select_audiolang(inFile, tsn)[-3:]:
                message = (False, "%s preferred audio track exists" % audio_lang)
        break

    return message
Пример #8
0
 def ToGo(self, handler, query):
     togo_path = config.get_server('togo_path')
     for name, data in config.getShares():
         if togo_path == name:
             togo_path = data.get('path')
     if togo_path:
         tivoIP = query['TiVo'][0]
         tsn = config.tivos_by_ip(tivoIP)
         tivo_mak = config.get_tsn('tivo_mak', tsn)
         urls = query.get('Url', [])
         decode = 'decode' in query
         save = 'save' in query
         for theurl in urls:
             status[theurl] = {'running': False, 'error': '', 'rate': '',
                               'queued': True, 'size': 0, 'finished': False,
                               'decode': decode, 'save': save}
             if tivoIP in queue:
                 queue[tivoIP].append(theurl)
             else:
                 queue[tivoIP] = [theurl]
                 thread.start_new_thread(ToGo.process_queue,
                                         (self, tivoIP, tivo_mak, togo_path))
             logger.info('[%s] Queued "%s" for transfer to %s' %
                         (time.strftime('%d/%b/%Y %H:%M:%S'),
                          unquote(theurl), togo_path))
         urlstring = '<br>'.join([unquote(x) for x in urls])
         message = TRANS_QUEUE % (urlstring, togo_path)
     else:
         message = MISSING
     handler.redir(message, 5)
Пример #9
0
def select_audiolang(inFile, tsn):
    vInfo = video_info(inFile)
    audio_lang = config.get_tsn('audio_lang', tsn)
    debug('audio_lang: %s' % audio_lang)
    if vInfo['mapAudio']:
        # default to first detected audio stream to begin with
        stream = vInfo['mapAudio'][0][0]
    if audio_lang != None and vInfo['mapVideo'] != None:
        langmatch_curr = []
        langmatch_prev = vInfo['mapAudio'][:]
        for lang in audio_lang.replace(' ', '').lower().split(','):
            for s, l in langmatch_prev:
                if lang in s + l.replace(' ', '').lower():
                    langmatch_curr.append((s, l))
                    stream = s
            # if only 1 item matched we're done
            if len(langmatch_curr) == 1:
                break
            # if more than 1 item matched copy the curr area to the prev
            # array we only need to look at the new shorter list from
            # now on
            elif len(langmatch_curr) > 1:
                langmatch_prev = langmatch_curr[:]
        # if we drop out of the loop with more than 1 item default to
        # the first item
        if len(langmatch_prev) > 1:
            stream = langmatch_prev[0][0]
    # don't let FFmpeg auto select audio stream, pyTivo defaults to
    # first detected
    if stream:
        debug('selected audio stream: %s' % stream)
        return '-map ' + vInfo['mapVideo'] + ' -map ' + stream
    # if no audio is found
    debug('selected audio stream: None detected')
    return ''
Пример #10
0
def select_audiolang(inFile, tsn):
    vInfo = video_info(inFile)
    audio_lang = config.get_tsn('audio_lang', tsn)
    debug('audio_lang: %s' % audio_lang)
    if vInfo['mapAudio']:
        # default to first detected audio stream to begin with
        stream = vInfo['mapAudio'][0][0]
    if audio_lang != None and vInfo['mapVideo'] != None:
        langmatch_curr = []
        langmatch_prev = vInfo['mapAudio'][:]
        for lang in audio_lang.replace(' ', '').lower().split(','):
            for s, l in langmatch_prev:
                if lang in s + l.replace(' ', '').lower():
                    langmatch_curr.append((s, l))
                    stream = s
            # if only 1 item matched we're done
            if len(langmatch_curr) == 1:
                break
            # if more than 1 item matched copy the curr area to the prev
            # array we only need to look at the new shorter list from
            # now on
            elif len(langmatch_curr) > 1:
                langmatch_prev = langmatch_curr[:]
        # if we drop out of the loop with more than 1 item default to
        # the first item
        if len(langmatch_prev) > 1:
            stream = langmatch_prev[0][0]
    # don't let FFmpeg auto select audio stream, pyTivo defaults to
    # first detected
    if stream:
        debug('selected audio stream: %s' % stream)
        return '-map ' + vInfo['mapVideo'] + ' -map ' + stream
    # if no audio is found
    debug('selected audio stream: None detected')
    return ''
Пример #11
0
def select_audiocodec(isQuery, inFile, tsn='', mime=''):
    if inFile[-5:].lower() == '.tivo':
        return '-acodec copy'
    vInfo = video_info(inFile)
    codectype = vInfo['vCodec']
    codec = config.get_tsn('audio_codec', tsn)
    if not codec:
        # Default, compatible with all TiVo's
        codec = 'ac3'
        if mime == 'video/mp4':
            compatiblecodecs = ('mpeg4aac', 'libfaad', 'mp4a', 'aac',
                                'ac3', 'liba52')
        else:
            compatiblecodecs = ('ac3', 'liba52', 'mp2')

        if vInfo['aCodec'] in compatiblecodecs:
            aKbps = vInfo['aKbps']
            aCh = vInfo['aCh']
            if aKbps == None:
                if vInfo['aCodec'] in ('mpeg4aac', 'libfaad', 'mp4a', 'aac'):
                    # along with the channel check below this should
                    # pass any AAC audio that has undefined 'aKbps' and
                    # is <= 2 channels.  Should be TiVo compatible.
                    codec = 'copy'
                elif not isQuery:
                    vInfoQuery = audio_check(inFile, tsn)
                    if vInfoQuery == None:
                        aKbps = None
                        aCh = None
                    else:
                        aKbps = vInfoQuery['aKbps']
                        aCh = vInfoQuery['aCh']
                else:
                    codec = 'TBA'
            if aKbps and int(aKbps) <= config.getMaxAudioBR(tsn):
                # compatible codec and bitrate, do not reencode audio
                codec = 'copy'
            if vInfo['aCodec'] != 'ac3' and (aCh == None or aCh > 2):
                codec = 'ac3'
    copy_flag = config.get_tsn('copy_ts', tsn)
    copyts = ' -copyts'
    if ((codec == 'copy' and codectype == 'mpeg2video' and not copy_flag) or
        (copy_flag and copy_flag.lower() == 'false')):
        copyts = ''
    return '-acodec ' + codec + copyts
Пример #12
0
def select_audiocodec(isQuery, inFile, tsn='', mime=''):
    if inFile[-5:].lower() == '.tivo':
        return '-acodec copy'
    vInfo = video_info(inFile)
    codectype = vInfo['vCodec']
    codec = config.get_tsn('audio_codec', tsn)
    if not codec:
        # Default, compatible with all TiVo's
        codec = 'ac3'
        if mime == 'video/mp4':
            compatiblecodecs = ('mpeg4aac', 'libfaad', 'mp4a', 'aac', 'ac3',
                                'liba52')
        else:
            compatiblecodecs = ('ac3', 'liba52', 'mp2')

        if vInfo['aCodec'] in compatiblecodecs:
            aKbps = vInfo['aKbps']
            aCh = vInfo['aCh']
            if aKbps == None:
                if vInfo['aCodec'] in ('mpeg4aac', 'libfaad', 'mp4a', 'aac'):
                    # along with the channel check below this should
                    # pass any AAC audio that has undefined 'aKbps' and
                    # is <= 2 channels.  Should be TiVo compatible.
                    codec = 'copy'
                elif not isQuery:
                    vInfoQuery = audio_check(inFile, tsn)
                    if vInfoQuery == None:
                        aKbps = None
                        aCh = None
                    else:
                        aKbps = vInfoQuery['aKbps']
                        aCh = vInfoQuery['aCh']
                else:
                    codec = 'TBA'
            if aKbps and int(aKbps) <= config.getMaxAudioBR(tsn):
                # compatible codec and bitrate, do not reencode audio
                codec = 'copy'
            if vInfo['aCodec'] != 'ac3' and (aCh == None or aCh > 2):
                codec = 'ac3'
    copy_flag = config.get_tsn('copy_ts', tsn)
    copyts = ' -copyts'
    if ((codec == 'copy' and codectype == 'mpeg2video' and not copy_flag)
            or (copy_flag and copy_flag.lower() == 'false')):
        copyts = ''
    return '-acodec ' + codec + copyts
Пример #13
0
def select_videofps(inFile, tsn):
    vInfo = video_info(inFile)
    fps = "-r 29.97"  # default
    if config.isHDtivo(tsn) and vInfo["vFps"] in GOOD_MPEG_FPS:
        fps = " "
    video_fps = config.get_tsn("video_fps", tsn)
    if video_fps != None:
        fps = "-r " + video_fps
    return fps
Пример #14
0
def select_audioch(inFile, tsn):
    ch = config.get_tsn('audio_ch', tsn)
    if ch:
        return '-ac ' + ch
    # AC-3 max channels is 5.1
    if video_info(inFile)['aCh'] > 6:
        debug('Too many audio channels for AC-3, using 5.1 instead')
        return '-ac 6'
    return ''
Пример #15
0
def select_videofps(inFile, tsn):
    vInfo = video_info(inFile)
    fps = '-r 29.97'  # default
    if config.isHDtivo(tsn) and vInfo['vFps'] in GOOD_MPEG_FPS:
        fps = ' '
    video_fps = config.get_tsn('video_fps', tsn)
    if video_fps != None:
        fps = '-r ' + video_fps
    return fps
Пример #16
0
def select_videofps(inFile, tsn):
    vInfo = video_info(inFile)
    fps = '-r 29.97'  # default
    if config.isHDtivo(tsn) and vInfo['vFps'] in GOOD_MPEG_FPS:
        fps = ' '
    video_fps = config.get_tsn('video_fps', tsn)
    if video_fps != None:
        fps = '-r ' + video_fps
    return fps
Пример #17
0
def select_audioch(inFile, tsn):
    ch = config.get_tsn('audio_ch', tsn)
    if ch:
        return '-ac ' + ch
    # AC-3 max channels is 5.1
    if video_info(inFile)['aCh'] > 6:
        debug('Too many audio channels for AC-3, using 5.1 instead')
        return '-ac 6'
    return ''
Пример #18
0
def select_audiofr(inFile, tsn):
    freq = '48000'  # default
    vInfo = video_info(inFile)
    if vInfo['aFreq'] == '44100':
        # compatible frequency
        freq = vInfo['aFreq']
    audio_fr = config.get_tsn('audio_fr', tsn)
    if audio_fr != None:
        freq = audio_fr
    return '-ar ' + freq
Пример #19
0
def select_audiofr(inFile, tsn):
    freq = '48000'  # default
    vInfo = video_info(inFile)
    if vInfo['aFreq'] == '44100':
        # compatible frequency
        freq = vInfo['aFreq']
    audio_fr = config.get_tsn('audio_fr', tsn)
    if audio_fr != None:
        freq = audio_fr
    return '-ar ' + freq
Пример #20
0
def select_audiofr(inFile, tsn):
    freq = "48000"  # default
    vInfo = video_info(inFile)
    if not vInfo["aFreq"] == None and vInfo["aFreq"] in ("44100", "48000"):
        # compatible frequency
        freq = vInfo["aFreq"]
    audio_fr = config.get_tsn("audio_fr", tsn)
    if audio_fr != None:
        freq = audio_fr
    return "-ar " + freq
Пример #21
0
    def __est_size(self, full_path, tsn='', mime=''):
        # Size is estimated by taking audio and video bit rate adding 2%

        if transcode.tivo_compatible(full_path, tsn, mime)[0]:
            return int(os.stat(unicode(full_path, 'utf-8')).st_size)
        else:
            # Must be re-encoded
            if config.get_tsn('audio_codec', tsn) == None:
                audioBPS = config.getMaxAudioBR(tsn) * 1000
            else:
                audioBPS = config.strtod(config.getAudioBR(tsn))
            videoBPS = transcode.select_videostr(full_path, tsn)
            bitrate = audioBPS + videoBPS
            return int(
                (self.__duration(full_path) / 1000) * (bitrate * 1.02 / 8))
Пример #22
0
    def __est_size(self, full_path, tsn='', mime=''):
        # Size is estimated by taking audio and video bit rate adding 2%

        if transcode.tivo_compatible(full_path, tsn, mime)[0]:
            return int(os.stat(unicode(full_path, 'utf-8')).st_size)
        else:
            # Must be re-encoded
            if config.get_tsn('audio_codec', tsn) == None:
                audioBPS = config.getMaxAudioBR(tsn) * 1000
            else:
                audioBPS = config.strtod(config.getAudioBR(tsn))
            videoBPS = transcode.select_videostr(full_path, tsn)
            bitrate =  audioBPS + videoBPS
            return int((self.__duration(full_path) / 1000) *
                       (bitrate * 1.02 / 8))
Пример #23
0
def select_audiolang(inFile, tsn):
    vInfo = video_info(inFile)
    audio_lang = config.get_tsn('audio_lang', tsn)
    if audio_lang != None and vInfo['mapVideo'] != None:
        stream = vInfo['mapAudio'][0][0]
        langmatch = []
        for lang in audio_lang.replace(' ','').lower().split(','):
            for s, l in vInfo['mapAudio']:
                if lang in s + l.replace(' ','').lower():
                    langmatch.append(s)
                    stream = s
                    break
            if langmatch: break
        if stream is not '':
            return '-map ' + vInfo['mapVideo'] + ' -map ' + stream
    return ''
Пример #24
0
def select_audiolang(inFile, tsn):
    vInfo = video_info(inFile)
    audio_lang = config.get_tsn("audio_lang", tsn)
    if audio_lang != None and vInfo["mapVideo"] != None:
        stream = vInfo["mapAudio"][0][0]
        langmatch = []
        for lang in audio_lang.replace(" ", "").lower().split(","):
            for s, l in vInfo["mapAudio"]:
                if lang in s + l.replace(" ", "").lower():
                    langmatch.append(s)
                    stream = s
                    break
            if langmatch:
                break
        if stream is not "":
            return "-map " + vInfo["mapVideo"] + " -map " + stream
    return ""
Пример #25
0
def tivo_compatible_audio(vInfo, inFile, tsn, mime=''):
    message = (True, '')
    while True:
        codec = vInfo.get('aCodec', '')
        if mime == 'video/mp4':
            if codec not in ('mpeg4aac', 'libfaad', 'mp4a', 'aac', 
                             'ac3', 'liba52'):
                message = (False, 'aCodec %s not compatible' % codec)

            break

        if mime == 'video/bif':
            if codec != 'wmav2':
                message = (False, 'aCodec %s not compatible' % codec)

            break

        if inFile[-5:].lower() == '.tivo':
            break

        if mime == 'video/x-tivo-mpeg-ts' and codec not in ('ac3', 'liba52'):
            message = (False, 'aCodec %s not compatible' % codec)
            break

        if codec not in ('ac3', 'liba52', 'mp2'):
            message = (False, 'aCodec %s not compatible' % codec)
            break

        if (not vInfo['aKbps'] or
            int(vInfo['aKbps']) > config.getMaxAudioBR(tsn)):
            message = (False, '%s kbps exceeds max audio bitrate' %
                              vInfo['aKbps'])
            break

        audio_lang = config.get_tsn('audio_lang', tsn)
        if audio_lang:
            if vInfo['mapAudio'][0][0] != select_audiolang(inFile, tsn)[-3:]:
                message = (False, '%s preferred audio track exists' % 
                                  audio_lang)
        break

    return message
Пример #26
0
 def ToGo(self, handler, query):
     togo_path = config.get_server('togo_path')
     for name, data in config.getShares():
         if togo_path == name:
             togo_path = data.get('path')
     if togo_path:
         tivoIP = query['TiVo'][0]
         tsn = config.tivos_by_ip(tivoIP)
         tivo_mak = config.get_tsn('tivo_mak', tsn)
         urls = query.get('Url', [])
         decode = 'decode' in query
         save = 'save' in query
         ts_format = 'ts_format' in query
         for theurl in urls:
             status[theurl] = {
                 'running': False,
                 'error': '',
                 'rate': '',
                 'queued': True,
                 'size': 0,
                 'finished': False,
                 'decode': decode,
                 'save': save,
                 'ts_format': ts_format
             }
             if tivoIP in queue:
                 queue[tivoIP].append(theurl)
             else:
                 queue[tivoIP] = [theurl]
                 thread.start_new_thread(
                     ToGo.process_queue,
                     (self, tivoIP, tivo_mak, togo_path))
             logger.info('[%s] Queued "%s" for transfer to %s' %
                         (time.strftime('%d/%b/%Y %H:%M:%S'),
                          unquote(theurl), togo_path))
         urlstring = '<br>'.join(
             [unicode(unquote(x), 'utf-8') for x in urls])
         message = TRANS_QUEUE % (urlstring, togo_path)
     else:
         message = MISSING
     handler.redir(message, 5)
Пример #27
0
def select_audiolang(inFile, tsn):
    vInfo = video_info(inFile)
    audio_lang = config.get_tsn("audio_lang", tsn)
    debug("audio_lang: %s" % audio_lang)
    if vInfo["mapAudio"]:
        # default to first detected audio stream to begin with
        stream = vInfo["mapAudio"][0][0]
        debug("set first detected audio stream by default: %s" % stream)
    if audio_lang != None and vInfo["mapVideo"] != None:
        langmatch_curr = []
        langmatch_prev = vInfo["mapAudio"][:]
        for lang in audio_lang.replace(" ", "").lower().split(","):
            debug("matching lang: %s" % lang)
            for s, l in langmatch_prev:
                if lang in s + l.replace(" ", "").lower():
                    debug("matched: %s" % s + l.replace(" ", "").lower())
                    langmatch_curr.append((s, l))
            # if only 1 item matched we're done
            if len(langmatch_curr) == 1:
                stream = langmatch_curr[0][0]
                debug("found exactly one match: %s" % stream)
                break
            # if more than 1 item matched copy the curr area to the prev
            # array we only need to look at the new shorter list from
            # now on
            elif len(langmatch_curr) > 1:
                langmatch_prev = langmatch_curr[:]
                # default to the first item matched thus far
                stream = langmatch_curr[0][0]
                debug("remember first match: %s" % stream)
                langmatch_curr = []
    # don't let FFmpeg auto select audio stream, pyTivo defaults to
    # first detected
    if stream:
        debug("selected audio stream: %s" % stream)
        return "-map " + vInfo["mapVideo"] + " -map " + stream
    # if no audio is found
    debug("selected audio stream: None detected")
    return ""
Пример #28
0
def tivo_compatible_audio(vInfo, inFile, tsn, mime=''):
    message = (True, '')
    while True:
        codec = vInfo.get('aCodec', '')

        if codec == None:
            debug('No audio stream detected')
            break

        if inFile[-5:].lower() == '.tivo':
            break

        if mime == 'video/x-tivo-mpeg-ts':
            if codec not in ('ac3', 'liba52', 'mp2', 'aac_latm'):
                message = (False, 'aCodec %s not compatible' % codec)

            break

        if codec not in ('ac3', 'liba52', 'mp2'):
            message = (False, 'aCodec %s not compatible' % codec)
            break

        if (not vInfo['aKbps']
                or int(vInfo['aKbps']) > config.getMaxAudioBR(tsn)):
            message = (False,
                       '%s kbps exceeds max audio bitrate' % vInfo['aKbps'])
            break

        audio_lang = config.get_tsn('audio_lang', tsn)
        if audio_lang:
            if vInfo['mapAudio'][0][0] != select_audiolang(inFile, tsn)[-3:]:
                message = (False,
                           '%s preferred audio track exists' % audio_lang)
        break

    return message
Пример #29
0
    def NPL(self, handler, query):

        def getint(thing):
            try:
                result = int(thing)
            except:
                result = 0
            return result

        global basic_meta
        shows_per_page = 50 # Change this to alter the number of shows returned
        folder = ''
        FirstAnchor = ''
        has_tivodecode = bool(config.get_bin('tivodecode'))
        useragent = handler.headers.getheader('User-Agent', '')

        if 'TiVo' in query:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            tivo_name = config.tivo_names[tsn]
            tivo_mak = config.get_tsn('tivo_mak', tsn)
            theurl = ('https://' + tivoIP +
                      '/TiVoConnect?Command=QueryContainer&ItemCount=' +
                      str(shows_per_page) + '&Container=/NowPlaying')
            if 'Folder' in query:
                folder += query['Folder'][0]
                theurl += '/' + folder
            if 'AnchorItem' in query:
                theurl += '&AnchorItem=' + quote(query['AnchorItem'][0])
            if 'AnchorOffset' in query:
                theurl += '&AnchorOffset=' + query['AnchorOffset'][0]

            if (theurl not in tivo_cache or
                (time.time() - tivo_cache[theurl]['thepage_time']) >= 60):
                # if page is not cached or old then retreive it
                auth_handler.add_password('TiVo DVR', tivoIP, 'tivo', tivo_mak)
                try:
                    page = self.tivo_open(theurl)
                except IOError, e:
                    handler.redir(UNABLE % tivoIP, 10)
                    return
                tivo_cache[theurl] = {'thepage': minidom.parse(page),
                                      'thepage_time': time.time()}
                page.close()

            xmldoc = tivo_cache[theurl]['thepage']
            items = xmldoc.getElementsByTagName('Item')
            TotalItems = tag_data(xmldoc, 'TiVoContainer/Details/TotalItems')
            ItemStart = tag_data(xmldoc, 'TiVoContainer/ItemStart')
            ItemCount = tag_data(xmldoc, 'TiVoContainer/ItemCount')
            title = tag_data(xmldoc, 'TiVoContainer/Details/Title')
            if items:
                FirstAnchor = tag_data(items[0], 'Links/Content/Url')

            data = []
            for item in items:
                entry = {}
                entry['ContentType'] = tag_data(item, 'Details/ContentType')
                for tag in ('CopyProtected', 'UniqueId'):
                    value = tag_data(item, 'Details/' + tag)
                    if value:
                        entry[tag] = value
                if entry['ContentType'] == 'x-tivo-container/folder':
                    entry['Title'] = tag_data(item, 'Details/Title')
                    entry['TotalItems'] = tag_data(item, 'Details/TotalItems')
                    lc = tag_data(item, 'Details/LastCaptureDate')
                    if not lc:
                        lc = tag_data(item, 'Details/LastChangeDate')
                    entry['LastChangeDate'] = time.strftime('%b %d, %Y',
                        time.localtime(int(lc, 16)))
                else:
                    keys = {'Icon': 'Links/CustomIcon/Url',
                            'Url': 'Links/Content/Url',
                            'SourceSize': 'Details/SourceSize',
                            'Duration': 'Details/Duration',
                            'CaptureDate': 'Details/CaptureDate'}
                    for key in keys:
                        value = tag_data(item, keys[key])
                        if value:
                            entry[key] = value

                    rawsize = entry['SourceSize']
                    entry['SourceSize'] = metadata.human_size(rawsize)

                    dur = getint(entry['Duration']) / 1000
                    entry['Duration'] = ( '%d:%02d:%02d' %
                        (dur / 3600, (dur % 3600) / 60, dur % 60) )

                    entry['CaptureDate'] = time.strftime('%b %d, %Y',
                        time.localtime(int(entry['CaptureDate'], 16)))

                    url = entry['Url']
                    if url in basic_meta:
                        entry.update(basic_meta[url])
                    else:
                        basic_data = metadata.from_container(item)
                        entry.update(basic_data)
                        basic_meta[url] = basic_data

                data.append(entry)
Пример #30
0
    def GetShowsList(self, handler, query):
        json_config = {}
        if 'TiVo' in query:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            attrs = config.tivos[tsn]
            tivo_name = attrs.get('name', tivoIP)
            tivo_mak = config.get_tsn('tivo_mak', tsn)

            protocol = attrs.get('protocol', 'https')
            ip_port = '%s:%d' % (tivoIP, attrs.get('port', 443))
            path = attrs.get('path', DEFPATH)
            baseurl = '%s://%s%s' % (protocol, ip_port, path)

            # Get the total item count first
            theurl = baseurl + '&Recurse=Yes&ItemCount=0'
            auth_handler.add_password('TiVo DVR', ip_port, 'tivo', tivo_mak)
            try:
                page = self.tivo_open(theurl)
            except IOError, e:
                handler.send_error(404)
                return

            xmldoc = minidom.parse(page)
            page.close()

            LastChangeDate = unicode(
                tag_data(xmldoc, 'TiVoContainer/Details/LastChangeDate'))

            # Check date of cache
            if (tsn in json_cache
                    and json_cache[tsn]['lastChangeDate'] == LastChangeDate):
                logger.debug("Retrieving shows from cache")
                handler.send_json(json_cache[tsn]['data'])
                return

            global basic_meta
            global details_urls

            # loop through grabbing 50 items at a time (50 is max TiVo will return)
            TotalItems = int(
                unicode(tag_data(xmldoc, 'TiVoContainer/Details/TotalItems')))
            if TotalItems <= 0:
                logger.debug("Total items 0")
                handler.send_json(json_config)
                return

            GotItems = 0
            GeneratedID = 0
            while (GotItems < TotalItems):
                logger.debug("Retrieving shows " + str(GotItems) + "-" +
                             str(GotItems + 50) + " of " + str(TotalItems) +
                             " from " + tivo_name)
                theurl = baseurl + '&Recurse=Yes&ItemCount=50'
                theurl += '&AnchorOffset=%d' % GotItems
                auth_handler.add_password('TiVo DVR', ip_port, 'tivo',
                                          tivo_mak)
                try:
                    page = self.tivo_open(theurl)
                except IOError, e:
                    handler.send_error(404)
                    return

                try:
                    xmldoc = minidom.parse(page)
                    items = xmldoc.getElementsByTagName('Item')
                    page.close()
                except:
                    logger.debug("XML parser error")
                    break

                if len(items) <= 0:
                    logger.debug("items collection empty")
                    break

                for item in items:
                    SeriesID = tag_data(item, 'Details/SeriesId')
                    if (not SeriesID):
                        SeriesID = 'PS%08d' % GeneratedID
                        GeneratedID += 1

                    if (not SeriesID in json_config):
                        json_config[SeriesID] = {}

                    EpisodeID = tag_data(item, 'Details/ProgramId')
                    if (not EpisodeID):
                        EpisodeID = 'PE%08d' % GeneratedID
                        GeneratedID += 1

                    # Check for duplicate episode IDs and replace with generated ID
                    while EpisodeID in json_config[SeriesID]:
                        EpisodeID = 'PE%08d' % GeneratedID
                        GeneratedID += 1

                    json_config[SeriesID][EpisodeID] = {}

                    json_config[SeriesID][EpisodeID]['title'] = tag_data(
                        item, 'Details/Title')
                    json_config[SeriesID][EpisodeID]['url'] = tag_data(
                        item, 'Links/Content/Url')
                    json_config[SeriesID][EpisodeID]['detailsUrl'] = tag_data(
                        item, 'Links/TiVoVideoDetails/Url')
                    json_config[SeriesID][EpisodeID][
                        'episodeTitle'] = tag_data(item,
                                                   'Details/EpisodeTitle')
                    json_config[SeriesID][EpisodeID]['description'] = tag_data(
                        item, 'Details/Description')
                    json_config[SeriesID][EpisodeID]['recordDate'] = tag_data(
                        item, 'Details/CaptureDate')
                    json_config[SeriesID][EpisodeID]['duration'] = tag_data(
                        item, 'Details/Duration')
                    json_config[SeriesID][EpisodeID]['sourceSize'] = tag_data(
                        item, 'Details/SourceSize')
                    json_config[SeriesID][EpisodeID]['channel'] = tag_data(
                        item, 'Details/SourceChannel')
                    json_config[SeriesID][EpisodeID]['stationID'] = tag_data(
                        item, 'Details/SourceStation')
                    json_config[SeriesID][EpisodeID]['episodeID'] = EpisodeID
                    json_config[SeriesID][EpisodeID]['seriesID'] = SeriesID

                    if tag_data(item, 'Details/InProgress') == 'Yes':
                        json_config[SeriesID][EpisodeID]['inProgress'] = True
                    else:
                        json_config[SeriesID][EpisodeID]['inProgress'] = False

                    if tag_data(item, 'Details/CopyProtected') == 'Yes':
                        json_config[SeriesID][EpisodeID]['isProtected'] = True
                    else:
                        json_config[SeriesID][EpisodeID]['isProtected'] = False

                    if tag_data(item, 'Links/CustomIcon/Url'
                                ) == 'urn:tivo:image:suggestion-recording':
                        json_config[SeriesID][EpisodeID]['isSuggestion'] = True
                    else:
                        json_config[SeriesID][EpisodeID][
                            'isSuggestion'] = False

                    if tag_data(item, 'Details/CopyProtected') == 'Yes':
                        json_config[SeriesID][EpisodeID]['icon'] = 'protected'
                    elif tag_data(item, 'Links/CustomIcon/Url'
                                  ) == 'urn:tivo:image:expires-soon-recording':
                        json_config[SeriesID][EpisodeID]['icon'] = 'expiring'
                    elif tag_data(item, 'Links/CustomIcon/Url'
                                  ) == 'urn:tivo:image:expired-recording':
                        json_config[SeriesID][EpisodeID]['icon'] = 'expired'
                    elif tag_data(
                            item, 'Links/CustomIcon/Url'
                    ) == 'urn:tivo:image:save-until-i-delete-recording':
                        json_config[SeriesID][EpisodeID]['icon'] = 'kuid'
                    elif tag_data(item, 'Links/CustomIcon/Url'
                                  ) == 'urn:tivo:image:suggestion-recording':
                        json_config[SeriesID][EpisodeID]['icon'] = 'suggestion'
                    elif tag_data(item, 'Links/CustomIcon/Url'
                                  ) == 'urn:tivo:image:in-progress-recording':
                        json_config[SeriesID][EpisodeID]['icon'] = 'inprogress'
                    else:
                        json_config[SeriesID][EpisodeID]['icon'] = 'normal'

                    url = urlparse.urljoin(
                        baseurl, json_config[SeriesID][EpisodeID]['url'])
                    json_config[SeriesID][EpisodeID]['url'] = url
                    if not url in basic_meta:
                        basic_meta[url] = metadata.from_container(item)
                        if 'detailsUrl' in json_config[SeriesID][EpisodeID]:
                            details_urls[url] = json_config[SeriesID][
                                EpisodeID]['detailsUrl']

                itemCount = tag_data(xmldoc, 'TiVoContainer/ItemCount')
                try:
                    logger.debug("Retrieved " + itemCount + " from " +
                                 tivo_name)
                    GotItems += int(itemCount)
                except ValueError:
                    GotItems += len(items)
Пример #31
0
def select_audioch(tsn):
    ch = config.get_tsn("audio_ch", tsn)
    if ch:
        return "-ac " + ch
    return ""
Пример #32
0
    def NPL(self, handler, query):
        global basic_meta
        shows_per_page = 50  # Change this to alter the number of shows returned
        folder = ''
        has_tivodecode = bool(config.get_bin('tivodecode'))

        if 'TiVo' in query:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            tivo_name = config.tivo_names[tsn]
            tivo_mak = config.get_tsn('tivo_mak', tsn)
            theurl = ('https://' + tivoIP +
                      '/TiVoConnect?Command=QueryContainer&ItemCount=' +
                      str(shows_per_page) + '&Container=/NowPlaying')
            if 'Folder' in query:
                folder += query['Folder'][0]
                theurl += '/' + folder
            if 'AnchorItem' in query:
                theurl += '&AnchorItem=' + quote(query['AnchorItem'][0])
            if 'AnchorOffset' in query:
                theurl += '&AnchorOffset=' + query['AnchorOffset'][0]

            if (theurl not in tivo_cache or
                (time.time() - tivo_cache[theurl]['thepage_time']) >= 60):
                # if page is not cached or old then retreive it
                auth_handler.add_password('TiVo DVR', tivoIP, 'tivo', tivo_mak)
                try:
                    page = self.tivo_open(theurl)
                except IOError, e:
                    handler.redir(UNABLE % tivoIP, 10)
                    return
                tivo_cache[theurl] = {
                    'thepage': minidom.parse(page),
                    'thepage_time': time.time()
                }
                page.close()

            xmldoc = tivo_cache[theurl]['thepage']
            items = xmldoc.getElementsByTagName('Item')
            TotalItems = tag_data(xmldoc, 'Details/TotalItems')
            ItemStart = tag_data(xmldoc, 'ItemStart')
            ItemCount = tag_data(xmldoc, 'ItemCount')
            FirstAnchor = tag_data(items[0], 'Links/Content/Url')

            data = []
            for item in items:
                entry = {}
                entry['ContentType'] = tag_data(item, 'ContentType')
                for tag in ('CopyProtected', 'UniqueId'):
                    value = tag_data(item, tag)
                    if value:
                        entry[tag] = value
                if entry['ContentType'] == 'x-tivo-container/folder':
                    entry['Title'] = tag_data(item, 'Title')
                    entry['TotalItems'] = tag_data(item, 'TotalItems')
                    lc = tag_data(item, 'LastCaptureDate')
                    if not lc:
                        lc = tag_data(item, 'LastChangeDate')
                    entry['LastChangeDate'] = time.strftime(
                        '%b %d, %Y', time.localtime(int(lc, 16)))
                else:
                    keys = {
                        'Icon': 'Links/CustomIcon/Url',
                        'Url': 'Links/Content/Url',
                        'SourceSize': 'Details/SourceSize',
                        'Duration': 'Details/Duration',
                        'CaptureDate': 'Details/CaptureDate'
                    }
                    for key in keys:
                        value = tag_data(item, keys[key])
                        if value:
                            entry[key] = value

                    entry['SourceSize'] = ('%.3f GB' %
                                           (float(entry['SourceSize']) /
                                            (1024**3)))

                    dur = int(entry['Duration']) / 1000
                    entry['Duration'] = ('%02d:%02d:%02d' %
                                         (dur / 3600,
                                          (dur % 3600) / 60, dur % 60))

                    entry['CaptureDate'] = time.strftime(
                        '%b %d, %Y',
                        time.localtime(int(entry['CaptureDate'], 16)))

                    url = entry['Url']
                    if url in basic_meta:
                        entry.update(basic_meta[url])
                    else:
                        basic_data = metadata.from_container(item)
                        entry.update(basic_data)
                        basic_meta[url] = basic_data

                data.append(entry)
Пример #33
0
        try:
            f = open(unicode(path, 'utf-8'), 'rb')
            tivo_header = bytearray(f.read(16))
            if tivo_header[0:4].decode("utf-8") == 'TiVo':
                is_tivo_file = True
                try:
                    if (tivo_header[7] & 0x20 != 0):
                        is_tivo_ts = True
                except Exception, msg:
                    test = 0
                tivo_header_size = struct.unpack_from('>L', tivo_header, 10)[0]
            f.close()
        except:
            pass

        tivo_mak = config.get_tsn('tivo_mak', tsn)
        has_tivolibre = bool(config.get_bin('tivolibre'))
        has_tivodecode = bool(config.get_bin('tivodecode'))

        use_tivolibre = False
        if has_tivolibre and bool(config.get_server('tivolibre_upload', True)):
            use_tivolibre = True

        if 'Format' in query:
            mime = query['Format'][0]

        needs_converion = (((is_tivo_file and is_tivo_ts) or
                            (is_tivo_file and not has_tivolibre))
                           and mime == 'video/mpeg')
        compatible = (not needs_converion
                      and transcode.tivo_compatible(path, tsn, mime)[0])
Пример #34
0
    def NPL(self, handler, query):
        def getint(thing):
            try:
                result = int(thing)
            except:
                result = 0
            return result

        global basic_meta
        global details_urls
        shows_per_page = 50  # Change this to alter the number of shows returned
        folder = ''
        FirstAnchor = ''
        has_tivodecode = bool(config.get_bin('tivodecode'))

        if 'TiVo' in query:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            attrs = config.tivos[tsn]
            tivo_name = attrs.get('name', tivoIP)
            tivo_mak = config.get_tsn('tivo_mak', tsn)

            protocol = attrs.get('protocol', 'https')
            ip_port = '%s:%d' % (tivoIP, attrs.get('port', 443))
            path = attrs.get('path', DEFPATH)
            baseurl = '%s://%s%s' % (protocol, ip_port, path)
            theurl = baseurl
            if 'Folder' in query:
                folder = query['Folder'][0]
                theurl = urlparse.urljoin(theurl, folder)
            theurl += '&ItemCount=%d' % shows_per_page
            if 'AnchorItem' in query:
                theurl += '&AnchorItem=' + quote(query['AnchorItem'][0])
            if 'AnchorOffset' in query:
                theurl += '&AnchorOffset=' + query['AnchorOffset'][0]

            if (theurl not in tivo_cache or
                (time.time() - tivo_cache[theurl]['thepage_time']) >= 60):
                # if page is not cached or old then retreive it
                auth_handler.add_password('TiVo DVR', ip_port, 'tivo',
                                          tivo_mak)
                try:
                    page = self.tivo_open(theurl)
                except IOError, e:
                    handler.redir(UNABLE % (tivoIP, cgi.escape(str(e))), 10)
                    return
                tivo_cache[theurl] = {
                    'thepage': minidom.parse(page),
                    'thepage_time': time.time()
                }
                page.close()

            xmldoc = tivo_cache[theurl]['thepage']
            items = xmldoc.getElementsByTagName('Item')
            TotalItems = tag_data(xmldoc, 'TiVoContainer/Details/TotalItems')
            ItemStart = tag_data(xmldoc, 'TiVoContainer/ItemStart')
            ItemCount = tag_data(xmldoc, 'TiVoContainer/ItemCount')
            title = tag_data(xmldoc, 'TiVoContainer/Details/Title')
            if items:
                FirstAnchor = tag_data(items[0], 'Links/Content/Url')

            data = []
            for item in items:
                entry = {}
                for tag in ('CopyProtected', 'ContentType'):
                    value = tag_data(item, 'Details/' + tag)
                    if value:
                        entry[tag] = value
                if entry['ContentType'].startswith('x-tivo-container'):
                    entry['Url'] = tag_data(item, 'Links/Content/Url')
                    entry['Title'] = tag_data(item, 'Details/Title')
                    entry['TotalItems'] = tag_data(item, 'Details/TotalItems')
                    lc = tag_data(item, 'Details/LastCaptureDate')
                    if not lc:
                        lc = tag_data(item, 'Details/LastChangeDate')
                    entry['LastChangeDate'] = time.strftime(
                        '%b %d, %Y', time.localtime(int(lc, 16)))
                else:
                    keys = {
                        'Icon': 'Links/CustomIcon/Url',
                        'Url': 'Links/Content/Url',
                        'Details': 'Links/TiVoVideoDetails/Url',
                        'SourceSize': 'Details/SourceSize',
                        'Duration': 'Details/Duration',
                        'CaptureDate': 'Details/CaptureDate'
                    }
                    for key in keys:
                        value = tag_data(item, keys[key])
                        if value:
                            entry[key] = value

                    if 'SourceSize' in entry:
                        rawsize = entry['SourceSize']
                        entry['SourceSize'] = metadata.human_size(rawsize)

                    if 'Duration' in entry:
                        dur = getint(entry['Duration']) / 1000
                        entry['Duration'] = ('%d:%02d:%02d' %
                                             (dur / 3600,
                                              (dur % 3600) / 60, dur % 60))

                    if 'CaptureDate' in entry:
                        entry['CaptureDate'] = time.strftime(
                            '%b %d, %Y',
                            time.localtime(int(entry['CaptureDate'], 16)))

                    url = urlparse.urljoin(baseurl, entry['Url'])
                    entry['Url'] = url
                    if url in basic_meta:
                        entry.update(basic_meta[url])
                    else:
                        basic_data = metadata.from_container(item)
                        entry.update(basic_data)
                        basic_meta[url] = basic_data
                        if 'Details' in entry:
                            details_urls[url] = entry['Details']

                data.append(entry)
Пример #35
0
    def ToGo(self, handler, query):
        togo_path = config.get_server('togo_path')
        for name, data in config.getShares():
            if togo_path == name:
                togo_path = data.get('path')
        if togo_path:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            tivo_mak = config.get_tsn('tivo_mak', tsn)
            urls = query.get('Url', [])
            decode = 'decode' in query
            save = 'save' in query

            if 'postprocess' in query:
                postprocess = query['postprocess'][0]
            else:
                postprocess = config.get_server('vrd_post_processing')

            if 'postprocess_profile' in query:
                postprocess_profile = query['postprocess_profile'][0]
            else:
                postprocess_profile = config.get_server('vrd_profile', '')

            postprocess_decrypt = 'postprocess_decrypt' in query
            if not postprocess_decrypt:
                try:
                    postprocess_decrypt = config.config.getboolean(
                        'Server', 'vrd_decrypt_qsf')
                except:
                    postprocess_decrypt = False

            postprocess_delete = 'postprocess_delete' in query
            if not postprocess_delete:
                try:
                    postprocess_delete = config.config.getboolean(
                        'Server', 'vrd_delete_on_success')
                except:
                    postprocess_delete = False

            ts_format = 'ts_format' in query and config.is_ts_capable(tsn)
            for theurl in urls:
                if theurl in status:
                    del status[theurl]

                status[theurl] = {
                    'running':
                    False,
                    'status':
                    '',
                    'error':
                    '',
                    'rate':
                    0,
                    'percent':
                    0,
                    'queued':
                    True,
                    'size':
                    0,
                    'postprocessing':
                    False,
                    'finished':
                    False,
                    'decode':
                    decode,
                    'save':
                    save,
                    'ts_format':
                    ts_format,
                    'postprocess':
                    postprocess,
                    'postprocess_profile':
                    postprocess_profile,
                    'postprocess_decrypt':
                    postprocess_decrypt,
                    'postprocess_delete':
                    postprocess_delete,
                    'retry':
                    0,
                    'ts_max_retries':
                    int(config.get_server('togo_ts_max_retries', 0)),
                    'ts_error_count':
                    0,
                    'best_file':
                    '',
                    'best_error_count':
                    0
                }
                if tivoIP in queue:
                    queue[tivoIP].append(theurl)
                else:
                    queue[tivoIP] = [theurl]
                    thread.start_new_thread(
                        ToGo.process_queue,
                        (self, tivoIP, tivo_mak, togo_path))
                logger.info('[%s] Queued "%s" for transfer to %s' %
                            (time.strftime('%d/%b/%Y %H:%M:%S'),
                             unquote(theurl), togo_path))
            urlstring = '<br>'.join(
                [unicode(unquote(x), 'utf-8') for x in urls])
            message = TRANS_QUEUE % (urlstring, togo_path)
        else:
            message = MISSING
        handler.redir(message, 5)
Пример #36
0
    def send_file(self, handler, path, query):
        global status

        self.cleanup_status() # Keep status object from getting too big

        mime = 'video/x-tivo-mpeg'
        tsn = handler.headers.get('tsn', '')

        try:
            assert(tsn)
            tivo_name = config.tivos[tsn].get('name', tsn)
        except:
            tivo_name = handler.address_string()

        if not tivo_name in status:
            status[tivo_name] = {}

        is_tivo_file = False
        tivo_header_size = 0
        is_tivo_ts = False

        try:
            with open(path, 'rb') as f:
                tivo_header = f.read(16)

            if tivo_header[0:4] == b'TiVo':
                is_tivo_file = True
                tivo_header_size = struct.unpack_from('>L', tivo_header, 10)[0]

                if (tivo_header[7] & 0x20 != 0):
                    is_tivo_ts = True
        except:
            pass

        tivo_mak = config.get_tsn('tivo_mak', tsn)
        has_tivolibre = bool(config.get_bin('tivolibre'))
        has_tivodecode = bool(config.get_bin('tivodecode'))

        use_tivolibre = False
        if has_tivolibre and bool(config.get_server('tivolibre_upload', True)):
            use_tivolibre = True

        if 'Format' in query:
            mime = query['Format'][0]

        needs_tivodecode = (((is_tivo_file and is_tivo_ts) or
                            (is_tivo_file and not has_tivolibre)) and
                           mime == 'video/mpeg')
        compatible = (not needs_tivodecode and
                      transcode.tivo_compatible(path, tsn, mime)[0])

        try:  # "bytes=XXX-"
            offset = int(handler.headers.get('Range')[6:-1])
        except:
            offset = 0

        if needs_tivodecode:
            valid = bool((has_tivodecode or has_tivolibre) and tivo_mak)
        else:
            valid = True

        if valid and offset:
            valid = ((compatible and offset < os.path.getsize(path)) or
                     (not compatible and transcode.is_resumable(path, offset)))

            if status[tivo_name][path]:
                # Don't let the TiVo loop over and over in the same spot
                valid = (offset != status[tivo_name][path]['offset'])
                status[tivo_name][path]['error'] = 'Repeat offset call'

        #faking = (mime in ['video/x-tivo-mpeg-ts', 'video/x-tivo-mpeg'] and
        faking = (mime == 'video/x-tivo-mpeg' and
                  not (is_tivo_file and compatible))
        thead = ''
        if faking:
            thead = self.tivo_header(tsn, path, mime)

        size = os.path.getsize(path) + len(thead)
        if compatible:
            handler.send_response(200)
            handler.send_header('Content-Length', size - offset)
            handler.send_header('Content-Range', 'bytes %d-%d/%d' %
                                (offset, size - offset - 1, size))
        else:
            handler.send_response(206)
            handler.send_header('Transfer-Encoding', 'chunked')
        handler.send_header('Content-Type', mime)
        handler.end_headers()

        logger.info('[%s] Start sending "%s" to %s' %
                    (time.strftime('%d/%b/%Y %H:%M:%S'), path, tivo_name))

        if valid:
            start_time = time.time()
            last_interval = start_time
            now = start_time
            count = 0
            output = 0

            if path in status[tivo_name]:
                status[tivo_name][path]['active'] = True
                status[tivo_name][path]['offset'] = offset
            else:
                status[tivo_name][path] = {'active':        True,
                                           'decrypting':    False,
                                           'transcoding':   False,
                                           'offset':        offset,
                                           'start':         start_time,
                                           'end':           start_time,
                                           'rate':          0,
                                           'size':          size,
                                           'output':        0,
                                           'error':         '',
                                          }

            if compatible:
                logger.debug('"%s" is tivo compatible' % path)
                f = open(path, 'rb')
                tivolibre = None
                if not offset:
                    if faking:
                        handler.wfile.write(thead)
                        count += len(thead)
                        output += len(thead)
                    elif tivo_header_size > 0:
                        block = f.read(tivo_header_size)
                        handler.wfile.write(block)
                        count += len(block)
                        output += len(block)
                try:
                    if is_tivo_file and use_tivolibre:
                        status[tivo_name][path]['decrypting'] = True

                        f.close()
                        tivolibre_path = config.get_bin('tivolibre')
                        tcmd = [tivolibre_path, '-m', tivo_mak, '-i', path]
                        tivolibre = subprocess.Popen(tcmd, stdout=subprocess.PIPE, bufsize=(512 * 1024))
                        f = tivolibre.stdout

                    if offset:
                        if tivolibre:
                            raise Exception('tivolibre does not support offset')
                        offset -= len(thead)
                        f.seek(offset)

                    while True:
                        block = f.read(512 * 1024)
                        if not block:
                            break
                        handler.wfile.write(block)
                        count += len(block)
                        output += len(block)

                        now = time.time()
                        elapsed = now - last_interval
                        if elapsed >= 1:
                            status[tivo_name][path]['rate'] = (count * 8.0) / elapsed
                            status[tivo_name][path]['output'] += count
                            count = 0
                            last_interval = now

                    if tivolibre:
                        tivolibre.wait()

                except Exception as msg:
                    status[tivo_name][path]['error'] = str(msg)
                    if tivolibre:
                        tivolibre.kill()
                        tivolibre.wait()

                    logger.info(msg)

                f.close()
            else:
                logger.debug('"%s" is not tivo compatible' % path)
                status[tivo_name][path]['transcoding'] = True
                if offset:
                    count = transcode.resume_transfer(path, handler.wfile,
                                                      offset, status[tivo_name][path])
                else:
                    count = transcode.transcode(False, path, handler.wfile,
                                                status[tivo_name][path], is_tivo_file,
                                                tsn, mime, thead)

            end_time = time.time()
            elapsed = end_time - status[tivo_name][path]['start']
            rate = count * 8.0 / elapsed    # bits / sec

            status[tivo_name][path]['active'] = False
            status[tivo_name][path]['end'] = end_time
            status[tivo_name][path]['rate'] = rate

            logger.info('[{timestamp:%d/%b/%Y %H:%M:%S}] Done sending "{fname}" to {tivo_name}, '
                        '{mbps[0]:.2f} {mbps[1]}B/s ({num_bytes[0]:.3f} {num_bytes[1]}Bytes / {seconds:.0f} s)'
                        .format(timestamp=datetime.fromtimestamp(end_time),
                                fname=path, tivo_name=tivo_name,
                                num_bytes=prefix_bin_qty(count),
                                mbps=prefix_bin_qty(rate / 8),
                                seconds=elapsed))

        else:
            logger.info('Invalid file "{}" requested by {}'.format(path, tivo_name))

        try:
            if not compatible:
                handler.wfile.write(b'0\r\n\r\n')
            handler.wfile.flush()
        except Exception as msg:
            logger.exception('Exception writing an empty response for an incompatible file')
Пример #37
0
def tivo_compatible_audio(vInfo, inFile, tsn, mime=''):
    message = (True, '')
    while True:
        codec = vInfo.get('aCodec', '')

        if codec == None:
            debug('No audio stream detected')
            break

        if mime == 'video/mp4':
            if codec not in ('mpeg4aac', 'libfaad', 'mp4a', 'aac', 'ac3',
                             'liba52'):
                message = (False, 'aCodec %s not compatible' % codec)
                break
            if vInfo['aCodec'] in ('mpeg4aac', 'libfaad', 'mp4a',
                                   'aac') and (vInfo['aCh'] == None
                                               or vInfo['aCh'] > 2):
                message = (
                    False,
                    'aCodec %s is only supported with 2 or less channels, the track has %s channels'
                    % (codec, vInfo['aCh']))
                break

            audio_lang = config.get_tsn('audio_lang', tsn)
            if audio_lang:
                if vInfo['mapAudio'][0][0] != select_audiolang(inFile,
                                                               tsn)[-3:]:
                    message = (False,
                               '%s preferred audio track exists' % audio_lang)
            break

        if mime == 'video/bif':
            if codec != 'wmav2':
                message = (False, 'aCodec %s not compatible' % codec)

            break

        if inFile[-5:].lower() == '.tivo':
            break

        if mime == 'video/x-tivo-mpeg-ts':
            if codec not in ('ac3', 'liba52', 'mp2', 'aac_latm'):
                message = (False, 'aCodec %s not compatible' % codec)

            break

        if codec not in ('ac3', 'liba52', 'mp2'):
            message = (False, 'aCodec %s not compatible' % codec)
            break

        if (not vInfo['aKbps']
                or int(vInfo['aKbps']) > config.getMaxAudioBR(tsn)):
            message = (False,
                       '%s kbps exceeds max audio bitrate' % vInfo['aKbps'])
            break

        audio_lang = config.get_tsn('audio_lang', tsn)
        if audio_lang:
            if vInfo['mapAudio'][0][0] != select_audiolang(inFile, tsn)[-3:]:
                message = (False,
                           '%s preferred audio track exists' % audio_lang)
        break

    return message
Пример #38
0
    def GetShowsList(handler, query):
        """
        HTTP command handler to return the list of shows on a particular TiVo
        """
        json_config = {}

        if 'TiVo' in query:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            attrs = config.tivos[tsn]
            tivo_name = attrs.get('name', tivoIP)
            tivo_mak = config.get_tsn('tivo_mak', tsn)

            protocol = attrs.get('protocol', 'https')
            ip_port = '%s:%d' % (tivoIP, attrs.get('port', 443))
            path = attrs.get('path', DEFPATH)
            baseurl = '%s://%s%s' % (protocol, ip_port, path)

            # Get the total item count first
            theurl = baseurl + '&Recurse=Yes&ItemCount=0'
            auth_handler.add_password('TiVo DVR', ip_port, 'tivo', tivo_mak)
            logger.debug('GetShowsList: (1) add password for TiVo DVR netloc: %s', ip_port)
            try:
                page = tivo_open(theurl)
            except IOError:
                handler.send_error(404)
                return

            xmldoc = minidom.parse(page)
            page.close()

            LastChangeDate = tag_data(xmldoc, 'TiVoContainer/Details/LastChangeDate')

            # Check date of cache
            if tsn in json_cache and json_cache[tsn]['lastChangeDate'] == LastChangeDate:
                logger.debug("Retrieving shows from cache")
                handler.send_json(json_cache[tsn]['data'])
                return

            # loop through grabbing 50 items at a time (50 is max TiVo will return)
            TotalItems = int(tag_data(xmldoc, 'TiVoContainer/Details/TotalItems'))
            if TotalItems <= 0:
                logger.debug("Total items 0")
                handler.send_json(json_config)
                return

            GotItems = 0
            GeneratedID = 0
            while GotItems < TotalItems:
                logger.debug("Retrieving shows %s-%s of %s from %s",
                             GotItems, GotItems + 50, TotalItems, tivo_name)
                theurl = baseurl + '&Recurse=Yes&ItemCount=50'
                theurl += '&AnchorOffset=%d' % GotItems
                auth_handler.add_password('TiVo DVR', ip_port, 'tivo', tivo_mak)
                logger.debug('GetShowsList: (2) add password for TiVo DVR netloc: %s', ip_port)
                try:
                    page = tivo_open(theurl)
                except IOError:
                    handler.send_error(404)
                    return

                try:
                    xmldoc = minidom.parse(page)
                    items = xmldoc.getElementsByTagName('Item')
                except Exception as e:          # pylint: disable=broad-except
                    logger.error('XML parser error: %s: %s', e.__class__.__name__, e)
                    break
                finally:
                    page.close()

                if len(items) <= 0:
                    logger.debug("items collection empty")
                    break

                for item in items:
                    dnld_url = tag_data(item, 'Links/Content/Url')
                    # the tivo download url seems to always be absolute, so is this necessary?
                    # I'm commenting it out -mjl 7/23/2017
                    #dnld_url = urljoin(baseurl, dnld_url)
                    if not dnld_url in showinfo:
                        showinfo[dnld_url] = ShowInfo().from_tivo_container_item(item)
                    item_showinfo = showinfo[dnld_url]
                    ep_info = item_showinfo.get_tivo_desktop_info()

                    if not ep_info['seriesID']:
                        ep_info['seriesID'] = 'TS%08d' % GeneratedID
                        GeneratedID += 1

                    if not ep_info['episodeID']:
                        ep_info['episodeID'] = 'EP%08d' % GeneratedID
                        GeneratedID += 1

                    if not ep_info['seriesID'] in json_config:
                        json_config[ep_info['seriesID']] = {}

                    # Check for duplicate episode IDs and replace with generated ID
                    while ep_info['episodeID'] in json_config[ep_info['seriesID']]:
                        ep_info['episodeID'] = 'EP%08d' % GeneratedID
                        GeneratedID += 1

                    json_config[ep_info['seriesID']][ep_info['episodeID']] = ep_info

                itemCount = tag_data(xmldoc, 'TiVoContainer/ItemCount')
                try:
                    logger.debug("Retrieved " + itemCount + " from " + tivo_name)
                    GotItems += int(itemCount)
                except ValueError:
                    GotItems += len(items)


            # Cache data for reuse
            json_cache[tsn] = {}
            json_cache[tsn]['data'] = json.dumps(json_config)
            json_cache[tsn]['lastChangeDate'] = LastChangeDate

            handler.send_json(json_cache[tsn]['data'])
        else:
            handler.send_json(json.dumps(json_config))
Пример #39
0
    def NPL(self, handler, query):

        def getint(thing):
            try:
                result = int(thing)
            except:
                result = 0
            return result

        global basic_meta
        global details_urls
        shows_per_page = 50 # Change this to alter the number of shows returned
        folder = ''
        FirstAnchor = ''
        has_tivodecode = bool(config.get_bin('tivodecode'))

        if 'TiVo' in query:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            attrs = config.tivos[tsn]
            tivo_name = attrs.get('name', tivoIP)
            tivo_mak = config.get_tsn('tivo_mak', tsn)

            protocol = attrs.get('protocol', 'https')
            ip_port = '%s:%d' % (tivoIP, attrs.get('port', 443))
            path = attrs.get('path', DEFPATH)
            baseurl = '%s://%s%s' % (protocol, ip_port, path)
            theurl = baseurl
            if 'Folder' in query:
                folder = query['Folder'][0]
                theurl = urlparse.urljoin(theurl, folder)
            theurl += '&ItemCount=%d' % shows_per_page
            if 'AnchorItem' in query:
                theurl += '&AnchorItem=' + quote(query['AnchorItem'][0])
            if 'AnchorOffset' in query:
                theurl += '&AnchorOffset=' + query['AnchorOffset'][0]

            if (theurl not in tivo_cache or
                (time.time() - tivo_cache[theurl]['thepage_time']) >= 60):
                # if page is not cached or old then retreive it
                auth_handler.add_password('TiVo DVR', ip_port, 'tivo', tivo_mak)
                try:
                    page = self.tivo_open(theurl)
                except IOError, e:
                    handler.redir(UNABLE % (tivoIP, cgi.escape(str(e))), 10)
                    return
                tivo_cache[theurl] = {'thepage': minidom.parse(page),
                                      'thepage_time': time.time()}
                page.close()

            xmldoc = tivo_cache[theurl]['thepage']
            items = xmldoc.getElementsByTagName('Item')
            TotalItems = tag_data(xmldoc, 'TiVoContainer/Details/TotalItems')
            ItemStart = tag_data(xmldoc, 'TiVoContainer/ItemStart')
            ItemCount = tag_data(xmldoc, 'TiVoContainer/ItemCount')
            title = tag_data(xmldoc, 'TiVoContainer/Details/Title')
            if items:
                FirstAnchor = tag_data(items[0], 'Links/Content/Url')

            data = []
            for item in items:
                entry = {}
                for tag in ('CopyProtected', 'ContentType'):
                    value = tag_data(item, 'Details/' + tag)
                    if value:
                        entry[tag] = value
                if entry['ContentType'].startswith('x-tivo-container'):
                    entry['Url'] = tag_data(item, 'Links/Content/Url')
                    entry['Title'] = tag_data(item, 'Details/Title')
                    entry['TotalItems'] = tag_data(item, 'Details/TotalItems')
                    lc = tag_data(item, 'Details/LastCaptureDate')
                    if not lc:
                        lc = tag_data(item, 'Details/LastChangeDate')
                    entry['LastChangeDate'] = time.strftime('%b %d, %Y',
                        time.localtime(int(lc, 16)))
                else:
                    keys = {'Icon': 'Links/CustomIcon/Url',
                            'Url': 'Links/Content/Url',
                            'Details': 'Links/TiVoVideoDetails/Url',
                            'SourceSize': 'Details/SourceSize',
                            'Duration': 'Details/Duration',
                            'CaptureDate': 'Details/CaptureDate'}
                    for key in keys:
                        value = tag_data(item, keys[key])
                        if value:
                            entry[key] = value

                    if 'SourceSize' in entry:
                        rawsize = entry['SourceSize']
                        entry['SourceSize'] = metadata.human_size(rawsize)

                    if 'Duration' in entry:
                        dur = getint(entry['Duration']) / 1000
                        entry['Duration'] = ( '%d:%02d:%02d' %
                            (dur / 3600, (dur % 3600) / 60, dur % 60) )

                    if 'CaptureDate' in entry:
                        entry['CaptureDate'] = time.strftime('%b %d, %Y',
                            time.localtime(int(entry['CaptureDate'], 16)))

                    url = urlparse.urljoin(baseurl, entry['Url'])
                    entry['Url'] = url
                    if url in basic_meta:
                        entry.update(basic_meta[url])
                    else:
                        basic_data = metadata.from_container(item)
                        entry.update(basic_data)
                        basic_meta[url] = basic_data
                        if 'Details' in entry:
                            details_urls[url] = entry['Details']

                data.append(entry)
Пример #40
0
    def NPL(handler, query):
        """
        ToGo.NPL returns an html page displaying the now playing list (NPL)
        from a particular TiVo device.
        The query may specify:
        - TiVo: the IPv4 address of the TiVo whose NPL is to be retrieved
        - ItemCount: the number of shows/folders to put on the page (default: 50, max: 50)
        - AnchorItem: the url identifying the 1st item in the retrieved list (default 1st item in folder)
        - AnchorOffset: the offset from the AnchorItem to start the retrieval from (default 0)
        - SortOrder:
        - Recurse:
        """

        def getint(thing):
            try:
                result = int(thing)
            except:                             # pylint: disable=bare-except
                result = 0
            return result


        shows_per_page = 50 # Change this to alter the number of shows returned (max is 50)
        if 'ItemCount' in query:
            shows_per_page = int(query['ItemCount'][0])

        if shows_per_page > 50:
            shows_per_page = 50

        folder = ''
        FirstAnchor = ''
        has_tivodecode = bool(config.get_bin('tivodecode'))
        has_tivolibre = bool(config.get_bin('tivolibre'))

        if 'TiVo' in query:
            tivoIP = query['TiVo'][0]
            try:
                tsn = config.tivos_by_ip(tivoIP)
                attrs = config.tivos[tsn]
                tivo_name = attrs.get('name', tivoIP)
                tivo_mak = config.get_tsn('tivo_mak', tsn)
            except config.Error as e:
                logger.error('NPL: %s', e)
                t = Template(ERROR_TEMPLATE)
                t.e = e
                t.additional_info = 'Your browser may have cached an old page'
                handler.send_html(str(t))
                return

            protocol = attrs.get('protocol', 'https')
            ip_port = '%s:%d' % (tivoIP, attrs.get('port', 443))
            path = attrs.get('path', DEFPATH)
            baseurl = '%s://%s%s' % (protocol, ip_port, path)
            theurl = baseurl
            if 'Folder' in query:
                folder = query['Folder'][0]
                theurl = urljoin(theurl, folder)
            theurl += '&ItemCount=%d' % shows_per_page
            if 'AnchorItem' in query:
                theurl += '&AnchorItem=' + quote(query['AnchorItem'][0])
            if 'AnchorOffset' in query:
                theurl += '&AnchorOffset=' + query['AnchorOffset'][0]
            if 'SortOrder' in query:
                theurl += '&SortOrder=' + query['SortOrder'][0]
            if 'Recurse' in query:
                theurl += '&Recurse=' + query['Recurse'][0]

            if (theurl not in tivo_cache or
                    (time.time() - tivo_cache[theurl]['thepage_time']) >= 60):
                # if page is not cached or old then retrieve it
                auth_handler.add_password('TiVo DVR', ip_port, 'tivo', tivo_mak)
                logger.debug('NPL: (1) add password for TiVo DVR netloc: %s', ip_port)
                try:
                    logger.debug("NPL.theurl: %s", theurl)
                    with tivo_open(theurl) as page:
                        tivo_cache[theurl] = {'thepage': minidom.parse(page),
                                              'thepage_time': time.time()}
                except IOError as e:
                    handler.redir(UNABLE % (tivoIP, html.escape(str(e))), 10)
                    return

            xmldoc = tivo_cache[theurl]['thepage']
            items = xmldoc.getElementsByTagName('Item')

            TotalItems = tag_data(xmldoc, 'TiVoContainer/Details/TotalItems')
            ItemStart = tag_data(xmldoc, 'TiVoContainer/ItemStart')
            ItemCount = tag_data(xmldoc, 'TiVoContainer/ItemCount')
            title = tag_data(xmldoc, 'TiVoContainer/Details/Title')
            if items:
                FirstAnchor = tag_data(items[0], 'Links/Content/Url')

            data = []
            for item in items:
                entry = {}
                for tag in ('CopyProtected', 'ContentType'):
                    value = tag_data(item, 'Details/' + tag)
                    if value:
                        entry[tag] = value
                if entry['ContentType'].startswith('x-tivo-container'):
                    entry['Url'] = tag_data(item, 'Links/Content/Url')
                    entry['Title'] = tag_data(item, 'Details/Title')
                    entry['TotalItems'] = tag_data(item, 'Details/TotalItems')
                    lc = tag_data(item, 'Details/LastCaptureDate')
                    if not lc:
                        lc = tag_data(item, 'Details/LastChangeDate')
                    entry['LastChangeDate'] = time.strftime('%b %d, %Y',
                                                            time.localtime(int(lc, 16)))
                else:
                    keys = {'Icon':         'Links/CustomIcon/Url',
                            'Url':          'Links/Content/Url',
                            'Details':      'Links/TiVoVideoDetails/Url',
                            'SourceSize':   'Details/SourceSize',
                            'Duration':     'Details/Duration',
                            'CaptureDate':  'Details/CaptureDate'}
                    for key in keys:
                        value = tag_data(item, keys[key])
                        if value:
                            entry[key] = value

                    if 'SourceSize' in entry:
                        rawsize = entry['SourceSize']
                        entry['SourceSize'] = metadata.human_size(rawsize)

                    if 'Duration' in entry:
                        dur = getint(entry['Duration']) // 1000
                        entry['Duration'] = ('%d:%02d:%02d' %
                                             (dur // 3600, (dur % 3600) // 60, dur % 60))

                    if 'CaptureDate' in entry:
                        entry['CaptureDate'] = time.strftime('%b %d, %Y',
                                                             time.localtime(int(entry['CaptureDate'], 16)))

                    dnld_url = entry['Url']
                    # the tivo download url seems to always be absolute, so is this necessary?
                    # I'm commenting it out -mjl 7/23/2017
                    #dnld_url = urljoin(baseurl, dnld_url)
                    if not dnld_url in showinfo:
                        showinfo[dnld_url] = ShowInfo()
                        showinfo[dnld_url].from_tivo_container_item(item)

                    entry.update(showinfo[dnld_url].get_old_basicmeta())

                data.append(entry)
        else:
            data = []
            tivoIP = ''
            TotalItems = 0
            ItemStart = 0
            ItemCount = 0
            title = ''
            tsn = ''
            tivo_name = ''

        t = Template(NPL_TEMPLATE)
        t.quote = quote
        t.folder = folder
        t.urlstatus = ToGo.get_urlstatus(tivoIP)
        t.has_tivodecode = has_tivodecode
        t.has_tivolibre = has_tivolibre
        t.togo_mpegts = config.is_ts_capable(tsn)
        t.tname = tivo_name
        t.tivoIP = tivoIP
        t.container = handler.cname
        t.data = data
        t.len = len
        t.TotalItems = getint(TotalItems)
        t.ItemStart = getint(ItemStart)
        t.ItemCount = getint(ItemCount)
        t.FirstAnchor = quote(FirstAnchor)
        t.shows_per_page = shows_per_page
        t.title = title
        handler.send_html(str(t), refresh='300')
Пример #41
0
    def ToGo(handler, query):
        """
        HTTP command handler to download a set of recordings from a Tivo.

        If there is already a thread downloading recordings from that Tivo,
        the new recordings will be appended to the existing download task
        list for that Tivo, otherwise a new task list will be created and
        a thread spawned to process it.
        """
        togo_path = config.get_togo('path')
        for name, data in config.getShares():
            if togo_path == name:
                togo_path = data.get('path')
        if togo_path:
            tivoIP = query['TiVo'][0]
            tsn = config.tivos_by_ip(tivoIP)
            tivo_name = config.tivos[tsn].get('name', tivoIP)
            tivo_mak = config.get_tsn('tivo_mak', tsn)
            urls = query.get('Url', [])
            decode = 'decode' in query
            save = 'save' in query
            ts_format = 'ts_format' in query and config.is_ts_capable(tsn)
            sortable = bool(config.get_togo('sortable_names', False))
            for theurl in urls:

                status = {'url': theurl,
                          'running': False,
                          'queued': True,
                          'finished': False,
                          'showinfo': showinfo[theurl], # metadata information about the show
                          'decode': decode,         # decode the downloaded tivo file
                          'save': save,             # save the tivo file's metadata to a .txt file
                          'ts_format': ts_format,   # download using transport stream otherwise program stream
                          'sortable': sortable,     # name saved tivo file in a sortable manner
                          'error': '',
                          'rate': 0,
                          'size': 0,
                          'retry': 0,
                          'download_attempts': [],  # information about each download attempt (used for sync error log)
                          'ts_error_packets': [],   # list of TS packets w/ sync lost as tuples (packet_no, count)
                          'best_attempt_index': None, # index into download_attempts of the attempt w/ fewest errors
                          'best_file': '',
                          'best_error_count': None} # count of TS packets lost (sync byte was wrong) in 'best_file'

                with active_tivos_lock:
                    if tivoIP in active_tivos:
                        with active_tivos[tivoIP]['lock']:
                            active_tivos[tivoIP]['queue'].append(status)
                    else:
                        # we have to add authentication info again because the
                        # download netloc may be different from that used to
                        # retrieve the list of recordings (and in fact the port
                        # is different, 443 to get the NPL and 80 for downloading).
                        auth_handler.add_password('TiVo DVR', urlsplit(theurl).netloc, 'tivo', tivo_mak)
                        logger.debug('ToGo: add password for TiVo DVR netloc: %s', urlsplit(theurl).netloc)

                        active_tivos[tivoIP] = {'tivoIP': tivoIP,
                                                'lock': RLock(),
                                                'thread': None,
                                                'tivo_name': tivo_name,
                                                'mak': tivo_mak,
                                                'dest_path': togo_path,
                                                'fn_format_info': {'episode': config.get_togo('episode_fn'),
                                                                   'movie': config.get_togo('movie_fn')
                                                                  },
                                                'ts_error_mode': config.get_togo('ts_error_mode', 'ignore'),
                                                'ts_max_retries': int(config.get_togo('ts_max_retries', 0)),
                                                'queue': [status]}

                        active_tivos[tivoIP]['thread'] = TivoDownload(tivoIP, active_tivos, active_tivos_lock, tivo_open)
                        active_tivos[tivoIP]['thread'].start()

                logger.info('[%s] Queued "%s" for transfer to %s',
                            time.strftime('%d/%b/%Y %H:%M:%S'),
                            unquote(theurl), togo_path)
            urlstring = '<br>'.join([unquote(x) for x in urls])
            message = TRANS_QUEUE % (urlstring, togo_path)
        else:
            message = MISSING
        handler.redir(message, 5)
Пример #42
0
def select_audioch(tsn):
    ch = config.get_tsn('audio_ch', tsn)
    if ch:
        return '-ac ' + ch
    return ''