Working example of script with python?

The beta with this fix in it is available now.

The actual problem was very simple really - inside Opus the global script objects were initialised in two steps:
[ol][li]Call the script engine's AddNamedItem method to add the object to its namespace[/li]
[li]Add the object to our own internal object map[/li][/ol]

Unfortunately, Python (unlike VBScript/JScript) queries us for the object while it is still processing the AddNamedItem call. In effect, in Python the process was:

[ol][li]Call the script engine's AddNamedItem method to add the object to its namespace[/li]
[li]<- Python calls back to us, to obtain the object's IDispatch interface[/li]
[li]Add the object to our own internal object map[/li][/ol]

This was of course failing, because at the time Python called us to query for the object, we hadn't yet added it to our internal map - and so the call would fail.
The fix was simply to add the object to our own map first, before adding it to the script engine (i.e. swap the order of the two steps).

1 Like

I can confirm that DOpus object works correctly now. :slight_smile:

Script Add-ins in python are still not recognized, so I don't know how about Script object.

As far as I can see the only reason it wouldn't be recognized is because Python hasn't configured the registry properly, so Opus is unable to map from a .py extension to the Python ActiveScript handler. If you add the following registry key it should "just work".

[HKEY_CLASSES_ROOT\Python.File\ScriptEngine] @="Python"
python.zip (222 Bytes)

I got it to work with perl too (I abused rename script to test it).
I used this:

${"DOpus"}->Output("Hello");

Somehow it looks a bit different but, well.. It worked.
I seem to remember writing something similar for earlier DO versions too.

Now if only script addins and such accepted .pl files, or for that matter, just about any file.
If other filetypes (iow, excluding .vbs and .js) were required to use the @script tag in the first line
just as rename scripts, that shouldn't be a problem.

Basically, DO does what it do with the files, and if it's an unrecognized fileextension, it checks the first line
for a @script tag. If it doesn't have it, the file is ignored, but if it does then DO tries to use the specified engine.

Did you actually read my last post? :slight_smile:

[quote]Basically, DO does what it do with the files, and if it's an unrecognized fileextension, it checks the first line
for a @script tag. If it doesn't have it, the file is ignored, but if it does then DO tries to use the specified engine.[/quote]

No this isn't true. Script add-ins never use a @script line - only the file extension is important.

[quote="jon"]Did you actually read my last post? :slight_smile:

[quote]Basically, DO does what it do with the files, and if it's an unrecognized fileextension, it checks the first line
for a @script tag. If it doesn't have it, the file is ignored, but if it does then DO tries to use the specified engine.[/quote]

No this isn't true. Script add-ins never use a @script line - only the file extension is important.[/quote]
I know, it was a suggestion, not a statement of how it currently works.

I tried replicating what you suggested for python and it seems to work.
I only have to work out the proper names to use for the functions.

Yay, function names are the normal ones.
To use addins with perl:
Modify jon's suggestion above for perl, iow something like:

[HKEY_CLASSES_ROOT\Perl\ScriptEngine] @="PerlScript"

To use DOpus and similar top-level objects, use

${"DOpus"}->Output("Test");

To specify data for properties and similar use

$varname{"propertyname"}=123;

and so on.

To specify events and such use:

[code]
sub OnInit{
my $initData=shift;
#${"DOpus"}->Output("OnInit");
$initData{"name"} = "Test";
$initData{"desc"} = "Test Perl";
$initData{"copyright"} = "";
$initData{"version"}="0.1";
$initData{"default_enable"}=1;
return 0;
}

sub OnAfterFolderChange{
my $afterFolderChangeData=shift;
${"DOpus"}->Output($afterFolderChangeData->tab->path);
}[/code]

The above works, but it seems that if I use strict, v5.14, or similar, then it gets compilation errors.
"Compilation error (0x80004005) Error at line 1, position 0" and similar doesn't tell much, as it says the same for just about any error.

I wonder how it actually should be used in perl. Tips or hints are welcome.

Where is the declaration for the hash that contains this element?

${'DOpus'}

You probably want to end the module with a:

1;

[quote="MrC"]Where is the declaration for the hash that contains this element?

${'DOpus'}

You probably want to end the module with a:

1;[/quote]
Huh? DOpus is apparently defined in %main::.
I've never really bothered with the plethora of vartypes available in perl, but DOpus is apparently
a scalar to begin with (I walked %main:: to confirm its existence and found a scalar DOpus), but using
$DOpus caused it to return something about using Dispatch on an empty something.

Now for some reason I can use $DOpus->Output (instead of the above) and it actually does what it should without
the "Can't call method "Dispatch" on an undefined value at -e line 5. (0x80004005)" error that
happened whenever I tried to use it normally.
If I use strict, v5.14 or similar it still gets that dispatch error I got annoyed with earlier on.

So $DOpus does exist in main, but ${"DOpus"} is something entirely different. You meant ${DOpus} if you were trying to use the disambiguating syntax of a variable name. Just use $DOpus, since you're going to dereference anyway with $DOpus-> ....

Is the code that contains the sub's in the same package as main, or is it in another namespace?

When using "use strict", you are disabling the auto-vivification of variables, and must declare them specifically, so since ${"DOpus"} is incorrect, you get a compilation error.

$DOpus is added by DOpus, and was one of the items returned by a stackoverflow tip I found.
I had to modify the code to use OutputDebugString to actually see any output (using DebugView) though.
I'm under the impression that just about everything not inside packages is in %main (considering the result of walking %main).

This works until I enable "use strict 'vars';":

