…blah

#!/bin/bash
#
#
#   Silly little script to grab Coffeebreak from the current "Podcast Host" 
#   and import it into my local Rivendell install.
#
#   Since there isn't a feed to grab from, gotta grab the files based on date;
#   ...and since I couldn't get Rivendell to compile with m4a support, 
#   I have to convert it to a format that Riv' will ingest. 
#
#
DAYOFWEEK=$(date +"%a")

if [ "${DAYOFWEEK}" == Mon ];  then    
    wget https://ice64.securenetsystems.net/media/WCYNAM/ondemand/CB-MON.m4a
    ffmpeg -i CB-MON.m4a CB-MON.wav
    rm CB-MON.m4a
    rdimport --verbose --segue-level=-10 --delete-cuts --delete-source --to-cart=070003 SHOWS CB-MON.wav; 
fi
if [ "${DAYOFWEEK}" == Tue ];  then
    wget https://ice64.securenetsystems.net/media/WCYNAM/ondemand/CB-TUES.m4a
    ffmpeg -i CB-TUES.m4a CB-TUES.wav
    rm CB-TUES.m4a
    rdimport --verbose --segue-level=-10 --delete-cuts --delete-source --to-cart=070003 SHOWS CB-TUES.wav; 
fi
if [ "${DAYOFWEEK}" == Wed ];  then
    wget https://ice64.securenetsystems.net/media/WCYNAM/ondemand/CB-WED.m4a
    ffmpeg -i CB-WED.m4a CB-WED.wav
    rm CB-WED.m4a
    rdimport --verbose --segue-level=-10 --delete-cuts --delete-source --to-cart=070003 SHOWS CB-WED.wav; 
fi
if [ "${DAYOFWEEK}" == Thu ];  then
    wget https://ice64.securenetsystems.net/media/WCYNAM/ondemand/CB-THURS.m4a
    ffmpeg -i CB-THURS.m4a CB-THURS.wav
    rm CB-THURS.m4a
    rdimport --verbose --segue-level=-10 --delete-cuts --delete-source --to-cart=070003 SHOWS CB-THURS.wav; 
fi
if [ "${DAYOFWEEK}" == Fri ];  then
    wget https://ice64.securenetsystems.net/media/WCYNAM/ondemand/CB-FRI.m4a
    ffmpeg -i CB-FRI.m4a CB-FRI.wav
    rm CB-FRI.m4a
    rdimport --verbose --segue-level=-10 --delete-cuts --delete-source --to-cart=070003 SHOWS CB-FRI.wav; 
fi

exit 0

Notes to self… (fighting a Rivendell install in an Ubuntu VM, and connecting it to a Rivendell “Broadcast Appliance”)

…just because it’s been forever and a day since I’ve posted anything, here’s a little something I’ve been fooling with at home. The notes are a mess, and might only make sense to me; actually, there’s a pretty good chance that they might not even make much sense to me, anymore.

Anyway, the gist–before you dig any deeper and get royally confused–is that I was fighting with trying to create a virtual machine on my bedroom PC in order to connect to my “streaming” PC downstairs, and go through some of the same headaches that someone at a radio station might experience on a routine basis. An actual post on all this stuff *might* show up in the future–and by “actual post” I mean something that took some time to write, instead of an ol’ copy-paste of notes.

…oh, the deal with the notes? Yeah, well, I had to crash my attempts a couple times, and got frustrated with trying to retrace my steps from memory. So, yeah. Notes! Plus, I figured I wanted to eventually come up with some sort of howto at a later date, as the Rivendell documentation–what documentation that exists–is a bit confusing. Oh, and JACK documentation, too.

Unfortunately, these notes kind of drop off toward the end, as I finally began to have success…

installed ubuntu 14.04–made sure to set a “real” hostname, as Rivendell will expect/work-a-helluvah-lot-better-with one
reboot

installed guest additions
changed ip to manual — Rivendell will expect/work-a-helluvah-lot-better-with manual IP… plus, I connect so many devices, I like handling IPs instead of relying upon DHCP
installed gnome-session-fallback gdm – made gdm default
logout, back in to get responsive session

enabled other canonical sources, refreshed
began instructions at https://help.ubuntu.com/community/UbuntuStudioPreparation
changed terminal to unlimited scrolling
saved suggested packages from first studio prep step… would not install–may check later if packages would be worthy tracking down–moved to kxstudio repo step
installed kxstudio repo
installed low-latency kernel
skipped wine, etc. why need wine, since running in VM?
did update step, and reboot.

