#!/usr/bin/python

# This is a hack to work around a dvdauthor bug which is #323140 in
# the Debian BTS.

# Given a root directory for a DVD tree, check that certain sector
# number fields in the .IFO/.BUP files match their expected values,
# and if not, fix them up.

def main(root_dir):

    import os, os.path, struct

    SECTOR_SIZE = 2048
    video_dir = os.path.join(root_dir, 'VIDEO_TS')

    for ts_num in range(0, 100):

        # Find the IFO and BUP files
        if ts_num == 0:
            ifo_name = os.path.join(video_dir, 'VIDEO_TS.IFO')
            bup_name = os.path.join(video_dir, 'VIDEO_TS.BUP')
        else:
            ifo_name = os.path.join(video_dir, 'VTS_%02d_0.IFO' % ts_num)
            if not os.path.exists(ifo_name):
                break
            bup_name = os.path.join(video_dir, 'VTS_%02d_0.BUP' % ts_num)
        print 'Checking %s' % ifo_name

        # Find actual sizes
        ifo_size = os.stat(ifo_name).st_size / SECTOR_SIZE
        total_size = ifo_size * 2
        if ts_num == 0:
            vob_name = os.path.join(video_dir, 'VIDEO_TS.VOB')
            if os.path.exists(vob_name):
                total_size = total_size + os.stat(vob_name).st_size / SECTOR_SIZE
        else:
            for vob_num in range(0, 10):
                vob_name = os.path.join(video_dir,
                                        'VTS_%02d_%d.VOB' % (ts_num, vob_num))
                if not os.path.exists(vob_name):
                    break
                total_size = total_size + os.stat(vob_name).st_size / SECTOR_SIZE

        # Fix broken fields
        ifo_file = open(ifo_name, 'r+b')
        bup_file = open(bup_name, 'r+b')
        def fix(offset, name, value):
            ifo_file.seek(offset, 0)
            value_read = struct.unpack('>I', ifo_file.read(4))[0]
            if value_read != value:
                print ('Changing %s field from 0x%x to 0x%x'
                       % (name, value_read, value))
                value_packed = struct.pack('>I', value)
                ifo_file.seek(offset, 0)
                ifo_file.write(value_packed)
                bup_file.seek(offset, 0)
                bup_file.write(value_packed)
        # I don't know what the real names of the fields are, but these
        # are their apparent meanings.
        fix(12, 'titleset last sector', total_size - 1)
        fix(28, 'IFO last sector', ifo_size - 1)
        fix(192, 'IFO size', ifo_size)
        ifo_file.close()
        bup_file.close()

if __name__ == '__main__':
    import sys
    main(sys.argv[1])
        
