How to enumerate items in mAirListDB Folders using mAirListScript?

One for Torben I think?
(and I hope you and your family are all well?) :smiley:

In a script, I need to connect to a mAirListDB, find a mAirListDB folder by name, then make an internal list (or collection, or similar) of all the Items in that folder. I can see some objects and methods in mAirListScript I will probably need to use, like IDatabase and IDatabaseTree, but I can’t see any obvious methods to navigate around mAirListDB. Can you help, please?

I am wondering if I’ll need to use the ntFolder constant to identify a Folder (then check its Name), then find its child nodes and use ntItem to find Items ‘in’ that Folder, as part of a larger process to walk the mAirListDB ‘tree?’

Ultimately my aim is to place selected Items into the running playlist.

Any and all help appreciated!


In v4.1 and newer, you can use the ProcessRequest method which allows access to a HTTP-like API to the database. (Actually the same API that is provided by the new mAirListDB Server component.)

In earlier versions, you can access the database via SQL.

For example, the following (untested) script picks a random item from a folder named “Some Folder” and inserts it at the top of the playlist:

  conn: IZConnection;
  stmt: IZPreparedStatement;
  rs: IZResultSet;
  folderID: integer;
  itemID: integer;
  item: IPlaylistItem;

  conn := ImAirListDB(Database(0)).GetConnection;

  stmt := conn.PrepareStatement('SELECT idx FROM folders WHERE name=?');
  stmt.SetString(1, 'Some Folder');
  rs := stmt.ExecuteQueryPrepared;
  if not rs.Next then begin
    SystemLog('Folder not found');
  folderID := rs.GetInt(1);

  stmt := conn.PrepareStatement('SELECT item FROM item_folders WHERE folder=? ORDER BY RANDOM()');
  rs := stmt.ExecuteQueryPrepared;
  if not rs.Next then begin
    SystemLog('There are no items in that folder');
  itemID := rs.GetInt(1);

  item := Database(0).CreatePlaylistItem(IntToStr(itemID)); 

  CurrentPlaylist.Insert(0, item);


Hope this helps.

And thanks, we’re all (busy but) fine.

Many thanks! I’ll give that a try later. ;D


I’ve tried your sample code, but unfortunately, I can’t get the statement

  conn := ImAirListDB(Database(0)).GetConnection;

to work. I got the message Unknown identifer ‘ImAirListDB’.

Next, I tried this:

dbMairList: IDatabase;
conn: IZConnection;

dbMairlist := Instance.GetDatabases.GetItem(0);
conn := dbMairlist.GetConnection;
I got the message Unknown identifer ‘GETCONNECTION’.

Any idea what I’m doing wrong? (This is in v4.2, incidentally, which I’m running on a demo license. mAirListDB itself seems AOK.)


Ok, I see.

First of all, Database(0) returns an IDatabase interface which only allows access to the general routines of a database, but not the SQL part - remember that not every database connection in an SQL database, iTunes is a notable exception.

So generally, you must typecast the return value from IDatabase to the correct interface type in order to access the more specific methods. For mAirListDB, that interface is ImAirListDB (in v3.x) or IDBConnection (from v4.x), respectively.

Now in v4.2, things are even more complicated, because not every mAirListDB is an SQL database - there is now “mAirListDB Internet Client” which accesses the database not directly through SQL, but through the new mAirListDB Server. So IDBConnection does not have any method GetConnection anymore.

Instead there is a method GetBackend which will return a reference to the “backend object” of type IDBBackend, which can be used to issue the HTTP-like requests I mentioned earlier. For a direct SQL-based mAirListDB connection, the backend can be typecasted into ISQLDBBackend, where you can finally request a reference to the connection object.

Pretty difficult, huh?

conn := ISQLDBBackend(IDBConnection(Database(0)).GetBackend).GetConnection;

[quote=“Torben, post:5, topic:8401”]Pretty difficult, huh?

conn := ISQLDBBackend(IDBConnection(Database(0)).GetBackend).GetConnection; [/quote]

I’d use the words ‘mildly awkward,’ rather than ‘pretty difficult.’ If I were a software vendor, I’d obviously describe it as ‘flexible,’ ‘future-proof,’ and ‘designed for future expansion.’ ;D

Seriously though, I’ll try that later. I’m going to a panto tonight (“oh no you’re not!”). Oh yes I am. :’( I’m not a fan of panto, just going as moral support for a friend who’s MD of the whole fiasco. :-\


Well, the script interface is exactly the same as the internal interface inside mAirList’s code. And “easy scripting” is not the main design goal of the internal code.

It looks like the GetBackend method isn’t exposed to mAirListScript:
Unknown identifier ‘GETBACKEND’.

Also, the string GetBackend doesn’t exist anywhere in mAirList.exe. That’s usually a good clue that a method, variable, etc. hasn’t been exposed. :wink:


Try build 1670 please.

If you’re interested, I can also show you how to use the HTTP-like interface; it might be more convenient than direct SQL access.

By all means: I’m always happy to learn, as you know!

I will try build 1670 later: I have to make a fish pie (starting with filleting and skinning a line-caught trout donated by a friend), and that always seems to take forever. :smiley:

Thanks again, and I look forward to seeing how to implement the HTTP-ish interface thingamabob. I’m guessing (probably incorrectly) that XML is likely to be involved somewhere? :slight_smile:

UPDATE: This has worked perfectly: thank you! 8)


This doesn’t seem to work anymore (version 6.2).

I figured out that:
IZConnection -> ISQLConnection
IZPreparedStatement -> ISQLPreparedStatement
IZResultSet -> ISQLResultSet
ImAirListDB -> ISQLDatabase

But it gives me the error “(10,3) Cannot cast an interface”…


In the ZIP Version of mAirlist, you can find a “Database Script”
Can this help, with your problem?

Found the solution, it’s actually much easier then above:


It returns an IPlaylist from which I can take 1 item with Random(), ideal!