logged in via gdm. saved machine state, thus far.

sudo apt-get install pulseaudio-module-jack
sudo apt-get install qjackctl
…installed the following suggested from the studio guide–eh, why not? look promising:
sudo apt-get install vlc vlc-plugin-jack audacious asunder soundconverter patchage

ran qjackctl to configure JACK
…left all defaults. started server via start ‘play’ button
…messages window showed a few errors.
…stopped jack
dbus error. dammit.
…killed qjackctl
started qjackctl, changed dbus option to off, exit qjackctl
killed jackdbus from sysmon
started qjackctl and server… tons of errors, it stopped jack.
sudo adduser username audio
start again. still borked.
…restart

error seems to be with trying to use dbus and sink module…
…managed to start/stop jack twice with dbus disabled.

…after a ton of tinkering, finally discovered a solution that is working
…have no idea of the steps i used, now. @#$%!
…did have to create .asoundrc in ~/
…am running via dbus interface again
…wish i could figure out what happened to make things work.
…created save point.

proceeded to rivendell part…
***in order to install qt3 dependency per instruction page, did this:
***echo “deb http://archive.ubuntu.com/ubuntu precise main universe multiverse” | sudo tee /etc/apt/sources.list.d/precise.list
***sudo apt-get update
sudo apt-get install libcdparanoia-dev libflac++-dev libsamplerate0-dev libid3tag0-dev libid3-3.8.3-dev libcurl4-gnutls-dev libsndfile-dev qt3-dev-tools libpam0g-dev libsoundtouch1-dev libasound2-dev libtwolame-dev libmad0-dev libjack-jackd2-dev libqt3-mt-mysql build-essential
sudo apt-get install libmp3lame-dev polymer qt3-qtconfig mysql-client
wget https://software.paravelsystems.com/source/rivendell/rivendell-2.13.0.tar.gz
tar -zxvf ~/rivendell-2.13.0.tar.gz
cd ~/rivendell-2.13.0
./configure
make

computer restarted. had to delete, untar, configure, make again.
make install
***note–for both runs of configure, did not configure to set rd-bin directory. had an issue in a previous attempt with this.
…skipped the copying of pixmaps, etc.
sudo addgroup rivendell
sudo adduser `whoami` rivendell
sudo gedit ~/rivendell-2.13.0/conf/rd.conf-sample
…changed audioowner
…changed hostname to server IP
…changed syslog to file
…changed log file paths
…saved as /etc/rd.conf
skipped apache conf
sudo mkdir /var/snd
sudo chown `whoami`:rivendell /var/snd
sudo chmod 0775 /var/snd
skipped ugly fonts
qtconfig — changed to guide recommended to make it pretty 🙂

mkdir /home/jeremiah/rdlogs
mkdir /home/jeremiah/scripts
sudo cp /etc/init.d/rivendell ~/scripts/rivendell-init-backup
…I wanna see if i can modify the script later…
sudo cp /etc/X11/xinit/xinitrc.d/start-rdmonitor.sh ~/scripts/start-rdmonitor.sh.backup
sudo rm /etc/X11/xinit/xinitrc.d/start-rdmonitor.sh
save, restart

#!/bin/bash
#FILE: jack-after-startup.sh

#Start Rivendell Daemons
/usr/local/bin/caed
/usr/local/bin/ripcd
/usr/local/bin/rdcatchd
sleep 5 #not strictly necessary

#!/bin/bash
#FILE: jack-on-shutdown.sh

#Stop Rivendell Daemons
killall rdcatchd ripcd caed
sleep 5

created above files, made executable, added to qjackctl
created simple patchbay for rivendell_0 playout_0L,R to system playback_1,2

…beginning the networking part–part riv, part my stuff
…riv nfs based stuff from https://tecwhisperer.com/install-rivendell-radio-automation-part-3-install-client/
sudo apt-get install cifs-utils nfs-common
…followed autonfs instructs
…noticed goofup in copying code. fixed. (copy did not keep formatting, plus html char$ came through) restarted script/job
…after files populated, noticed wouldn’t play due to differing UID and GID. before tweaking server’s export options–which were set to root for share, restarted VM

