Scripting Tips & Tricks
(MediaMonkey) Scripting in general
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.
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 while the scripting help 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.
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)
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.
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 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 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.
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
Usually indexes start from 0 (e.g. for normal arrays). However, sometimes (e.g. for string positions) they start from 1.
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:
- Put all these DB operations in an transaction, i.e. use ISDBDatabase::BeginTransaction and ISDBDatabase::Commit.
- Close already running SQL queries before you call things like ISDBSongData::UpdateDB.
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.
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).