Add advertisements and news

Hello Torben,

Could someone please :-* correct this original ‘add advertisements and news’ script (from the German forum) for the latest version of mAirList? This script looks nice to me (us) but it has several error messages and after trying and changing during 1 hour, I give it up sry.

Some tryings:

  • invalid number of parameters (removed [ , true ] and [ , false ] ) ?
  • unknown identifier: CreateContainerPlaylistItem (fixed with Factory. ) ?
  • unknown identifier: CreatePlaylistItemFromFile (fixed with Factory. ) ?

Regards
Vincent.

[code]const
MusicDir = ‘D:\TestRadio\Muziek’;
AdsDir = ‘D:\TestRadio\Ads’;
NewsDir = ‘D:\TestRadio\Nieuws’;
JinglesDir = ‘D:\TestRadio\Jingles’;

// Sekunden vor der vollen Stunde, bevor der News-Opener kommt
NewsDelay = 7;

var
ads: IContainerPlaylistItem;
pi: IPlaylistItem;
nextHour: TDateTime;
delay: single;

begin
// nächste Stunde als Delphi TDateTime berechnen
nextHour := (trunc(now *24) + 1) / 24;

// Werbung als Container laden
ads := CreateContainerPlaylistItem;
ads.GetPlaylist.LoadFromFile(AdsDir + FormatDateTime(‘yyyy-mm-dd-hh’, now) + ‘.m3u’, false);
IPlaylistItem(ads).SetTitle(‘Werbung’);

// ausrechnen, wann die Werbung starten muss, erstmal in Sekunden vor der vollen Stunde
delay := NewsDelay;
delay := delay + (IPlaylistItem(ads).GetDuration/10000000);

// jetzt umrechnen in TDateTime
delay := delay / (246060);

// Fixzeit setzen
IPlaylistItem(ads).SetStartTime(sttFixed, nextHour - delay);
CurrentPlaylist.Add(IPlaylistItem(ads));

// News-Opener einfügen
pi := CreatePlaylistItemFromFile(JinglesDir + ‘news-open.mp3’, true);
CurrentPlaylist.Add(pi);

// News einfügen
pi := CreatePlaylistItemFromFile(NewsDir + FormatDateTime(‘yyyy-mm-dd-hh’, nextHour) + ‘.mp3’, false);
CurrentPlaylist.Add(pi);

// News-Closer einfügen
pi := CreatePlaylistItemFromFile(JinglesDir + ‘news-close.mp3’, true);
CurrentPlaylist.Add(pi);

// Musik der nächsten Stunde einfügen
CurrentPlaylist.AppendPlaylist(CreatePlaylistFromFile(MusicDir + FormatDateTime(‘yyyy-mm-dd-hh’, nextHour) + ‘.m3u’));
end.[/code]

[quote=“Torben, post:10, topic:4321”]Das Script macht genau das, was ich oben beschrieben habe:

  1. Die Werbung als Container laden.
  2. Die Fix-Zeit des Containers so anpassen, dass die Werbung genau x Sekunden (ist oben konfigurierbar, Beispiel 7) vor der vollen Stunde zuende sind.
  3. News-Opener, -Inhalt und -Closer anhängen.
  4. Musik anhängen. Fertig :)[/quote]

Hi, trying to adapt this to an auto Playlist builder.

So far just trying to load a single item without joy (or any other girl). Here is the code:

[code]const
MusicDir1 = ‘C:\audio’;
MusicDir2 = ‘C:\audio2’;
MusicDir3 = ‘C:\audio3’;
MusicDir4 = ‘C:\audio4’;

VAR
PI: IPlaylistItem;

Begin

/ / Insert Music
pi: = Create Playlist Item From File (MusicDir1) + ‘’,

true);
CurrentPlaylist.Add (PI);
End.
End.[/code]

And the error:

Error:identifier expected

Any ideas appreciated.

Kind regards Tony

Here’s a corrected version of what you had:

[code]const
MusicDir1 = ‘C:\audio’;
MusicDir2 = ‘C:\audio2’;
MusicDir3 = ‘C:\audio3’;
MusicDir4 = ‘C:\audio4’;

var
pi: IPlaylistItem;

begin
// Insert Music
pi := CreatePlaylistItemFromFile(MusicDir1 + ‘’, true);
CurrentPlaylist.Add(pi);
end.[/code]

Corrections:

[ul][li]Removed space between //[/li]
[li]Made pi the same (not PI) on every occurrence[/li]
[li]Removed spaces from and after CreatePlaylistItemFromFile[/li]
[li]Removed extra ([/li]
[li]Removed space after CurrentPlaylist.Add[/li]
[li]Removed second End.[/li][/ul]

When you call a function like CurrentPlaylist.Add or CreatePlaylistItemFromFile, you must put the ( directly after the function name. You also cannot have any spaces in a function name!

Note that (for once!) I haven’t tested the above (hopefully fully corrected) code. But isn’t Music1 etc. just a folder and not actually a file?

BFN
CAD

Hi Cad, thanks for the corrections and pointers.

Unfortunately it still fails at unknown identifier ‘CreatePlaylistItemFromFile’

Yes the MusicDir1 is a folder, I was trying to load a file on a random basis from each folder without any form of scheduling rules. Pointing directly at an audio file and we still have an error - Unknown identifier 12:7):‘CreatePlaylistItemFromFile’.

Looking at the original example should we also be declaring a line that creates a playlist first.

Kind regards Tony

Hi, still working on this. the error message is now Unknown identifier ‘CreatePlaylistItemFromFile’.

Here is the code I am trying:

[code] var

pi:IPlaylistItem;

begin
pi :=CreatePlaylistItemFromFile(‘C:\audio\07b.wav’;
false);CurrentPlaylist.Add(pi):
end. [/code]

Any ideas?

Kind Regards tony

This works though:

begin CurrentPlaylist.LoadFromM3u('C:\ads\15.m3u'); end.

It adds to the current playlist but only if something is playing otherwise it replaces playlist, onto some mods.

You need to use the new “Factory” object.

pi := Factory.CreatePlaylistItemFromFileFromFile('C:\audio\07b.wav', false);

See the IFactory interface in the scripting help for other playlist items you can create through the factory.

Hi Torben, thanks but this code fails in 2.1.44.490

[code]var
pi:IPlayListItem;

begin
pi := Factory.CreatePlaylistItemFromFile(‘C:\audio\btp011a.mp3’, false);
end. [/code]

You will see from your code I have removed FromFile at 1 point as this generated an unknown identifier.

Kind regards tony

The real two things that I need to know to fix this are:

[ul][li]How to create a PlayListContainerItem (IFactory again?).[/li]
[li]How to Add a ‘PlaylistItemFromFile’ to a PlayListContainerItem.[/li][/ul]

Once I know the precise code to do both of those, I think I can make Vincent’s script work as originally intended, creating a Titled PlaylistContainerItem with a Fixed Start Time on its first item, which is Appended to the current Playlist followed by his other files, jingles, etc.

Is IFactory documented in the latest mairlistscript.chm? I know there are entries for CreatePlaylistItemFromFile and CreatePlaylistContainerItem, but those don’t seem to work, so maybe they should not be in the documentation? :wink:

BFN
CAD

You probably got a “type mismatch” error. This is because CreateContainerPlaylistItem item returns an IContainerPlaylistItem interface (to access the special container properties). You need to typecast it to IPlaylistItem to add it to the playlist.

var
  cpi: IContainerPlaylistItem;
  pi: IPlaylistItem;

begin
  // create a container
  cpi := Factory.CreateContainerPlaylistItem;

  // create a copy of the reference as an IPlaylistItem interface
  pi := IPlaylistItem(cpi);

  // now cpi can be used to access the container properties ...
  cpi.GetPlaylist.Add(Factory.CreatePlaylistItemFromFile('c:\firstfile.mp3', false));
  cpi.GetPlaylist.Add(Factory.CreatePlaylistItemFromFile('c:\secondfile.mp3', false));

  // ... and pi to access the ordinary item properties and to add that item to a playlist
  pi.SetTitle('Container with two files');

  CurrentPlaylist.Add(pi);
end.

(untested)

Hi Torben, many thanks this bit works. Over to Cad to finish the rest as Ihave already admitted to not being a programmer.

Kind Regards tony

btw;Is it possible to use a similar script without creating a container item first?

[quote=“Torben, post:9, topic:4993”] // create a copy of the reference as an IPlaylistItem interface pi := IPlaylistItem(cpi); [/quote]

AH! I had been trying:

  // access the container's Playlist (THIS DOES NOT WORK!)
  pi := cpi.GetPlaylist;

so your example clears all that up. Sorry to be so dim about Delphi, but as an increasing number of folks here know, I’m really a VB man at heart! ;D

Many thanks again: I can fix that script now.

To Tony: actually it’s much easier to do something similar without using a container! I think Vincent originally wanted to use a Container to have the ads. display as a single labelled item in the Playlist rather than as a stack of ads.

All that said, it’s been extremely useful for all of us to find out how to manipulate Containers within a script. I’ll post two versions of the results (using and not using a Container) once I’ve got this script working.

BFN
CAD

Cheers Cad. 2 reasons for the ads to be as individual items rather than a container.

1.It keeps the presenter awake!
2.As long as the item is played (with Idents in correct place), you can change the order “On The Fly”. So although a break may contain the same ads it can appear and sound slightly different.

Can you insert a message before the first item warning the presenter these items must be played, then close by saying thank you etc. Just for cheek!

I guess you could also add a comment to the Open Ident/Close Ident explaining this too, obviously comments may also need expanding as the audio is added to the playlist.

Hopefully not too much work, I’m just thinking of the non experienced presenter about hitting Ad Breaks.

Kind regards Tony

btw:other uses will be community features etc.

OK, I’ll first apologise for not yet having done the ‘non-container’ version. Sorry, Tony, but I’ve concentrated solely on the Container scripting, to ensure that I really understand it all.

On the container/item argument for ads.: it depends on your station and principally on your presenters.

If you have an experienced bunch who know how it all goes, you can run your ads. either way.

If you have a completely inexperienced bunch, there are arguments for both approaches: I would simply say ‘try both’ and then see which works better.

If you have presenters who think they are more experienced than they are ;), we found they had a tendency to ‘forget’ or ‘ignore’ playing ads. because ‘they spoil the flow and mood of my show’ ::slight_smile: or some similar rubbish. In other words, they were doing everything possible to resist playing ads. Eventually we had to use a sign-off sheet to force them to comply! So for those types of ego-centric presenters, I think a Container has plus points: it’s a ‘black box’ which they can’t ‘tinker’ with as much as a separate list of ads.