jack started freaking out again, and sound from pulse started coming at the wrong rate. :-/
performed dist-upgrade, restarted guest and host.
…had to re-install vbox additions due to dist-upgrade; restart again.

looked at rivendell script, noticed it really wasn’t calling anything that relied upon original location, so moved to /usr/local/bin. still requires sudo to run. will figure this out later, by adding to sudoers

having too many issues with jack. going for jack 1, now, instead of jack 2. this removed qjackctl. :-/
attempted to work with jack using cadence. worked for a while. still having issues. going to try and kill pulse altogether, and use jack+alsa like the machine downstairs. :-/
edited /etc/pulse/client.conf–autospawn=no
…did this because total removal of pulse starts killing ubuntu.
reinstalling jackd2 and qjackctl, then restarting.

after trying to figure out the issue with the sample rate for the card, finally discovered an answer:
https://www.withoutthesarcasm.com/fixing-audio-in-linux-guests-virtualbox/
…crap. maybe. jack still failed. going back to jack 1, and trying to compile qjackctl, as ubuntu keeps trying to force jack 2 if i install qjack
using 0.4.2 from sourceforge, extracted to home. discovered need of following packages and symlink through configure and make attempts:
sudo apt-get install libjack-dev qt5base-dev sudo apt-get install libqt5x11extras5-dev System Settings)
Noticed that if daemons haven’t already been called, rd apps will call for startup and initialization of daemons on their own.

“modprobe snd-aloop” added to /etc/rc.local — there’s gotta be a better/different way, but i’m still learning linux as i go

edited sudoers to allow nopasswd on rivendell “daemons” for my user and the rivendell group

Re-enabling disabled tracks from certain categories in the background

I’d run across an issue in my setup where I would occasionally have a huge chunk of my catalog end up disabled, and wanted to find a quicker and easier way of re-enabling said tracks without using RadioDJ’s Track Manager; today, I finally sat down and did it.

Basically, what would happen would be some sort of interruption in the connection between the PC hosting all of my media and the PC running RadioDJ. When an interruption like that happens–say, from a kid turning off the machine–RadioDJ automatically disables the tracks, as they’re not available. To fix, one simply goes back into the database and re-enables said tracks. This task can be very daunting if performed through the Track Manager… so, SQL commands to the rescue!

In my particular setup, RadioDJ’s automated rotations pull primarily from three sub-categories: Regular Play, Limited Play, and After 10PM. Your install will of course vary, as this is just personal preference stuff. After poking around in the database, I found the IDs for those sub-categories, and constructed a simple update query:

update `songs` set enabled=1 where enabled=0 and id_subcat in (30,57,46);

…and to make the process a little more automated, I created a startup event for RadioDJ to process a batch file containing that command. Basically, the batch contains:

c:\xampp\mysql\bin\mysql.exe -e "UPDATE `songs` SET enabled=1 WHERE enabled=0 AND id_subcat IN (30,57,46);" --user=MYSQL_USERNAME --password=MYSQL_PASSWORD radiodj161

I may rethink the process at a later date and set a timed event to perform this operation, or write a php file for me to invoke an update on the fly if/when I put my operation into “production”…

A Streaming “Popup” Player for RadioDJ w/ Icecast

Just because I like to tinker with all sorts of toys, I put together a little page that can be used as a “pop-up” player for my RadioDJ/Icecast stream. Needless to say, a lot of this relies upon the hard-work of other RadioDJ users and enthusiasts–credit/links to be given at the end of this post.

My current iteration of the player relies upon six little files:

  1. img.js
  2. img.php
  3. song.js
  4. song.php
  5. serv_inc.php
  6. index.html

If you don’t already know about the serv_inc file, it’s the one that allows you to make your database connections. The only mods that are needed are, of course, those which will be necessary and unique to your particular installation. More info on that goodness can be found here:
Demo Script For RadioDJ RC1 and Newer

The img.* and song.* files are based upon files found here:
A live real time refreshing solution for web data (stream titles etc) and at that topic author’s site:
http://stream.oxygenrad.io/

The index.html file is my own cobbled together creation.

Contents of the *.js and corresponding *.php files are very similar; as such, I’ll give the song.* ones below, and just point out the changes to make for the img.* ones, if you wanna have the page load album art–if you’ve set up your system for that (…a whole other topic for another day, BTW):

