## ------------------------------------------------------------
## ffmpegGen.py
## Created: Dec 1, 2011 by Christian Leake, CGI TD, Golden Era Productions
## Last Edited: 
## 
## ffmpeg Event Plugin to Deadline Queue System
## Command Line Utility to convert image sequences and create QuickTime Movies from image sequences 
## Tested with Windows 7x64 OS and potentially 'compatiable' with Linux / Mac OSX OS
## ------------------------------------------------------------
import re

from System.IO import *
from System.Text import *

from Deadline.Events import *
from Deadline.Scripting import *

######################################################################
## This is the function that Deadline calls to get an instance of the
## main DeadlineEventListener class.
######################################################################
def GetDeadlineEventListener():
    return DJVQuicktimeGen()

######################################################################
## This is the main DeadlineEventListener class for DJVQuicktimeGen.
######################################################################
class DJVQuicktimeGen (DeadlineEventListener):

	def OnJobFinished( self, job ):
		# Only submit an ff job for finished "aecs4" jobs AND only if they are in the "toediting" pool.
		if job.JobPlugin != "AfterEffects" or job.JobPool != "toediting":
			return

		LogInfo( "On Job Finished Event Plugin: AfterEffects - FF Quicktime Generation Started" )

		def GetSupportedFormats( self ):
			formatFilename = Path.Combine( ScriptUtils.GetRootDirectory(), "scripts/Submission/FFmpegSubmission/SupportedFormats.ini" )
			return File.ReadAllLines( formatFilename )

		def IsInputFormatSupported( self, InputFile ):
			extension = Path.GetExtension( InputFile ).lower()
			supportedFormats = GetSupportedFormats( self )
			for format in supportedFormats:
				if extension == format.lower():
					return True
			return False

		outputDirectories = job.JobOutputDirectories
		outputFilenames = job.JobOutputFileNames
		#paddingRegex = re.compile("[^\\?#]*([\\?#]+).*")

		# Submit an FFmpeg QT job for all outputs.
		for i in range( 0, len(outputFilenames) ):
		
		 outputDirectory = outputDirectories[i] #outputDirectories[i]
		 outputFilename = outputFilenames[i] #outputFilenames[i]
		 outputPath = Path.Combine(outputDirectory,outputFilename).replace("//","/")

		# Swap out the padding character for an actual frame.Not sure if I need this or not...
		#m = re.match(paddingRegex,outputPath)
		#if( m != None):
			#padding = m.group(1)
			#frame = StringUtils.ToZeroPaddedString(job.JobFramesList[0],len(padding),False)
			#outputPath = outputPath.replace( padding, frame )
		paddingSize = FrameUtils.GetPaddingSizeFromFilename(outputPath)
		fileName = FrameUtils.GetFilenameWithoutPadding(outputPath)
		fileNoExt = fileName.split('.')
		padding = str(paddingSize)
		newFileName = fileNoExt[0]+'%'+'0'+padding+'d'	
		InputFile = outputPath
		LogInfo("Inputfile: %s" %InputFile)

		# Check InputFile file format is supported by FFmpeg
		if( not IsInputFormatSupported( self, InputFile ) ):
			LogWarning( "The After Effects rendered input file " + InputFile + " is not a supported format for FFmpeg. If this format is supported by FFmpeg, you can add its file extension to " + Path.Combine( ScriptUtils.GetRootDirectory(), "scripts/Submission/FFmpegSubmission/SupportedFormats.ini" ) + " to prevent this automatic event plugin from failing" )
			return

			# Check input image sequence as FFmpeg ONLY supports 0 based image sequences
			FramesList = job.JobFramesList
			if len(FramesList) > 0:
				for i in range( FramesList[0], FramesList[-1] ):
					if int( FramesList[i+1] ) - int( FramesList[i] ) != 0:
						LogWarning( "Only N+1th based image sequences are supported by FFmpeg" )
						return

			outputFile = Path.ChangeExtension( FrameUtils.GetFilenameWithoutPadding( InputFile ), ".mov" )
			outputDirectory = Path.GetDirectoryName( outputFile )
			movieName = Path.GetFileNameWithoutExtension( outputFile )
			movieFrames = job.JobFrames

			# Create job info file.
			jobInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "FFmpeg_job_info.job" )
			writer = StreamWriter( jobInfoFilename, False, Encoding.Unicode )
			writer.WriteLine( "Plugin=FFmpeg" )
			writer.WriteLine( "Name=%s" % movieName )
			writer.WriteLine( "Comment=Auto-submitted FFmpeg QT" )
			writer.WriteLine( "Department=%s" % job.JobDepartment )
			writer.WriteLine( "Pool=%s" % job.JobPool )
			writer.WriteLine( "Group=%s" % job.JobGroup )
			writer.WriteLine( "Priority=%s" % job.JobPriority )
			writer.WriteLine( "MachineLimit=1" )
			writer.WriteLine( "Frames=%s" % movieFrames )
			writer.WriteLine( "ChunkSize=100000" )
			writer.WriteLine( "OutputDirectory0=%s" % outputDirectory )
			writer.WriteLine( "OutputFilename0=%s" % outputFile )
			writer.Close()

			# Create plugin info file.
			pluginInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "FFmpeg_plugin_info.job" )
			writer = StreamWriter( pluginInfoFilename, False, Encoding.Unicode )
			## FFmpeg
			writer.WriteLine( "Version=%s" % GetConfigEntryWithDefault( "Version" , "083" ) )
			writer.WriteLine( "Build=%s" % GetConfigEntryWithDefault( "Build", "64bit" ) )
			writer.WriteLine( "Build0=None" )
			writer.WriteLine( "Build1=32bit" )
			writer.WriteLine( "Build2=64bit" )
			writer.WriteLine( "InputFile=%s" % InputFile )
			writer.WriteLine( "OutputFile=%s" % outputFile )
			writer.Close()

			# Now submit the job.
			ClientUtils.ExecuteCommand( (jobInfoFilename,pluginInfoFilename) )
			
			LogInfo( "On Job Finished Event Plugin: AfterEffects - FFmpeg Quicktime Generation Submitted" )
