mailto: blog -at- heyrick -dot- eu

Navi: Previous entry Display calendar Next entry
Switch to desktop version

FYI! Last read at 02:26 on 2024/05/01.

96.4 The Eagle, on RISC OS

When I used to live in the UK, a radio station that I listened to frequently was The Eagle (96.4FM in the Guildford area). The selection of music is fairly heavily slanted towards the '80s and I don't think I've ever heard anything that resembles rap on the station. It's sort of easy listening for the Lost Generation (GenX), though they will play new songs if they fit in the general ambience of the station.

For a long time it was blocked to people living outside of the UK. I tried it on a whim a couple of days ago and their website streamed to my iPad. I figured this was a good start to see if I could get the station playing on RISC OS.

After some poking around, I discovered that the base URL for the stream is http://str1.sad.ukrd.com/eagle, but this won't work directly with !DigitalCD because it is a redirect. The server responds with:

HTTP/1.1 302 Found
Date: Sat, 05 Mar 2016 15:23:04 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.6.17
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Location: http://fg2.sad.ukrd.com/eagle?ts=123456789
Content-Length: 0
Connection: close
Content-Type: audio/mpeg
Now, we can't just point ourselves at the fg2 server because not only does the server vary (load balancing?) but most importantly the ?ts=123456789 is actually a number valid for your connection, and a change of IP address, or not listening for a few minutes, causes the number to be invalid.
The next complication is that there is no programmatic way to alter DigitalCD's playlist entries on the fly.

As such, what we need is a little program that will run just before DigitalCD that will retrieve the connection link and modify the playlist file. Thus, when DigitalCD loads its playlist, it will be able to pick up a valid link to the station.

The end of the !DigitalCD.!Run file is this:

| Start DigitalCD
WimpSlot -min 492k -max 492k
Run DigitalCD:DigitalCD %*0
Just prior to those lines, insert this:
| Find out The Eagle's current link
Run DigitalCD:EagleFinder

And now here is the EagleFinder program itself:

REM >EagleFinder
REM
REM Find where 96.4 The Eagle is, and patch the DigitalCD playlist
REM
REM By Rick Murray, 2016/03/03
REM
REM If it works, the playlist is updated and the previous copied as "PrevPlaylist".
REM If it fails, we just exit...

ON ERROR PRINT REPORT$+" at "+STR$(ERL) : END
REM TRACE ON

DIM buffy% 4095                : REM 4K buffer
domain$ = "str1.sad.ukrd.com"  : REM Domain to fetch from
path$   = "/eagle"             : REM What to fetch (path)
port%   = 80                   : REM Port (80 = HTTP)
handle% = 0                    : REM Socket handle
ip% = 0                        : REM IP address
rb% = 0                        : REM Resolver data block
edited% = FALSE                : REM Existing entry edited?

REM Ensure Stack is loaded
SYS "XOS_SWINumberFromString", 0, "Socket_Creat" TO swi%
IF swi% <> &41200 THEN END                           : REM No stack loaded

REM Ensure Resolver is loaded. This is a little different because the
REM various resolvers share SWI numbers but have different names.
SYS "XOS_SWINumberToString", &46000, buffy%, 64
swi$ = FNGetStringAtAddress(buffy%, 0)
IF swi$ = "User" THEN END                            : REM No resolver loaded

REM Resolve the domain
REPEAT
  SYS "XResolver_GetHost", domain$ TO stat%, rb% ; flag%
  IF (flag% AND 1) = 1 THEN END
UNTIL stat% <> 36                                    : REM "EINPROGRESS"
REM ##TODO## Timeout?
IF rb% = 0 THEN END                                  : REM Unable to resolve domain
ip% = !(!(rb%!16))                                   : REM Yikes!

REM Create socket
SYS "Socket_Creat", 2, 1, 0 TO handle%
IF handle% = -1 THEN END                             : REM Unable to connect socket (ish...)

REM Connect to the remote machine
buffy%!0  = 2 OR ((port% DIV 256) << 16) OR ((port% MOD 256) << 24)
buffy%!4  = ip%
buffy%!8  = 0
buffy%!12 = 0
SYS "XSocket_Connect", handle%, buffy%, 16, 0 TO ; flag%
IF ((flag% AND 1) = 1) THEN
  SYS "Socket_Close", handle%
  handle% = 0
  END                                                : REM Connection refused (most likely)
ENDIF

REM Send our request
$buffy% = "GET "+path$+" HTTP/1.0"+CHR$(10)
$buffy%+= "Host: "+domain$+CHR$(10)
$buffy%+= "Accept: */*"+CHR$(10)
$buffy%+= "User-Agent: EagleFinder/0.1; RISC OS 5"+CHR$(10)+CHR$(10)
SYS "Socket_Write", handle%, buffy%, LEN($buffy%)

REM We don't poll (as we're running prior to DigitalCD starting up)
REM so waste a second to give time for the server to reply.
SYS "Hourglass_Start", 1
t% = TIME
REPEAT : UNTIL ((t% + 100) < TIME)
SYS "Hourglass_Off"