song.js:
$(function() {
function reload(elem, interval) {
var $elem = $(elem);
var $original = $elem.html();
$.ajax({
cache: false,
url: 'PATH_TO_SONG.PHP_GOES_HERE',
type: 'get',
success: function(data) {
if ($original == data) {
setTimeout(function() {
reload(elem, interval)
}, interval);
return
}
$elem.html(data);
setTimeout(function() {
reload(elem, interval)
}, interval)
}
})
}
reload('#song_info', 5000)
$("#song_info").fadeOut();
$("#song_info").fadeIn("slow");
});

…for the img.js, set the URL to your img.php path, and change references to song_info to song_art.

song.php:

<?php
require_once('serv_inc.php');
function convertTime($seconds) {
$sec = $seconds;
// Time conversion
$hours = intval(intval($sec) / 3600);
$padHours = True;
$hms = ($padHours)
? str_pad($hours, 2, "0", STR_PAD_LEFT). ':'
: $hours. ':';
$minutes = intval(($sec / 60) % 60);
$hms .= str_pad($minutes, 2, "0", STR_PAD_LEFT). ':';
$seconds = intval($sec % 60);
$hms .= str_pad($seconds, 2, "0", STR_PAD_LEFT);
return $hms;
}
$resLimit = 0;
?>
<?php
db_conn();
$shuffleQuery = null;
// ======================== //
$query = "SELECT `ID`, `date_played`, `artist`, `title`, `duration` FROM `history` ORDER BY `date_played` DESC LIMIT 0," . ($resLimit+1);
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) {
echo " " . htmlspecialchars($row['artist'], ENT_QUOTES) . " <br /> " . htmlspecialchars($row['title'], ENT_QUOTES) . " <br /> Track Length [" . convertTime($row['duration']) . "] ";
}
@mysql_free_result($result);
db_close($opened_db);
?>

…this gets trickier for img.php. Your query will need to change to something like:

$query = "SELECT h.date_played, s.artist, s.title, s.duration, s.album_art
FROM `history` AS h, `songs` AS s
WHERE s.title = h.title AND s.artist = h.artist
ORDER BY h.date_played DESC
LIMIT 0," . ($resLimit+1);

…and your echo statement to something like:

echo " <img class=\"album_art\" align=\"left\" width=\"200\" src=\"URI_PATH_TO_ALBUM_ART" . htmlspecialchars($row['album_art']) . "\" onerror=\"this.src='URI_PATH_TO_DEFAULT_IMAGE'\"/>";

index.html (or whatever you wanna call it, of course):

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>YOUR_SITE_TITLE</title>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="song.js"></script><!-- CHANGE PATH IF NECESSARY -->
<script src="img.js"></script><!-- CHANGE PATH IF NECESSARY -->
</head>
<body topmargin="15" alink="#e8e8e8" bgcolor="#000000" link="#e8e8e8" vlink="#e8e8e8">
<div style="text-align: center; line-height: 20px; color: #e8e8e8; text-decoration: none; letter-spacing: 0px; font-weight: bold; font-size: 10px; font-family: verdana;"></div>
<table>
<tr>
<td width=* height=200px><div id="song_info" style="text-align: center; line-height: 20px; color: #e8e8e8; text-decoration: none; letter-spacing: 0px; font-weight: bold; font-size: 12px; font-family: verdana;"></div></td>
<td width=200px height=200px><div id="song_art"><img src="PATH_TO_A_DEFAULT_IMAGE"></div></td>
</tr>
<tr>
<td colspan="2">
<br />
<div style="text-align: center;">
<!-- BEGINS: AUTO-GENERATED MUSES RADIO PLAYER CODE -->
<script type="text/javascript" src="https://hosted.muses.org/mrp.js"></script>
<script type="text/javascript">
MRP.insert({
'url':'YOUR_FULL_ICECAST_MOUNTPOINT',
'codec':'mp3',
'volume':100,
'autoplay':true,
'buffering':5,
'title':'YOUR_STATION_NAME',
'bgcolor':'#000000',
'skin':'greyslim',
'width':494,
'height':35
});
</script>
<!-- ENDS: AUTO-GENERATED MUSES RADIO PLAYER CODE -->
</div>
</td>
<tr>
<td colspan="2">
<div style="text-align: center; line-height: 20px; color: #e8e8e8; text-decoration: none; letter-spacing: 0px; font-weight: bold; font-size: 10px; font-family: verdana;">
<br><a href="javascript:self.close()">Close Player</a></div>
</td>
</tr>
</table>
</body>
</html>