I 100% disagree with ‘please’ and ‘thank you’ messages for playing ads.! If your station has ads., playing the ads. out on time SHOULD be as inviolate as taking News on the hour, and if ANYone fails to do so, it should be a disciplinary offence with NO exceptions. Cajoling, pleading, etc. simply should not enter the picture: it should be a simple management/rules issue. (Learn from our mistakes!)

BFN
CAD

Vincent: here is my fully working and tested version of the script you originally posted. ;D
I have made a few very minor changes, including giving your News MP3 a fixed start time, and making the opener and closer jingles constants so you can change them more easily later. I also translated the original German comments so I’m sure you can replace those! :slight_smile:

// Original posted by Vincent Volmer
// New version by Cad Delworth

const
  ADS_DIR = 'D:\TestRadio\Ads\';
  JINGLES_DIR = 'D:\TestRadio\Jingles\';
  MUSIC_DIR = 'D:\TestRadio\Muziek\';
  NEWS_DIR = 'D:\TestRadio\Nieuws\';

  NEWS_OPENER = 'news-open.mp3';
  NEWS_CLOSER = 'news-close.mp3';

// Seconds before the hour to play the News Opener
  NEWS_DELAY = 7;

var
  ads: IContainerPlaylistItem;
  adsPlaylist: IPlaylist;
  adsContainerAsPlaylistItem, piNews: IPlaylistItem;
  nextHour: TDateTime;
  delay: single;

