#!/usr/bin/python2.3

"""
multi_encoder

LiVES plugin which uses the following encoding programs:

mpeg_encoder.py
ogm_encoder.py
mkv_encoder.py

in order to generate movies in the following formats:

MPEG-1/MP2/MPG (various aspect ratios/frame rates)
MPEG-4/OGG/OGM (various aspect ratios/frame rates)
MPEG-4/OGG/MKV (various aspect ratios/frame rates)
VCD/SVCD/DVD (NTSC video)

See each *.py encoder for complete list of requirements
(you can type e.g. mpeg_encoder.py -C)

You can download the *.py encoders (and detailed instructions
on how they work) from:

http://www.reimeika.ca/amv/lives/lives_guide.html

Copyright (C) 2004 Marco De la Cruz (marco@reimeika.ca)
It's a trivial program, but might as well GPL it, so see:
http://www.gnu.org/copyleft/gpl.html for license.

See my vids at http://amv.reimeika.ca !
"""

version = '0.0.6'
mpeg = 'mpeg_encoder.py'
ogm = 'ogm_encoder.py'
mkv = 'mkv_encoder.py'

usage = \
      """
multi_encoder -h
multi_encoder [directive [args]]
      """

help = \
     """
SUMMARY (ver. %s):

LiVES plugin which calls one of the following programs:

mpeg_encoder.py
ogm_encoder.py
mkv_encoder.py

in order to generate movies in one of the following formats:

MPEG-1/MP2/MPG (various aspect ratios/frame rates)
MPEG-4/OGG/OGM (various aspect ratios/frame rates)
MPEG-4/OGG/MKV (various aspect ratios/frame rates)
VCD/SVCD/DVD (NTSC video)

The *.py encoder programs are either part of your LiVES
ditribution and/or available from:

http://www.reimeika.ca/amv/lives/lives_guide.html

OPTIONS:

-h          for help.

-v          be verbose.

-V          shows the version number.

directive   one of the following LiVES directives:

            version
            init
            get_capabilities
            get_formats
            finalise
            get_format_request
            encode
            clear

            See the LiVES documentation for details:
            http://www.xs4all.nl/~salsaman/lives/docs.html
     """ % version

# This is the directory where all temp files will be stored.
# It will reside within the LiVES temp directory (where the
# images and the audio files are located), so it's up to
# LiVES to make sure it always calls this plugin in the right
# location! I use this short name because mp2enc corrupts the
# filename is the length of the "/path/file.mp2" string is over
# 80 characters long. This should be fixed in a future version
# of MJPEGtools (> 1.6.2).
TEMPDIR = './metd'

def run(command):
    """
    Run a shell command
    """

    if verbose:
        print 'Running: \n' + command + '\n=== ... ==='
    os.system(command)


def which(command):
    """
    Finds (or not) a command a la "which"
    """

    command_found = False

    if command[0] == '/':
        if os.path.isfile(command) and \
               os.access(command, os.X_OK):
            command_found = True
            abs_command = command
    else:
        path = os.environ.get('PATH', '').split(os.pathsep)
        for dir in path:
            abs_command = os.path.join(dir, command)
            if os.path.isfile(abs_command) and \
               os.access(abs_command, os.X_OK):
                command_found = True
                break

    if not command_found:
        abs_command = ''

    return abs_command


def is_installed(prog):
    """
    See whether "prog" is installed
    """

    wprog = which(prog)

    if wprog == '':
        if verbose:
            print prog + ': command not found'
        raise SystemExit
    elif verbose:
        print wprog + ': found'


def clear():
    """
    Clean up temp dirs and files.
    """

    if verbose: print 'Deleting ' + tempdir

    shutil.rmtree(tempdir, True)

    for link in glob.glob('./temporary_symlink*'):
        try:
            if verbose: print 'Deleting ' + link
            os.remove(link)
        except:
            if verbose: print 'Tried deleting ' + link
            pass
    if os.path.exists('./divx2pass.log'):
        os.remove('./divx2pass.log')


