ecvbob Posted December 23, 2009 Share Posted December 23, 2009 Well I bought SAM4 bout 9 months ago just for the great feature called PAL scripts. Little did I realize they work great if you want to learn to be a code writer to use them. I just need a script or whatever to queue and play two songs by a random artist, then repeat with a different artist all day, be a good idea if if followed the playlist rules set fourth. I'm not against learning to help myself but I can't find hardly anything on writing PAL Scripts and well the spacial audity support part of the site and forum has left me wanting to get rid of SAM but I like the other features so I guess I will keep it for now. Script would be nice but any helpful information is appreciated. Bob Mannelin THUNDER711.com Link to comment Share on other sites More sharing options...
countrywesterndj Posted December 23, 2009 Share Posted December 23, 2009 There is a ton of help on PAL scripts on the Spacial Audio forums. All you need to do is search it out. Here is a 2-fer script, written by FesterHead, that I use on Tuesdays. You can modify the setup and make it work for other days. { Don't be a loser. Leave this here. Twofer script by FesterHead (aka Steve Kunitzer) $Id: twofer.pal,v 1.6 2006/05/20 20:09:43 FesterHead Exp $ What this PAL does: * Plays twofers * artist(2), artist(2), artist(2), ... What is configurable: * Toggle debug mode * Toggle memory leak warning * Show updating title, description, and resets * Day(s) to run twofers * Categories to select songs * Percentage weights for list of categories * Rule selection for list of categories * PAL id for automated schedule highlighting * Wait count * Maximum failure count before giving up * Failure wait count * Minimum songs available for twofer selection Schedule this PAL with SAMs Event Scheduler (ES): * Switch to a desktop with the ES visible OR Make the ES visible by clicking the 'Window' menu item and selecting 'Event Scheduler' * Click '+' (Add new scheduled event) * Enter a name such as 'Twofers' * 'Event action' tab: * Under 'Action' click 'Execute PAL script' * In the 'PAL Script' section, click the folder icon and navigate to this script * 'Scheduled times' tab: * For a one time event: * Select the 'Execute one' button * Adjust the date/time * Click '+ Add' * Repeat as necessary for extra one time events * For recurring events: * Select the 'Execute every' button * Adjust date/time * Click '+ Add' * Save settings by clicking the 'File' menu item and selecting 'Save Configuration' For my station, this PAL runs at 12:01AM every day To handle requests as twofers, see 'Categories Processing' PAL Show your support for the effort, see [url]http://www.festerhead.com/forums/viewtopic.php?t=4[/url] Mahalo for your kokua WARNING! IF YOU DON'T CONFIGURE THE SCRIPT, DON'T EXPECT IT TO WORK PROPERLY! I built this PAL for my station using my station configuration Your results and mileage may vary I suggest running the PAL in debugOn mode for a couple days to see if it needs tweaking See below for change log } // Make the PAL run fast! PAL.LockExecution; { ************************** * START OF CONFIGURABLES * ************************** } { Run in debug mode? This will write to the screen without any queue interaction Useful for testing the script settings Turns on memory leak warning } var debugOn : Boolean = false; { Enable memory leak warning? Automatically enabled if debugOn is true Stoping then starting a running script will give false memory leak warnings. To stop/start do one of the following: 1. a. Add some spaces to the end of a line b. Save the script c. Compile the script d. Run the script 2. a. Remove the script b. Add the script c. Compile the script d. Run the script } var memoryLeakAlwaysOn : Boolean = false; { Define automatic show updating values } var text1Update : String = 'Now playing: Twofers!'; var text2Update : String = 'Back-to-back songs by your favorite artists'; var text1Reset : String = 'Now playing: Regular schedule'; var text2Reset : String = 'Normal rotation and listener requests'; { What days do you want the Twofers played? If debugOn is true, then we run no matter what day is here } var theDays : Array of Integer = [Tuesday]; { Define the categories to pick song candidates from See below for setting thePercentages } var theCategories : Array of String = ['Tracks', 'Classics', 'Texas', 'CDX', 'New Releases']; { Define the percentages of each category These need to add to 100. Use a calculator if necessary The order here corresponds to the order of theCategories above } var thePercentages : Array of Integer = [20, 10, 30, 10, 30]; { Define the choosing methods of each category The order here corresponds to the order of theCategories above } var theChoosers : Array of Integer = [smRandom, smRandom, smRandom, smRandom, smRandom]; { Define the enforcing methods of each category The order here corresponds to the order of theCategories above } var theEnforcers : Array of Boolean = [EnforceRules, EnforceRules, EnforceRules, EnforceRules, EnforceRules]; { Database table name for logging show history Debug table automatically appended with '_debug' } var tableName : String = 'twofer'; { Define the PAL ids for automated schedule page highlighting Leave this alone if you don't have automated schedule page highlighting } var idThisPAL : Integer = 1; var idResetPAL : Integer = 0; { How many songs to wait before running the script again? Check your SAM configuration for your setting If you're not sure what to do here, leave this alone } var waitCount : Integer = PlaylistRules.MinQueueSize + 1; { Use PAL.WaitForQueue instead of PAL.WaitForPlay? If there are other regularly scheduled jingles, ads, and/or what-nots the queue could fill up with a lot of twofers if we use PAL.WaitForPlay In my view, this is unacceptable Feel free to set to false to use PAL.WaitForPlay and have fun Watch your queue Automatically switched to false if debugOn is true } var useWaitForQueue : Boolean = true; { Maximum times the script can fail to get a twofer before giving up If gives up, it'll add the singleton song candidate Don't set this too high This is to prevent a runaway PAL script. } var maxFailures : Integer = 5; { How many songs to wait if we fail to generate a twofer before restarting? } var failureCountWait : Integer = 1; { Maximum candidate matches required to consider a song as twoferable After choosing a candidate, there needs to be this number of other songs to choose from Don't set this too high or less than one } var minimumAvailable : Integer = 10; { Is this cool or what? var cool : Boolean = true; } { ************************ * END OF CONFIGURABLES * ************************ } // IF YOU EDIT BELOW HERE, MAKE DARN SURE YOU KNOW WHAT'S GOING ON // Declare variables var theCandidate : TSongInfo; var theSongChooser, currentShow : TDataSet; // Declare and initialize stuff var randomInteger : Integer = 0; var song1 : Integer = -1; var song2 : Integer = -1; var counter : Integer = 0; var bad : Boolean = false; var good : Boolean = false; var runNow : Boolean = false; var theCategory : String = ''; var theChooser : Integer = smRandom; var theEnforcer : Boolean = EnforceRules; var theSQL : String = ''; var looper : Integer = 0; var accumulator : Integer = 0; var found : Boolean = false; // Randomize! Randomize; if (debugOn or memoryLeakAlwaysOn) then begin PAL.MemoryLeakWarning := true; WriteLn('Memory leak warning is ON'); end; if (debugOn) then begin useWaitForQueue := false; WriteLn('WaitForPlay is ON'); end; // Determine if we runNow. Loop through theDays and find the one to use for looper := 0 to theDays.length-1 do begin // Run now? if ((DayOfWeek(Now) = theDays[looper]) and (not runNow)) then begin runNow := true; PAL.Loop := true; end; end; if (debugOn) then begin if (PAL.GetLoop) then begin WriteLn('PAL.Loop := true'); end else begin WriteLn('PAL.Loop := false'); end; end; if (not runNow) then begin PAL.Loop := false; end; while ((counter begin // Setup automatic show updating if (not debugOn) then begin // Create the table if it doesn't already exist ExecSQL('CREATE TABLE IF NOT EXISTS currentshow ' + '(id MEDIUMINT(9), text1 VARCHAR(255), text2 VARCHAR(255))', []); currentShow := Query('SELECT COUNT(*) AS cnt FROM currentshow', [], true); // If no rows in currentshow, do an insert // Else, do an update if (currentShow['cnt'] = 0) then begin ExecSQL('INSERT INTO currentshow (id, text1, text2) ' + 'VALUES (' + IntToStr(idThisPAL) + ', ' + QuotedStr(text1Update) + ', ' + QuotedStr(text2Update) + ')', []); end else begin ExecSQL('UPDATE currentshow SET id = ' + IntToStr(idThisPAL), []); ExecSQL('UPDATE currentshow SET text1 = ' + QuotedStr(text1Update), []); ExecSQL('UPDATE currentshow SET text2 = ' + QuotedStr(text2Update), []); end; end; // Increment the number of times run counter := counter + 1; if (debugOn) then begin WriteLn('Counter = ' + IntToStr(counter)); end; // Generate a random number randomInteger := RandomInt(100) + 1; if (debugOn) then begin WriteLn('Random number = ' + IntToStr(randomInteger)); end; found := false; // Select a category // Loop through theCategories and find the one to use for looper := 0 to theCategories.length-1 do begin // Accumulate the accumulator accumulator := accumulator + thePercentages[looper]; // This the one to use? if ((randomInteger begin theCategory := theCategories[looper]; theChooser := theChoosers[looper]; theEnforcer := theEnforcers[looper]; found := true; end; end; // Grab a candidate theCandidate := CAT[theCategory].ChooseSong(theChooser, theEnforcer); if (theCandidate nil) then begin if (debugOn) then begin WriteLn('Potential candidate: ' + theCandidate['artist'] + ' --- ' + theCandidate['title']); end; song1 := theCandidate['id']; // Do the query theSongChooser := Query('SELECT COUNT(*) AS cnt ' + 'FROM songlist ' + 'WHERE id ' + IntToStr(theCandidate['id']) + ' ' + 'AND title ' + QuotedStr(theCandidate['title']) + ' ' + 'AND artist = ' + QuotedStr(theCandidate['artist']) + ' ' + 'AND date_played 'AND songtype = ''S''', [], true); if (debugOn) then begin WriteLn('There are ' + IntToStr(theSongChooser['cnt']) + ' songs to choose from'); end; // Validate the count // If less than minimumAvailable songs to choose from, candidate is a failure if (theSongChooser['cnt'] begin if (debugOn) then begin WriteLn('Less than ' + IntToStr(minimumAvailable) + ' songs to choose from! Counter = ' + IntToStr(counter) + '. Starting over...'); end; // Not good, but haven't reached maximum failure count if (counter >= maxFailures) then begin // Failed to generate a twofer bad := true; WriteLn('Max failures reached! Counter = ' + IntToStr(counter) + '. Adding candidate and waiting ' + IntToStr(failureCountWait) + ' song(s)...'); // Add the candidate if (not debugOn) then begin Queue.Add(theCandidate, ipBottom); end; end; end // We have more than one song to choose from. Candidate is a success. else begin good := true; // Do the query theSongChooser := Query('SELECT artist, title, filename, id ' + 'FROM songlist ' + 'WHERE id ' + IntToStr(theCandidate['id']) + ' ' + 'AND title ' + QuotedStr(theCandidate['title']) + ' ' + 'AND artist = ' + QuotedStr(theCandidate['artist']) + ' ' + 'AND date_played 'AND songtype = ''S'' ' + 'ORDER BY RAND() LIMIT 1', [], true); // Grab the song id song2 := theSongChooser['id']; // Put candidate and random song in queue bottom if (not debugOn) then begin Queue.Add(theCandidate, ipBottom); Queue.AddFile(theSongChooser['filename'], ipBottom); end; // Log the twofer to the screen WriteLn('Added: ' + QuotedStr(theCandidate['artist']) + ' --- ' + QuotedStr(theCandidate['title'])); WriteLn('Added: ' + QuotedStr(theSongChooser['artist']) + ' --- ' + QuotedStr(theSongChooser['title'])); // Keeping separate just in case we want to log more // stuff when in debugOn mode if (debugOn) then begin // Create the table if it doesn't already exist ExecSQL('CREATE TABLE IF NOT EXISTS ' + tableName + '_debug ' + '(id MEDIUMINT(9) AUTO_INCREMENT PRIMARY KEY, ' + 'date DATETIME, ' + 'song1 MEDIUMINT(9), ' + 'song2 MEDIUMINT(9), ' + 'counter MEDIUMINT(9))', []); ExecSQL('INSERT INTO ' + tableName + '_debug (date, song1, song2, counter) VALUES (''' + FormatDateTime('yyyy-mm-dd hh:mm:ss', Now) + ''', ' + IntToStr(song1) + ', ' + IntToStr(song2) + ', ' + IntToStr(counter) + ')', []); end else begin // Create the table if it doesn't already exist ExecSQL('CREATE TABLE IF NOT EXISTS ' + tableName + ' ' + '(id MEDIUMINT(9) AUTO_INCREMENT PRIMARY KEY, ' + 'date DATETIME, ' + 'song1 MEDIUMINT(9), ' + 'song2 MEDIUMINT(9), ' + 'counter MEDIUMINT(9))', []); ExecSQL('INSERT INTO ' + tableName + ' (date, song1, song2, counter) VALUES (''' + FormatDateTime('yyyy-mm-dd hh:mm:ss', Now) + ''', ' + IntToStr(song1) + ', ' + IntToStr(song2) + ', ' + IntToStr(counter) + ')', []); end; end; end else begin WriteLn('NIL candidate. That sucks. Running again...'); end; end; // Stop the PAL from running fast! PAL.UnlockExecution; // Do an action based on a bad or good twofer generation // Yes these are separate if-then statements. Deal with it. if (bad and runNow) then begin if (debugOn) then begin WriteLn('Waiting for SAM to play ' + IntToStr(failureCountWait) + ' songs'); end; PAL.WaitForPlayCount(failureCountWait); end; if (good and runNow) then begin if (useWaitForQueue) then begin if (debugOn) then begin WriteLn('Waiting for queue to reach ' + IntToStr(waitCount) + ' songs'); end; PAL.WaitForQueue(waitCount); end else begin if (debugOn) then begin WriteLn('Waiting for SAM to play ' + IntToStr(waitCount) + ' songs'); end; PAL.WaitForPlayCount(waitCount); end; end; if (runNow and (not debugOn)) then begin // Reset the show ExecSQL('UPDATE currentshow SET id = ' + IntToStr(idResetPAL), []); ExecSQL('UPDATE currentshow SET text1 = ' + QuotedStr(text1Reset), []); ExecSQL('UPDATE currentshow SET text2 = ' + QuotedStr(text2Reset), []); end; // Be nice... Free up the data structures theSongChooser.Free; theCandidate.Free; currentShow.Free; Queue.Free; CAT.Free; Spacial SVS Support Team http://support.spacialaudio.com/forums/ Get help with PAL Scripts at http://www.palscripts.com Link to comment Share on other sites More sharing options...
GKIye Posted December 23, 2009 Share Posted December 23, 2009 You'll find some details and PALs who can be usefull at this BW link http://forums.broadcastingworld.net/showthread.php?t=7199 at the end of that page you'll find a link to the part 2 Happy Holidays ! Visit and listen @ BW ! Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.