procedure AddCurrentPlaylistItemFromFile(f: String; b: boolean);
begin
  CurrentPlaylist.Add(Factory.CreatePlaylistItemFromFile(f, b));
end;

begin

  // calculate next hour as Delphi TDateTime
  nextHour := (trunc(now * 24) + 1) / 24;

  // create a new Container Item and put the ads. in it
  ads := Factory.CreateContainerPlaylistItem;
  adsPlaylist := ads.GetPlaylist;
  adsPlaylist.AppendPlaylist(Factory.CreatePlaylistFromFile(
    ADS_DIR + FormatDateTime('yyyy-mm-dd-hh', now) + '.m3u'
    ));

  // calculate when the advertising must start,
  // accounting for the seconds-before-the-hour delay
  delay := (adsPlaylist.GetDuration / 10000000) + NEWS_DELAY;

  // now convert to TDateTime
  delay := delay / (24 * 60 * 60);

  // reference the entire Container as a PlaylistItem and title it
  adsContainerAsPlaylistItem := IPlaylistItem(ads);
  adsContainerAsPlaylistItem.SetTitle(
    'Ads. before '
    + FormatDateTime('hh', nextHour)
    + ':00 News');

  // Set fixed start time for entire Container
  adsContainerAsPlaylistItem.SetStartTime(sttFixed, nextHour - delay);

  // Add Container PlaylistItem to current Playlist
  CurrentPlaylist.Add(adsContainerAsPlaylistItem);

  // Add News Opener to Playlist
  AddCurrentPlaylistItemFromFile(JINGLES_DIR + NEWS_OPENER, true);

  // insert News
  piNews := Factory.CreatePlaylistItemFromFile(
    NEWS_DIR + FormatDateTime('yyyy-mm-dd-hh', nextHour) + '.mp3', false
    )
  // set fixed start on-the-hour for the News, then add to Playlist
  piNews.SetStartTime(sttFixed, nextHour);
  CurrentPlaylist.Add(piNews);

  // Insert News Closer
  AddCurrentPlaylistItemFromFile(JINGLES_DIR + NEWS_CLOSER, true);

  // Paste music log for next hour
  CurrentPlaylist.AppendPlaylist(Factory.CreatePlaylistFromFile(
    MUSIC_DIR + FormatDateTime('yyyy-mm-dd-hh', nextHour) + '.m3u'
    ));

end.

I would however STRONGLY recommend that you add a description to your ‘hourly’ files, so that they would be named (for example):
2008-05-08-20-Ads.m3u or 2008-05-08-20-Music.m3u

I suggest this change because I found during testing that it is VERY easy to overwrite (say) the Music M3U file with the Ads M3U, or to be completely lost as to which file is which!

BFN
CAD

[quote=“Cad, post:14, topic:4993”]Vincent: here is my fully working and tested version of the script you originally posted. ;D
I have made a few very minor changes, including giving your News MP3 a fixed start time, and making the opener and closer jingles constants so you can change them more easily later. I also translated the original German comments so I’m sure you can replace those! :)[/quote]
Thank you very much Cad for changing the script. I’ll test it this weekend. This script makes it a lot easier to insert Ads and News. I’ll also compare your script with the original script to see if I can understand something of the changes you made… (I guess not…) :-\ And maybe, some day I’ll understand scripting… ::slight_smile:

