Log in

View Full Version : Can I access the script filename in a predefined string variable?


martin53
5th March 2009, 22:06
I usually name .avs scripts same as the video files.
Usually, my first script line reads something like 's= "myVideo" ' and I refer to that string in the source functions, appending ".avi", ".wav" or whatever.

It would be extremely convenient to have a predefined variable (like "last"), that allowed me to use the name of the script file within the script.

I would then just set 's' to the script name and as soon as I copied an .avs template to the filename of a video file, the script would work instantly on that file - no more need to edit the script!

Maybe even calling a script that is called "myVideo--TFF.avs" is able to open "myVideo.avi" and setting a TFF switch - but that would require string separation commands, and I don't think I saw functions like BASIC's Left(), Mid() and InStr() in the doc..?

Can anyone please help me on this?

EDIT: I am copying stickboy's previous solution from the other thread here. :thanks: stickboy!
- I just changed from complete name to basename for *.avs files, because this way you just need to write 'GetScriptBasename()+".avi"' to reference your video file -

function GetScriptBasename()
{
Try
{
assert(false)
}
Catch(err_msg)
{
err_msg = MidStr(err_msg, FindStr(err_msg, "(") + 1)
filename = LeftStr(err_msg, StrLen(err_msg) - FindStr(RevStr(err_msg), ",") - 4)
return filename
}
}
Please note that you must enter the function directly into the .avs script. You cannot use it from an .avsi include file.

squid_80
6th March 2009, 01:19
There's LeftStr, MidStr, RightStr and FindStr functions. Unfortunately there's no function (that I know of) to give the name of the current script, maybe IanB will add it if we ask nicely enough. ;)

krieger2005
6th March 2009, 10:01
I remember someone asked for something similar before. Till them nothing happend. Maybe none asked IanB :-D.

juhok
6th March 2009, 13:07
I've also been looking for something like this. :)

Gavino
6th March 2009, 14:22
It's been done before. See this thread; in particular, stickboy's solution.

squid_80
6th March 2009, 14:28
Lol stickboy's right, that is sick ;)

stickboy
7th March 2009, 01:04
mf really deserves the credit/blame for the concept. :)

jmartinr
11th March 2009, 14:04
I tried to solve the problem by writing a plugin that retrieves the commandline and from there gets the name of the script. It was my first C++ program and fun to make, and it works ok in a lot of cases, but not always (it doesn't work if you open the script from an open file dialog).

The other solution that's posted before is better.

Getting the commandline from a plugin also gives the opportunity of getting the name of the calling program, which in turn gives a lot of possibilities for other tweaks.

If anyone is interested in my new ProgramName solution which retrieves the name of the calling program, just say so.

squid_80
11th March 2009, 14:10
Getting the program name using VC++ is easy: _get_pgmptr().

jmartinr
11th March 2009, 15:00
Getting the program name using VC++ is easy: _get_pgmptr().

OK. It was my first C++ avisynth thingy. ;) The interesting part is maybe the possibility in avisynth to generate different output for different programs, for example a simple fast output for previewing (with for example framenumbers) and a denoised slow output for encoding. You could also use this value to process things differently in the avisynth filter of ffdshow.

J_Darnley
11th March 2009, 15:07
If anyone is interested in my new ProgramName solution which retrieves the name of the calling program, just say so.

/me sticks his hand up with great enthusiasm

I was looking for this about a week ago so that the script could automatically switch from the previews I was doing to the slow(ish) encoding script.

In the end I just ended up using (true) ? a : b and manually editing the true/false.

jmartinr
11th March 2009, 16:28
/me sticks his hand up with great enthusiasm

I was looking for this about a week ago so that the script could automatically switch from the previews I was doing to the slow(ish) encoding script.

In the end I just ended up using (true) ? a : b and manually editing the true/false.

You can get it at: http://www.roelofs-coaching.nl/blobs/downloads/ProgramName.zip.