REM Read the first 160 bytes and discard them (early HTTP header stuff)
SYS "XSocket_Read", handle%, buffy%, 160 TO size% ; flag%

REM Now read 255 bytes. This part contains what we want to look at
FOR t% = 0 TO 255 : buffy%?t% = 0 : NEXT             : REM Ensure buffer is empty
SYS "XSocket_Read", handle%, buffy%, 255 TO size% ; flag%
IF ( (flag% AND 1) OR (size% = -1) ) THEN
  REM Failed!
  SYS "Socket_Shutdown", handle%, 2
  SYS "Socket_Close", handle%
  END
ENDIF

reply$ = FNGetStringAtAddress(buffy%, 0)

posn% = INSTR(reply$, "Location:")
IF (posn% = 0) THEN END                              : REM No "Location:" found

posn% += 10                                          : REM Skip "Location:"
reply$ = MID$(reply$, posn%)
$buffy% = reply$
reply$ = FNGetStringAtAddress(buffy%, 13)            : REM Lame-ass way to trim line ;-)
REM PRINT reply$                : REM ^^ Server appears to reply <13><10>!

REM At this stage, reply$ will contain the "new" URL.

REM Back-up current playlist.
OSCLI("%Copy <Choices$Dir>.DigitalCD.PlayList <Choices$Dir>.DigitalCD.PrevPlayList ~C~DF~N~P~Q~S~V")
REM Don't confirm, don't delete original, force, not 'only if newer',
REM don't prompt, not quick, don't stamp, not verbose.
REM In other words, shuddup and copy it.

REM Open the files (Prev for reading from, main for writing to)
REM This is accessing Choices incorrectly (Choices: / Choices$Write)
REM because I know the file has read/write access AND I want to be
REM sure to edit the original...
in% = OPENIN("<Choices$Dir>.DigitalCD.PrevPlayList")
out% = OPENOUT("<Choices$Dir>.DigitalCD.PlayList")

REM Copy line by line, checking for "ukrd"
REPEAT
  inline$ = GET$#in%
  IF (INSTR(inline$, "ukrd") <> 0) THEN
    REM Found, so update with it
    inline$ = GET$#in%                               : REM Discard next line
    posn% = INSTR(reply$, "eagle")                   : REM Find the split point
    BPUT#out%, LEFT$(reply$, (posn% - 1))            : REM Line1 - domain
    BPUT#out%, MID$(reply$, posn%);                  : REM Line2 - path + check value
    BPUT#out%, "*aUKRD,f257,r128,t96.4 Eagle,v85"    : REM Line2 - other stuff
    edited% = TRUE
    PRINT "Eagle edited."
  ELSE
    REM Just copy the line to the output
    BPUT#out%, inline$
  ENDIF
UNTIL EOF#in%

IF (edited% = FALSE) THEN
  REM There wasn't a copy to edit, so append new...
  posn% = INSTR(reply$, "eagle")                     : REM Find the split point
  BPUT#out%, LEFT$(reply$, (posn% - 1))              : REM Line1 - domain
  BPUT#out%, MID$(reply$, posn%);                    : REM Line2 - path + check value
  BPUT#out%, "*aUKRD,f257,r128,t96.4 Eagle,v85"      : REM Line2 - other stuff
  PRINT "Eagle appended."
ENDIF

REM Close files
CLOSE#in%
CLOSE#out%

REM And the socket...
SYS "Socket_Close", hande%

REM We're done.
SYS "Wimp_CommandWindow", -1
END

:

DEFFNGetStringAtAddress(array%, term%)
  LOCAL s$
  s$ = ""
  WHILE (?array% <> term%)
    s$ += CHR$(?array%)
    array% += 1
  ENDWHILE
=s$
Basically, this will directly modify the playlist to either replace an older entry, or to append it if it doesn't exist. If there are any problems, it will exit without doing anything. The program will briefly flash up a message saying that the Eagle has been modified or appended, as applicable. You won't get enough time to read it, but if the screen flashes and redraws upon starting DigitalCD, you'll know the update worked.
I ought to work for you. Things are trickier for me as I'm using WiFi through a metre-and-a-half thick stone wall, so the signal can be a little flaky in rainy/damp weather, but I've been listening to the station a fair bit yesterday and today and the Vonets WiFi adaptor picks up the weak signal better than the iPad...

 

The Eagle is part of the UKRD group, so while I have not tested it, you may be able to modify this program for the following local stations:

You can pick up the base links at http://str1.sad.ukrd.com/, with playlist details for Windows/Android/etc media players, or the raw stream for parsing with EagleFinder on RISC OS.

 

Observation: I've not been in the UK since early 2002 and... The Guildford Flames (ice hockey) are still kicking ass, and The Ripley Bypass (A3 near Wisley) is still a traffic disaster at rush hour. There is a Little Chef nearby, in case the traffic gets too much of a pain in the backside. Some things never change...

 

 

 

Your comments:

No comments yet...

Add a comment (v0.11) [help?]
Your name:

 
Your email (optional):

 
Validation:
Please type 20672 backwards.

 
Your comment:

 

Navi: Previous entry Display calendar Next entry
Switch to desktop version

Search:

See the rest of HeyRick :-)