I would however STRONGLY recommend that you add a description to your 'hourly' files, so that they would be named (for example): [b]2008-05-08-20-Ads.m3u[/b] or [b]2008-05-08-20-Music.m3u[/b]

I suggest this change because I found during testing that it is VERY easy to overwrite (say) the Music M3U file with the Ads M3U, or to be completely lost as to which file is which!

BFN
CAD


You are right about that (as usually :wink: ) It was only there for testing purposes but I’ll change it to ‘Music’ and ‘Ads’.

Have a nice weekend
Regards.,
Vincent Volmer

[quote=“Cad, post:13, topic:4993”]OK, I’ll first apologise for not yet having done the ‘non-container’ version. Sorry, Tony, but I’ve concentrated solely on the Container scripting, to ensure that I really understand it all.

On the container/item argument for ads.: it depends on your station and principally on your presenters.

If you have an experienced bunch who know how it all goes, you can run your ads. either way.

If you have a completely inexperienced bunch, there are arguments for both approaches: I would simply say ‘try both’ and then see which works better.[/quote]
I like the ‘container’ way… For the presentors I’ll keep it KIS (keep it simple) and, most importend, they don’t see what happends and, hopefully, don’t change anything.

If you have presenters who think they are more experienced than they are ;), we found they had a tendency to 'forget' or 'ignore' playing ads. because 'they spoil the flow and mood of my show' ::) or some similar rubbish. In other words, they were doing everything possible to [i]resist[/i] playing ads. Eventually we had to use a sign-off sheet to force them to comply! So for those types of ego-centric presenters, I think a Container has plus points: it's a 'black box' which they can't 'tinker' with as much as a separate list of ads.
100% agree with that.
I 100% disagree with 'please' and 'thank you' messages for playing ads.! If your station has ads., playing the ads. out on time SHOULD be as inviolate as taking News on the hour, and if ANYone fails to do so, it should be a disciplinary offence with NO exceptions. Cajoling, pleading, etc. simply should not enter the picture: it should be a simple management/rules issue. (Learn from our mistakes!) -- BFN CAD
Well, the advertisements are bringing in some money. Without that money the pretenders can't do their job like they can now. So if they doesn't play the Ads, they are taking the job away from him selves and others. Not that we own/run a commercial station but some sponsored money, which make things more comfortable, is always welcome ;D

Regards,
Vincent.

The main change is that when you ‘create’ something (like a Container for example), I now understand that you need to use a statement from the ‘Factory.’ This is similar to other programming languages which use ‘objects’ (IPlaylist, IPlaylistItem, IPlaylistContainerItem etc. are all ‘objects’ in programming terms). Unlike a variable like a string or an integer, an ‘object’ is not available immediately, you have to specifically ‘create’ it before you can do anything with it.

Think of the Factory like an automat (vending machine) at the train station. You put in your money and press the correct buttons, then you get a can of Coke out. You can do whatever you like with the can after that (open it or not, drink it or not, throw it away full or empty) but the point is you can’t ‘create’ a can of Coke yourself: you need the automat (=‘factory’) for that!

So if you want to use a Container for example, you cannot simply write:

var
  c: IPlayListContainerItem;
begin
  c.<whatever>;
end.

Instead, you have to do it this way:

var
  c: IPlayListContainerItem;
begin
  c := Factory.CreatePlayListContainerItem;
  c.<whatever>;
end.

Note that you always write Factory. in your code and not IFactory. There is only ONE Factory in mAirListScript! :wink:

Anyway, I was glad to help with this, and it has extended my understanding of mAirList and mAirListScript as well!

BFN
CAD

Well, looks like Tony has changed his mind now, but here’s the non-Container version of the script anyway. In other words, the ads. M3U is brought in as separate Playlist items instead of one big Container.

If nothing else, I hope this is educational for others trying to learn scripting.

// Original posted by Vincent Volmer
// New version by Cad Delworth, NOT using containers
// (requested by Tony Wilding)

const
  ADS_DIR = 'D:\TestRadio\Ads\';
  JINGLES_DIR = 'D:\TestRadio\Jingles\';
  MUSIC_DIR = 'D:\TestRadio\Muziek\';
  NEWS_DIR = 'D:\TestRadio\Nieuws\';

  NEWS_OPENER = 'news-open.mp3';
  NEWS_CLOSER = 'news-close.mp3';

// Seconds before the hour to play the News Opener
// (= duration of NEWS_OPENER file in seconds)
  NEWS_DELAY = 7;

var
  ads: IPlaylist;
  piNews: IPlaylistItem;
  nextHour: TDateTime;
  delay: single;

procedure AddCurrentPlaylistItemFromFile(f: String; b: boolean);
begin
  CurrentPlaylist.Add(Factory.CreatePlaylistItemFromFile(f, b));
end;

begin

  // Calculate 'next hour' time (nn:00:00) as Delphi TDateTime
  nextHour := (trunc(now * 24) + 1) / 24;

  // Create a new 'virtual' Playlist and put the ads. in it
  ads := Factory.CreatePlaylist;
  ads.AppendPlaylist(Factory.CreatePlaylistFromFile(
    ADS_DIR + FormatDateTime('yyyy-mm-dd-hh', now) + '.m3u'
    ));

  // CALCULATE ADS START TIME
  // Compute duration of Ads 'virtual' Playlist plus NEWS_OPENER, in seconds
  delay := (ads.GetDuration / 10000000) + NEWS_DELAY;
  // Convert to a value compatible with TDateTime format
  delay := delay / (24 * 60 * 60);
  // Set a fixed start time for first item in Ads 'virtual' Playlist
  // of 'next hour' less the duration of (Ads plus NEWS_OPENER)
  ads.GetItem(0).SetStartTime(sttFixed, nextHour - delay);

  // Append the Ads 'virtual' Playlist to Playlist
  CurrentPlaylist.AppendPlaylist(ads);

  // Add News Opener to Playlist
  AddCurrentPlaylistItemFromFile(JINGLES_DIR + NEWS_OPENER, true);

  // INSERT NEWS (i.e. news bulletin audio file)
  // (create a specific Item so we can more easily change its Start time)
  piNews := Factory.CreatePlaylistItemFromFile(
    NEWS_DIR + FormatDateTime('yyyy-mm-dd-hh', nextHour) + '.mp3', false
    )
  // Set a fixed on-the-hour start time for News, THEN add to Playlist
  piNews.SetStartTime(sttFixed, nextHour);
  CurrentPlaylist.Add(piNews);

  // Add News Closer to Playlist
  AddCurrentPlaylistItemFromFile(JINGLES_DIR + NEWS_CLOSER, true);

  // Paste music log for next hour
  CurrentPlaylist.AppendPlaylist(Factory.CreatePlaylistFromFile(
    MUSIC_DIR + FormatDateTime('yyyy-mm-dd-hh', nextHour) + '.m3u'
    ));

end.


BFN
CAD

Hi Cad, thanks for the scripts. No I still need the non container version of the script as it allows for a bit of variety in the order things play. I was just napping, its off to work in 20 minutes or so. This weekend, I’m on 12 hour nights starting tonight and expect to be home Monday around 8am.

My comments for putting reminders in a playlist about playing items was for cheek but with non-experienced presenters in many community stations it acts as a helping hand. Although as you suggest its a matter of discipline and training for whatever level of radio station you happen to be.

As always thanks for your help and expertise, these completed scripts posted by yourself and Charlie are a source of learning for us all.

Kind regards Tony

With a little help from Torbens’ script example we can label the contents of the container.

The example:

// ... and pi to access the ordinary item properties and to add that item to a playlist pi.SetTitle('Container with two files');

The change:

// ... and pi to access the ordinary item properties and to add that item to a playlist pi.SetTitle('Container with Ad Break and News');

This then becomes a basic description for the container, with no need to look inside.

Kind Regards Tony