…all of that, of course, can be customized to however you want it/need it.

Hopefully, if things have gone right, you’ll end up with something like this:

Untitled

Resources:

http://www.radiodj.ro/community/index.php?topic=3502.0
http://www.radiodj.ro/community/index.php?topic=7471.0
http://stream.oxygenrad.io/
https://www.muses.org/setup

Interrupting RadioDJ for WX Alerts

As a nice little thought problem, I decided to try and figure out a way to interrupt RadioDJ for weather watches and warnings–and I believe I’ve found a solution that works for my installation.

*NOTE: this solution is definitely NOT recommended for any sort of broadcast use–that’s what all that wonderful EAS equipment is for…

My first thought was to hook up an old NWR to the PC and have a tone detector monitor the input–a thought I might revisit–however, I ended up settling on a solution where a message received via IM triggers an AutoHotkey script. (…this idea came after a ton of other attempts at trying to find ways to push data to the PC, rather than having it poll at certain intervals.)

Unfortunately, I can’t jump in and give all the good details on the AHK script that I made–this is due to the fact that your system will be configured differently than mine, plus I really wouldn’t want to have you put that much faith in something I had some troubles with.
But, anyway… the basic idea to how I put everything together is this:

  1. I receive an SMS from the weather service on my personal phone.
  2. Using a neat little program installed on my phone, the message is forwarded to my AIM account via AOL’s SMS gateway. (…which will eventually get shut-down–I mean, everyone’s been killing off their gateways; honestly I was shocked to find AOL still had one in existence!)
    1. The program (SMS Forwarder) searches incoming messages beginning with “New Event.” or “Event Modified.”
    2. SMS Forwarder then replaces the found string with “Send *MY_AOL_USERNAME* and forwards it all to 246246
  3. My RadioDJ PC receives the message via Pidgin and “pounces” upon it.
    1. I configured Pidgin to have a “recurring” pounce that responds to any message received from my mobile number. I chose Pidgin simply because I remembered that it could execute a specified command when it sees/receives a message from a user. Another reason why I chose Pidgin is that I can tell it to sit in the system tray and not do any other attention grabbing or screen stealing stuff.
  4. My AHK script–which has been converted to an *.exe–is activated by the Pidgin pounce.
  5.  AHK loads and plays a preconfigured RadioDJ playlist–which only consists of a manual event for interrupting the current song and all other events.

As stated before, I really can’t delve into how the AutoHotkey script works. Similarly, I’m not going to go into detail on the creation of my manual event. Sorry. But, here’s the gist of it, so that you can try to figure it out on your own, if you’d like:

  1. Pause playback of the current song
  2. Disable AutoDJ
  3. Pause all events
  4. Load and playback the NWS stream from the database into Auxilary Player 1
    1. I found where someone setup a stream for my area’s NWS broadcast on Weather Underground. You may have luck doing the same…
  5. Wait 2 minutes
    1. I decided to use two minutes as the delay before returning to normal playback, based upon info I found that stated this was the old “standard” for delayed return in decades past. (Don’t ask me where I found this–I can’t remember.)
  6. Stop playback of Aux Player 1
  7. Unpause playback
  8. Re-enable AutoDJ
  9. Re-enable Events

…as for the “playlist”: load up the playlist builder, insert the manual event, and save the playlist.

Obviously, there’s a lot more tinkering that could be done to the whole process in order to make it act a lot more like a “real” station’s setup–which is why I say I’m thinking about revisiting my idea of hooking a NWR up to the PC.

Unfortunately, there’s a couple points of failure in my setup–reliance upon my receiving an SMS, using AIM to trigger the playback of that stream, and the stream itself. If I were to use a radio and detect it’s tone, I’d eliminate those three points… but, I still face the potential failure of the radio receiving signal, and the possibility of having false-positives in tone-detection if I use and older radio that won’t reset without user intervention. (…I discovered that I’d need to do a lot of tweaking to the detection level of the given tone, as a poor quality signal can distort and create the tones I’d be looking for.)

…but, for now, this is a workable solution as I’m only using the program for my own enjoyment. 😉

Adding other Microsoft TTS voices

If you’re playing around with TTS–in RadioDJ or any other Windows program–you might find that the pre-installed system voice on your computer leaves much to be desired. The instructions I’m about to give are a bit of a hack and only complete to the point in which I got it to work for the purpose I had in mind. I’ve gotten this little hack to work in Vista 32 and 7 64-bit versions…

First, seek out and install Microsoft Speech Server 11.0 x86 [aka Microsoft Speech Platform – Runtime (Version 11)].

Second, get and install the voices for Speech Server 11.0 [Microsoft Speech Platform – Runtime Languages (Version 11)].

Third–the fun part–open regedit and export the “Tokens” for the newly installed voices. Depending upon your version of windows, you’ll find the voices referenced under one or both of the following:

HKLM\SOFTWARE\Microsoft\Speech Server\v11.0\Voices

HKLM\SOFTWARE\Wow6432Node\Microsoft\Speech Server\v11.0\Voices

…if you’ve found them, right-click and export the “Tokens” folder to a file — say, something like voices1.reg and voices2.reg, respectively.

Edit those exported entries with your favorite text-editor, replacing the instances of \Speech Server\v11.0\ with \Speech\ . When you’re done, save, and then import the entries back into the registry (double-clicking will suffice).

You may want to reboot the machine–I didn’t have to on one, but did on the other.

After all that’s done, all you have to do is change your computer’s default voice–c’est voila!–no more Microsoft Anna!

Personally, the voice I like the sound of Zira Pro.

…and for the RadioDJ user, don’t forget–if you’re using the AutoDJ TTS feature–the voice number referenced in the XML files begins numbering at 0, and will go in order that it appears in the TTS plugin’s drop-down voice list.

References/Additional Info:

http://forums.anandtech.com/showthread.php?t=2226829

http://www.radiodj.ro/community/index.php?topic=5073.0

Building a TTS spoken 7-day weather forecast .wav file

For the fun of it, I thought I’d give a 7-Day forecast to my RadioDJ installation for playback in the morning–and maybe at other points throughout the day. After a bit of tinkering, I’ve come up with a solution that’ll pull my local forecast and speak it into a waveform file, which I have imported into RDJ as a “variable duration”–see my previous post for a quick explanation of that RDJ file-type.

In a folder under RDJ, I put the executable and dlls from GNUWin32’s wget port, and a little .vbs script (for TTS conversion) from the Jampal mp3 Library.

Next, I put together a batch file and a powershell script that would process the NWS Forecast information and create the waveform:

nws.bat:

@echo off
CD C:\RadioDJ\Media\NWS
:: get the forecast
wget ftp://tgftp.nws.noaa.gov/data/forecasts/zone/ky/kyz037.txt

:: remove header, end characters
for /f "skip=14 delims=$$" %%a in (kyz037.txt) do (
echo %%a >>forecast.tmp1
)

:: put text into one line (for TTS readability)
setlocal DisableDelayedExpansion
(for /F "usebackq delims=" %%a in (forecast.tmp1) do (
set /P "=%%a" < NUL )) > forecast.tmp

:: filter NWS abbreviations (and certain words) and replace with TTS friendly pronunciation values
powershell -command .\nws-filter.ps1

:: read the forecast into a WAV (NOTE: uses the 'default' computer voice)
cscript ptts.vbs -w forecast.wav -s 48000 -c 1 -r 2 < forecast.txt

:: cleanup the temp files
del *.tmp*
del *.txt

nws-filter.ps1:

$lookupTable = @{
'50s' = 'FIFTIES'
'60s' = 'SIXTIES'
'70s' = 'SEVENTIES'
'80s' = 'EIGHTIES'
'90s' = 'NINETIES'
'100s' = 'ONE-HUNDREDS'
'mph' = 'MILES-PER-HOUR'
'winds' = 'WINNEDS'
}

$original_file = 'forecast.tmp'
$destination_file = 'forecast.txt'

Get-Content -Path $original_file | ForEach-Object {
$line = $_

$lookupTable.GetEnumerator() | ForEach-Object {
if ($line -match $_.Key)
{
$line = $line -replace $_.Key, $_.Value
}
}
$line
} | Set-Content -Path $destination_file

…personally, I love the change I have to make to “winds” 😉

The powershell script can be edited later, for when I inevitably run across other words that aren’t pronounced right. Other filtering may be mandatory with other voices/engines… For example, the default voice I’m using–Microsoft Speech Server ZiraPro–will skip over ellipsis, whereas Microsoft Anna reads them as dot-dot-dot. Your mileage may vary.

…I guess the next thing I have to figure out is how to handle “immediate” bulletins… 😉

 

Juicing with RadioDJ – a revisit to a post that I haven’t posted yet…

…okay, so I just went to look for the previous writing, and it apparently never made it to my wordpress.com blog… hmm…

A month or so ago I wrote of how I was experimenting with playing locally saved podcast episodes in RadioDJ; while the process worked, it left a bit to be desired–especially when I moved things to an older/slower machine.

I’m still using Juice to download the podcasts–if it ain’t broke, etc., etc.–but I’ve done a bit of tweaking to everything else. First off, I changed the path to where I’m saving the episodes–simply because where I had things going was nuts! Second, I gave up on the creation of .m3u playlists, and went with using RadioDJ’s “Variable Duration File” abilities.

Huh? Say what?

Okay, RDJ has the ability to import a track once–as a “Variable Duration”–and will go back and scan it later to double check it’s length when it’s time to play again. …a feature just for this purpose!

With that new-found knowledge, I wrote a single quick-n-dirty batch file (using some Google-fu ninja tricks to help) that goes through the podcast sub-directories, keeps only the most recent episode, and renames it to the file that RDJ will be looking for. (I’ve also got RadioDJ running this batch as an event… so far, the performance hit isn’t as noticeable as my previous backwards methods.)

…so, anyway… to the batch-cave!

CD C:\RadioDJ\Media\Podcasts

for /f "delims=" %%i in ('dir C:\RadioDJ\Media\Podcasts /ad/s/b') do (
for /f "skip=1 delims=" %%j in ('dir "%%i\*.mp3" /b /o-d /a-d') do del "%%i\%%j"
)

for /f "delims=" %%k in ('dir C:\RadioDJ\Media\Podcasts /ad/s/b') do (
for /f "skip=1 delims=" %%l in ('dir "%%k\*.m4a" /b /o-d /a-d') do del "%%k\%%l"
)

FOR /D /R %%# in (*) DO (
PUSHD "%%#"
FOR %%@ in ("*") DO (
Echo Ren: ".\%%~n#\%%@" "%%~n#%%~x@"
Ren "%%@" "%%~n#%%~x@"
)
POPD
)

Scrobbling from RadioDJ (redux)

A couple days ago, I wrote a post about a quick and dirty–and half-working–solution to scrobbling tracks from RadioDJ… After further experimentation, I’ve found a cleaner automated way to do so. The method I’m employing scrobbles every hour, and reports the previous hour’s worth of tracks.

Additional software needed:

QTscrobbler–Command Line version available at Sourceforge

First, we need to build a compatible log-file–we’ll start to do this using the mySQL command line (assuming you’re using mySQL for your RadioDJ database–mine came packaged with all the other goodies in XAMPP). Immediately following is just the query, full-blown command line operation will be in the example batch file [scroll down for that hot goodness].

SELECT `artist`, `album`, `title`, `track_no`, cast(duration as decimal(10,0)), 'L' AS `listened_dummy_field`, UNIX_TIMESTAMP(date_played) FROM `history` WHERE `song_type`='0' AND `date_played` > DATE_ADD( NOW(), INTERVAL -1 HOUR ) ORDER BY `date_played` DESC INTO OUTFILE 'C:/RadioDJ/Media/last.fm/part.scrobbler.log' FIELDS TERMINATED BY '\t';

…as you can see, the query is dumping the info into a [tab-delimited] file; you’ll also see that for my own sanity, I’ve got it dumping into a directory created just for this, under the RadioDJ folder. Adjust for your own setup, of course. 😉

…also, you’ll see that the query is creating a dummy column–this is to satisfy QTscrobbler’s needs–it’s picky, whereas other scrobbling clients aren’t… and, yes, I’m going ahead and making mySQL do the UNIX time conversion–I had some issues when I tried to let other clients do the conversion for me.

Next, we need to put the audioscrobbler log file headers into the final part of the log file. (I did mention that QTscrobbler is a little picky, didn’t I?) For that, I created a static file in the aforementioned directory. Contents of that file–which I named “head.scrobbler.log”–is as follows:

#AUDIOSCROBBLER/1.0
#TZ/UTC
#CLIENT/RadioDJ

Now, we have to put the two *.scrobbler.log files together–I do this by dumping the head- file and then the part- file into the final .scrobbler.log file. [See the batch, further down this post.] With all that done, we can now–finally–scrobble the log file:

scrobbler-0.11.exe -c qtscrob.ini -f -l c:\radiodj\media\last.fm

NOTE: you’ll need a config file for QTscrobbler to use. I’m not entirely sure of what you can use or include in the config file–I ended up toying with the GUI version in order to create one that works. As an example, here’s my config file–minus the username and pass-hash:

[application]
version=0.11
utc_offset=0
tz_override=false
auto_open=true
del_apple_playlist=false
display_utc=false
mru=@Invalid()

[Last.fm]
enabled=true
username=YOUR_USERNAME_HERE
password_hash=MD5_HASH_OF_YOUR_PASSWORD

…ready to see the batch pulling all this off? I hope so, ’cause here it is:

@ECHO OFF
CD c:\radiodj\media\last.fm

::get_log
c:\xampp\mysql\bin\mysql.exe -e "SELECT `artist`, `album`, `title`, `track_no`, cast(duration as decimal(10,0)), 'L' AS `listened_dummy_field`, UNIX_TIMESTAMP(date_played) FROM `history` WHERE `song_type`='0' AND `date_played` > DATE_ADD( NOW(), INTERVAL -1 HOUR ) ORDER BY `date_played` DESC INTO OUTFILE 'C:/RadioDJ/Media/last.fm/part.scrobbler.log' FIELDS TERMINATED BY '\t';" --user=MYSQL_USERNAME_HERE --password=MYSQL_PASSWORD_HERE radiodj161

::build_log
type head.scrobbler.log>>.scrobbler.log
type part.scrobbler.log>>.scrobbler.log
del part.scrobbler.log

::scrobble
scrobbler-0.11.exe -c qtscrob.ini -f -l c:\radiodj\media\last.fm

::end
exit

To automate all this, I’m attempting to take advantage of RadioDJ’s ability to run commands as events. Currently, I’ve got an event set to run the batch hourly at xx:05:00. A tip to doing this–after you select RadioDJ to run cmd.exe, format the execution of the batch file [in the arguments field] like this:

cmd.exe /c start "scrobble" /min C:\RadioDJ\Media\last.fm\scrobble.bat ^& exit

…and you’ll be rewarded with a window that pops minimized, runs the batch, and exits when it’s finished!

Build a .scrobbler.log file from the RadioDJ history table

One thing that I’ve been trying to figure out how to do is report the tracks I’ve listened to/played via RadioDJ to last.fm. With the little bit of time I’ve had the best solution I’ve been able to come up with thus far is creating a log file from the info stored in RadioDJ’s database, then uploading that log file via someone else’s “scrobbler”.

First, the SQL query to build a .scrobbler.log file:
SELECT `artist`, `album`, `title`, `track_no`, cast(duration as decimal(10,0)), 'L' AS `listened_dummy_field`, UNIX_TIMESTAMP(date_played) FROM `history` WHERE `song_type`='0' AND `date_played` LIKE '2015-06-25%' ORDER BY `date_played` DESC INTO OUTFILE 'C:/.scrobbler.log' FIELDS TERMINATED BY '\t';

The code above currently pulls the info from the history table–assuming that the RadioDJ database has already been selected for use, of course–and outputs all the plays for the set date (set by the `date_played` LIKE '2015-06-25%') into a tab delimited text file. As of now, I’ve found two services that will use the file created: the online scroblr.net, and a standalone client called LogScrobbler. I’m hoping that I can later tweak the query and find a way to inject the proper headers into the .scrobbler.log file, so that the log-file is more compatible with other scrobbling clients. My end-goal is to create either a batch process that does all that, and uses a command-line scrobbling client, OR some sort of php script that handles querying the database and posting to last.fm…

…needless to say, I also want a better way to handle the date option. And, finding a way to scrobble in “real-time” would be preferable, rather than this “bulk” scrobbling option.

Inspiration for this little project:
http://www.rockbox.org/wiki/LastFMLog
http://www.audioscrobbler.net/wiki/Portable_Player_Logging