M3U Ad Log inside M3U Music Log

Scheduling hourly M3U music logs with entries for d:\ad logs\ad break 1000.m3u seems to work - the Ad Log is treated as a Container Item and plays in 1 Player, however - When re-saving an M3U playlist, the Ad Log entry is removed. I can understand that perhaps an M3U isn’t able to understand a complex Container entry - but the log is just path names and usual #mAirList Break/Dummy markers:

D:\SONGS\Artist - Title.mp3 D:\JINGLES\ID - Into Ads 1.mp3 D:\AD LOGS\AD BREAK 1000.m3u D:\JINGLES\ID - Back To The Music 1.mp3

Is there a simple solution to this whilst keeping the logs in M3U format ?

M3U files are “flat” and contain one file per line. Containers however establish some kind of nested “tree” hierarchy (you can even place containers inside containers!). This is a job for XML.

What we could do is insert markers into the M3U file:

Song 1.mp3 Song 2.mp3 #mAirList BEGINCONTAINER Ad 1.mp3 Ad 2.mp3 Ad 3.mp3 #mAirList ENDCONTAINER Song 3.mp3 Song 4.mp3 ...

This would require a little coding on my side, but should be possible.


Sounds good - So in other words, anything between the markers actually comes from the “advert” playlist ?

Song 2.mp3 #mAirList BEGINCONTAINER advert list.m3u #mAirList ENDCONTAINER Song 3.mp3

The above would be my original music log, for example.

I can’t speak for others, but I’m not fussed how mAirList loads/treats the advert log - Whether it becomes a container or opens the playlist contents and puts them in as individual items - There is very little need to stop an ad break half-way through! But maybe you could err on the side of flexibility - if they import as seperate items, the user can re-arrange or add items (quickly) as opposed to a container…

Maybe :wink:

Let’s recall how mAirList loads and saves M3U files. When you load a playlist like the one from your original example

D:\SONGS\Artist - Title.mp3 D:\JINGLES\ID - Into Ads 1.mp3 D:\AD LOGS\AD BREAK 1000.m3u D:\JINGLES\ID - Back To The Music 1.mp3

mAirList will note the .m3u extension and load the contents as a container item, as you noticed. With this mechanism of referencing additional M3U files, importing Containers is no problem.

When it comes to exporting M3U, we run into problems. mAirList must save the data to a single M3U file. And it does not remember the names of the original sub-M3Us either. This is why we need a mechanism to store a complex hierarchy of a master playlist plus optional Container items with sub-playlists into a single M3U file.

The BEGINCONTAINER/ENDCONTAINER mechanism proposed above should be a nice solution. mAirList will create a Container item of anything found between these keywords, and you can also nest the BEGINCONTAINER/ENDCONTAINER blocks inside each other in order to create complex hierarchies (whoever would need this :wink: However, you can still omit the BEGINCONTAINER/ENDCONTAINER blocks and reference an external .m3u file when importing M3U data.

Another option is to establish a new “playlist file” item class. It will be treated as a single item, just like the containers, but instead of storing the contents of the M3U file, it will just keep a reference to the M3U file.


I think from a programming/class hierarchy POV, the idea of a new ‘playlist file’ object is a better and ‘cleaner’ solution to this than ‘faking it’ by adding clumsy-looking BEGIN/END CONTAINER statements.

It would make re-saving a playlist ‘as it was’ much easier; unless anything within the referenced M3U file is changed by the user (e.g. changing the order of the items) between loading and re-saving the playlist. Should you note such changes to ‘internal’ playlists in mAirList, and propose to also re-save the ‘internal’ M3U when the user re-saves the amended ‘outer’ playlist?

My answer is ‘yes:’ the outer playlist would be saved as it originally was (with the ‘.m3u’ line inside it) regardless, but the user might assume that the changed internal file is also being saved when that happens. So I think you would need, when a playlist is changed, to offer the option to also save any internal playlists. Whether you do this with a simple ‘Save changed internal playlists as well YES/NO?’ message box, or a dialog offering radio buttons labelled: ‘only save external playlist,’ ‘ask for each changed internal playlist,’ and ‘save all changed internal playlists without asking,’ is up to Torben :).