[code]use strict 'refs';
use strict 'subs';
#use strict 'vars';
sub OnInit{
my $initData=shift;

$DOpus->Output("OnInit START");
$initData->{name} = "Test";
$initData->{desc} = "Test Perl";
$initData->{copyright} = "";
$initData->{version}="0.1";
$initData->{default_enable}=1;

$cmd = $initData->AddCommand();
$cmd->{desc} = $initData->{desc};
$cmd->{hide} = 0;
$cmd->{icon} = "info";
$cmd->{label} = "TestIt";
$cmd->{method} = "OnTestIt";
$cmd->{name} = "TestIt";
$cmd->{template} = "";
$DOpus->Output("OnInit END");
return 0;
}

Implement the TestIt command

sub OnTestIt{
my $scriptCommandData=shift;
$DOpus->Output("TestIt");
}

sub OnAfterFolderChange{
my $afterFolderChangeData=shift;
$DOpus->Output($afterFolderChangeData->tab->path);
}
1;[/code]

If I take your script, use use perl -c on it:

$ perl -c in.pl
Global symbol "$DOpus" requires explicit package name at in line 7.
Global symbol "$cmd" requires explicit package name at in line 14.
Global symbol "$cmd" requires explicit package name at in line 15.
Global symbol "$cmd" requires explicit package name at in line 16.
Global symbol "$cmd" requires explicit package name at in line 17.
Global symbol "$cmd" requires explicit package name at in line 18.
Global symbol "$cmd" requires explicit package name at in line 19.
Global symbol "$cmd" requires explicit package name at in line 20.
Global symbol "$cmd" requires explicit package name at in line 21.
Global symbol "$DOpus" requires explicit package name at in line 22.
Global symbol "$DOpus" requires explicit package name at in line 29.
Global symbol "$DOpus" requires explicit package name at in line 34.
in had compilation errors.

Yup, I finally got it to work.

I forgot the "my $cmd" at the top.
I had to use $::DOpus->Output("Test"), not $DOpus->Output("Test") to be able to use "use strict;".

Working result:

[code]use v5.14;
use warnings;
use strict;

sub OnInit{
my $initData=shift;
my $cmd;
$::DOpus->Output("OnInit START");
$initData->{name} = "Test";
$initData->{desc} = "Test Perl";
$initData->{copyright} = "";
$initData->{version}="0.1";
$initData->{default_enable}=1;

$cmd = $initData->AddCommand();
$cmd->{desc} = $initData->{desc};
$cmd->{hide} = 0;
$cmd->{icon} = "info";
$cmd->{label} = "TestIt";
$cmd->{method} = "OnTestIt";
$cmd->{name} = "TestIt";
$cmd->{template} = "";
$::DOpus->Output("OnInit END");
return 0;
}

Implement the TestIt command

sub OnTestIt{
my $scriptCommandData=shift;
$::DOpus->Output("TestIt");
}

Called to display an About dialog for this script

sub OnAboutScript{
my $aboutData=shift;
my $dlg = $::DOpus->Dlg();
$dlg->{window} = $aboutData->window;
$dlg->{message} = "Test";
$dlg->{title} = "About Test";
$dlg->{buttons} = "OK";
$dlg->{icon} = "info";
$dlg->Show();
}

sub OnAfterFolderChange{
my $afterFolderChangeData=shift;
$::DOpus->Output($afterFolderChangeData->tab->path);
}

1;[/code]

Exactly, because $DOpus is in the main namespace.

$::DOpus is equivalent to $main::DOpus.

@MrC, Thanks for the help and suggestions.
It seems it is possible to create workable perl addins now, not just rename scripts.
I haven't really cared much for anything but the regex engine in perl, and then I still need to that the slow way (excluding the regex syntax itself).
The perl syntax is, well, unfamiliar to say the least.
But then again, it is by far the most flexible language I know of, for better or worse (it does give you alot of rope to, well..).

Great!

I wrote a Perl program that interfaces with JRiver's Media Center to allow uses to run Perl "scriptlets' or simple Perl expressions against a selection of tracks in Media Center. I've provided a bunch of sample scriptlets that perform a variety of actions, from operating on and updating metadata, creating playlists, perform acoustic fingerprint matching of songs, etc. It uses the clipboard as the means of efficient communication of the row/column data for the selection. But I can easily see this script being converted to work w/DOpus. It would provide yet another scripting language to use to manipulate DOpus selections (or other).

Have a look: yabb.jriver.com/interact/index.php?topic=85990.0

There's also a Discogs and AMG script on that board too...

What's the advantage of using this strange language over something like JScript again? :slight_smile:

We'll probably disagree, but Perl is a much more powerful, richer and (time-tested) scripting language with thousands of modules available. It is also easier to do simple things than in VBScript (a toy language) and JScript. The brevity of syntax and Do What I Mean behavior of Perl should not be underestimated.

Try doing simple arbitrary captures and replacements to a string - how many lines of code does this require in either the {VB,J}Script languages? Now extend that to include expression-based computed values in the replacement side. Often these are simple one-liners.

And didn't you have to create a Vector object because Yeah, JScript has some issues with arrays which we weren't aware of until recently? So the language JScript is so good that it turns out that JScript arrays do not work correctly, at least in the way we need them to. :slight_smile:

If you want to test my statements above, try implementing my Dynamic Renamer in JScript. You'll may be surprised at the difficulty and complexity required to do that.

That said, I appreciate where you're coming from here, and would encourage folks to use the languages that they are most productive in. The good news is that now matter what the language, DOpus users win.