Ticket #10071: mythburn20111006.patch

File mythburn20111006.patch, 54.0 KB (added by J.Pilk@…, 13 years ago)

Unified diff from 0.24-fixes mythburn.py combining this with other patches

  • .py

    old new  
     1
    12#!/usr/bin/env python2.7
     3# -*- coding: utf-8 -*-
    24# mythburn.py
    35# The ported MythBurn scripts which feature:
    46
     
    2628
    2729#Optional for shrink-to-fit requantisation
    2830#M2VRequantiser (from flexion, based on the newer code from Metakine)
     31# Download available from https://launchpad.net/m2vrequantiser/
    2932
    3033#Optional (for Right To Left languages)
    3134#pyfribidi
    3235
    3336#Optional (alternate demuxer)
    34 #ProjectX - 0.90.4.00
     37#ProjectX >= 0.91 from http://project-x.cvs.sourceforge.net/project-x/Project-X/
    3538
    3639#******************************************************************************
    3740#******************************************************************************
    3841#******************************************************************************
    3942
     43
     44# All strings in this file should be unicode, not byte string!! They get converted to utf-8 only
     45
    4046# version of script - change after each update
    41 VERSION="0.1.20101206-1"
     47VERSION="0.1.20101206-1jp-0.24framecutlist+ticket10071"
     48
     49# Local setting.  Set location of generated iso image, preferably not on the arctmp spindle
     50isopath="/mnt/f10store/myth/arctmp/isos/mythburn.iso" # is not stored in the db
    4251
    4352# keep all temporary files for debugging purposes
    4453# set this to True before a first run through when testing
     
    94103
    95104#Single and dual layer recordable DVD free space in MBytes
    96105dvdrsize=(4482,8106)
     106#dvdrsize=(400,8106)
    97107
    98108frameratePAL=25
    99109framerateNTSC=29.97
     
    102112aspectRatioThreshold = 1.4
    103113
    104114#Just blank globals at startup
     115
    105116temppath=""
    106117logpath=""
    107118scriptpath=""
     
    239250
    240251def write(text, progress=True):
    241252    """Simple place to channel all text output through"""
     253
     254    text = text.encode("utf-8", "replace")
    242255    sys.stdout.write(text + "\n")
    243256    sys.stdout.flush()
    244257
    245258    if progress == True and progresslog != "":
    246         progressfile.write(time.strftime("%Y-%m-%d %H:%M:%S ") + text + "\n")
    247         progressfile.flush()
     259      if len(text)<30 :
     260         progressfile.write(time.strftime("%H:%M:%S  %Y-%m-%d ") + text + "\n")
     261      else:
     262         progressfile.write(time.strftime("%H:%M:%S ") + text + "\n")
     263
     264      progressfile.flush()
    248265
    249266#############################################################
    250267# Display an error message and exit
     
    253270    """Display an error message and exit app"""
    254271    write("*"*60)
    255272    write("ERROR: " + msg)
     273    write("See mythburn.log for more information.")
    256274    write("*"*60)
    257275    write("")
    258276    saveSetting("MythArchiveLastRunResult", "Failed: " + quoteString(msg));
     
    287305# Try to work out how many cpus we have available
    288306
    289307def getCPUCount():
    290     """return the number of CPU's"""
     308    """return the number of CPUs"""
    291309    cpustat = open("/proc/cpuinfo")
    292310    cpudata = cpustat.readlines()
    293311    cpustat.close()
     
    349367
    350368def getDatabaseConnection():
    351369    """Returns a mySQL connection to mythconverg database."""
    352     return MySQLdb.connect(host=mysql_host, user=mysql_user, passwd=mysql_passwd, db=mysql_db, init_command='SET NAMES utf8')
     370    return MySQLdb.connect(host=mysql_host, user=mysql_user, passwd=mysql_passwd, db=mysql_db, charset="utf8", use_unicode=True)
    353371
    354372#############################################################
    355373# Returns true/false if a given file or path exists.
     
    359377    return os.path.exists( file )
    360378
    361379#############################################################
    362 # Escape quotes in a filename
     380# Escape quotes in a command line argument
    363381
    364 def quoteFilename(filename):
    365     filename = filename.replace('"', '\\"')
    366     filename = filename.replace('`', '\\`')
    367     return '"%s"' % filename
     382def quoteCmdArg(arg):
     383    arg = arg.replace('"', '\\"')
     384    arg = arg.replace('`', '\\`')
     385    return '"%s"' % arg
    368386
    369387#############################################################
    370388# Returns the text contents from a given XML element.
     
    436454                os.remove(os.path.join(root, name))
    437455
    438456#############################################################
     457# Romoves all the objects from a directory
     458
     459def deleteEverythingInFolder(folder):
     460    for root, dirs, files in os.walk(folder, topdown=False):
     461        for name in files:
     462                os.remove(os.path.join(root, name))
     463        for name in dirs:
     464                if os.path.islink(os.path.join(root, name)):
     465                    os.remove(os.path.join(root, name))
     466                else:
     467                    os.rmdir(os.path.join(root, name))
     468
     469#############################################################
    439470# Check to see if the user has cancelled the DVD creation process
    440471
    441472def checkCancelFlag():
     
    454485def runCommand(command):
    455486    checkCancelFlag()
    456487
    457     result = os.system(command)
     488    # mytharchivehelper needes this locale to work correctly
     489    try:
     490       oldlocale = os.environ["LC_ALL"]
     491    except:
     492       oldlocale = ""
     493    os.putenv("LC_ALL", "en_US.UTF-8")
     494    result = os.system(command.encode('utf-8'))
     495    os.putenv("LC_ALL", oldlocale)
    458496
    459497    if os.WIFEXITED(result):
    460498        result = os.WEXITSTATUS(result)
    461499    checkCancelFlag()
    462500    return result
     501   
     502############################################################
     503# Truncate to even value ( to silence 'odd y-coordinate' complaints)
     504
     505def even(num):
     506    evennum = int(num / 2) * 2
     507    return evennum
     508
    463509
    464510#############################################################
    465511# Convert a time in seconds to a frame number
     
    485531
    486532    totalframes=int(musiclength * framespersecond)
    487533
    488     command = path_jpeg2yuv[0] + " -n %s -v0 -I p -f %s -j '%s' | %s -b 5000 -a %s -v 1 -f 8 -o '%s'" \
    489               % (totalframes, framespersecond, background, path_mpeg2enc[0], aspectratio, tempvideo)
     534    command = "ionice -c3 "
     535    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" \
     536              % (totalframes, framespersecond, quoteCmdArg(background), quoteCmdArg(path_mpeg2enc[0]), aspectratio, quoteCmdArg(tempvideo))
    490537    result = runCommand(command)
    491538    if result<>0:
    492539        fatalError("Failed while running jpeg2yuv - %s" % command)
    493540
    494     command = path_mplex[0] + " -f 8 -v 0 -o '%s' '%s' '%s'" % (tempmovie, tempvideo, music)
     541    command = "ionice -c3 "
     542    command += quoteCmdArg(path_mplex[0]) + " -f 8 -v 0 -o %s %s %s" % (quoteCmdArg(tempmovie), quoteCmdArg(tempvideo), quoteCmdArg(music))
    495543    result = runCommand(command)
    496544    if result<>0:
    497545        fatalError("Failed while running mplex - %s" % command)
    498546
    499547    if xmlfile != "":
    500         command = path_spumux[0] + " -m dvd -s 0 '%s' < '%s' > '%s'" % (xmlfile, tempmovie, finaloutput)
     548        command = "ionice -c3 "
     549        command += quoteCmdArg(path_spumux[0]) + " -m dvd -s 0 %s < %s > %s" % (quoteCmdArg(xmlfile), quoteCmdArg(tempmovie), quoteCmdArg(finaloutput))
    501550        result = runCommand(command)
    502551        if result<>0:
    503552            fatalError("Failed while running spumux - %s" % command)
     
    15091558            top_element.appendChild(node)   
    15101559
    15111560            node = infoDOM.createElement("title")
    1512             node.appendChild(infoDOM.createTextNode(unicode(record[6], "UTF-8")))
     1561            node.appendChild(infoDOM.createTextNode(record[6]))
    15131562            top_element.appendChild(node)
    15141563
    15151564            #date time is returned as 2005-12-19 00:15:00           
     
    15231572            top_element.appendChild(node)   
    15241573
    15251574            node = infoDOM.createElement("subtitle")
    1526             node.appendChild(infoDOM.createTextNode(unicode(record[5], "UTF-8")))
     1575            node.appendChild(infoDOM.createTextNode(record[5]))
     1576
    15271577            top_element.appendChild(node)   
    15281578
    15291579            node = infoDOM.createElement("description")
    1530             node.appendChild(infoDOM.createTextNode(unicode(record[4], "UTF-8")))
     1580            node.appendChild(infoDOM.createTextNode(record[4]))
     1581
    15311582            top_element.appendChild(node)   
    15321583
    15331584            node = infoDOM.createElement("rating")
     
    16301681            top_element.appendChild(node)   
    16311682
    16321683            node = infoDOM.createElement("title")
    1633             node.appendChild(infoDOM.createTextNode(unicode(record[0], "UTF-8")))
     1684            node.appendChild(infoDOM.createTextNode(record[0]))
    16341685            top_element.appendChild(node)   
    16351686
    16361687            node = infoDOM.createElement("recordingdate")
     
    16471698            top_element.appendChild(node)   
    16481699
    16491700            node = infoDOM.createElement("subtitle")
    1650             node.appendChild(infoDOM.createTextNode(unicode(record[9], "UTF-8")))
     1701            node.appendChild(infoDOM.createTextNode(record[9]))
    16511702            top_element.appendChild(node)   
    16521703
    16531704            node = infoDOM.createElement("description")
    16541705            if record[2] != None:
    1655                 desc = unicode(record[2], "UTF-8")
     1706                desc = record[2]
    16561707                if desc != "None":
    16571708                    node.appendChild(infoDOM.createTextNode(desc))
    16581709                else:
     
    18051856def encodeAudio(format, sourcefile, destinationfile, deletesourceafterencode):
    18061857    write( "Encoding audio to "+format)
    18071858    if format == "ac3":
    1808         cmd = path_ffmpeg[0] + " -v 0 -y "
     1859        cmd = quoteCmdArg(path_ffmpeg[0]) + " -v 0 -y "
    18091860
    18101861        if cpuCount > 1:
    18111862            cmd += "-threads %d " % cpuCount
    18121863
    1813         cmd += "-i '%s' -f ac3 -ab 192k -ar 48000 '%s'" % (sourcefile, destinationfile)
     1864        cmd += "-i %s -f ac3 -ab 192k -ar 48000 %s" % (quoteCmdArg(sourcefile), quoteCmdArg(destinationfile))
    18141865        result = runCommand(cmd)
    18151866
    18161867        if result != 0:
     
    18991950        return result
    19001951    else:
    19011952        if result != 0:
    1902             fatalError("mplex failed with result %d" % result)
     1953            nonfatalError("mplex failed with result %d" % result)
    19031954
    19041955    # run spumux to add subtitles if they exist
    19051956    if os.path.exists(os.path.dirname(destination) + "/stream.d/spumux.xml"):
    19061957        write("Checking integrity of subtitle pngs")
    1907         command = os.path.join(scriptpath, "testsubtitlepngs.sh") + " %s/stream.d/spumux.xml" % (os.path.dirname(destination))
     1958        command = quoteCmdArg(os.path.join(scriptpath, "testsubtitlepngs.sh")) + " " + quoteCmdArg(os.path.dirname(destination) + "/stream.d/spumux.xml")
    19081959        result = runCommand(command)
    19091960        if result<>0:
    19101961            fatalError("Failed while running testsubtitlepngs.sh - %s" % command)
    19111962
    19121963        write("Running spumux to add subtitles")
    1913         command = path_spumux[0] + " -P %s/stream.d/spumux.xml <%s >%s" % (os.path.dirname(destination), destination, os.path.splitext(destination)[0] + "-sub.mpg")
     1964       
     1965        command = "ionice -c3 "
     1966        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"))
    19141967        result = runCommand(command)
    19151968        if result<>0:
    19161969            nonfatalError("Failed while running spumux.\n"
     
    19281981
    19291982def getStreamInformation(filename, xmlFilename, lenMethod):
    19301983    """create a stream.xml file for filename"""
    1931     filename = quoteFilename(filename)
    1932     command = "mytharchivehelper -i %s %s %d" % (filename, xmlFilename, lenMethod)
     1984
     1985    command = "mytharchivehelper -i %s %s %d" % (quoteCmdArg(filename), quoteCmdArg(xmlFilename), lenMethod)
     1986    write(command)
    19331987
    19341988    result = runCommand(command)
    19351989
     
    19381992
    19391993    # print out the streaminfo.xml file to the log
    19401994    infoDOM = xml.dom.minidom.parse(xmlFilename)
    1941     write("streaminfo.xml :-\n" + infoDOM.toprettyxml("    ", ""), False)
     1995    write(xmlFilename + ":-\n" + infoDOM.toprettyxml("    ", ""), False)
    19421996
    19431997#############################################################
    19441998# Gets the video width and height from a file's stream xml file
     
    19712025    """Use mythtranscode to cut commercials and/or clean up an mpeg2 file"""
    19722026
    19732027    if localfile != "":
    1974         localfile = quoteFilename(localfile)
    19752028        if usecutlist == True:
    1976             command = "mythtranscode --mpeg2 --honorcutlist -i %s -o %s" % (localfile, destination)
     2029            command = "mythtranscode --mpeg2 --honorcutlist -i %s -o %s" % (quoteCmdArg(localfile), quoteCmdArg(destination))
    19772030        else:
    1978             command = "mythtranscode --mpeg2 -i %s -o %s" % (localfile, destination)
     2031            command = "mythtranscode --mpeg2 -i %s -o %s" % (quoteCmdArg(localfile), quoteCmdArg(destination))
    19792032    else:
    19802033        if usecutlist == True:
    1981             command = "mythtranscode --mpeg2 --honorcutlist -c %s -s %s -o %s" % (chanid, starttime, destination)
     2034            command = "mythtranscode --mpeg2 --honorcutlist -c %s -s %s -o %s" % (chanid, starttime, quoteCmdArg(destination))
    19822035        else:
    1983             command = "mythtranscode --mpeg2 -c %s -s %s -o %s" % (chanid, starttime, destination)
     2036            command = "mythtranscode --mpeg2 -c %s -s %s -o %s" % (chanid, starttime, quoteCmdArg(destination))
    19842037
    19852038    result = runCommand(command)
    19862039
     
    19982051def generateProjectXCutlist(chanid, starttime, folder):
    19992052    """generate cutlist_x.txt for ProjectX"""
    20002053
    2001     sqlstatement  = """SELECT mark FROM recordedmarkup 
    2002                     WHERE chanid = '%s' AND starttime = '%s' 
     2054    sqlstatement  = """SELECT mark FROM recordedmarkup
     2055                    WHERE chanid = '%s' AND starttime = '%s'
    20032056                    AND type IN (0,1) ORDER BY mark""" % (chanid, starttime)
    20042057
    20052058    db = getDatabaseConnection()
     
    20142067        db.close()
    20152068        del db
    20162069        del cursor
    2017         return False
     2070        return False   
     2071
     2072    sqlstatement  = """SELECT mark FROM recordedmarkup
     2073                    WHERE chanid = '%s' AND starttime = '%s'
     2074                    AND type=1 ORDER BY mark LIMIT 1 """ % (chanid, starttime)
     2075
     2076    cursor.execute(sqlstatement)
     2077    firstcut = cursor.fetchall()   
     2078
     2079    sqlstatement  = """SELECT mark FROM recordedmarkup
     2080                    WHERE chanid = '%s' AND starttime = '%s'
     2081                    AND type IN (0,1) ORDER BY mark LIMIT 1 """ % (chanid, starttime)
    20182082
     2083    cursor.execute(sqlstatement)
     2084    firstedit = cursor.fetchall()
     2085   
    20192086    cutlist_f=open(os.path.join(folder, "cutlist_x.txt"), 'w')
    20202087    cutlist_f.write("CollectionPanel.CutMode=2\n")
    20212088
     2089    if firstcut == firstedit:
     2090         cutlist_f.write("0\n")
     2091
    20222092    # iterate through resultset
    20232093    for i in range(len(result)):
    2024         if i == 0:
    2025             if result[i][0] <> 0  and result[i][0] != "":
    2026                 cutlist_f.write("0\n")
    20272094        if result[i][0] != "" and result[i][0] <> 0:
    20282095            cutlist_f.write("%d\n" % result[i])
    20292096
     
    20432110            write("Failed to generate Project-X cutlist.")
    20442111            return False
    20452112
    2046     pxbasename = os.path.splitext(os.path.basename(file))[0]
    2047 
    20482113    if os.path.exists(file) != True:
    20492114        write("Error: input file doesn't exist on local filesystem")
    20502115        return False
    2051 
    2052 
    2053     qdestdir = quoteFilename(folder)
    2054     qpxbasename = quoteFilename(pxbasename)
    2055     qfile = quoteFilename(file)
    2056     qcutlist = os.path.join(folder, "cutlist_x.txt")
    2057 
    2058     command = path_projectx[0] + " -id %s" % getStreamList(folder)
     2116       
     2117    command = "ionice -c3 java -jar "   
     2118    command += quoteCmdArg(path_projectx[0]) + " %s -id '%s' -set ExternPanel.appendPidToFileName=1 -out %s -name stream" % (quoteCmdArg(file), getStreamList(folder), quoteCmdArg(folder))
    20592119    if usecutlist == True:
    2060         command += " -cut %s -out %s -name %s %s" % (qcutlist, qdestdir, qpxbasename, qfile)
    2061     else:
    2062         command += " -out %s -name %s %s" % (qdestdir, qpxbasename, qfile)
    2063 
     2120        command += " -cut %s" % quoteCmdArg(os.path.join(folder, "cutlist_x.txt"))
    20642121    write(command)
    20652122
    20662123    result = runCommand(command)
     
    20722129
    20732130
    20742131    # workout which files we need and rename them
    2075     renameProjectXFiles(folder, pxbasename)
     2132    video, audio1, audio2 = selectStreams(folder)
     2133    if addSubtitles:
     2134        subtitles = selectSubtitleStream(folder)
     2135
     2136    videoID_hex = "0x%x" % video[VIDEO_ID]
     2137    if audio1[AUDIO_ID] != -1:
     2138        audio1ID_hex = "0x%x" % audio1[AUDIO_ID]
     2139    else:
     2140        audio1ID_hex = ""
     2141    if audio2[AUDIO_ID] != -1:
     2142        audio2ID_hex = "0x%x" % audio2[AUDIO_ID]
     2143    else:
     2144        audio2ID_hex = ""
     2145    if addSubtitles and subtitles[SUBTITLE_ID] != -1:
     2146        subtitlesID_hex = "0x%x" % subtitles[SUBTITLE_ID]
     2147    else:
     2148        subtitlesID_hex = ""
     2149
     2150
     2151    files = os.listdir(folder)
     2152    for file in files:
     2153        if file[0:9] == "stream{0x": # don't rename files that have already been renamed
     2154            PID = file[7:13]
     2155            SubID = file[19:23]
     2156            if PID == videoID_hex or SubID == videoID_hex:
     2157                os.rename(os.path.join(folder, file), os.path.join(folder, "stream.mv2"))
     2158            elif PID == audio1ID_hex or SubID == audio1ID_hex:
     2159                os.rename(os.path.join(folder, file), os.path.join(folder, "stream0." + file[-3:]))
     2160            elif PID == audio2ID_hex or SubID == audio2ID_hex:
     2161                os.rename(os.path.join(folder, file), os.path.join(folder, "stream1." + file[-3:]))
     2162            elif PID == subtitlesID_hex or SubID == subtitlesID_hex:
     2163                if file[-3:] == "sup":
     2164                    os.rename(os.path.join(folder, file), os.path.join(folder, "stream.sup"))
     2165                else:
     2166                    os.rename(os.path.join(folder, file), os.path.join(folder, "stream.sup.IFO"))
     2167
     2168
     2169    # Fallback if assignment and renaming by ID failed
     2170   
     2171    files = os.listdir(folder)
     2172    for file in files:
     2173        if file[0:9] == "stream{0x": # don't rename files that have already been renamed
     2174            if not os.path.exists(os.path.join(folder, "stream.mv2")) and file[-3:] == "m2v":
     2175                os.rename(os.path.join(folder, file), os.path.join(folder, "stream.mv2"))
     2176            elif not (os.path.exists(os.path.join(folder, "stream0.ac3")) or os.path.exists(os.path.join(folder, "stream0.mp2"))) and file[-3:] == "ac3":
     2177                os.rename(os.path.join(folder, file), os.path.join(folder, "stream0.ac3"))
     2178            elif not (os.path.exists(os.path.join(folder, "stream0.ac3")) or os.path.exists(os.path.join(folder, "stream0.mp2"))) and file[-3:] == "mp2":
     2179                os.rename(os.path.join(folder, file), os.path.join(folder, "stream0.mp2"))
     2180            elif not (os.path.exists(os.path.join(folder, "stream1.ac3")) or os.path.exists(os.path.join(folder, "stream1.mp2"))) and file[-3:] == "ac3":
     2181                os.rename(os.path.join(folder, file), os.path.join(folder, "stream1.ac3"))
     2182            elif not (os.path.exists(os.path.join(folder, "stream1.ac3")) or os.path.exists(os.path.join(folder, "stream1.mp2"))) and file[-3:] == "mp2":
     2183                os.rename(os.path.join(folder, file), os.path.join(folder, "stream1.mp2"))
     2184            elif not os.path.exists(os.path.join(folder, "stream.sup")) and file[-3:] == "sup":
     2185                os.rename(os.path.join(folder, file), os.path.join(folder, "stream.sup"))
     2186            elif not os.path.exists(os.path.join(folder, "stream.sup.IFO")) and file[-3:] == "IFO":
     2187                os.rename(os.path.join(folder, file), os.path.join(folder, "stream.sup.IFO"))
     2188
    20762189
    20772190    # if we have some dvb subtitles and the user wants to add them to the DVD
    20782191    # convert them to pngs and create the spumux xml file
     
    20812194            os.path.exists(os.path.join(folder, "stream.sup.IFO"))):
    20822195            write("Found DVB subtitles converting to DVD subtitles")
    20832196            command = "mytharchivehelper --sup2dast "
    2084             command += " %s %s 0" % (os.path.join(folder, "stream.sup"), os.path.join(folder, "stream.sup.IFO"))
     2197            command += " %s %s 0" % (quoteCmdArg(os.path.join(folder, "stream.sup")), quoteCmdArg(os.path.join(folder, "stream.sup.IFO")))
    20852198
    20862199            result = runCommand(command)
    20872200
     
    20962209    return True
    20972210
    20982211#############################################################
    2099 # find the required stream files and rename them
    2100 
    2101 def renameProjectXFiles(folder, pxbasename):
    2102 
    2103     write("renameProjectXFiles start -----------------------------------------", False)
    2104     logf = open(os.path.join(folder, pxbasename + "_log.txt"))
    2105     logdata = logf.readlines()
    2106     logf.close()
    2107 
    2108     # find stream PIDs and Files
    2109     streamIds = []
    2110     streamFiles = []   
    2111     for line in logdata:
    2112          tokens = line.split()
    2113          if len(tokens) > 0:
    2114             if tokens[0] == "++>":
    2115               # From ProjectX/resources/pjxresources_en.properties:
    2116               if tokens[1] == "Mpg":
    2117                 if tokens[2] == "Video:":
    2118                   write("found MPEG video stream %s" % tokens[4], False)
    2119                   streamIds.append(int(tokens[4], 16))
    2120                 if tokens[2] == "Audio:":
    2121                   write("found MPEG audio stream %s" % tokens[4], False)
    2122                   streamIds.append(int(tokens[4], 16))
    2123               if tokens[1] == "AC3/DTS":
    2124                 write("found AC3/DTS audio stream %s" % tokens[4], False)
    2125                 streamIds.append(int(tokens[4], 16))             
    2126               if tokens[1] == "LPCM":
    2127                 write("found LPCM audio stream %s" % tokens[4], False)
    2128                 streamIds.append(int(tokens[4], 16))             
    2129               if tokens[1] == "Teletext:":
    2130                 write("found Teletext stream %s" % tokens[3], False)
    2131                 streamIds.append(int(tokens[3], 16))             
    2132               if tokens[1] == "Subpicture:":
    2133                 write("found Subpicture stream %s" % tokens[3], False)
    2134                 streamIds.append(int(tokens[3], 16))
    2135               if tokens[1] == "Generic_VBI:":
    2136                 write("found Generic_VBI stream %s" % tokens[3], False)
    2137                 streamIds.append(int(tokens[3], 16))                                           
    2138             if tokens[0] == "--->":
    2139               if tokens[1] == "new":
    2140                 if tokens[2] == "File:":
    2141                   write("found file for stream 0x%x, %s" % (streamIds[len(streamIds)-1], tokens[3]), False)
    2142                   streamFiles.append(tokens[3].replace("'","")) # let's hope the path never has a space in it
    2143             if tokens[0] == "-->":
    2144               if tokens[1] == "stream":
    2145                 if tokens[2] == "omitted":
    2146                   write("stream 0x%x omitted" % streamIds[len(streamIds)-1], False)
    2147                   streamFiles.append("")
    2148                  
    2149     write("streadmIds=%s" % streamIds)
    2150     write("streamFiles=%s" % streamFiles)
    2151 
    2152     # choose which streams we need
    2153     video, audio1, audio2 = selectStreams(folder)
    2154 
    2155     if getFileType(folder) == "mpeg":
    2156         videoID  = video[VIDEO_ID] & 255
    2157         audio1ID = audio1[AUDIO_ID] & 255
    2158         audio2ID = audio2[AUDIO_ID] & 255
    2159     else:
    2160         videoID  = video[VIDEO_ID]
    2161         audio1ID = audio1[AUDIO_ID]
    2162         audio2ID = audio2[AUDIO_ID]
    2163 
    2164     # sanity check - we should have a file for each ID
    2165     if len(streamIds) == len(streamFiles):
    2166         # loop thought the available streams looking for the ones we want
    2167         for stream in streamIds:
    2168             write("got stream: %d" % stream, False)
    2169             if stream == videoID:
    2170                 write("found video streamID", False)
    2171                 if os.path.exists(streamFiles[streamIds.index(stream)]):
    2172                     write("found video stream file", False)
    2173                     os.rename(streamFiles[streamIds.index(stream)], os.path.join(folder, "stream.mv2"))
    2174 
    2175             if stream == audio1ID:
    2176                 write("found audio1 streamID", False)
    2177                 if os.path.exists(streamFiles[streamIds.index(stream)]):
    2178                     write("found audio1 stream file", False)
    2179                     if audio1[AUDIO_CODEC] == "AC3":
    2180                         os.rename(streamFiles[streamIds.index(stream)], os.path.join(folder, "stream0.ac3"))
    2181                     else:
    2182                         os.rename(streamFiles[streamIds.index(stream)], os.path.join(folder, "stream0.mp2"))
    2183 
    2184             if stream == audio2ID:
    2185                 write("found audio2 streamID", False)
    2186                 if os.path.exists(streamFiles[streamIds.index(stream)]):
    2187                     write("found audio2 stream file", False)
    2188                     if audio2[AUDIO_CODEC] == "AC3":
    2189                         os.rename(streamFiles[streamIds.index(stream)], os.path.join(folder, "stream1.ac3"))
    2190                     else:
    2191                         os.rename(streamFiles[streamIds.index(stream)], os.path.join(folder, "stream1.mp2"))
    2192 
    2193     # final chance to find the correct stream files
    2194     if not os.path.exists(os.path.join(folder, "stream.mv2")):
    2195         if os.path.exists(os.path.join(folder, pxbasename + ".m2v")):
    2196             os.rename(os.path.join(folder, pxbasename + ".m2v"), os.path.join(folder, "stream.mv2"))
    2197 
    2198     if not os.path.exists(os.path.join(folder, "stream0.mp2")) or not os.path.exists(os.path.join(folder, "stream0.ac3")):
    2199         if os.path.exists(os.path.join(folder, pxbasename + ".mp2")):
    2200             os.rename(os.path.join(folder, pxbasename + ".mp2"), os.path.join(folder, "stream0.mp2"))
    2201         if os.path.exists(os.path.join(folder, pxbasename + ".ac3")):
    2202             os.rename(os.path.join(folder, pxbasename + ".ac3"), os.path.join(folder, "stream0.ac3"))
    2203 
    2204     if not os.path.exists(os.path.join(folder, "stream1.mp2")) or not os.path.exists(os.path.join(folder, "stream1.ac3")):
    2205         if os.path.exists(os.path.join(folder, pxbasename + "[1].mp2")):
    2206             os.rename(os.path.join(folder, pxbasename + "[1].mp2"), os.path.join(folder, "stream1.mp2"))
    2207         if os.path.exists(os.path.join(folder, pxbasename + "[1].ac3")):
    2208             os.rename(os.path.join(folder, pxbasename + "[1].ac3"), os.path.join(folder, "stream1.ac3"))
    2209 
    2210     # do we have any subtitle files
    2211     if os.path.exists(os.path.join(folder, pxbasename + ".sup")):
    2212         os.rename(os.path.join(folder, pxbasename + ".sup"), os.path.join(folder, "stream.sup"))
    2213 
    2214     if os.path.exists(os.path.join(folder, pxbasename + ".sup.IFO")):
    2215         os.rename(os.path.join(folder, pxbasename + ".sup.IFO"), os.path.join(folder, "stream.sup.IFO"))
    2216 
    2217     write("renameProjectXFiles end -----------------------------------------", False)
    2218 
    2219 #############################################################
    22202212# convert time stamp to pts
    22212213
    22222214def ts2pts(time):
     
    22872279        else:
    22882280            fr=framerateNTSC
    22892281
    2290         source = quoteFilename(source)
    2291 
    2292         command = "mytharchivehelper -t  %s '%s' %s" % (source, seconds, destination)
     2282        command = "ionice -c3 "
     2283        command += "mytharchivehelper -t %s '%s' %s" % (quoteCmdArg(source),seconds, quoteCmdArg(destination))
    22932284        result = runCommand(command)
    22942285        if result <> 0:
    22952286            fatalError("Failed while running mytharchivehelper to get thumbnails.\n"
     
    23122303    write("Extracting thumbnail images from: %s - at %s" % (source, thumbList))
    23132304    write("Destination file %s" % destination)
    23142305
    2315     source = quoteFilename(source)
    23162306
    2317     command = "mytharchivehelper -v important -t %s '%s' %s" % (source, thumbList, destination)
     2307    command = "ionice -c3 "
     2308    command += "mytharchivehelper -v important -t %s '%s' %s" % (quoteCmdArg(source), thumbList, quoteCmdArg(destination))
     2309    write(command)
     2310
    23182311    result = runCommand(command)
    23192312    if result <> 0:
    2320         fatalError("Failed while running mytharchivehelper to get thumbnails")
     2313        fatalError("Failed while running mytharchivehelper to get thumbnails. \n"
     2314                   "Result: %d, Command was %s" % (result, command))
    23212315
    23222316#############################################################
    23232317# Re-encodes a file to mpeg2
     
    23292323
    23302324    passes = int(getText(profileNode.getElementsByTagName("passes")[0]))
    23312325
    2332     command = path_ffmpeg[0]
     2326    command = quoteCmdArg(path_ffmpeg[0])
    23332327
    23342328    if cpuCount > 1:
    23352329        command += " -threads %d" % cpuCount
     
    23422336
    23432337        # do some parameter substitution
    23442338        if value == "%inputfile":
    2345             value = quoteFilename(source)
     2339            value = quoteCmdArg(source)
    23462340        if value == "%outputfile":
    2347             value = quoteFilename(destvideofile)
     2341            value = quoteCmdArg(destvideofile)
    23482342        if value == "%aspect":
    23492343            value = aspectratio
    23502344
     
    23982392        passLog = os.path.join(getTempPath(), 'pass')
    23992393
    24002394        pass1 = string.replace(command, "%passno","1")
    2401         pass1 = string.replace(pass1, "%passlogfile", passLog)
     2395        pass1 = string.replace(pass1, "%passlogfile", quoteCmdArg(passLog))
    24022396        write("Pass 1 - " + pass1)
    24032397        result = runCommand(pass1)
    24042398
     
    24102404            os.remove(destvideofile)
    24112405
    24122406        pass2 = string.replace(command, "%passno","2")
    2413         pass2 = string.replace(pass2, "%passlogfile", passLog)
     2407        pass2 = string.replace(pass2, "%passlogfile", quoteCmdArg(passLog))
    24142408        write("Pass 2 - " + pass2)
    24152409        result = runCommand(pass2)
    24162410
     
    25152509    samplerate, channels = getAudioParams(folder)
    25162510    videores, fps, aspectratio = getVideoParams(folder)
    25172511
    2518     command =  path_ffmpeg[0] + " -y "
     2512    command =  quoteCmdArg(path_ffmpeg[0]) + " -y "
    25192513
    25202514    if cpuCount > 1:
    25212515        command += "-threads %d " % cpuCount
    25222516
    2523     command += "-f s16le -ar %s -ac %s -i %s " % (samplerate, channels, os.path.join(folder, "audout"))
     2517    command += "-f s16le -ar %s -ac %s -i %s " % (samplerate, channels, quoteCmdArg(os.path.join(folder, "audout")))
    25242518    command += "-f rawvideo -pix_fmt yuv420p -s %s -aspect %s -r %s " % (videores, aspectratio, fps)
    2525     command += "-i %s " % os.path.join(folder, "vidout")
     2519    command += "-i %s " % quoteCmdArg(os.path.join(folder, "vidout"))
    25262520    command += "-aspect %s -r %s " % (aspectratio, fps)
    25272521    if (deinterlace == 1):
    25282522        command += "-deinterlace "
     
    25302524    command += "-s %s -b %s -vcodec mpeg2video " % (outvideores, outvideobitrate)
    25312525    command += "-qmin %s -qmax %s -qdiff %s " % (qmin, qmax, qdiff)
    25322526    command += "-ab %s -ar %s -acodec %s " % (outaudiobitrate, outaudiosamplerate, outaudiocodec)
    2533     command += "-f dvd %s" % quoteFilename(destvideofile)
     2527    command += "-f dvd %s" % quoteCmdArg(destvideofile)
    25342528
    25352529    #wait for mythtranscode to create the fifos
    25362530    tries = 30
     
    25552549
    25562550def runDVDAuthor():
    25572551    write( "Starting dvdauthor")
    2558     checkCancelFlag()
    2559     result=os.spawnlp(os.P_WAIT, path_dvdauthor[0],path_dvdauthor[1],'-x',os.path.join(getTempPath(),'dvdauthor.xml'))
     2552#    checkCancelFlag()
     2553#    result=os.spawnlp(os.P_WAIT, path_dvdauthor[0],path_dvdauthor[1],'-x',os.path.join(getTempPath(),'dvdauthor.xml'))
     2554    command ="ionice -c3 "
     2555    command += path_dvdauthor[0] + ' -x ' + os.path.join(getTempPath(),'dvdauthor.xml')
     2556
     2557    write("Command is %s " % command)
     2558    result = runCommand(command)
     2559
    25602560    if result<>0:
    2561         fatalError("Failed while running dvdauthor. Result: %d" % result)
     2561      nonfatalError("Failed while running dvdauthor. Result: %d" % result)
    25622562    write( "Finished  dvdauthor")
    25632563
     2564
    25642565#############################################################
     2566   
    25652567# Creates an ISO image from the contents of a directory
    25662568
    25672569def CreateDVDISO(title):
    25682570    write("Creating ISO image")
    25692571    checkCancelFlag()
    2570     command = path_mkisofs[0] + ' -dvd-video '
    2571     command += ' -V ' + quoteFilename(title)
    2572     command += ' -o ' + os.path.join(getTempPath(), 'mythburn.iso')
    2573     command += " " + os.path.join(getTempPath(),'dvd')
    25742572
     2573    command = "ionice -c3 "
     2574    command += quoteCmdArg(path_mkisofs[0]) + ' -dvd-video '
     2575    command += ' -V ' + quoteCmdArg(title)
     2576    command += ' -o ' + quoteCmdArg(isopath)
     2577    command += " " + quoteCmdArg(os.path.join(getTempPath(),'dvd'))
     2578
     2579    write("Command is %s " % command)
    25752580    result = runCommand(command)
    25762581
    25772582    if result<>0:
    25782583        fatalError("Failed while running mkisofs.\n"
    25792584                   "Command was %s" % command)
    25802585
    2581     write("Finished creating ISO image")
     2586#    vobsize = os.path.getsize(path.join(getTempPath(), 'mythburn.iso'))
     2587    vobsize= os.path.getsize(isopath)
     2588    write("Finished creating mythburn.iso, size %.2f Mb." % (float(vobsize)/(1024.0*1024.0)) )
     2589    write("DVD capacities are %s, %s Mb " % ( dvdrsize[0], dvdrsize[1]) )
    25822590
     2591   
    25832592#############################################################
    25842593# Burns the contents of a directory to create a DVD
    25852594
    25862595def BurnDVDISO(title):
    25872596    write( "Burning ISO image to %s" % dvddrivepath)
    2588     checkCancelFlag()
    25892597
    25902598    finished = False
    2591     tries = 0
    2592     while not finished and tries < 10:
    2593         f = os.open(dvddrivepath, os.O_RDONLY | os.O_NONBLOCK)
    2594         drivestatus = ioctl(f,CDROM.CDROM_DRIVE_STATUS, 0)
    2595         os.close(f);
     2599    while not finished:
     2600        # Maybe the user has no appropriate medium or something alike. Give her the chance to cancel.
     2601        checkCancelFlag()
     2602
     2603        def drivestatus():
     2604            f = os.open(dvddrivepath, os.O_RDONLY | os.O_NONBLOCK)
     2605            return ioctl(f,CDROM.CDROM_DRIVE_STATUS, 0)
     2606            os.close(f);
     2607
     2608        # I drive needs some time (for example to close the tray) give it to it
     2609        tries = 0
     2610        while drivestatus() == CDROM.CDS_DRIVE_NOT_READY and tries < 6:
     2611            time.sleep(5)
     2612            tries += 1
    25962613
    2597         if drivestatus == CDROM.CDS_DISC_OK or drivestatus == CDROM.CDS_NO_INFO:
     2614        if drivestatus() == CDROM.CDS_DISC_OK or drivestatus() == CDROM.CDS_NO_INFO:
    25982615
    25992616            # If the frontend has a previously burnt DVD+RW mounted,
    26002617            # growisofs will fail to burn it, so try to pumount it first...
    2601             runCommand("pumount " + dvddrivepath);
     2618            runCommand("pumount " + quoteCmdArg(dvddrivepath));
    26022619
    26032620            if mediatype == DVD_RW and erasedvdrw == True:
    26042621                command = path_growisofs[0] + " -dvd-compat "
     
    26182635            write("Running growisofs to burn DVD")
    26192636
    26202637            result = runCommand(command)
    2621             if result != 0:
     2638            if result == 0:
     2639                finished = True
     2640            elif result == 252:
     2641                write("-"*60)
     2642                write("You probably inserted a medium of wrong type.")
     2643                if mediatype == DVD_SL:
     2644                  write("Please insert an empty single-layer disc (DVD+R or DVD-R).")
     2645                if mediatype == DVD_DL:
     2646                  write("Please insert an empty double-layer disc (DVD+R DL or DVD-R DL).")
     2647                if mediatype == DVD_RW:
     2648                  write("Please insert a rewritable disc (DVD+RW or DVD-RW).")
     2649            else:
    26222650                write("-"*60)
    26232651                write("ERROR: Failed while running growisofs.")
    26242652                write("Result %d, Command was: %s" % (result, command))
    26252653                write("Please check the troubleshooting section of the README for ways to fix this error")
    26262654                write("-"*60)
    26272655                write("")
    2628                 sys.exit(1)
    2629             finished = True
     2656                write("Going to try it again until canceled by user:")
     2657                write("-"*60)
     2658                write("")
    26302659
    26312660            try:
    26322661                # eject the burned disc
     2662                runCommand("pumount " + quoteCmdArg(dvddrivepath));
    26332663                f = os.open(dvddrivepath, os.O_RDONLY | os.O_NONBLOCK)
    26342664                r = ioctl(f,CDROM.CDROMEJECT, 0)
    26352665                os.close(f)
     
    26372667                write("Failed to eject the disc! "
    26382668                      "Maybe the media monitor has mounted it")
    26392669
    2640         elif drivestatus == CDROM.CDS_TRAY_OPEN:
    2641             # Give the user 10secs to close the Tray
     2670        elif drivestatus() == CDROM.CDS_TRAY_OPEN:
    26422671            write("Waiting for tray to close.")
    2643             time.sleep(10)
    2644         elif drivestatus == CDROM.CDS_NO_DISC:
     2672            # Wait until user closes tray or cancels
     2673            while drivestatus() == CDROM.CDS_TRAY_OPEN:
     2674                checkCancelFlag()
     2675                time.sleep(5)
     2676        elif drivestatus() == CDROM.CDS_NO_DISC:
    26452677            # Open the Tray, if there is one.
    26462678            write("Opening tray to get it fed with a DVD.")
    26472679            f = os.open(dvddrivepath, os.O_RDONLY | os.O_NONBLOCK)
    26482680            ioctl(f,CDROM.CDROMEJECT, 0)
    26492681            os.close(f);
    2650         elif drivestatus == CDROM.CDS_DRIVE_NOT_READY:
    2651             # Try a hard reset
     2682        elif drivestatus() == CDROM.CDS_DRIVE_NOT_READY:
     2683            # Try a hard reset if the device is still not ready
    26522684            write("Trying a hard-reset of the device")
    26532685            f = os.open(dvddrivepath, os.O_RDONLY | os.O_NONBLOCK)
    26542686            ioctl(f,CDROM.CDROMEJECT, 0)
    26552687            os.close(f);
    26562688
    2657         time.sleep(1)
    2658         tries += 1
    2659 
    2660     if not finished:
    2661         fatalError("Tried 10 times to get a good status from DVD drive - Giving up!")
    26622689
    26632690    write("Finished burning ISO image")
    26642691
     
    26692696def deMultiplexMPEG2File(folder, mediafile, video, audio1, audio2):
    26702697
    26712698    if getFileType(folder) == "mpegts":
    2672         command = "mythreplex --demux --fix_sync -t TS -o %s " % (folder + "/stream")
     2699        command = "mythreplex --demux --fix_sync -t TS -o %s " % quoteCmdArg(folder + "/stream")
    26732700        command += "-v %d " % (video[VIDEO_ID])
    26742701
    26752702        if audio1[AUDIO_ID] != -1:
     
    26892716                command += "-c %d " % (audio2[AUDIO_ID])
    26902717
    26912718    else:
    2692         command = "mythreplex --demux --fix_sync -o %s " % (folder + "/stream")
     2719        command = "mythreplex --demux --fix_sync -o %s " % quoteCmdArg(folder + "/stream")
    26932720        command += "-v %d " % (video[VIDEO_ID] & 255)
    26942721
    26952722        if audio1[AUDIO_ID] != -1:
     
    27092736            elif audio2[AUDIO_CODEC] == 'EAC3':
    27102737                command += "-c %d " % (audio2[AUDIO_ID] & 255)
    27112738
    2712     mediafile = quoteFilename(mediafile)
     2739    mediafile = quoteCmdArg(mediafile)
    27132740    command += mediafile
    27142741    write("Running: " + command)
    27152742
     
    27262753    M2Vsize0 = os.path.getsize(source)
    27272754    write("Initial M2Vsize is %.2f Mb , target is %.2f Mb" % ( (float(M2Vsize0)/mega), (float(M2Vsize0)/(factor*mega)) ))
    27282755
    2729     command = path_M2VRequantiser[0]   
     2756    command = quoteCmdArg(path_M2VRequantiser[0])   
    27302757    command += " %.5f "  % factor
    27312758    command += " %s "  % M2Vsize0
    2732     command += " <  %s " % source
    2733     command += " >  %s " % destination
     2759    command += " <  %s " % quoteCmdArg(source)
     2760    command += " >  %s " % quoteCmdArg(destination)
    27342761 
    27352762    write("Running: " + command)
    27362763    result = runCommand(command)
     2764    if result<>0:
     2765        fatalError("Failed while running M2VRequantiser. Command was %s" % command)
    27372766
    27382767    M2Vsize1 = os.path.getsize(destination)
    27392768       
    27402769    write("M2Vsize after requant is  %.2f Mb " % (float(M2Vsize1)/mega))
    27412770    fac1=float(M2Vsize0) / float(M2Vsize1)
    27422771    write("Factor demanded %.5f, achieved %.5f, ratio %.5f " % ( factor, fac1, fac1/factor))
    2743            
    2744     if result<>0:
    2745         fatalError("Failed while running M2VRequantiser. Command was %s" % command)
     2772
    27462773
    27472774#############################################################
    27482775# Calculates the total size of all the video, audio and menu files
     
    28332860        fatalError("Audio and menu files are too big. No room for video. Giving up!")
    28342861
    28352862    if totalvideosize>mv2space:
    2836         write( "Video files are %.1f Mb too big. Need to shrink." % ((totalvideosize - mv2space)/mega) )
     2863        write( "***** Video files are %.1f Mb too big. Need to shrink." % ((totalvideosize - mv2space)/mega) )
    28372864
    28382865        if path_M2VRequantiser[0] == "":
    28392866            fatalError("M2VRequantiser is not available to resize the files.  Giving up!")
     
    28842911            progvsize=os.path.getsize(file)
    28852912            progduration=getLengthOfVideo(filecount)
    28862913            progvbitrate=progvsize/progduration
    2887             write( "File %s, size %.2f Mb, rate %.2f, limit %.2f kb/s " %( filecount, float(progvsize)/mega, progvbitrate/1000.0, vrate/1000.0 ))
     2914            write( "*** File %s, size %.2f Mb, rate %.2f, limit %.2f kb/s " %( filecount, float(progvsize)/mega, progvbitrate/1000.0, vrate/1000.0 ))
    28882915            if progvbitrate>vrate :
    28892916                scalefactor=1.0+(fudge_requant*float(progvbitrate-vrate)/float(vrate))
    28902917                if scalefactor>3.0 :
     
    28932920                os.remove(os.path.join(getItemTempPath(filecount),"stream.mv2"))
    28942921                os.rename(os.path.join(getItemTempPath(filecount),"stream.small.mv2"),os.path.join(getItemTempPath(filecount),"stream.mv2"))
    28952922    else:
    2896         write( "Unpackaged total %.2f Mb. About %.0f Mb will be unused." % ((allfiles/mega),(mv2space-totalvideosize)/mega))
     2923        write( "*** No need to shrink. *** Unpackaged total %.2f Mb. About %.0f Mb will be unused." % ((allfiles/mega),(mv2space-totalvideosize)/mega))
    28972924
    28982925#############################################################
    28992926# Creates the DVDAuthor xml file used to create a standard DVD with menus
     
    35013528                height = getScaledAttribute(node, "h")
    35023529                frames = int(secondsToFrames(menulength))
    35033530
    3504                 command = "mytharchivehelper -t  %s '%s' '%s' %d" % (inputfile, starttime, outputfile, frames)
     3531                command = "mytharchivehelper -t %s '%s' '%s' %d" % (quoteCmdArg(inputfile), starttime, quoteCmdArg(outputfile), frames)
    35053532                result = runCommand(command)
    35063533                if (result != 0):
    35073534                    write( "mytharchivehelper failed with code %d. Command = %s" % (result, command) )
     
    36133640                button = spumuxdom.createElement("button")
    36143641                button.setAttribute("name","previous")
    36153642                button.setAttribute("x0","%s" % getScaledAttribute(node, "x"))
    3616                 button.setAttribute("y0","%s" % getScaledAttribute(node, "y"))
     3643                button.setAttribute("y0","%s" % even(getScaledAttribute(node, "y")))
    36173644                button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") +
    36183645                                                getScaledAttribute(node, "w")))
    3619                 button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") +
     3646                button.setAttribute("y1","%s" % even(getScaledAttribute(node, "y") +
    36203647                                                getScaledAttribute(node, "h")))
    36213648                spunode.appendChild(button)
    36223649
     
    36373664                button = spumuxdom.createElement("button")
    36383665                button.setAttribute("name","next")
    36393666                button.setAttribute("x0","%s" % getScaledAttribute(node, "x"))
    3640                 button.setAttribute("y0","%s" % getScaledAttribute(node, "y"))
     3667                button.setAttribute("y0","%s" % even(getScaledAttribute(node, "y")))
    36413668                button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") +
    36423669                                                 getScaledAttribute(node, "w")))
    3643                 button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") +
    3644                                                  getScaledAttribute(node, "h")))
     3670                button.setAttribute("y1","%s" % even((getScaledAttribute(node, "y") +
     3671                                                 getScaledAttribute(node, "h"))))
    36453672                spunode.appendChild(button)
    36463673
    36473674                write("Added next page button")
     
    36583685            button = spumuxdom.createElement("button")
    36593686            button.setAttribute("name","playall")
    36603687            button.setAttribute("x0","%s" % getScaledAttribute(node, "x"))
    3661             button.setAttribute("y0","%s" % getScaledAttribute(node, "y"))
     3688            button.setAttribute("y0","%s" % even(getScaledAttribute(node, "y")))
    36623689            button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") +
    36633690                                             getScaledAttribute(node, "w")))
    3664             button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") +
    3665                                              getScaledAttribute(node, "h")))
     3691            button.setAttribute("y1","%s" % even((getScaledAttribute(node, "y") +
     3692                                             getScaledAttribute(node, "h"))))
    36663693            spunode.appendChild(button)
    36673694
    36683695            write("Added playall button")
     
    36813708                button = spumuxdom.createElement("button")
    36823709                button.setAttribute("name","titlemenu")
    36833710                button.setAttribute("x0","%s" % getScaledAttribute(node, "x"))
    3684                 button.setAttribute("y0","%s" % getScaledAttribute(node, "y"))
     3711                button.setAttribute("y0","%s" % even(getScaledAttribute(node, "y")))
    36853712                button.setAttribute("x1","%s" % (getScaledAttribute(node, "x") +
    36863713                                                getScaledAttribute(node, "w")))
    3687                 button.setAttribute("y1","%s" % (getScaledAttribute(node, "y") +
    3688                                                 getScaledAttribute(node, "h")))
     3714                button.setAttribute("y1","%s" % even((getScaledAttribute(node, "y") +
     3715                                                getScaledAttribute(node, "h"))))
    36893716                spunode.appendChild(button)
    36903717
    36913718                write( "Added titlemenu button")
     
    37303757    else:
    37313758        node.setAttribute("name","%s" % itemnum)
    37323759    node.setAttribute("x0","%d" % int(boundarybox[0]))
    3733     node.setAttribute("y0","%d" % int(boundarybox[1]))
     3760    node.setAttribute("y0","%d" % even(boundarybox[1]))
    37343761    node.setAttribute("x1","%d" % int(boundarybox[2] + 1))
    3735     node.setAttribute("y1","%d" % int(boundarybox[3] + 1))
     3762    node.setAttribute("y1","%d" % even(boundarybox[3] + 1))
    37363763    spunode.appendChild(node)
    37373764
    37383765#############################################################
     
    37683795        highlightcolor = menunode.attributes["highlightcolor"].value
    37693796
    37703797    #Get menu music
    3771     menumusic = "menumusic.ac3"
    3772     if menunode.hasAttribute("music"):
    3773         menumusic = menunode.attributes["music"].value
     3798    menumusic = "menumusic.mp2"
     3799#    menumusic = "menumusic.ac3"
     3800#    if menunode.hasAttribute("music"):
     3801#        menumusic = menunode.attributes["music"].value
    37743802
    37753803    #Get menu length
    37763804    menulength = 15
     
    39794007    if menunode.hasAttribute("highlightcolor"):
    39804008        highlightcolor = menunode.attributes["highlightcolor"].value
    39814009
     4010 
    39824011    #Get menu music
    3983     menumusic = "menumusic.ac3"
    3984     if menunode.hasAttribute("music"):
    3985         menumusic = menunode.attributes["music"].value
     4012    menumusic = "menumusic.mp2"
     4013#    menumusic = "menumusic.ac3"
     4014#    if menunode.hasAttribute("music"):
     4015#        menumusic = menunode.attributes["music"].value
    39864016
    39874017    #Get menu length
    39884018    menulength = 15
     
    41754205        fatalError("Background image not found (%s)" % backgroundfilename)
    41764206
    41774207    #Get menu music
    4178     menumusic = "menumusic.ac3"
    4179     if detailnode.hasAttribute("music"):
    4180         menumusic = detailnode.attributes["music"].value
     4208    menumusic = "menumusic.mp2"   
     4209#    menumusic = "menumusic.ac3"
     4210#    if detailnode.hasAttribute("music"):
     4211#        menumusic = detailnode.attributes["music"].value
    41814212
    41824213    #Get menu length
    41834214    menulength = 15
     
    43674398    # 2. if there is one or more stream(s) using the 2nd preferred language we use that
    43684399    # 3. if we still haven't found a stream we use the stream with the lowest PID
    43694400    # 4. we prefer ac3 over mp2
    4370     # 5. if there are more that one stream with the chosen language we use the one with the lowest PID
     4401    # 5. if there are more than one stream with the chosen language we use the one with the lowest PID
    43714402
    43724403    write("Preferred audio languages %s and %s" % (preferredlang1, preferredlang2))
    43734404
     
    45114542
    45124543    found = False
    45134544    # first try to find a stream with preferred language 1
     4545    # inc Pontoppidan patch dvbsub > DVBSUB
    45144546    for node in nodes:
    45154547        index = int(node.attributes["ffmpegindex"].value)
    45164548        lang = node.attributes["language"].value
    45174549        format = string.upper(node.attributes["codec"].value)
    45184550        pid = int(node.attributes["id"].value)
    4519         if not found and lang == preferredlang1 and format == "dvbsub":
     4551        if not found and lang == preferredlang1 and format == "DVBSUB":
    45204552            subtitle = (index, format, pid, lang)
    45214553            found = True
    45224554
     
    45274559            lang = node.attributes["language"].value
    45284560            format = string.upper(node.attributes["codec"].value)
    45294561            pid = int(node.attributes["id"].value)
    4530             if not found and lang == preferredlang2 and format == "dvbsub":
     4562            if not found and lang == preferredlang2 and format == "DVBSUB":
    45314563                subtitle = (index, format, pid, lang)
    45324564                found = True
    45334565
     
    47074739def doProcessFile(file, folder, count):
    47084740    """Process a single video/recording file ready for burning."""
    47094741
    4710     write( "*************************************************************")
     4742#    write( "*************************************************************")
    47114743    write( "Processing %s %d: '%s'" % (file.attributes["type"].value, count, file.attributes["filename"].value))
    4712     write( "*************************************************************")
     4744#    write( "*************************************************************")
    47134745
    47144746    #As part of this routine we need to pre-process the video this MAY mean:
    47154747    #1. removing commercials/cleaning up mpeg2 stream
     
    49074939        else:
    49084940            extractVideoFrame(os.path.join(folder, "stream.mv2"), titleImage, thumboffset)
    49094941
    4910     write( "*************************************************************")
    4911     write( "Finished processing '%s'" % file.attributes["filename"].value)
    4912     write( "*************************************************************")
     4942#    write( "*************************************************************")
     4943    write( "*** Finished processing '%s'" % file.attributes["filename"].value)
     4944#    write( "*************************************************************")
    49134945
    49144946
    49154947#############################################################
     
    49214953
    49224954    write( "*************************************************************")
    49234955    write( "Processing %s %d: '%s'" % (file.attributes["type"].value, count, file.attributes["filename"].value))
    4924     write( "*************************************************************")
     4956#    write( "*************************************************************")
    49254957
    49264958    #As part of this routine we need to pre-process the video this MAY mean:
    49274959    #1. encoding to mpeg2 (if its an avi for instance or isn't DVD compatible)
     
    50765108        else:
    50775109            extractVideoFrame(os.path.join(folder, "stream.mv2"), titleImage, thumboffset)
    50785110
    5079     write( "*************************************************************")
    5080     write( "Finished processing file '%s'" % file.attributes["filename"].value)
    5081     write( "*************************************************************")
     5111#    write( "*************************************************************")
     5112    write( "*** Finished processing file '%s'" % file.attributes["filename"].value)
     5113#    write( "*************************************************************")
    50825114
    50835115#############################################################
    50845116# copy files on remote filesystems to the local filesystem
     
    50915123        tmpfile = node.attributes["filename"].value
    50925124        filename = os.path.basename(tmpfile)
    50935125
    5094         res = runCommand("mytharchivehelper -r " + quoteFilename(tmpfile))
     5126        res = runCommand("mytharchivehelper -r " + quoteCmdArg(tmpfile))
     5127
    50955128        if res == 2:
    50965129            # file is on a remote filesystem so copy it to a local file
    50975130            write("Copying file from " + tmpfile)
     
    51565189
    51575190        write( "Final DVD Video format will be " + videomode)
    51585191
    5159         #Ensure the destination dvd folder is empty
    5160         if doesFileExist(os.path.join(getTempPath(),"dvd")):
    5161             deleteAllFilesInFolder(os.path.join(getTempPath(),"dvd"))
    51625192
    51635193        #Loop through all the files
    51645194        files=media[0].getElementsByTagName("file")
     
    51685198
    51695199            if debug_secondrunthrough==False:
    51705200                #Delete all the temporary files that currently exist
    5171                 deleteAllFilesInFolder(getTempPath())
     5201                deleteEverythingInFolder(getTempPath())
    51725202
    51735203            #If User wants to, copy remote files to a tmp dir
    51745204            if copyremoteFiles==True:
    51755205                if debug_secondrunthrough==False:
    51765206                    localCopyFolder=os.path.join(getTempPath(),"localcopy")
    5177                     #If it already exists destroy it to remove previous debris
    5178                     if os.path.exists(localCopyFolder):
    5179                         #Remove all the files first
    5180                         deleteAllFilesInFolder(localCopyFolder)
    5181                         #Remove the folder
    5182                         os.rmdir (localCopyFolder)
    51835207                    os.makedirs(localCopyFolder)
    51845208                files=copyRemote(files,getTempPath())
    51855209
     
    51935217                folder=getItemTempPath(filecount)
    51945218
    51955219                if debug_secondrunthrough==False:
    5196                     #If it already exists destroy it to remove previous debris
    5197                     if os.path.exists(folder):
    5198                         #Remove all the files first
    5199                         deleteAllFilesInFolder(folder)
    5200                         subtitlefolder = os.path.join(folder, "stream.d")
    5201                         if os.path.exists(subtitlefolder):
    5202                             deleteAllFilesInFolder(subtitlefolder)
    5203                             os.rmdir(subtitlefolder)
    5204                         previewfolder = os.path.join(folder, "preview")
    5205                         if os.path.exists(previewfolder):
    5206                             deleteAllFilesInFolder(previewfolder)
    5207                             os.rmdir(previewfolder)
    5208                         #Remove the folder
    5209                         os.rmdir (folder)
    52105220                    os.makedirs(folder)
    52115221                #Do the pre-process work
    52125222                preProcessFile(node,folder,filecount)
     
    55185528            saveSetting("MythArchiveLastRunStatus", "Success")
    55195529            saveSetting("MythArchiveLastRunEnd", time.strftime("%Y-%m-%d %H:%M:%S "))
    55205530            write("Finished processing jobs!!!")
     5531            # Show bigger end marker.  Display and editor font widths differ.
     5532            write(" ")
     5533            write("    OO      K        K")
     5534            write("  O     O   K    K")
     5535            write("  O     O   K K")
     5536            write("  O     O   K    K")
     5537            write("    OO      K        K")
     5538            write(" ")
    55215539        finally:
    55225540            # remove our lock file
    55235541            os.remove(lckpath)