When inserting a playlist file (.m3u or even .mlp) into the main playlist, either by drag & drop or by loading an m3u file which references the sub-.m3u file, there are three possible ways to handle this inner playlist file:

  1. Expand the playlist and insert its contents as single items into the main playlist.
  2. Create a Container item in the main playlist and load the sub-playlist into it.
  3. Create a “playlist file” playlist item which only keeps a reference to the .m3u/.mlp file.

The difference between #2 and #3 is that #2 load the contents of the sub-playlist into the (complex) main playlist. #3 does not only keep a reference to the sub-playlist file, and the contents of the sub-playlist is only read when the item is loaded into a player for playback.

mAirList 2.0 only supports #1. mAirList 2.1 supports #1 and #2 at the moment. When loading .m3u, #2 is the default for inner playlists. When using drag&drop, #1 is the default, and #2 will be performed when holding the Shift key during drag&drop.

When saving, a playlist created in the #2 way should be saved as a single file, containing the complex structure. This can be easily done with mAirList’s native XML file, and emulated with .m3u as described above. When saving #3, only the reference to the external playlist file should be saved into the main playlist.

So what I need to do is implement the #3 way of handling sub-playlists.


Sort of a reverse-solution required to what was discussed here…

Trying out scheduling blocks of RegionalContainers, but would like them displayed in the Playlist as individual items. Because scheduling each container is major problem in the music scheduler (see my other topic for how it’s done!), I’ve decided to use a 2nd copy of StationPlaylist to create the Ad blocks… Now, each Ad Set is an M3U file but obviously when referencing them in another M3U playlist, we are presented with a Container Item that can’t access the Regional properties ;(

Is there some way of opening the sub-Playlist within the main ?


+C:\Adverts\Mon 1927.m3u

Like with HotDir we can expand a folder…

You mean like this?

#mAirList INCLUDE c:\wherever\whatever.m3u

(No, this does not work currently.)

Yes, just like that… :slight_smile:

This would cover the eventual scenario of commercial stations scheduling their adverts + music/jingles separately (which most do), and being able to merge them for playout. Also, the DJ could then access/edit the RegionalContainer.

Please try the latest snapshot #503 :wink:

Perfect… Thanks again.

I doscovered last night that if you play out from a container, only the container (not its individual contents) is logged by mAirList. In other words, you can’t won’t see entries for individual ads in the (mAirList!) log if you play them from a container. This might well be something your traffic management staff might not be happy about! :o


This is true, but it’s rather a feature request than a bug. Remember that container items appear as a single item to the user and also to the other internal components of mAirList. The player does not know that it is actually a sequence of items.

Here’s some technical background for those interested in the internal architecture of mAirList:

Each IPlaylistItem (except for those which are not playable like dummy items) has a method BuildSource. You pass information about the audio device to use (given as an IAudioDevice interface) and receive an IAudioSource interface. The IAudioSource interface can then be used to start and stop playback of that item on that device, for seeking, setting the volume etc. Take a look at the CHM file for the various methods of IAudioSource.

When loading an item into a player, the player creates two IAudioSource: one for ordinary playback (using the playback device) and one for PFL (using the PFL device).

For single files and BASS.DLL playback, the object returned by BuildSource is really simple, because it just passes the requested actions (start, stop, seek, …) to BASS.DLL using the corresponding calls from the BASS API.

For containers, the audio source object is much more complex: It creates a separate IAudioSource for each item from the internal playlist (using BuildSource again), and starts and stops them as needed as you call its IAudioSource methods. For example, when seeking to a specific position, it needs to determine which of the items is the “current” one at that point, seek and start it and stop any other.

However, both objects implement the very same IAudioSource interface. The player does only use this interface to start and stop playback, and he cannot tell one from the other. In fact, he does not care.

IAudioSource has the opportunity to offer a “dynamic title”, retrieved by the GetDynamicTitle method. This feature is used by the stream and container audio source objects in order to display the title of the current song in the player. Presently, this is the only way for the player to “look into” the source and identify some “internal sub-structure”.

In order to implement logging for the individual sub-items from the container, the IAudioSource object needed a way to advise the player that playback of a different internal item has begun. This is not difficult, but it requires a little work.

PS: Cad, I just noticed that you posted this in the Feature Request forum. Well done!