Scripting Tips & Tricks (MM4): Difference between revisions

From MediaMonkey Wiki
Jump to navigation Jump to search
(Added link to Iviewer.dll (required by OLEView))
No edit summary
Line 1: Line 1:
==(MediaMonkey) Scripting in general==
==(MediaMonkey) Scripting in general==


=== 'Correctly' update song properties ===
Using the SongData object, you can either update the database/library (UpdateDB) and/or update the file's tags (WriteTags). So there's no way to let the song changes be saved like the user selected in the Options panel (menu Tools > Options > Library > Tags & Playlists > "Update tags when editing properties").
Using the SongData object, you can either update the database/library (UpdateDB) and/or update the file's tags (WriteTags). So there's no way to let the song changes be saved like the user selected in the Options panel (menu Tools > Options > Library > Tags & Playlists > "Update tags when editing properties").
However, the UpdateAll method for the SongList object ''does'' take into account this user-specified option. So you can create a new SongList object using SDB.NewSongList and add your SDBSongData object(s) to it. Then call the UpdateAll method on the songlist, and your song(s) will be saved in user-specified way.
However, the UpdateAll method for the SongList object ''does'' take into account this user-specified option. So you can create a new SongList object using SDB.NewSongList and add your SDBSongData object(s) to it. Then call the UpdateAll method on the songlist, and your song(s) will be saved in user-specified way.


 
=== See MM Scripting interface using OLEView ===
MS Visual Studio contains a tool called [http://www.microsoft.com/downloads/details.aspx?familyid=5233B70D-D9B2-4CB5-AEB6-45664BE858B6&displaylang=en OLEView] ("OLE Viewer" or "OLE/COM Object Viewer") ([http://download.microsoft.com/download/win2000platform/oleview/1.00.0.1/nt5/en-us/oleview_setup.exe direct link]), which can show the type library of the SongsDB object: "MediaMonkey Library". It requires the Iviewers.dll, which is not included, but can be downloaded from [http://www.dlldll.com/downdll/2757.html here] or other 3rd-party locations. There, you can see all supported properties and methods of the MediaMonkey scripting interface. This can be handy to find out new scripting methods while the scripting help isn't up-to-date yet.
MS Visual Studio contains a tool called [http://www.microsoft.com/downloads/details.aspx?familyid=5233B70D-D9B2-4CB5-AEB6-45664BE858B6&displaylang=en OLEView] ("OLE Viewer" or "OLE/COM Object Viewer") ([http://download.microsoft.com/download/win2000platform/oleview/1.00.0.1/nt5/en-us/oleview_setup.exe direct link]), which can show the type library of the SongsDB object "MediaMonkey Library". It requires the Iviewers.dll, which is not included, but can be downloaded from [http://www.dlldll.com/downdll/2757.html here] or other 3rd-party locations. There, you can see all supported properties and methods of the MediaMonkey scripting interface. This can be handy to find out new scripting methods in case that the scripting reference isn't up-to-date yet.
<br>The way to get there: ''OleView'' > Type Libraries > MediaMonkey Library > (double click)
<br>The way to get there: ''OleView'' > Type Libraries > MediaMonkey Library > (double click)
<br>and then in the ''ITypeLib Viewer'' > SongsDB (MediaMonkey Library) > Interfaces.
<br>and then in the ''ITypeLib Viewer'' > SongsDB (MediaMonkey Library) > Interfaces.


 
=== Detecting docking of a panel ===
When you un(dock) a dockable panel, the OnResize event is triggered twice:
When you un(dock) a dockable panel, the OnResize event is triggered twice:
*Once while the panel is being (un)docked with DockedTo = 0
*Once while the panel is being (un)docked with DockedTo = 0
*Once after the panel has been (undocked): with DockedTo = -1 (panel undocked) or DockedTo = X (panel docked, X is the number that represents the docking position)
*Once after the panel has been (undocked): with DockedTo = -1 (panel undocked) or DockedTo = X (panel docked, X is the number that represents the docking position)


=== Keep reference to Form/Panel ===
When you create a form or panel, always add a reference to the SDB.Objects dictionary. If you don't add it, the form/panel will be gone immediately after you created it, with or without error message. Instead of using the SDB.Objects dictionary you can also store a reference as a global script variable, in most cases.


A dockable panel always has to be added to the SDB.Objects dictionary. If you don't add it, it will be gone immediately after you created it.
=== Event mechanisms ===
 
There are still 2 event mechanisms available:
 
There are still 2 scripting mechanisms available:
*Using the (mostly deprecated) ''old event mechanism'' (using ''Control''.OnClickFunc and ''Control''.UseScript), your global variables aren't remembered in the event handlers (e.g. kind of like the script is reopened). For those scripts, you had to use ''ParentControl''.ChildControl("control name") or save object references to SDB's ''Objects'' dictionary.
*Using the (mostly deprecated) ''old event mechanism'' (using ''Control''.OnClickFunc and ''Control''.UseScript), your global variables aren't remembered in the event handlers (e.g. kind of like the script is reopened). For those scripts, you had to use ''ParentControl''.ChildControl("control name") or save object references to SDB's ''Objects'' dictionary.
*Using the ''new event mechanism'', your global variables ''are'' remembered so you can use their values in the event handlers. The Objects dictionary is now only necessary to communicate/store object references between different scripts.
*Using the ''new event mechanism'', your global variables ''are'' remembered so you can use their values in the event handlers. The Objects dictionary is now only necessary to communicate/store object references between different scripts.
==> So always use the new event mechanism where you can. Only for option panels (sheets) this is not yet possible. There you'll need to store values between the main program and the event handlers in SDB.Objects, in the INI or in the Registry.
So always use the new event mechanism where you can. Only for option panels (sheets) this is not yet possible. There you'll need to store values between the main program and the event handlers in SDB.Objects, in the INI or in the Registry.
 


=== Changing the current tree node ===
Changing the selected node from a script (using SDB.MainTree.CurrentNode = ...........) takes some time to happen, and it happens asynchronicly (the code execution doesn't wait until the node is really selected). For that reason, you can't use (get value of) SDB.MainTree.CurrentNode directly after you have assigned a new node to it (set value to), because changes won't have happened yet.
Changing the selected node from a script (using SDB.MainTree.CurrentNode = ...........) takes some time to happen, and it happens asynchronicly (the code execution doesn't wait until the node is really selected). For that reason, you can't use (get value of) SDB.MainTree.CurrentNode directly after you have assigned a new node to it (set value to), because changes won't have happened yet.


 
=== Interaction with MediaMonkey from outside ===
There are at least three ways to interact with MediaMonkey from an external program:
There are at least three ways to interact with MediaMonkey from an external program:
*Open the MediaMonkey.exe program with command line options (arguments).
*Open the MediaMonkey.exe program with command line options (arguments).
Line 35: Line 36:
*:Be sure to set ''SDB.ShutdownAfterDisconnect'' to ''False'' if you opened the MediaMonkey program by calling the SDB object, and you don't want it to be closed when your external program exits (or if you disconnect the SDB object = COM link).
*:Be sure to set ''SDB.ShutdownAfterDisconnect'' to ''False'' if you opened the MediaMonkey program by calling the SDB object, and you don't want it to be closed when your external program exits (or if you disconnect the SDB object = COM link).


'''Helpful sites:'''
*http://www.microsoft.com/scripting


'''Handy editors:'''
==Visual Basic Script==
*[http://www.vbsedit.com/ VBSEdit]
 
*[http://notepad-plus.sourceforge.net/ NotePad++]
=== Index in VBScript ===
*[http://www.pspad.com/ PSPad]
 
*[http://www.sapien.com/ PrimalScript]
Usually indexes start from '''0''' (e.g. for normal arrays). However, sometimes (e.g. for string positions or for [[ISDBCommonDialog::FilterIndex]]) they start from '''1'''.
*[http://www.microsoft.com/downloads/details.aspx?familyid=2f465be0-94fd-4569-b3c4-dffdf19ccd99&displaylang=en Microsoft VBScript 5.6 Debugger for Win 2000/XP]
 
*[http://www.editpadpro.com/ EditPad (Pro)]
=== Code readability ===
 
To maintain good readability of your scripting code, make sure to add comments where necessary, split large methods in smaller ones, use appropriate indentation (tabs or 2/3/4 spaces), and if necessary split long lines of code over several lines. To split a line of VBScript code (not text or numbers), add a ''space'' and an ''underscore'', and continue on the next line. Don't forget the space before the underscore or it won't work.
<source lang="vb">
MsgBox "This is quite a long text to display on one single line and for readability we better split it on multiple lines"
 
MsgBox "This is quite a long text to display on one single line" & " and for readability we better split it on multiple lines"
 
MsgBox "This is quite a long text to display on one single line" _
    & " and for readability we better split it on multiple lines"
</source>
In the third example the code is more readable, but the result is still the same: a message box with one long line of text. To split this over multiple lines, we preferably use the constant vbNewLine. If necessary, you can also use ''vbCr'' (Unix-style) or ''vbCrLf''(Windows-style). Using these constants is more clear than using respectively ''Chr(13)'' (Unix-style) or ''Chr(13) & Chr(10)'' (Windows-style).
<source lang="vb">
MsgBox "This is quite a long text to display on one single line" & vbNewLine _
    & " and for readability we better split it on multiple lines"
</source>


==Visual Basic Script==
=== Using Flags in VBScript ===


Usually indexes start from '''0''' (e.g. for normal arrays). However, sometimes (e.g. for string positions) they start from '''1'''.
The concept of [[Flags]] can be a difficult for novice programmers. Click the link for an explanation of how to use them in VBScript (or Visual Basic).


=== Links ===


'''Helpful sites:'''
'''Helpful sites:'''
*[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/0a8270d7-7d8f-4368-b2a7-065acb52fc54.asp User guide and language reference]
* [http://msdn2.microsoft.com/en-us/library/ms950396.aspx Reference for scripting resources]
*[http://www.microsoft.com/technet/scriptcenter/scripts/default.mspx?mfr=true Script Center Repository]
* [http://www.microsoft.com/technet/scriptcenter/default.mspx Microsoft Script Center]
*[http://www.w3schools.com/vbscript/default.asp W3Schools VBScript]
* [http://msdn2.microsoft.com/en-us/library/t0aew7h6.aspx VBScript User's Guide and Language Reference]
* [http://www.microsoft.com/technet/scriptcenter/scripts/default.mspx?mfr=true VBScript Script Repository]
* [http://www.w3schools.com/vbscript/default.asp W3Schools VBScript learning]
 
'''VBScript editors:'''
* [http://www.vbsedit.com/ VBSEdit] (debugging, object and COM lookup, integrated help)
* [http://notepad-plus.sourceforge.net/ NotePad++]
* [http://www.pspad.com/ PSPad]
* [http://www.sapien.com/ PrimalScript]
* [http://www.microsoft.com/downloads/details.aspx?familyid=2f465be0-94fd-4569-b3c4-dffdf19ccd99&displaylang=en Microsoft VBScript 5.6 Debugger for Win 2000/XP] (debugging)
* [http://www.editpadpro.com/ EditPad (Pro)]


==Database transactions==
== Database & SQL ==
 
=== Database transactions ===


Starting from MM 3.0 transactions are often used when working with database. It can cause some problems to script authors in case they don't know some details. One example where you can face a problem is when you use [[ISDBSongData::UpdateDB]] method while you have some SQL query open. What happens in this case is, that MM wants to start a transaction, but there's still an SQL query open. This results either in an error message (in debug build) or possibly an apparent freeze of MM in the release build.
Starting from MM 3.0 transactions are often used when working with database. It can cause some problems to script authors in case they don't know some details. One example where you can face a problem is when you use [[ISDBSongData::UpdateDB]] method while you have some SQL query open. What happens in this case is, that MM wants to start a transaction, but there's still an SQL query open. This results either in an error message (in debug build) or possibly an apparent freeze of MM in the release build.
Line 64: Line 91:
* Close already running SQL queries before you call things like [[ISDBSongData::UpdateDB]].
* Close already running SQL queries before you call things like [[ISDBSongData::UpdateDB]].


==SQL==
=== Creating complex SQL queries ===
 
To easily create complex SQL queries, you can use the Query graphical user interface in Access interface, and show the SQL code when you are done. In any case, make sure that your SQL code is organized is such a way that it can be understood easily, e.g. by putting SELECT, INSERT, FROM, ORDER BY, ... on separate lines with appropriate indentation.
To easily create complex SQL queries, you can use the Query graphical user interface in Access interface, and show the SQL code when you are done.
 


=== Avoid SQL date problems ===
One of the problems with SQL is that dates are often confused, which sometimes give programming bugs. The best way to circumvent this problem is by using the format #yyyy-mm-dd# for all dates in SQL (e.g. #2006-10-31# for 31th October 2006).
One of the problems with SQL is that dates are often confused, which sometimes give programming bugs. The best way to circumvent this problem is by using the format #yyyy-mm-dd# for all dates in SQL (e.g. #2006-10-31# for 31th October 2006).


 
=== Links ===
'''Helpful sites:'''
'''Helpful sites:'''
*[http://www.w3schools.com/sql/default.asp W3Schools SQL]
*[http://www.w3schools.com/sql/default.asp W3Schools SQL learning]

Revision as of 17:34, 4 November 2007

(MediaMonkey) Scripting in general

'Correctly' update song properties

Using the SongData object, you can either update the database/library (UpdateDB) and/or update the file's tags (WriteTags). So there's no way to let the song changes be saved like the user selected in the Options panel (menu Tools > Options > Library > Tags & Playlists > "Update tags when editing properties"). However, the UpdateAll method for the SongList object does take into account this user-specified option. So you can create a new SongList object using SDB.NewSongList and add your SDBSongData object(s) to it. Then call the UpdateAll method on the songlist, and your song(s) will be saved in user-specified way.

See MM Scripting interface using OLEView

MS Visual Studio contains a tool called OLEView ("OLE Viewer" or "OLE/COM Object Viewer") (direct link), which can show the type library of the SongsDB object "MediaMonkey Library". It requires the Iviewers.dll, which is not included, but can be downloaded from here or other 3rd-party locations. There, you can see all supported properties and methods of the MediaMonkey scripting interface. This can be handy to find out new scripting methods in case that the scripting reference isn't up-to-date yet.
The way to get there: OleView > Type Libraries > MediaMonkey Library > (double click)
and then in the ITypeLib Viewer > SongsDB (MediaMonkey Library) > Interfaces.

Detecting docking of a panel

When you un(dock) a dockable panel, the OnResize event is triggered twice:

  • Once while the panel is being (un)docked with DockedTo = 0
  • Once after the panel has been (undocked): with DockedTo = -1 (panel undocked) or DockedTo = X (panel docked, X is the number that represents the docking position)

Keep reference to Form/Panel

When you create a form or panel, always add a reference to the SDB.Objects dictionary. If you don't add it, the form/panel will be gone immediately after you created it, with or without error message. Instead of using the SDB.Objects dictionary you can also store a reference as a global script variable, in most cases.

Event mechanisms

There are still 2 event mechanisms available:

  • Using the (mostly deprecated) old event mechanism (using Control.OnClickFunc and Control.UseScript), your global variables aren't remembered in the event handlers (e.g. kind of like the script is reopened). For those scripts, you had to use ParentControl.ChildControl("control name") or save object references to SDB's Objects dictionary.
  • Using the new event mechanism, your global variables are remembered so you can use their values in the event handlers. The Objects dictionary is now only necessary to communicate/store object references between different scripts.

So always use the new event mechanism where you can. Only for option panels (sheets) this is not yet possible. There you'll need to store values between the main program and the event handlers in SDB.Objects, in the INI or in the Registry.

Changing the current tree node

Changing the selected node from a script (using SDB.MainTree.CurrentNode = ...........) takes some time to happen, and it happens asynchronicly (the code execution doesn't wait until the node is really selected). For that reason, you can't use (get value of) SDB.MainTree.CurrentNode directly after you have assigned a new node to it (set value to), because changes won't have happened yet.

Interaction with MediaMonkey from outside

There are at least three ways to interact with MediaMonkey from an external program:

  • Open the MediaMonkey.exe program with command line options (arguments).
  • Using the same Windows Messages (SendMessage/PostMessage) as in Winamp (WM_USER and WM_COMMAND). MM partially emulates how WinAmp works (not 100%, but very close) and so it can use WinAmp plug-ins. The class name to communicate with is "Winamp v1.x".
  • Using OLE Automation, which can be very easily used e.g. from VB Script.
    Dim SDB : Set SDB = CreateObject("SongsDB.SDBApplication")
    SongsDB.SDBApplicationClass SDB = new SongsDB.SDBApplicationClass();
    Be sure to set SDB.ShutdownAfterDisconnect to False if you opened the MediaMonkey program by calling the SDB object, and you don't want it to be closed when your external program exits (or if you disconnect the SDB object = COM link).


Visual Basic Script

Index in VBScript

Usually indexes start from 0 (e.g. for normal arrays). However, sometimes (e.g. for string positions or for ISDBCommonDialog::FilterIndex) they start from 1.

Code readability

To maintain good readability of your scripting code, make sure to add comments where necessary, split large methods in smaller ones, use appropriate indentation (tabs or 2/3/4 spaces), and if necessary split long lines of code over several lines. To split a line of VBScript code (not text or numbers), add a space and an underscore, and continue on the next line. Don't forget the space before the underscore or it won't work.

MsgBox "This is quite a long text to display on one single line and for readability we better split it on multiple lines"

MsgBox "This is quite a long text to display on one single line" & " and for readability we better split it on multiple lines"

MsgBox "This is quite a long text to display on one single line" _
     & " and for readability we better split it on multiple lines"

In the third example the code is more readable, but the result is still the same: a message box with one long line of text. To split this over multiple lines, we preferably use the constant vbNewLine. If necessary, you can also use vbCr (Unix-style) or vbCrLf(Windows-style). Using these constants is more clear than using respectively Chr(13) (Unix-style) or Chr(13) & Chr(10) (Windows-style).

MsgBox "This is quite a long text to display on one single line" & vbNewLine _
     & " and for readability we better split it on multiple lines"

Using Flags in VBScript

The concept of Flags can be a difficult for novice programmers. Click the link for an explanation of how to use them in VBScript (or Visual Basic).

Links

Helpful sites:

VBScript editors:

Database & SQL

Database transactions

Starting from MM 3.0 transactions are often used when working with database. It can cause some problems to script authors in case they don't know some details. One example where you can face a problem is when you use ISDBSongData::UpdateDB method while you have some SQL query open. What happens in this case is, that MM wants to start a transaction, but there's still an SQL query open. This results either in an error message (in debug build) or possibly an apparent freeze of MM in the release build.

In order to prevent this problem, you can either:

Creating complex SQL queries

To easily create complex SQL queries, you can use the Query graphical user interface in Access interface, and show the SQL code when you are done. In any case, make sure that your SQL code is organized is such a way that it can be understood easily, e.g. by putting SELECT, INSERT, FROM, ORDER BY, ... on separate lines with appropriate indentation.

Avoid SQL date problems

One of the problems with SQL is that dates are often confused, which sometimes give programming bugs. The best way to circumvent this problem is by using the format #yyyy-mm-dd# for all dates in SQL (e.g. #2006-10-31# for 31th October 2006).

Links

Helpful sites: