Ticket #13562: mytharchive_python3_compatibility.patch

File mytharchive_python3_compatibility.patch, 42.6 KB (added by rcrdnalor, 4 years ago)

Patch using the configured python version and updates compatibility of mythburn.py to python2 and python3 as well.

  • mythplugins/mytharchive/mytharchive/mythburn.cpp

    diff --git a/mythplugins/mytharchive/mytharchive/mythburn.cpp b/mythplugins/mytharchive/mytharchive/mythburn.cpp
    index 5ef8122904..fadbb2db94 100644
    a b  
    2929#include <mythsystemlegacy.h>
    3030#include <mythmiscutil.h>
    3131#include <exitcodes.h>
     32#include <mythconfig.h>
    3233
    3334// mytharchive
    3435#include "archiveutil.h"
    void MythBurn::runScript() 
    909910        QFile::remove(logDir + "/mythburncancel.lck");
    910911
    911912    createConfigFile(configDir + "/mydata.xml");
    912     commandline = "python " + GetShareDir() + "mytharchive/scripts/mythburn.py";
     913    commandline = PYTHON_EXE;
     914    commandline += " " + GetShareDir() + "mytharchive/scripts/mythburn.py";
    913915    commandline += " -j " + configDir + "/mydata.xml";          // job file
    914916    commandline += " -l " + logDir + "/progress.log";           // progress log
    915917    commandline += " > "  + logDir + "/mythburn.log 2>&1 &";    // Logs
  • mythplugins/mytharchive/mythburn/scripts/mythburn.py

    diff --git a/mythplugins/mytharchive/mythburn/scripts/mythburn.py b/mythplugins/mytharchive/mythburn/scripts/mythburn.py
    index 4f5a96d7ab..bb7f0f5033 100755
    a b  
    22# -*- coding: utf-8 -*-
    33from __future__ import unicode_literals
    44
     5# python 3 doesn't have a unicode type
     6try:
     7    unicode
     8except:
     9    unicode = str
     10
     11# python 3 doesn't have a long type
     12try:
     13    long
     14except:
     15    long = int
     16
     17
    518# mythburn.py
    619# The ported MythBurn scripts which feature:
    720
    from __future__ import unicode_literals 
    4962
    5063
    5164# version of script - change after each update
    52 VERSION="0.1.20131119-1"
     65VERSION="0.2.2020017-1"
    5366
    5467# keep all temporary files for debugging purposes
    5568# set this to True before a first run through when testing
    drivespeed = 0; 
    155168#main menu aspect ratio (4:3 or 16:9)
    156169mainmenuAspectRatio = "16:9"
    157170
    158 #chapter menu aspect ratio (4:3, 16:9 or Video) 
     171#chapter menu aspect ratio (4:3, 16:9 or Video)
    159172#video means same aspect ratio as the video title
    160173chaptermenuAspectRatio = "Video"
    161174
    def encodeMenu(background, tempvideo, music, musiclength, tempmovie, xmlfile, fi 
    505518    command = quoteCmdArg(path_jpeg2yuv[0]) + " -n %s -v0 -I p -f %s -j %s | %s -b 5000 -a %s -v 1 -f 8 -o %s" \
    506519              % (totalframes, framespersecond, quoteCmdArg(background), quoteCmdArg(path_mpeg2enc[0]), aspectratio, quoteCmdArg(tempvideo))
    507520    result = runCommand(command)
    508     if result<>0:
     521    if result!=0:
    509522        fatalError("Failed while running jpeg2yuv - %s" % command)
    510523
    511524    command = quoteCmdArg(path_mplex[0]) + " -f 8 -v 0 -o %s %s %s" % (quoteCmdArg(tempmovie), quoteCmdArg(tempvideo), quoteCmdArg(music))
    512525    result = runCommand(command)
    513     if result<>0:
     526    if result!=0:
    514527        fatalError("Failed while running mplex - %s" % command)
    515528
    516529    if xmlfile != "":
    517530        command = quoteCmdArg(path_spumux[0]) + " -m dvd -s 0 %s < %s > %s" % (quoteCmdArg(xmlfile), quoteCmdArg(tempmovie), quoteCmdArg(finaloutput))
    518531        result = runCommand(command)
    519         if result<>0:
     532        if result!=0:
    520533            fatalError("Failed while running spumux - %s" % command)
    521534    else:
    522535        os.rename(tempmovie, finaloutput)
    def encodeMenu(background, tempvideo, music, musiclength, tempmovie, xmlfile, fi 
    527540            os.remove(tempmovie)
    528541
    529542#############################################################
    530 # Return an xml node from a re-encoding profile xml file for 
     543# Return an xml node from a re-encoding profile xml file for
    531544# a given profile name
    532545
    533546def findEncodingProfile(profile):
    def getLengthOfVideo(index): 
    606619    return duration
    607620
    608621#############################################################
    609 # Gets the audio sample rate and number of channels of a video file 
     622# Gets the audio sample rate and number of channels of a video file
    610623# from its stream info file
    611624
    612625def getAudioParams(folder):
    def getVideoParams(folder): 
    643656    if video.attributes["aspectratio"].value != 'N/A':
    644657        aspect_ratio = video.attributes["aspectratio"].value
    645658    else:
    646         aspect_ratio = "1.77778" 
     659        aspect_ratio = "1.77778"
    647660
    648661    videores = video.attributes["width"].value + 'x' + video.attributes["height"].value
    649662    fps = video.attributes["fps"].value
    def createVideoChapters(itemnum, numofchapters, lengthofvideo, getthumbnails): 
    801814#############################################################
    802815# Creates some fixed length chapter marks
    803816
    804 def createVideoChaptersFixedLength(itemnum, segment, lengthofvideo): 
    805     """Returns chapter marks at cut list ends, 
     817def createVideoChaptersFixedLength(itemnum, segment, lengthofvideo):
     818    """Returns chapter marks at cut list ends,
    806819       or evenly spaced chapters 'segment' seconds through the file"""
    807820
    808821
    def getDefaultParametersFromMythTVDB(): 
    845858    sqlstatement="""SELECT value, data FROM settings WHERE value IN(
    846859                        'DBSchemaVer',
    847860                        'ISO639Language0',
    848                         'ISO639Language1') 
     861                        'ISO639Language1')
    849862                    OR (hostname=%s AND value IN(
    850863                        'VideoStartupDir',
    851864                        'GalleryDir',
    def intelliDraw(drawer, text, font, containerWidth): 
    9941007    #write("containerWidth: %s" % containerWidth)
    9951008    words = text.split()
    9961009    lines = [] # prepare a return argument
    997     lines.append(words) 
     1010    lines.append(words)
    9981011    finished = False
    9991012    line = 0
    10001013    while not finished:
    def intelliDraw(drawer, text, font, containerWidth): 
    10081021            if drawer.textsize(' '.join(thistext),font.getFont())[0] > containerWidth:
    10091022                # this is the heart of the algorithm: we pop words off the current
    10101023                # sentence until the width is ok, then in the next outer loop
    1011                 # we move on to the next sentence. 
     1024                # we move on to the next sentence.
    10121025                if str(thistext).find(' ') != -1:
    10131026                    newline.insert(0,thistext.pop(-1))
    10141027                else:
    def paintButton(draw, bgimage, bgimagemask, node, infoDOM, itemnum, page, 
    11331146#############################################################
    11341147# Paint some theme text on to an image
    11351148
    1136 def paintText(draw, image, text, node, color = None, 
     1149def paintText(draw, image, text, node, color = None,
    11371150              x = None, y = None, width = None, height = None):
    11381151    """Takes a piece of text and draws it onto an image inside a bounding box."""
    11391152    #The text is wider than the width of the bounding box
    11401153
    11411154    if x == None:
    1142         x = getScaledAttribute(node, "x") 
     1155        x = getScaledAttribute(node, "x")
    11431156        y = getScaledAttribute(node, "y")
    11441157        width = getScaledAttribute(node, "w")
    11451158        height = getScaledAttribute(node, "h")
    def paintImage(filename, maskfilename, imageDom, destimage, stretch=True): 
    12301243    (imgw, imgh) = picture.size
    12311244    write("Image (%s, %s) into space of (%s, %s) at (%s, %s)" % (imgw, imgh, w, h, xpos, ypos), False)
    12321245
    1233     # the theme can override the default stretch behaviour 
    1234     if imageDom.hasAttribute("stretch"): 
     1246    # the theme can override the default stretch behaviour
     1247    if imageDom.hasAttribute("stretch"):
    12351248        if imageDom.attributes["stretch"].value == "True":
    12361249            stretch = True
    12371250        else:
    def paintImage(filename, maskfilename, imageDom, destimage, stretch=True): 
    12721285    picture = picture.resize((imgw, imgh))
    12731286    picture = picture.convert("RGBA")
    12741287
    1275     if maskfilename <> None and doesFileExist(maskfilename):
     1288    if maskfilename != None and doesFileExist(maskfilename):
    12761289        maskpicture = Image.open(maskfilename, "r").resize((imgw, imgh))
    12771290        maskpicture = maskpicture.convert("RGBA")
    12781291    else:
    def paintImage(filename, maskfilename, imageDom, destimage, stretch=True): 
    12801293
    12811294    destimage.paste(picture, (xpos, ypos), maskpicture)
    12821295    del picture
    1283     if maskfilename <> None and doesFileExist(maskfilename):
     1296    if maskfilename != None and doesFileExist(maskfilename):
    12841297        del maskpicture
    12851298
    12861299    write ("Added image %s" % filename)
    def paintImage(filename, maskfilename, imageDom, destimage, stretch=True): 
    12941307def checkBoundaryBox(boundarybox, node):
    12951308    # We work out how much space all of our graphics and text are taking up
    12961309    # in a bounding rectangle so that we can use this as an automatic highlight
    1297     # on the DVD menu   
     1310    # on the DVD menu
    12981311    if getText(node.attributes["static"]) == "False":
    12991312        if getScaledAttribute(node, "x") < boundarybox[0]:
    13001313            boundarybox = getScaledAttribute(node, "x"), boundarybox[1], boundarybox[2], boundarybox[3]
    def getFileInformation(file, folder): 
    13891402        if file.attributes["type"].value=="recording":
    13901403            filename = file.attributes["filename"].value
    13911404            try:
    1392                 rec = DB.searchRecorded(basename=os.path.basename(filename)).next()
     1405                rec = next(DB.searchRecorded(basename=os.path.basename(filename)))
    13931406            except StopIteration:
    13941407                fatalError("Failed to get recording details from the DB for %s" % filename)
    13951408
    def getFileInformation(file, folder): 
    14121425    elif file.attributes["type"].value=="recording":
    14131426        filename = file.attributes["filename"].value
    14141427        try:
    1415             rec = DB.searchRecorded(basename=os.path.basename(filename)).next()
     1428            rec = next(DB.searchRecorded(basename=os.path.basename(filename)))
    14161429        except StopIteration:
    14171430            fatalError("Failed to get recording details from the DB for %s" % filename)
    14181431
    def getFileInformation(file, folder): 
    14431456    elif file.attributes["type"].value=="video":
    14441457        filename = file.attributes["filename"].value
    14451458        try:
    1446             vid = MVID.searchVideos(file=filename).next()
     1459            vid = next(MVID.searchVideos(file=filename))
    14471460        except StopIteration:
    14481461            vid = Video.fromFilename(filename)
    14491462
    def getFileInformation(file, folder): 
    14891502
    14901503        data.thumblist = ','.join(thumblist)
    14911504
    1492     for k,v in data.items():
     1505    for k,v in list(data.items()):
    14931506        write( "Node = %s, Data = %s" % (k, v))
    14941507        node = infoDOM.createElement(k)
    14951508        # v may be either an integer. Therefore we have to
    def multiplexMPEGStream(video, audio1, audio2, destination, syncOffset): 
    15881601
    15891602    write("Multiplexing MPEG stream to %s" % destination)
    15901603
    1591     # no need to use a sync offset if projectx was used to demux the streams 
     1604    # no need to use a sync offset if projectx was used to demux the streams
    15921605    if useprojectx:
    15931606        syncOffset = 0
    15941607    else:
    def multiplexMPEGStream(video, audio1, audio2, destination, syncOffset): 
    16631676        write("Checking integrity of subtitle pngs")
    16641677        command = quoteCmdArg(os.path.join(scriptpath, "testsubtitlepngs.sh")) + " " + quoteCmdArg(os.path.dirname(destination) + "/stream.d/spumux.xml")
    16651678        result = runCommand(command)
    1666         if result<>0:
     1679        if result!=0:
    16671680            fatalError("Failed while running testsubtitlepngs.sh - %s" % command)
    16681681
    16691682        write("Running spumux to add subtitles")
    16701683        command = quoteCmdArg(path_spumux[0]) + " -P %s <%s >%s" % (quoteCmdArg(os.path.dirname(destination) + "/stream.d/spumux.xml"), quoteCmdArg(destination), quoteCmdArg(os.path.splitext(destination)[0] + "-sub.mpg"))
    16711684        result = runCommand(command)
    1672         if result<>0:
     1685        if result!=0:
    16731686            nonfatalError("Failed while running spumux.\n"
    16741687                          "Command was - %s.\n"
    16751688                          "Look in the full log to see why it failed" % command)
    def getStreamInformation(filename, xmlFilename, lenMethod): 
    16911704
    16921705    result = runCommand(command)
    16931706
    1694     if result <> 0:
     1707    if result != 0:
    16951708        fatalError("Failed while running mytharchivehelper to get stream information.\n"
    16961709                   "Result: %d, Command was %s" % (result, command))
    16971710
    def runMythtranscode(chanid, starttime, destination, usecutlist, localfile): 
    17301743    """Use mythtranscode to cut commercials and/or clean up an mpeg2 file"""
    17311744
    17321745    try:
    1733         rec = DB.searchRecorded(chanid=chanid, starttime=starttime).next()
     1746        rec = next(DB.searchRecorded(chanid=chanid, starttime=starttime))
    17341747        cutlist = rec.markup.getcutlist()
    17351748    except StopIteration:
    17361749        cutlist = []
    def runMythtranscode(chanid, starttime, destination, usecutlist, localfile): 
    17701783def generateProjectXCutlist(chanid, starttime, folder):
    17711784    """generate cutlist_x.txt for ProjectX"""
    17721785
    1773     rec = DB.searchRecorded(chanid=chanid, starttime=starttime).next()
     1786    rec = next(DB.searchRecorded(chanid=chanid, starttime=starttime))
    17741787    starttime = rec.starttime.utcisoformat()
    17751788    cutlist = rec.markup.getcutlist()
    17761789
    def generateProjectXCutlist(chanid, starttime, folder): 
    17811794            for cut in cutlist:
    17821795                # we need to reverse the cutlist because ProjectX wants to know
    17831796                # the bits to keep not what to cut
    1784                
     1797
    17851798                if i == 0:
    17861799                    if cut[0] != 0:
    17871800                        cutlist_f.write('0\n%d\n' % cut[0])
    def extractVideoFrame(source, destination, seconds): 
    19791992
    19801993        command = "mytharchivehelper -q -q --createthumbnail --infile %s --thumblist '%s' --outfile %s" % (quoteCmdArg(source), seconds, quoteCmdArg(destination))
    19811994        result = runCommand(command)
    1982         if result <> 0:
     1995        if result != 0:
    19831996            fatalError("Failed while running mytharchivehelper to get thumbnails.\n"
    19841997                       "Result: %d, Command was %s" % (result, command))
    19851998    try:
    19861999        myimage=Image.open(destination,"r")
    19872000
    1988         if myimage.format <> "JPEG":
     2001        if myimage.format != "JPEG":
    19892002            write( "Something went wrong with thumbnail capture - " + myimage.format)
    1990             return (0L,0L)
     2003            return (long(0),long(0))
    19912004        else:
    19922005            return myimage.size
    19932006    except IOError:
    1994         return (0L, 0L)
     2007        return (long(0),long(0))
    19952008
    19962009#############################################################
    19972010# Grabs a list of single frames from a file
    def extractVideoFrames(source, destination, thumbList): 
    20032016    command = "mytharchivehelper -q -q --createthumbnail --infile %s --thumblist '%s' --outfile %s" % (quoteCmdArg(source), thumbList, quoteCmdArg(destination))
    20042017    write(command)
    20052018    result = runCommand(command)
    2006     if result <> 0:
     2019    if result != 0:
    20072020        fatalError("Failed while running mytharchivehelper to get thumbnails.\n"
    20082021                   "Result: %d, Command was %s" % (result, command))
    20092022
    def encodeNuvToMPEG2(chanid, starttime, mediafile, destvideofile, folder, profil 
    21172130    profileNode = findEncodingProfile(profile)
    21182131    parameters = profileNode.getElementsByTagName("parameter")
    21192132
    2120     # default values - will be overriden by values from the profile 
     2133    # default values - will be overriden by values from the profile
    21212134    outvideobitrate = "5000k"
    21222135    if videomode == "ntsc":
    21232136        outvideores = "720x480"
    def encodeNuvToMPEG2(chanid, starttime, mediafile, destvideofile, folder, profil 
    21982211    if cpuCount > 1:
    21992212        command += "-threads %d " % cpuCount
    22002213
    2201     command += "-f s16le -ar %s -ac %s -i %s " % (samplerate, channels, quoteCmdArg(os.path.join(folder, "audout"))) 
     2214    command += "-f s16le -ar %s -ac %s -i %s " % (samplerate, channels, quoteCmdArg(os.path.join(folder, "audout")))
    22022215    command += "-f rawvideo -pix_fmt yuv420p -s %s -aspect %s -r %s " % (videores, aspectratio, fps)
    22032216    command += "-i %s " % quoteCmdArg(os.path.join(folder, "vidout"))
    22042217    command += "-aspect %s -r %s " % (aspectratio, fps)
    def runDVDAuthor(): 
    22352248    write( "Starting dvdauthor")
    22362249    checkCancelFlag()
    22372250    result=os.spawnlp(os.P_WAIT, path_dvdauthor[0],path_dvdauthor[1],'-x',os.path.join(getTempPath(),'dvdauthor.xml'))
    2238     if result<>0:
     2251    if result!=0:
    22392252        fatalError("Failed while running dvdauthor. Result: %d" % result)
    22402253    write( "Finished  dvdauthor")
    22412254
    def CreateDVDISO(title): 
    22522265
    22532266    result = runCommand(command)
    22542267
    2255     if result<>0:
     2268    if result!=0:
    22562269        fatalError("Failed while running mkisofs.\n"
    22572270                   "Command was %s" % command)
    22582271
    22592272    write("Finished creating ISO image")
    22602273
    22612274#############################################################
    2262 # Burns the contents of a directory to create a DVD 
     2275# Burns the contents of a directory to create a DVD
    22632276
    22642277
    22652278def BurnDVDISO(title):
    def BurnDVDISO(title): 
    23142327            except:
    23152328              write("Sending command ", action, " to drive failed", False)
    23162329              res = False
    2317             os.close(f) 
    2318         return res 
     2330            os.close(f)
     2331        return res
    23192332    def waitForDrive():
    23202333        tries = 0
    23212334        while drivestatus() == CDROM.CDS_DRIVE_NOT_READY:
    def BurnDVDISO(title): 
    23632376            result = runCommand(command)
    23642377            if result == 0:
    23652378                finished = True
    2366                
     2379
    23672380                # Wait till the drive is not busy any longer
    23682381                f = os.open(dvddrivepath, os.O_RDONLY | os.O_NONBLOCK)
    23692382                busy = True
    def deMultiplexMPEG2File(folder, mediafile, video, audio1, audio2): 
    24272440        command = "mythreplex --demux --fix_sync -t TS -o %s " % quoteCmdArg(folder + "/stream")
    24282441        command += "-v %d " % (video[VIDEO_ID])
    24292442
    2430         if audio1[AUDIO_ID] != -1: 
     2443        if audio1[AUDIO_ID] != -1:
    24312444            if audio1[AUDIO_CODEC] == 'MP2':
    24322445                command += "-a %d " % (audio1[AUDIO_ID])
    24332446            elif audio1[AUDIO_CODEC] == 'AC3':
    def deMultiplexMPEG2File(folder, mediafile, video, audio1, audio2): 
    24352448            elif audio1[AUDIO_CODEC] == 'EAC3':
    24362449                command += "-c %d " % (audio1[AUDIO_ID])
    24372450
    2438         if audio2[AUDIO_ID] != -1: 
     2451        if audio2[AUDIO_ID] != -1:
    24392452            if audio2[AUDIO_CODEC] == 'MP2':
    24402453                command += "-a %d " % (audio2[AUDIO_ID])
    24412454            elif audio2[AUDIO_CODEC] == 'AC3':
    def deMultiplexMPEG2File(folder, mediafile, video, audio1, audio2): 
    24472460        command = "mythreplex --demux --fix_sync -o %s " % quoteCmdArg(folder + "/stream")
    24482461        command += "-v %d " % (video[VIDEO_ID] & 255)
    24492462
    2450         if audio1[AUDIO_ID] != -1: 
     2463        if audio1[AUDIO_ID] != -1:
    24512464            if audio1[AUDIO_CODEC] == 'MP2':
    24522465                command += "-a %d " % (audio1[AUDIO_ID] & 255)
    24532466            elif audio1[AUDIO_CODEC] == 'AC3':
    def deMultiplexMPEG2File(folder, mediafile, video, audio1, audio2): 
    24562469                command += "-c %d " % (audio1[AUDIO_ID] & 255)
    24572470
    24582471
    2459         if audio2[AUDIO_ID] != -1: 
     2472        if audio2[AUDIO_ID] != -1:
    24602473            if audio2[AUDIO_CODEC] == 'MP2':
    24612474                command += "-a %d " % (audio2[AUDIO_ID] & 255)
    24622475            elif audio2[AUDIO_CODEC] == 'AC3':
    def deMultiplexMPEG2File(folder, mediafile, video, audio1, audio2): 
    24702483
    24712484    result = runCommand(command)
    24722485
    2473     if result<>0:
     2486    if result!=0:
    24742487        fatalError("Failed while running mythreplex. Command was %s" % command)
    24752488
    24762489#############################################################
    def runM2VRequantiser(source,destination,factor): 
    24862499    command += " %s "  % M2Vsize0
    24872500    command += " <  %s " % quoteCmdArg(source)
    24882501    command += " >  %s " % quoteCmdArg(destination)
    2489  
     2502
    24902503    write("Running: " + command)
    24912504    result = runCommand(command)
    2492     if result<>0:
     2505    if result!=0:
    24932506        fatalError("Failed while running M2VRequantiser. Command was %s" % command)
    24942507
    24952508    M2Vsize1 = os.path.getsize(destination)
    2496        
     2509
    24972510    write("M2Vsize after requant is  %.2f Mb " % (float(M2Vsize1)/mega))
    24982511    fac1=float(M2Vsize0) / float(M2Vsize1)
    24992512    write("Factor demanded %.5f, achieved %.5f, ratio %.5f " % ( factor, fac1, fac1/factor))
    25002513
    25012514#############################################################
    2502 # Calculates the total size of all the video, audio and menu files 
     2515# Calculates the total size of all the video, audio and menu files
    25032516
    25042517def calculateFileSizes(files):
    25052518    """ Returns the sizes of all video, audio and menu files"""
    def calculateFileSizes(files): 
    25152528        #Process this file
    25162529        file=os.path.join(folder,"stream.mv2")
    25172530        #Get size of vobfile in MBytes
    2518         totalvideosize+=os.path.getsize(file) 
     2531        totalvideosize+=os.path.getsize(file)
    25192532
    25202533        #Get size of audio track 1
    25212534        if doesFileExist(os.path.join(folder,"stream0.ac3")):
    2522             totalaudiosize+=os.path.getsize(os.path.join(folder,"stream0.ac3")) 
     2535            totalaudiosize+=os.path.getsize(os.path.join(folder,"stream0.ac3"))
    25232536        if doesFileExist(os.path.join(folder,"stream0.mp2")):
    2524             totalaudiosize+=os.path.getsize(os.path.join(folder,"stream0.mp2")) 
     2537            totalaudiosize+=os.path.getsize(os.path.join(folder,"stream0.mp2"))
    25252538
    2526         #Get size of audio track 2 if available 
     2539        #Get size of audio track 2 if available
    25272540        if doesFileExist(os.path.join(folder,"stream1.ac3")):
    2528             totalaudiosize+=os.path.getsize(os.path.join(folder,"stream1.ac3")) 
     2541            totalaudiosize+=os.path.getsize(os.path.join(folder,"stream1.ac3"))
    25292542        if doesFileExist(os.path.join(folder,"stream1.mp2")):
    2530             totalaudiosize+=os.path.getsize(os.path.join(folder,"stream1.mp2")) 
     2543            totalaudiosize+=os.path.getsize(os.path.join(folder,"stream1.mp2"))
    25312544
    25322545        # add chapter menu if available
    25332546        if doesFileExist(os.path.join(getTempPath(),"chaptermenu-%s.mpg" % filecount)):
    2534             totalmenusize+=os.path.getsize(os.path.join(getTempPath(),"chaptermenu-%s.mpg" % filecount)) 
     2547            totalmenusize+=os.path.getsize(os.path.join(getTempPath(),"chaptermenu-%s.mpg" % filecount))
    25352548
    25362549        # add details page if available
    25372550        if doesFileExist(os.path.join(getTempPath(),"details-%s.mpg" % filecount)):
    def calculateFileSizes(files): 
    25472560########################################
    25482561#returns total size of bitrate-limited m2v files
    25492562
    2550 def total_mv2_brl(files,rate): 
    2551     tvsize=0 
     2563def total_mv2_brl(files,rate):
     2564    tvsize=0
    25522565    filecount=0
    25532566    for node in files:
    25542567        filecount+=1
    def total_mv2_brl(files,rate): 
    25572570        file=os.path.join(folder,"stream.mv2")
    25582571        progvsize=os.path.getsize(file)
    25592572        progvbitrate=progvsize/progduration
    2560         if progvbitrate>rate : 
     2573        if progvbitrate>rate :
    25612574            tvsize+=progduration*rate
    25622575        else:
    25632576            tvsize+=progvsize
    25642577
    2565     return tvsize   
     2578    return tvsize
    25662579
    25672580#########################################
    2568 # Uses requantiser if available to shrink the video streams so 
     2581# Uses requantiser if available to shrink the video streams so
    25692582# they will fit on a DVD
    25702583
    25712584def performMPEG2Shrink(files,dvdrsize):
    def performMPEG2Shrink(files,dvdrsize): 
    25822595
    25832596    #Subtract the audio, menus and packaging overhead from the size of the disk (we cannot shrink this further)
    25842597    mv2space=((dvdrsize*mega-totalmenusize)/fudge_pack)-totalaudiosize
    2585  
     2598
    25862599    if mv2space<0:
    25872600        fatalError("Audio and menu files are too big. No room for video. Giving up!")
    25882601
    def performMPEG2Shrink(files,dvdrsize): 
    26022615            vsize+=os.path.getsize(file)
    26032616            duration+=getLengthOfVideo(filecount)
    26042617
    2605         #We need to shrink the video files to fit into the space available.  It seems sensible 
    2606         #to do this by imposing a common upper limit on the mean video bit-rate of each recording; 
     2618        #We need to shrink the video files to fit into the space available.  It seems sensible
     2619        #to do this by imposing a common upper limit on the mean video bit-rate of each recording;
    26072620        #this will not further reduce the visual quality of any that were transmitted at lower bit-rates.
    26082621
    2609         #Now find the bit-rate limit by iteration between initially defined upper and lower bounds. 
     2622        #Now find the bit-rate limit by iteration between initially defined upper and lower bounds.
    26102623        #The code is based on 'rtbis' from Numerical Recipes by W H Press et al., CUP.
    2611        
     2624
    26122625        #A small multiple of the average input bit-rate should be ok as the initial upper bound,
    26132626        #(although a fixed value or one related to the max value could be used), and zero as the lower bound.
    26142627        #The function relating bit-rate upper limit to total file size is smooth and monotonic,
    2615         #so there should be no convergence problem. 
    2616      
     2628        #so there should be no convergence problem.
     2629
    26172630        vrLo=0.0
    26182631        vrHi=3.0*float(vsize)/duration
    2619        
     2632
    26202633        vrate=vrLo
    26212634        vrinc=vrHi-vrLo
    26222635        count=0
    def performMPEG2Shrink(files,dvdrsize): 
    26282641            testsize=total_mv2_brl(files,vrtest)
    26292642            if (testsize<mv2space):
    26302643                vrate=vrtest
    2631            
     2644
    26322645        write("vrate %.3f kb/s, testsize %.4f , mv2space %.4f Mb " % ((vrate)/1000.0, (testsize)/mega, (mv2space)/mega) )
    26332646        filecount=0
    26342647        for node in files:
    def createDVDAuthorXML(screensize, numberofitems): 
    27752788        #g4 holds the menu page last displayed
    27762789        pre = dvddom.createElement("pre")
    27772790        pre.appendChild(dvddom.createTextNode("{button=g2*1024;g4=%s;}" % page))
    2778         menupgc.appendChild(pre)   
     2791        menupgc.appendChild(pre)
    27792792
    27802793        vob = dvddom.createElement("vob")
    27812794        vob.setAttribute("file",os.path.join(getTempPath(),"menu-%s.mpg" % page))
    def createDVDAuthorXML(screensize, numberofitems): 
    28332846            elif chaptermenuAspectRatio == "16:9":
    28342847                video.setAttribute("aspect", "16:9")
    28352848                video.setAttribute("widescreen", "nopanscan")
    2836             else: 
     2849            else:
    28372850                # use same aspect ratio as the video
    28382851                if getAspectRatioOfVideo(itemnum) > aspectRatioThreshold:
    28392852                    video.setAttribute("aspect", "16:9")
    def createDVDAuthorXML(screensize, numberofitems): 
    28492862
    28502863                pre = dvddom.createElement("pre")
    28512864                mymenupgc.appendChild(pre)
    2852                 if wantDetailsPage: 
     2865                if wantDetailsPage:
    28532866                    pre.appendChild(dvddom.createTextNode("{button=s7 - 1 * 1024;}"))
    28542867                else:
    28552868                    pre.appendChild(dvddom.createTextNode("{button=s7 * 1024;}"))
    28562869
    28572870                vob = dvddom.createElement("vob")
    28582871                vob.setAttribute("file",os.path.join(getTempPath(),"chaptermenu-%s.mpg" % itemnum))
    2859                 mymenupgc.appendChild(vob)   
     2872                mymenupgc.appendChild(vob)
    28602873
    28612874                #Loop menu forever
    28622875                post = dvddom.createElement("post")
    28632876                post.appendChild(dvddom.createTextNode("jump cell 1;"))
    28642877                mymenupgc.appendChild(post)
    28652878
    2866                 # the first chapter MUST be 00:00:00 if its not dvdauthor adds it which 
     2879                # the first chapter MUST be 00:00:00 if its not dvdauthor adds it which
    28672880                # throws of the chapter selection - so make sure we add it if needed so we
    2868                 # can compensate for it in the chapter selection menu 
     2881                # can compensate for it in the chapter selection menu
    28692882                firstChapter = 0
    28702883                thumblist = createVideoChapters(itemnum, chapters, getLengthOfVideo(itemnum), False)
    28712884                chapterlist = string.split(thumblist, ",")
    def createDVDAuthorXML(screensize, numberofitems): 
    28762889                    #Add this recording to this page's menu...
    28772890                    button = dvddom.createElement("button")
    28782891                    button.setAttribute("name","%s" % x)
    2879                     if wantDetailsPage: 
     2892                    if wantDetailsPage:
    28802893                        button.appendChild(dvddom.createTextNode("jump title %s chapter %s;" % (1, firstChapter + x + 1)))
    28812894                    else:
    28822895                        button.appendChild(dvddom.createTextNode("jump title %s chapter %s;" % (1, firstChapter + x)))
    def createDVDAuthorXML(screensize, numberofitems): 
    29382951                    thumblist = '00:00:00,' + thumblist
    29392952                vob.setAttribute("chapters", thumblist)
    29402953            else:
    2941                 vob.setAttribute("chapters", 
     2954                vob.setAttribute("chapters",
    29422955                    createVideoChaptersFixedLength(itemnum,
    2943                                                    chapterLength, 
     2956                                                   chapterLength,
    29442957                                                   getLengthOfVideo(itemnum)))
    29452958
    29462959            vob.setAttribute("file",os.path.join(getItemTempPath(itemnum),"final.vob"))
    def createDVDAuthorXML(screensize, numberofitems): 
    30063019
    30073020    pre = dvddom.createElement("pre")
    30083021    pre.appendChild(dvddom.createTextNode(dvdcode))
    3009     menupgc.appendChild(pre)   
     3022    menupgc.appendChild(pre)
    30103023
    30113024    if wantIntro:
    30123025        #Menu creation is finished so we know how many pages were created
    def createDVDAuthorXML(screensize, numberofitems): 
    30183031            dvdcode+="jump menu %s;" % (page + 1)
    30193032            if (page>1):
    30203033                dvdcode+=" else "
    3021         dvdcode+="}"       
     3034        dvdcode+="}"
    30223035        vmgm_pre_node.appendChild(dvddom.createTextNode(dvdcode))
    30233036
    30243037    #write(dvddom.toprettyxml())
    def createDVDAuthorXML(screensize, numberofitems): 
    30263039    WriteXMLToFile (dvddom,os.path.join(getTempPath(),"dvdauthor.xml"))
    30273040
    30283041    #Destroy the DOM and free memory
    3029     dvddom.unlink()   
     3042    dvddom.unlink()
    30303043
    30313044#############################################################
    30323045# Creates the DVDAuthor xml file used to create a DVD with no main menu
    def createDVDAuthorXMLNoMenus(screensize, numberofitems): 
    32203233    dvddom.unlink()
    32213234
    32223235#############################################################
    3223 # Creates the directory to hold the preview images for an animated menu 
     3236# Creates the directory to hold the preview images for an animated menu
    32243237
    32253238def createEmptyPreviewFolder(videoitem):
    32263239    previewfolder = os.path.join(getItemTempPath(videoitem), "preview")
    def generateVideoPreview(videoitem, itemonthispage, menuitem, starttime, menulen 
    32643277                #see if this graphics item has a mask
    32653278                if node.hasAttribute("mask"):
    32663279                    imagemaskfilename = getThemeFile(themeName, node.attributes["mask"].value)
    3267                     if node.attributes["mask"].value <> "" and doesFileExist(imagemaskfilename):
     3280                    if node.attributes["mask"].value != "" and doesFileExist(imagemaskfilename):
    32683281                        maskpicture = Image.open(imagemaskfilename,"r").resize((width, height))
    32693282                        maskpicture = maskpicture.convert("RGBA")
    32703283
    def generateVideoPreview(videoitem, itemonthispage, menuitem, starttime, menulen 
    32763289def drawThemeItem(page, itemsonthispage, itemnum, menuitem, bgimage, draw,
    32773290                  bgimagemask, drawmask, highlightcolor, spumuxdom, spunode,
    32783291                  numberofitems, chapternumber, chapterlist):
    3279     """Draws text and graphics onto a dvd menu, called by 
     3292    """Draws text and graphics onto a dvd menu, called by
    32803293       createMenu and createChapterMenu"""
    32813294
    32823295    #Get the XML containing information about this item
    def drawThemeItem(page, itemsonthispage, itemnum, menuitem, bgimage, draw, 
    32873300        fatalError("The info.xml file (%s) doesn't look right" %
    32883301                    os.path.join(getItemTempPath(itemnum),"info.xml"))
    32893302
    3290     #boundarybox holds the max and min dimensions for this item 
     3303    #boundarybox holds the max and min dimensions for this item
    32913304    #so we can auto build a menu highlight box
    32923305    boundarybox = 9999,9999,0,0
    32933306    wantHighlightBox = True
    def drawThemeItem(page, itemsonthispage, itemnum, menuitem, bgimage, draw, 
    33193332
    33203333                # see if an image mask exists
    33213334                maskfilename = None
    3322                 if node.hasAttribute("mask") and node.attributes["mask"].value <> "":
     3335                if node.hasAttribute("mask") and node.attributes["mask"].value != "":
    33233336                    maskfilename = getThemeFile(themeName, node.attributes["mask"].value)
    33243337
    3325                 # if this is a thumb image and is a MythVideo coverart image then preserve 
     3338                # if this is a thumb image and is a MythVideo coverart image then preserve
    33263339                # its aspect ratio unless overriden later by the theme
    33273340                if (node.attributes["filename"].value == "%thumbnail"
    33283341                  and getText(infoDOM.getElementsByTagName("coverfile")[0]) !=""):
    def drawThemeItem(page, itemsonthispage, itemnum, menuitem, bgimage, draw, 
    33663379                button.setAttribute("name","previous")
    33673380                button.setAttribute("x0","%s" % getScaledAttribute(node, "x"))
    33683381                button.setAttribute("y0","%s" % getScaledAttribute(node, "y"))
    3369                 button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") + 
     3382                button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") +
    33703383                                                getScaledAttribute(node, "w")))
    33713384                button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") +
    33723385                                                getScaledAttribute(node, "h")))
    def drawThemeItem(page, itemsonthispage, itemnum, menuitem, bgimage, draw, 
    33903403                button.setAttribute("name","next")
    33913404                button.setAttribute("x0","%s" % getScaledAttribute(node, "x"))
    33923405                button.setAttribute("y0","%s" % getScaledAttribute(node, "y"))
    3393                 button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") + 
     3406                button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") +
    33943407                                                 getScaledAttribute(node, "w")))
    3395                 button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") + 
     3408                button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") +
    33963409                                                 getScaledAttribute(node, "h")))
    33973410                spunode.appendChild(button)
    33983411
    def drawThemeItem(page, itemsonthispage, itemnum, menuitem, bgimage, draw, 
    34113424            button.setAttribute("name","playall")
    34123425            button.setAttribute("x0","%s" % getScaledAttribute(node, "x"))
    34133426            button.setAttribute("y0","%s" % getScaledAttribute(node, "y"))
    3414             button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") + 
     3427            button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") +
    34153428                                             getScaledAttribute(node, "w")))
    34163429            button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") +
    34173430                                             getScaledAttribute(node, "h")))
    def drawThemeItem(page, itemsonthispage, itemnum, menuitem, bgimage, draw, 
    34263439                # draw background if required
    34273440                paintBackground(bgimage, node)
    34283441
    3429                 paintButton(draw, bgimage, bgimagemask, node, infoDOM, 
    3430                             itemnum, page, itemsonthispage, chapternumber, 
     3442                paintButton(draw, bgimage, bgimagemask, node, infoDOM,
     3443                            itemnum, page, itemsonthispage, chapternumber,
    34313444                            chapterlist)
    34323445
    34333446                button = spumuxdom.createElement("button")
    def createMenu(screensize, screendpi, numberofitems): 
    36213634
    36223635        #now that the base background has been made and all the previews generated
    36233636        #we need to add the previews to the background
    3624         #Assumption: We assume that there is nothing in the location of where the items go 
     3637        #Assumption: We assume that there is nothing in the location of where the items go
    36253638        #(ie, no text on the images)
    36263639
    36273640        itemsonthispage = 0
    def createChapterMenu(screensize, screendpi, numberofitems): 
    38133826            chapter+=1
    38143827
    38153828            drawThemeItem(page, itemsperpage, page, menuitem,
    3816                         overlayimage, draw, 
     3829                        overlayimage, draw,
    38173830                        bgimagemask, drawmask, highlightcolor,
    38183831                        spumuxdom, spunode,
    38193832                        999, chapter, chapterlist)
    def createChapterMenu(screensize, screendpi, numberofitems): 
    38733886            aspect_ratio = '2'
    38743887        elif chaptermenuAspectRatio == "16:9":
    38753888            aspect_ratio = '3'
    3876         else: 
     3889        else:
    38773890            if getAspectRatioOfVideo(page) > aspectRatioThreshold:
    38783891                aspect_ratio = '3'
    38793892            else:
    def isMediaAVIFile(file): 
    40434056    return Magic=="RIFF"
    40444057
    40454058#############################################################
    4046 # checks to see if an audio stream need to be converted to ac3 
     4059# checks to see if an audio stream need to be converted to ac3
    40474060
    40484061def processAudio(folder):
    40494062    """encode audio to ac3 for better compression and compatability with NTSC players"""
    def processFile(file, folder, count): 
    44544467
    44554468#############################################################
    44564469# process a single file ready for burning using mythtranscode/mythreplex
    4457 # to cut and demux 
     4470# to cut and demux
    44584471
    44594472def doProcessFile(file, folder, count):
    44604473    """Process a single video/recording file ready for burning."""
    def doProcessFile(file, folder, count): 
    45104523                    write("Failed to run mythtranscode to remove unwanted segments")
    45114524            else:
    45124525                #does the user always want to run recordings through mythtranscode?
    4513                 #may help to fix any errors in the file 
    4514                 if (alwaysRunMythtranscode == True or 
     4526                #may help to fix any errors in the file
     4527                if (alwaysRunMythtranscode == True or
    45154528                        (getFileType(folder) == "mpegts" and isFileOkayForDVD(file, folder))):
    45164529                    # Run from local file?
    45174530                    if file.hasAttribute("localfilename"):
    def doProcessFile(file, folder, count): 
    45274540                        write("Failed to run mythtranscode to fix any errors")
    45284541    else:
    45294542        #does the user always want to run mpeg2 files through mythtranscode?
    4530         #may help to fix any errors in the file 
     4543        #may help to fix any errors in the file
    45314544        write("File type is '%s'" % getFileType(folder))
    45324545        write("Video codec is '%s'" % getVideoCodec(folder))
    45334546
    def doProcessFile(file, folder, count): 
    45794592                mediafile = -1
    45804593                chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
    45814594                starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
    4582                 usecutlist = (file.attributes["usecutlist"].value == "1" and 
     4595                usecutlist = (file.attributes["usecutlist"].value == "1" and
    45834596                            getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes")
    45844597            else:
    45854598                chanid = -1
    def doProcessFile(file, folder, count): 
    46124625            else:
    46134626                profile = defaultEncodingProfile
    46144627
    4615             #do the re-encode 
     4628            #do the re-encode
    46164629            encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video,
    46174630                            audio1, audio2, aspectratio, profile)
    46184631            mediafile = os.path.join(folder, 'newfile2.mpg')
    def doProcessFileProjectX(file, folder, count): 
    46774690
    46784691    #As part of this routine we need to pre-process the video this MAY mean:
    46794692    #1. encoding to mpeg2 (if its an avi for instance or isn't DVD compatible)
    4680     #2. removing commercials/cleaning up mpeg2 stream 
     4693    #2. removing commercials/cleaning up mpeg2 stream
    46814694    #3. selecting audio track(s) to use and encoding audio from mp2 into ac3
    46824695    #4. de-multiplexing into video and audio steams
    46834696
    def doProcessFileProjectX(file, folder, count): 
    47334746                mediafile = -1
    47344747                chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
    47354748                starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
    4736                 usecutlist = (file.attributes["usecutlist"].value == "1" and 
     4749                usecutlist = (file.attributes["usecutlist"].value == "1" and
    47374750                            getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes")
    47384751            else:
    47394752                chanid = -1
    def doProcessFileProjectX(file, folder, count): 
    47664779            else:
    47674780                profile = defaultEncodingProfile
    47684781
    4769             #do the re-encode 
     4782            #do the re-encode
    47704783            encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video,
    47714784                            audio1, audio2, aspectratio, profile)
    47724785            mediafile = os.path.join(folder, 'newfile2.mpg')
    def doProcessFileProjectX(file, folder, count): 
    47874800    # now attempt to split the source file into video and audio parts
    47884801    # using projectX
    47894802
    4790     # If this is an mpeg2 myth recording and there is a cut list available and the 
     4803    # If this is an mpeg2 myth recording and there is a cut list available and the
    47914804    # user wants to use it run projectx to cut out commercials etc
    47924805    if file.attributes["type"].value == "recording":
    47934806        if file.attributes["usecutlist"].value == "1" and getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes":
    def processJob(job): 
    49955008                filecount+=1
    49965009                folder=getItemTempPath(filecount)
    49975010                #Multiplex this file
    4998                 #(This also removes non-required audio feeds inside mpeg streams 
     5011                #(This also removes non-required audio feeds inside mpeg streams
    49995012                #(through re-multiplexing) we only take 1 video and 1 or 2 audio streams)
    50005013                pid=multiplexMPEGStream(os.path.join(folder,'stream.mv2'),
    50015014                        os.path.join(folder,'stream0'),
    def main(): 
    52385251            except:
    52395252                os.remove(lckpath)
    52405253                raise
    5241         except OSError, e:
     5254        except OSError as e:
    52425255            if e.errno == errno.EEXIST:
    52435256                write("Lock file exists -- already running???")
    52445257                sys.exit(1)
    def main(): 
    52815294            # remove our lock file
    52825295            os.remove(lckpath)
    52835296
    5284             # make sure the files we created are read/writable by all 
     5297            # make sure the files we created are read/writable by all
    52855298            os.system("chmod -R a+rw-x+X %s" % defaultsettings["MythArchiveTempDir"])
    52865299    except SystemExit:
    52875300        write("Terminated")