jmartinr
11th March 2009, 17:21
Getting the program name using VC++ is easy: _get_pgmptr(). I get using that a failed assertion: _pgmptr !=NULL

vampiredom
21st November 2011, 05:02
I know this is a fairly old thread... I remember reading it when it was new; as determining the script name is something that would be important and handy for me. I have revisited the problem from time to time, finding no perfect solution. (and to my knowledge, no complete solution for AviSynth 2.5.8 exists)

I do believe, however, that I have made a "slightly" more elegant modification to this wonderfully dirty method of getting the script name. Given the limitation that the error itself (from which the script name is parsed) can only work in a script and not in an .avsi file, I have striven to pare down the scripting as much as possible.

First, let's make a parsing function called _ScriptName() and put that into an .avsi file:

function _ScriptName(string err_msg) {
err_msg = MidStr(err_msg, FindStr(err_msg, "(") + 1)
filename = LeftStr(err_msg, StrLen(err_msg) - FindStr(RevStr(err_msg), ","))
return filename
}

Then, in your .avs script, you can use the _ variable to catch the error and hold the filename, so long as no other variables in your script are called _ :

Try {_} Catch(_) {_=_ScriptName(_)}

# now access it for some function
subtitle(_)

It seems to me that this is something you could call once and only once, at the very beginning of a script, since the script name will never change.

I like the _ because it is brief as can be and it reminds me of Special Variables in other scripting languages. Plus, you only need one line of code in your script to get the variable - and it is a cool and bizarre-looking line at that!

Chikuzen
21st November 2011, 05:50
avs2.6 has internal functions ScriptName()/ScriptFile()/ScriptDir().
What is lost does not have anything and many obtain, that is the reason I use 2.6.0a3.

Gavino
21st November 2011, 10:26
... I have striven to pare down the scripting as much as possible.
Yes, good idea, extract the common part into a function which need be written only once.

function _ScriptName(err_msg) {
err_meg = default(err_msg, "")
...
}
No need for the 'default' line, since you have made err_msg a mandatory parameter (by not putting quotes around the name in the function header). However it should be declared as a string:
function _ScriptName(string err_msg)

Actually, just spotted you have used err_meg in the default line, so the assigned value was never used. :)

jmartinr
21st November 2011, 10:29
Try {_} Catch(_) {_=_ScriptName(_)}

# now access it for some function
subtitle(_)
Why don't you keep it simple and call your variable ScriptName?

vampiredom
21st November 2011, 17:12
No need for the 'default' line, since you have made err_msg a mandatory parameter (by not putting quotes around the name in the function header). However it should be declared as a string:

Oops! Pure sloppiness on my part. Edited and fixed. Thanks!

Why don't you keep it simple and call your variable ScriptName?

Well, whether "_" or "ScriptName" is simpler is a matter of opinion, I guess. I like the _ because it is so amazingly brief (I am actually surprised you can use that as a variable name!) Really though, it reminds of using Perl's $_ variable ... and I love Perl.

vampiredom
22nd November 2011, 20:09
For completeness and forward-compatibility, it would make sense to have the _ScriptName() function attempt to return the results of the native function for those who have AviSynth 2.6 installed (or more future versions, presumably)



# in .avs script
Try {_} Catch(_) {_=_ScriptName(_)}
AVSfilename = _

# in .avsi file
function _ScriptName(string err_msg) {
Try {
# If AviSynth 2.6 is installed, use the native function
ScriptName()
} Catch(err) {
err_msg = MidStr(err_msg, FindStr(err_msg, "(") + 1)
filename = LeftStr(err_msg, StrLen(err_msg) - FindStr(RevStr(err_msg), ","))
filename
}
}

jmartinr
23rd November 2011, 00:34
Or maybe:

# in .avs script
Try {_ = ScriptName()} Catch(_) {_=_ScriptName(_)}
AVSfilename = _

# in .avsi file
function _ScriptName(string err_msg) {
err_msg = MidStr(err_msg, FindStr(err_msg, "(") + 1)
filename = LeftStr(err_msg, StrLen(err_msg) - FindStr(RevStr(err_msg), ","))
filename
}
}