if __name__ == '__main__':

    import os
    import sys
    import getopt
    import shutil
    import glob

    tempdir = os.path.abspath(TEMPDIR)

    try:
        if sys.version_info[0:3] < (2, 3, 0):
            raise SystemExit
    except:
        print 'You need Python 2.3.0 or greater to run me!'
        raise SystemExit

    try:
        (opts, args) = getopt.getopt(sys.argv[1:], \
                                         'hvV')
    except:
        print "Something's wrong. Try the '-h' flag."
        raise SystemExit

    opts = dict(opts)

    if not opts and not args:
        print usage
        raise SystemExit

    if '-h' in opts:
        print usage + help
        raise SystemExit

    if '-V' in opts:
        print 'multi_encoder version ' + version
        raise SystemExit

    if '-v' in opts:
        verbose = True
    else:
        verbose = False

    if len(args) < 1:
        print 'You must specify a directive.'
        raise SystemExit

    dir = args[0]

    if dir not in ['version', 'init', \
                   'get_capabilities', 'get_formats', 'finalise', \
                   'get_format_request', 'encode', 'clear']:
        print 'Directive "' + dir + '" not recognized.'
        raise SystemExit
    elif verbose:
        print 'Directive "' + dir + '" chosen.'


    if dir == 'version':
        print version
        raise SystemExit

    if dir == 'init':
        try:
            is_installed(mpeg)
            is_installed(ogm)
            is_installed(mkv)
        except:
            print 'Missing encoder. Make sure mpeg_encoder.py, ogm_encoder.py' + \
                ' and mkv_encoder.py are installed and that they work.'
            raise SystemExit, 1
        print 'initialised'
        raise SystemExit

    if dir == 'get_capabilities':
       # Can encode png (4) + not pure perl (8)
       print '12'
       raise SystemExit

    if dir == 'get_formats':
       # Vorbis = 8 (bit 3), MP2 = 4 (bit 2)
       fps = 'fps=23.976;24.000;25.000;29.970;30.000;50.000;59.940;60.000'
       tvfps = 'fps=25.000'
       ar = 'aspect=1:1;4:3;16:9;2.21:1'
       hb = 'hblock=16'
       sr = 'arate=44100'
       print 'lo_mpeg|Low Quality MPEG-1|4|%s,%s,%s,%s|mpg|' % (fps, ar, hb, sr)
       print 'ml_mpeg|Medium-Low Quality MPEG-1|4|%s,%s,%s,%s|mpg|' % (fps, ar, hb, sr)
       print 'mh_mpeg|Medium-High Quality MPEG-1|4|%s,%s,%s,%s|mpg|' % (fps, ar, hb, sr)
       print 'hi_mpeg|High Quality MPEG-1|4|%s,%s,%s,%s|mpg|' % (fps, ar, hb, sr)
       print 'vcd_mpeg|VCD-compatible MPEG (NTSC)|4|%s,%s,%s,%s|mpg|' % (tvfps, ar, hb, sr)
       print 'svcd_mpeg|SVCD-compatible MPEG (NTSC)|4|%s,%s,%s,%s|mpg|' % (tvfps, ar, hb, sr)
       # For DVD the encoder will resample the sound rate to 48000
       print 'dvd_mpeg|DVD-compatible MPEG (NTSC)|4|%s,%s,%s,%s|mpg|' % (tvfps, ar, hb, sr)
       print 'lo_ogm|Low Quality OGM|8|%s,%s,%s,%s|ogm|' % (fps, ar, hb, sr)
       print 'ml_ogm|Medium-Low Quality OGM|8|%s,%s,%s,%s|ogm|' % (fps, ar, hb, sr)
       print 'mh_ogm|Medium-High Quality OGM|8|%s,%s,%s,%s|ogm|' % (fps, ar, hb, sr)
       print 'hi_ogm|High Quality OGM|8|%s,%s,%s,%s|ogm|' % (fps, ar, hb, sr)
       print 'lo_mkv|Low Quality MKV|8|%s,%s,%s,%s|mkv|' % (fps, ar, hb, sr)
       print 'ml_mkv|Medium-Low Quality MKV|8|%s,%s,%s,%s|mkv|' % (fps, ar, hb, sr)
       print 'mh_mkv|Medium-High Quality MKV|8|%s,%s,%s,%s|mkv|' % (fps, ar, hb, sr)
       print 'hi_mkv|High Quality MKV|8|%s,%s,%s,%s|mkv|' % (fps, ar, hb, sr)
       raise SystemExit

    if dir == 'get_format_request':
       # wav (1) + clipped audio (2) + selected frames (4)
       print '7'
       raise SystemExit

    if dir == 'encode':

        fps = args[1]
        outfile = args[2]
        start = args[3]
        end = args[4]
        ext = args[5]
        vformat = args[6]
        aformat = args[7]
        debug = args[8]

	if debug == '1':
            verbose = True
        
        if fps == '23.976': fpsc = '1'
        elif fps == '24.000': fpsc = '2'
        elif fps == '25.000': fpsc = '3'
        elif fps == '29.970': fpsc = '4'
        elif fps == '30.000': fpsc = '5'
        elif fps == '50.000': fpsc = '6'
        elif fps == '59.940': fpsc = '7'
        elif fps == '60.000': fpsc = '8'
        else:
            print 'Invalid framerate!'
            raise SystemExit

        (type, prog) = vformat.split('_')

        if verbose:
            quiet = ''
            tonull = ''
        else:
            quiet = '-q'
            tonull = '2> /dev/null'

        encode_command = ' '.join([prog + '_encoder.py', '-o', \
                                   outfile, '-w', tempdir, \
                                   '-f', fpsc, quiet, '-t', \
                                   type, '-s ./audiodump.wav', \
                                   start, end, tonull])

        message = """
        I got the following arguments:

        fps = %s
        outfile = %s
        start = %s
        end = %s
        ext = %s
        vformat = %s
        aformat = %s

        I will use the following:

        fpsc = %s
        type = %s
        prog = %s
        tempdir = %s

        I will run the following command:
        %s

        """ % (fps, outfile, start, end, ext, vformat, \
               aformat, fpsc, type, prog, tempdir, encode_command)

        if verbose:
            print message

        # Uncomment to debug
        # output = open('/tmp/multi_encoder_debug.log', 'w')
        # output.write(message)
        # output.close()
        
        os.system(encode_command)
        clear()
        raise SystemExit

    if dir == 'clear':
        clear()
        raise SystemExit

    if dir == 'finalise':
        print 'finalised'
        raise SystemExit

"""
CHANGELOG:

21 Jul 2004 : 0.0.3 : added more directives
                      redefined on fps values
                      added this changelog :)
28 Jul 2004 : 0.0.4 : implemented 'encode' and 'clear' directives
29 Jul 2004 : 0.0.5 : remove 'divx2pass.log' if present
                      dies quietly now when cancelled from LiVES
02 Aug 2004 : 0.0.6 : added default extension to 'get_formats'
                      changed 'format' to 'vformat' for clarity
                      added support for 'debug' argument
"""
