# AVSLib :: 'filters' package :: 'frames' module
# Copyright (c) 2007 George Zarkadas (gzarkadas@users.sourceforge.net)

# This program is free software; you can redistribute it and/or modify it under the terms of 
# the GNU General Public License as published by the Free Software Foundation; either 
# version 2 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
# PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program; 
# if not, write to the "Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
# MA  02111-1307  USA"

__lib__ = "avslib" #$$ [__lib__ = "avslib-debug"]

DefineModule(__lib__, "filters", "frames")

global __load__ = IsPackageLoaded(__lib__, "string") ? NOP : Eval("""
	LoadPackage(__lib__, "string")
	""")
global __load__ = Eval("""
	LoadModule(__lib__, "base", "constants")
	LoadModule(__lib__, "array", "core")
	LoadModule(__lib__, "array", "operators")
	LoadModule(__lib__, "filters", "utility")
	""")

# Shared FrameFilter... utility code

global __frame_filter_cnt = 0   # function call GUID generator
global __frame_filter_src = ""  # StrReplace'd script

Function __frame_filter_repvar(int ivar, string svar) {
	global __frame_filter_src = StrReplace( \
		__frame_filter_src, "${var" + String(ivar) + "}", \
		svar.ArrayGetString(ivar - 1))
	return true
}

# Applies a (filter) script to each frame. The script has in its disposal all runtime vars
# plus (any number of) the literals "${var1}, ${var2},... (substituted with StrReplace inside 
# the script string; supplied by the 'vars' argument array) plus up to 50 positional arguments
# (%? placeholders, as defined in StrPrint, supplied by the filter's 'p1'...'p50' arguments). 

Function FrameFilter(clip orig, string script, val "p1", val "p2", val "p3", val "p4", \
	val "p5", val "p6", val "p7", val "p8", val "p9", val "p10", val "p11", val "p12", \
	val "p13", val "p14", val "p15", val "p16", val "p17", val "p18", val "p19", val "p20", \
	val "p21", val "p22", val "p23", val "p24", val "p25", val "p26", val "p27", val "p28", \
	val "p29", val "p30", val "p31", val "p32", val "p33", val "p34", val "p35", val "p36", \
	val "p37", val "p38", val "p39", val "p40", val "p41", val "p42", val "p43", val "p44", \
	val "p45", val "p46", val "p47", val "p48", val "p49", val "p50", string "vars", \
	bool "show", bool "after_frame")
{
	global __frame_filter_src = StrPrint(script, p1, p2, p3, p4, p5, p6, p7, p8, \
		p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, \
		p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, \
		p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50)
	vars = Default(vars, "")
	nvars = vars.ArrayLen
	dummy = nvars > 0 ? Eval("""
		ivars = ArrayRange(1, nvars)
		dummy = ivars.ArrayOpFunc("__frame_filter_repvar", vars)
	""") : NOP
    return ScriptClip(orig, __frame_filter_src, show, after_frame)
}

# Applies a (filter) script to each frame. The script has in its disposal all runtime vars
# plus the literals and positional arguments of the FrameFilter plus the literals ${read1}, 
# ${read2}, ..., ${readN}, N == filename.ArrayLen (they are replaced by FrameFilterReader 
# with the actual global vars' names whose values are set from elements of 'filenames' with 
# ConditionalReader. 
# 'filenames' is a CRLF delimited array (each filename in a single line).
# The type and value of each ${readI} can be anything that suits your script; it just 
# has to be compatible with the type declared in the ConditionalReader's file.
# If 'filenames' == "" ConditionalReader will *not* be used. 
	
	Function __frame_filter_initvar(int n) { 
		var = "__frame_filter_" + String(n)
		dummy = Eval("global " + var + " = 0")
		return true
	}

	Function __frame_filter_repread(int ivar) {
		svar = String(ivar)
		global __frame_filter_src = StrReplace(__frame_filter_src, \
			"${read" + svar + "}", "__frame_filter_" + svar)
		return true
	}
	
	Function __frame_filter_readpars(string filename, int ivar) {
		strvar = "__frame_filter_" + String(ivar)
		return StrQuote(filename) + ", " + StrQuote(strvar) + ", false"
	}

Function FrameFilterReader(clip orig, string script, string filenames, val "p1", val "p2", \
	val "p3", val "p4", val "p5", val "p6", val "p7", val "p8", val "p9", val "p10", \
	val "p11", val "p12", val "p13", val "p14", val "p15", val "p16", val "p17", val "p18", \
	val "p19", val "p20", val "p21", val "p22", val "p23", val "p24", val "p25", val "p26", \
	val "p27", val "p28", val "p29", val "p30", val "p31", val "p32", val "p33", val "p34", \
	val "p35", val "p36", val "p37", val "p38", val "p39", val "p40", val "p41", val "p42", \
	val "p43", val "p44", val "p45", val "p46", val "p47", val "p48", val "p49", val "p50", \
	string "vars", bool "show", bool "after_frame")
{
	use_reader = filenames != ""

	global __frame_filter_src = StrPrint(script, p1, p2, p3, p4, p5, p6, p7, p8, \
		p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, \
		p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, \
		p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50)

	vars = Default(vars, "")
	nvars = vars.ArrayLen
	dummy = nvars > 0 ? Eval("""	# update __frame_filter_src with ${varN} replacements
		ivars = ArrayRange(1, nvars)
		dummy = ivars.ArrayOpFunc("__frame_filter_repvar", vars)
	""") : NOP

	dummy = use_reader ? Eval("""	# update __frame_filter_src with ${readN} replacements
		old = ArrayDelimiterSet(CRLF)	# set our settings
		filevars = filenames.ArrayLen
		global __frame_filter_cnt = __frame_filter_cnt + filevars
		fvars = ArrayRange(1, filevars)
		dummy = fvars.ArrayOpFunc("__frame_filter_initvar") # build call's GUIDs
		dummy = fvars.ArrayOpFunc("__frame_filter_repread")
		old = ArrayDelimiterSet(old)  # guard ScriptClip call; script may uses arrays
	""") : NOP

	filtered = ScriptClip(orig, __frame_filter_src, show, after_frame)

	dummy = use_reader ? Eval("""
		old = ArrayDelimiterSet(CRLF)	# guard end
		var_params = ArrayOpArrayFunc(filenames, fvars, "__frame_filter_readpars")
		old = ArrayDelimiterSet(old)	# restore caller's settings
		var_times = ArrayFill(1, filevars)
		filtered = filtered.FilterVarChain("ConditionalReader", var_times, var_params)
	""") : NOP
	
	return filtered
}