vampiredom
23rd November 2011, 01:01
Or maybe:
# in .avs script
Try {_ = ScriptName()} Catch(_) {_=_ScriptName(_)}
AVSfilename = _

# in .avsi file
function _ScriptName(string err_msg) {
err_msg = MidStr(err_msg, FindStr(err_msg, "(") + 1)
filename = LeftStr(err_msg, StrLen(err_msg) - FindStr(RevStr(err_msg), ","))
filename
}
}


Indeed. That is an option (though it appears you have an extra "}" in the function there). I like the previous approach, however, as it keeps the line in script as brief as possible... but it really does not matter. Either way, I think it is about as good as it will get for AviSynth 2.5.8 compatibility.

How about others here: do you have a preference as to whether the attempt at 2.6's native ScriptName() is tried in the .avs or the function?

Gavino
23rd November 2011, 11:19
do you have a preference as to whether the attempt at 2.6's native ScriptName() is tried in the .avs or the function?
I don't think it matters much either way, but FWIW I think jmartinr's solution is slightly 'cleaner', as
- it uses one try/catch instead of two;
- it does not depend on '_' being previously undefined (and so can be used more than once in a script);
- it makes the function more self-contained - its job is then simply to extract the file name from a specified error message, so it could in principle be used in other contexts.

vampiredom
23rd November 2011, 17:06
FWIW I think jmartinr's solution is slightly 'cleaner', as [...]

Alright then. Those are reasons enough for me! Here it is again, almost like in jmartinr's post but cleaned up a little more (and using '_' in the function for brevity and consistency)

# in .avs script
Try {_ = ScriptName()} Catch(_) {_=_ScriptName(_)}
AVSfilename = _

# in .avsi file
function _ScriptName(string _) {
_ = MidStr(_, FindStr(_, "(") + 1)
LeftStr(_, StrLen(_) - FindStr(RevStr(_), ","))
}

As good as it gets?

alzamer2
6th September 2012, 21:21
if you put theses function in the top of your avs file you will get the same effect of ScriptName(), and ScriptDir() in version 2.58

Function ScriptName(){try{_}catch(err_msg){return Chr(34)+RevStr(MidStr(RevStr(MidStr(err_msg,Findstr(err_msg,"(")+1)),FindStr(RevStr(MidStr(err_msg,Findstr(err_msg,"("))),",")+1))+Chr(34)}}
Function ScriptFile(){try{_}catch(err_msg){return Chr(34)+MidStr(RevStr(MidStr(RevStr(MidStr(err_msg,Findstr(err_msg,"(")+1)),FindStr(RevStr(MidStr(err_msg,Findstr(err_msg,"("))),",")+1)),StrLen(RevStr(MidStr(RevStr(MidStr(err_msg,Findstr(err_msg,"(")+1)),FindStr(RevStr(MidStr(err_msg,Findstr(err_msg,"("))),",")+1)))-FindStr(MidStr(RevStr(MidStr(err_msg,Findstr(err_msg,"(")+1)),FindStr(RevStr(MidStr(err_msg,Findstr(err_msg,"("))),",")+1),"\")+2)+Chr(34)}}
Function ScriptDir(){try{_}catch(err_msg){return Chr(34)+RevStr(MidStr(MidStr(RevStr(MidStr(err_msg,Findstr(err_msg,"(")+1)),FindStr(RevStr(MidStr(err_msg,Findstr(err_msg,"("))),",")+1),FindStr(MidStr(RevStr(MidStr(err_msg,Findstr(err_msg,"(")+1)),FindStr(RevStr(MidStr(err_msg,Findstr(err_msg,"("))),",")+1),"\")))+Chr(34)}}

StainlessS
6th September 2012, 22:04
You need to remove the CHR(34)'s
EDIT: They are already strings, it's good to enclose in quotes before you give a filename to eg a DOS
command, but not before eg concatenating file name node to a directory, you would need to remove the
quotes, concatenate and then put them back again, not good.
EDIT: Name changes might be good too, eg ScriptDir25 or whatever.

EDIT: this might be handy,

ver = VersionNumber() # Float, Implemented v2.07

StainlessS
6th September 2012, 23:37
Thought it might be an idea to point out somewhere in these simulated ScriptName etc threads that
SMPlayer (built on MPlayer)) returns returns paths with a '/' separator instead of DOS '\' causing
the simulated functions to fail, 2.6 functions cope just fine. EDIT: Perhaps it dont, see next post.

StainlessS
7th September 2012, 00:13
Correction on previous post, v2.6 may not cope just fine when called via eg smplayer with Unix style '/' path separators.



# 2.6, Windows Media Player 2
Scriptname= C:\z\26.avs
ScriptDir= C:\z\
Scriptfile= 26.avs

simulated scriptdir= C:\z\


# 2.6 smplayer
Scriptname= C:/z/26.avs
ScriptDir= C:\z\
Scriptfile= 26.avs

simulated scriptdir= C:/z/26.avs, line 10)


2.6 ScriptDir DOS style '\' whereas, ScriptName uses Unix '/', presume this one or other is an error.

StainlessS
7th September 2012, 23:17
# _GetWorkingDir(), Get Current Working Directory as used by Avisynth for easy importing of scripts:- By StainlessS
# Unaffected by problems suffered by either 2.6a3 Script??? functions or synthetic versions, eg AVSPMod (null paths)
# or smplayer (unix style slash).
# Can live anywhere, unaffected by location of the function, can avsi autoload or import.
# Any script using "SetWorkingDir()" will of course change the return value, but assuming working dir not changed,
# then should return the location of your main AVS script. May have advantage over eg ScriptDir as can deliberately
# use SetWorkingDir to something other than the main script directory.
Function _GetWorkingDir(){Try{Import("?\")}Catch(_){s=FindStr(_,Chr(34))_=MidStr(_,s+1,FindStr(_,"?")-s-1)}_}

Function GetFullPathName(String Path,String n) {
# Convert relative path name to full path name. By StainlessS
# If n (path or filename) starts with eg "C:" or "\\" then returns n.
# Otherwise, appends n to the Path arg ("" defaults Current WorkingDir) and returns the result.
# Result may be either a filename or directory converted from relative to explicit, dependant upon n.
n=StrReplace(n,"/","\")(FindStr(n,":")!=2 && FindStr(n,"\\") != 1)? Eval("""
Path=(Path=="")?_GetWorkingDir():StrReplace(Path,"/","\")
Path=(FindStr(RevStr(Path),"\")==1)?Path:Path+"\"
n=(FindStr(n,"\")==1)?MidStr(n,2):n n=Path+n"""): NOP n
}

Function StrReplace(string s,string find,string replace) # Repeated, string replacements
# Original:- http://forum.doom9.org/showthread.php?p=1540504#post1540504 By Vampiredom, Gavino, IanB
#{i=s.FindStr(find)return(i==0?s: s.LeftStr(i-1)+replace+s.MidStr(Strlen(find)+i).StrReplace(find,replace))}
# Converted to use RT_Stats RT_StrAddStr() to avoid 2.58/2.6a3 string concatenation bug:-
{i=s.FindStr(find) return(i==0?s:RT_StrAddStr(s.LeftStr(i-1),replace,s.MidStr(Strlen(find)+i).StrReplace(find,replace)))}

Function StrReplaceDeep(string s,string find,string replace) # DEEP Repeated, string replacements
# When replacing eg pairs of SPACE characters by single SPACE, StrReplace can leave some pairs non replaced.
# Assumes that you want to rescan where replaced string could constitute part of a new find substring,
# Length of replace must be shorter than length of find, else will call StrReplace instead.
# Based On:- http://forum.doom9.org/showthread.php?p=1540504#post1540504 By Vampiredom, Gavino, IanB
# {i=s.FindStr(find)return i==0?s:s.LeftStr(i-1)+( strlen(replace)<strlen(find)? \
# StrReplaceDeep(replace+s.MidStr(Strlen(find)+i),find,replace) : replace+StrReplace(s.MidStr(Strlen(find)+i),find,replace))}
# Converted to use RT_Stats RT_StrAddStr() to avoid 2.58/2.6a3 string concatenation bug:-
{i=s.FindStr(find)return i==0?s:RT_StrAddStr(s.LeftStr(i-1),( strlen(replace)<strlen(find)? \
StrReplaceDeep(RT_StrAddStr(replace,s.MidStr(Strlen(find)+i)),find,replace) : \
RT_StrAddStr(replace,StrReplace(s.MidStr(Strlen(find)+i),find,replace))))}



Added StrReplaceDeep function, to fix problem noted 2 posts later.

martin53
29th September 2012, 15:08
@all,
after mf/stickboy's help, I made myself an .avs file template in 2009. I can create this template by using shortcuts in various file commanders, or dragging a video file onto a vbs icon, or using windows' "new" context menu command ...

In my case, the template contains the try ... function, but I gave that function the name Me().

Thus:
function Me() {
Try { assert(false) } Catch(err_msg) {
err_msg = MidStr(err_msg, FindStr(err_msg, "(") + 1)
filename = LeftStr(err_msg, StrLen(err_msg) - FindStr(RevStr(err_msg), ",") - 4)
return filename
}}

Below, the template says
Show(Me+"") #object oriented people say: Me.Show
and that's all.


Show() is another function that I put together over the years. It checks for existence various extensions to Me, so it can work the same, whether Me is the basename of an .avi, a .mp4, a .mpg, a .flv ... and it uses totally different source filters, depending on the found extension, of course. It automatically Audiodub()s two sources for demuxed media etc.
Show() also automatically splices up to about 20 media files together. I.e. the script 01+02.avs will find the sources 01.avi and 02.avi, and present them as one.

And I made Show() also parse the string Me not only for the file name, but in fact that string can contain AviSynth commands. I decided to separate the part of the Me string that comes in front of the first pair of semicolons, and to use the rest of the script name as space that is executed by Eval():
pos = findstr(name, ";;")
args = pos > 0 ? MidStr(name, pos+2) : ""
name = pos > 0 ? LeftStr(name, pos-1) : name
...
GEval( Replace( Replace( args, ";;", chr(13) ), "''", chr(34) ) )

That means I can write an AVS script into the file name of the script itself, where I type a pair of ;; for a newline and a pair of single quotes '' for a quote ".

The reason for adding an empty string +"" to Me for Show() is, of course, that I can also add script commands to a file that is open in the editor, instead of changing the file name in this case.

Why am I writing all this in the forum?

First, because it is one possible answer on how to modify the script behaviour easily, without opening an editor - by a different variable definition in the name of two scripts (e.g: two template files myfile;;preview=true.avs and myfile;;preview=false.avs provide the variable preview inside your script, so it can react on it. Show() reacts on a set of variables I need often.

Second, to point out the importance of having the base name, in contrast to the complete file name, of the .avs script. Of course, that can easily be derived from ScriptName. But that again needs one user function to be written (many of us will have to do so, or one does it and many copy it), so it would be less effort in total - and reasonable - if AviSynth provided ScriptBaseName right away.

StainlessS
15th October 2012, 22:42
Problem in StrReplace() script function: 2 posts earlier, and here:
http://forum.doom9.org/showthread.php?p=1540504#post1540504


Q="[10] 9 -0.13 0.16 0.004 0.99927"

RT_Debug("Source_string ='",Q+"'")
x=StrReplace(Q," "," ") # Repeated replace pairs of SPACE's with single SPACE, ie SPACE compact.
RT_Debug("StrReplace ='",x+"'")
y=StrReplaceDeep(Q," "," ") # Repeated replace pairs of SPACE's with single SPACE, ie SPACE compact.
RT_Debug("StrReplaceDeep='",y+"'")

return colorbars()

Function StrReplace(string s,string find,string replace) # Repeated, string replacements
# Original:- http://forum.doom9.org/showthread.php?p=1540504#post1540504 By Vampiredom, Gavino, IanB
#{i=s.FindStr(find)return(i==0?s: s.LeftStr(i-1)+replace+s.MidStr(Strlen(find)+i).StrReplace(find,replace))}
# Converted to use RT_Stats RT_StrAddStr() to avoid 2.58/2.6a3 string concatenation bug:-
{i=s.FindStr(find) return(i==0?s:RT_StrAddStr(s.LeftStr(i-1),replace,s.MidStr(Strlen(find)+i).StrReplace(find,replace)))}

Function StrReplaceDeep(string s,string find,string replace) # DEEP Repeated, string replacements
# When replacing eg pairs of SPACE characters by single SPACE, StrReplace can leave some pairs non replaced.
# Assumes that you want to rescan where replaced string could constitute part of a new find substring,
# Length of replace must be shorter than length of find, else will call StrReplace instead.
# Based On:- http://forum.doom9.org/showthread.php?p=1540504#post1540504 By Vampiredom, Gavino, IanB
# {i=s.FindStr(find)return i==0?s:s.LeftStr(i-1)+( strlen(replace)<strlen(find)? \
# StrReplaceDeep(replace+s.MidStr(Strlen(find)+i),find,replace) : replace+StrReplace(s.MidStr(Strlen(find)+i),find,replace))}
# Converted to use RT_Stats RT_StrAddStr() to avoid 2.58/2.6a3 string concatenation bug:-
{i=s.FindStr(find)return i==0?s:RT_StrAddStr(s.LeftStr(i-1),( strlen(replace)<strlen(find)? \
StrReplaceDeep(RT_StrAddStr(replace,s.MidStr(Strlen(find)+i)),find,replace) : \
RT_StrAddStr(replace,StrReplace(s.MidStr(Strlen(find)+i),find,replace))))}


Results

00000006 18.30790710 [2872] RT_Debug: Source_string =' [10] 9 -0.13 0.16 0.004 0.99927'
00000007 18.32215691 [2872] RT_Debug: StrReplace =' [10] 9 -0.13 0.16 0.004 0.99927'
00000008 18.34622955 [2872] RT_Debug: StrReplaceDeep=' [10] 9 -0.13 0.16 0.004 0.99927'


Both above funcs have standard Avisynth versions (commented out) and RT_StrAddStr() version which fixes a bug in 2.58 & 2.6a3.

EDIT:
Have edited to implement as a new separate function, StrReplaceDeep (alternative name suggestions ?).

martin53
2nd December 2012, 21:50
I am using V2.60, build: Aug 28 2012 [18:17:07].

Usage of ScriptName() etc. throws an error. :confused:

jmartinr
2nd December 2012, 22:24
I am using V2.60, build: Aug 28 2012 [18:17:07].

Usage of ScriptName() etc. throws an error. :confused:

And what error might that be? What does it say?

StainlessS
3rd December 2012, 16:48
And what error might that be? What does it say?

And also, from whence did you obtain Aug 2012 executable.

(ScriptName is builtin to 2.6) EDIT: Although it will (I think) be using script version instead, if supplied.

martin53
3rd December 2012, 18:54
Yep, sorry. I really forgot to be more specific.

Version.Subtitle(foo) says I don't know what "foo" means as expected.
Version.Subtitle(ScriptName) says Script error: Invalid Arguments to function "Subtitle"
Version.Subtitle(ScriptName()) says the same, also Version.Subtitle(ScriptDir), Version.Subtitle(Scriptfile) with and without additional function brackets.

Version.Subtitle("<"+string(Scriptname)+">") produces the version clip with <> subtitle.

assert(false,IsString(Scriptname)?"true":"false") returns false, likewise IsBool, IsClip, IsFloat, IsInt and Defined. While assert(false,IsString(foo)?"true":"false") returns I don't know...

ScriptName seems to be existent but of no type somehow.

I cannot remember where I downloaded the package from. Its file name is avisynth_2.60MTalpha_SEt_120828. The dll properties reveal version 2.6.0.3, 1.65MB from 08/28/2012 16:45

jmartinr
4th December 2012, 10:59
Here it works.

Version.Subtitle(ScriptName)

Using Avisynth 2.60, build may 16 2012. If it's important to you, you might want to change versions.

Don't remember where I got this from, but it is an MT-version. It's still in my dowload-archive as a 7z-file. If you want you can download it at: http://roelofs-coaching.nl/downloads/avisynth.7z (http://roelofs-coaching.nl/downloads/avisynth.7z)

Gavino
4th December 2012, 11:16
Here it works.

Using Avisynth 2.60, build may 16 2012.
Judging from the date, that is the previous version of SEt's 2.60 MT build, while martin53 appears to be using the latest one.

Looks like a bug has been introduced in the latest version - I don't know if SEt reads all the threads here, so I suggest you report it on the 2.60 MT thread.

vdcrim
4th December 2012, 16:25
So the ScriptName function you're using is the included in AviSynth 2.6 or one of the script functions posted in this thread? If it's the former your problem must be that the program you're using to load the script doesn't support the v2.6 interface.

There's two ways to load an AviSynth script, using the VFW interface and loading AviSynth directly as a library and then calling env->Invoke + Eval. The ScriptName, ScriptDir and ScriptFile functions just return the string saved in a global variable of the same name that is set by AviSynth when using the VFW approach. On the second case the variables are still declared by AviSynth when creating the environment but as the script file is not opened by AviSynth itself they are left uninitialized. This is called in the AviSynth language a variable of type void. Void variables can't be created by scripting, I figure that that's why there isn't a IsVoid function.

So the caller application is responsible for setting those variables before creating the clip. I don't know how many programs currently do this. AvsPmod only started doing it in the recent 2.4.0 version.

Edit:there seems to be a mismatch between the AviSynth source code files and the wiki, as the later refers to not declared variables also as void.

martin53
4th December 2012, 18:06
vdcrim,
thanks for the helpful info.

I was using the included, not a script function, and I was using AvsPmod 2.3.0

The reason I appreciate the builtin function is that you cannot use script functions from included .avsi files - they return the name of that script instead of the calling one. So when you provide a filter script to others that needs to write files and you want to prevent collisions if the user opens more than one clip at a time... you need something unique, and the calling script name is good for that.

I verified that indeed opening the same script in VDub shows the string correctly.
However, between VDub (1.10.1 portable) and AvsPmod (2.4.0), there is an annoying difference:

in VDub, ScriptName shows the filename with path, while in AvsPmod, it shows only the filename without path.
In VDub, ScriptFile shows only the filename without path, while in AvsPmod, it shows the complete filename with path.

Now which one is intended and which is wrong? The terms 'name' and 'file' are not very unmistakable.
Edit: according to the prior usage of the function names in this thread, AvsPmod is wrong. Solution is in pyavs.py lines 126/127, but I cannot build AvsPmod.

I kindly ask the AviSynth developer team to please clarify the intention of the variable names and initiate the solution. Should I help to forward the issue somehow?
Edit: posted the issue in the AvsPmod thread (http://forum.doom9.org/showthread.php?p=1603869#post1603869)

Gavino
4th December 2012, 18:14
There's two ways to load an AviSynth script, using the VFW interface and loading AviSynth directly as a library and then calling env->Invoke + Eval. The ScriptName, ScriptDir and ScriptFile functions just return the string saved in a global variable of the same name that is set by AviSynth when using the VFW approach. On the second case the variables are still declared by AviSynth when creating the environment but as the script file is not opened by AviSynth itself they are left uninitialized.
If the script is in a file, the usual way to load it using Avisynth as a library is to call env->Invoke("Import") (not Eval).
It's the Import() function (not the VfW interface per se) that sets the global variables, so ScriptName() should still work with this approach. AvsP[Mod] is different as it already has the text in a buffer, so uses Eval instead of Import.

This is called in the AviSynth language a variable of type void. Void variables can't be created by scripting, I figure that that's why there isn't a IsVoid function.
The Defined (http://avisynth.org/mediawiki/Internal_functions/Boolean_functions)() function is the equivalent of IsVoid. A void variable (http://avisynth.org/mediawiki/Script_variables) can be created by passing a default parameter, or (in v2.60) using the Undefined (http://avisynth.org/mediawiki/Internal_functions/Control_functions)() function.

Edit:there seems to be a mismatch between the AviSynth source code files and the wiki, as the later refers to not declared variables also as void.
Not sure what you mean here. Where is the mismatch?

Gavino
4th December 2012, 18:28
in VDub, ScriptName shows the filename with path, while in AvsPmod, it shows only the filename without path.
In VDub, ScriptFile shows only the filename without path, while in AvsPmod, it shows the complete filename with path.

Now which one is intended and which is wrong?
As implemented by Avisynth, ScriptName is the actual string passed in to Import(), and may or may not be the full path, depending on the caller.

ScriptDir and ScriptFile are the full path of the containing folder, and the basic filename part, respectively.

See this post by IanB.

vdcrim
4th December 2012, 19:30
according to the prior usage of the function names in this thread, AvsPmod is wrong
My fault, will be fixed soon.

If the script is in a file, the usual way to load it using Avisynth as a library is to call env->Invoke("Import") (not Eval)
Oh I forgot about Import. It's still an useful note as other applications besides AvsP may need to use eval.


The Defined (http://avisynth.org/mediawiki/Internal_functions/Boolean_functions)() function is the equivalent of IsVoid. A void variable (http://avisynth.org/mediawiki/Script_variables) can be created by passing a default parameter, or (in v2.60) using the Undefined (http://avisynth.org/mediawiki/Internal_functions/Control_functions)() function.

Not sure what you mean here. Where is the mismatch?
Void can refer to not initialized variables on both the AviSynth scripting language and C/C++. I was referring to the second case. An user can't create a variable in such state from a script. The AviSynth documentation forgets that second case, which makes sense as the user shouldn't find that kind of variable anyway, though it's what happened in this topic. Defined returns True for these variables, so it's not exactly equivalent to IsVoid.

Gavino
4th December 2012, 20:41
Void can refer to not initialized variables on both the AviSynth scripting language and C/C++. I was referring to the second case. An user can't create a variable in such state from a script. The AviSynth documentation forgets that second case, which makes sense as the user shouldn't find that kind of variable anyway, though it's what happened in this topic. Defined returns True for these variables, so it's not exactly equivalent to IsVoid.
Sorry, I still don't fully understand what you are saying - perhaps I am misunderstanding completely.

Inside Avisynth, the value of a (script) variable is represented by an instance of C++ class AVSValue.
Such objects have a 1-character type field which denotes the script language type of the value (eg 'i' for int, 'f' for float).
A C++ variable of type AVSValue, if simply declared and not initialised, will have its type set to 'v' by the AVSValue constructor, meaning void (or 'undefined'), and not just left as random garbage.

The Defined() function merely checks the value of this type field, returning false for 'v' and true for anything else, so will return 'false' for an uninitialised variable.

And indeed that's what martin53 found in this case:
assert(false,IsString(Scriptname)?"true":"false") returns false, likewise IsBool, IsClip, IsFloat, IsInt and Defined.
ie Defined(Scriptname) returned 'false'.

vdcrim
4th December 2012, 20:59
You're right. Shouldn't just have trusted on my memories from the discussion (http://forum.doom9.org/showthread.php?p=1590302#post1590302) some months ago. Also testing mistakes.