| Scripting Discuss scripting and programming for SL and other platforms |
![]() |
| | LinkBack | Thread Tools | Display Modes |
| | #1 (permalink) |
| dorkasaurus ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]()
good looking ullu di patthi
Join Date: Mar 2008 Location: N.E. United States
Posts: 2,651
My Mood: SL Join Date: Nov 2007
Business: Pocket Gardens & Madhu's Cafe Client: Viewer 2.x Blog Entries: 4 | Script to read song information from a stream? Hello folks, I am looking for a script that can read song information from a stream playing on a parcel, parse out the title and artist information, and return it as a string (for example, for LLSetText). I have a full-perm radio that does this, but I am not an confident or experienced enough programmer to decipher which parts of the script I need to strip out and which parts control other aspects of the radio. Well, I probably could with a bunch of trial and error, but if someone already has a suitable script that would be much easier on me. ![]() Background: I have, in Madhu's inventory, a very simple display board that reads title and artist from the stream, writes it to hovertext, and shouts into chat when the song changes. It's not transferable, and I would like one for Carter, who has taken over all my DJ gigs. The shop I bought it from now has a newer version, but it is a huge monstrosity that uses XY-text and looks like an ugly club board. I asked the shopkeeper if he could sell me another copy of the old version, and he said he no longer had it and the creator of it has left SL. So I was hoping I could build one for myself, and I'd hoped I could decipher the full-perm radio script, but I'm a bit daunted by the task. I'd appreciate any help anyone can offer. I'd also be happy just to buy a new display if anyone knows of one that's not too big and not too ugly (or that is modifiable). |
| | |
| |
| | #2 (permalink) |
| Hypersonic Absolutist ![]() ![]() ![]()
Fully Zeno certified
Join Date: Aug 2007
Posts: 1,506
| Madhu: I've never played around with scripting the media stream, so this response is offered solely on a "just in case a better one doesn't come along". ![]() I'd be happy to at least have a quick look if you could post said script here. |
| | |
| 1 User Said Thanks: |
| | #3 (permalink) |
| Senior Member ![]() ![]() ![]() ![]()
DEUS EST HOMO
| Very basic script for shoutcast servers. Code: // 7.html gives the following in the body
// 0 -> current listeners
// 1 -> status
// 2 -> listener peak
// 3 -> max listeners
// 4 -> reported listeners
// 5 -> bitrate
// 6 -> song
string stream = "YOUR STREAM URL";
key kSentRequest;
default
{
state_entry()
{
string URL = stream + "/7.html HTTP/1.0\nUser-Agent: XML Getter (Mozilla Compatible)\n\n";
kSentRequest = llHTTPRequest(URL, [], "");
}
http_response (key kRecRequest, integer intStatus, list lstMeta, string strBody)
{
if (kRecRequest == kSentRequest)
{
// Strip the html out of the received information and just show what is inbetween the body tags
list html = llParseString2List(strBody,["<body>", "</body>"],[]);
string info = (llList2String(html,1));
list status = llCSV2List(info);
llSay(0," Current Listeners: " + llList2String(status,0));
llSay(0,"Status: " + llList2String(status,1));
llSay(0,"listener peak: " + llList2String(status,2));
llSay(0,"max listeners: " + llList2String(status,3));
llSay(0,"reported listeners: " + llList2String(status,4));
llSay(0,"bitrate: " + llList2String(status,5));
llSay(0,"Song: " + llList2String(status,6));
kSentRequest = NULL_KEY;
}
}
} |
| | |
| 2 Users Said Thanks : |
| 1 User Agreed: |
| | #4 (permalink) |
| dorkasaurus ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]()
good looking ullu di patthi
Join Date: Mar 2008 Location: N.E. United States
Posts: 2,651
My Mood: SL Join Date: Nov 2007
Business: Pocket Gardens & Madhu's Cafe Client: Viewer 2.x Blog Entries: 4 | Thank you both so much! Johnnie: dumb question. Will that script automatically update when the song changes, or do I need to put the http_response portion inside of some timer event to get it to check periodically? |
| | |
| | #5 (permalink) |
| SUPER BANNED ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
Auratusnaut
| Here is a *simple* script modified from the one I wrote for my own DJ titler. It can take the music url from the music_url string or from the description field of the object. I don't think there is a way to get the music url from the land profile (at least I've never found a way). Code: // leave music_url blank if set in object's description
string music_url = "";
key HTTPRequest;
string feed;
string URL;
string currSongTitle;
string lastSongTitle;
list feedList;
default
{
state_entry()
{
llSetText(" ",<1,1,1>,1);
llSetTimerEvent(5.0);
if(music_url)
{
URL = music_url;
} else {
URL = llGetObjectDesc();
}
}
timer()
{
HTTPRequest=llHTTPRequest(URL + "/7.html HTTP/1.0\nUser-Agent: LSL Script (Mozilla Compatible)\n\n",[],"");
}
http_response(key k,integer status, list meta, string body)
{
if(k != HTTPRequest) return;
feed = llGetSubString(body,llSubStringIndex(body, "<body>") + llStringLength("<body>"), llSubStringIndex(body,"</body>") - 1);
feedList = llParseString2List(feed,[","],[]);
currSongTitle = llList2String(feedList,6);
integer length = llGetListLength(feedList);
if(llList2String(feedList,7))
{
integer a = 7;
for(; a<length; ++a)
{
currSongTitle += ", " + llList2String(feedList,a);
}
}
if (currSongTitle != lastSongTitle)
{
llSetText(currSongTitle,<1,1,1>,0.75);
lastSongTitle = currSongTitle;
}
}
} Last edited by Free Xue; 07-14-2009 at 09:29 PM. |
| | |
| 3 Users Said Thanks : |
| | #6 (permalink) |
| dorkasaurus ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]()
good looking ullu di patthi
Join Date: Mar 2008 Location: N.E. United States
Posts: 2,651
My Mood: SL Join Date: Nov 2007
Business: Pocket Gardens & Madhu's Cafe Client: Viewer 2.x Blog Entries: 4 | Thank you thank you ! |
| | |
| | #8 (permalink) | |
| Junior Member ![]() Join Date: Aug 2009
Posts: 7
| Quote:
I have tried this Script but it didnt do nothing to my object. .... am i doing something wrong for it not to work?? Code: string music_url = "http://gold.neostreams.info:12254/";
key HTTPRequest;
string feed;
string URL;
string currSongTitle;
string lastSongTitle;
list feedList;
default
{
state_entry()
{
llSetText(" ",<1,1,1>,1);
llSetTimerEvent(5.0);
if(music_url)
{
URL = music_url;
} else {
URL = llGetObjectDesc();
}
}
timer()
{
HTTPRequest=llHTTPRequest(URL + "/7.html HTTP/1.0\nUser-Agent: LSL Script (Mozilla Compatible)\n\n",[],"");
}
http_response(key k,integer status, list meta, string body)
{
if(k != HTTPRequest) return;
feed = llGetSubString(body,llSubStringIndex(body, "<body>") + llStringLength("<body>"), llSubStringIndex(body,"</body>") - 1);
feedList = llParseString2List(feed,[","],[]);
currSongTitle = llList2String(feedList,6);
integer length = llGetListLength(feedList);
if(llList2String(feedList,7))
{
integer a = 7;
for(; a<length; ++a)
{
currSongTitle += ", " + llList2String(feedList,a);
}
}
if (currSongTitle != lastSongTitle)
{
llSetText(currSongTitle,<1,1,1>,0.75);
lastSongTitle = currSongTitle;
}
}
} | |
| | |
| | #9 (permalink) | |||
| SUPER BANNED ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
Auratusnaut
| Quote:
Quote:
Quote:
| |||
| | |
| | #10 (permalink) |
| Junior Member ![]() Join Date: Aug 2009
Posts: 7
| sorry im dumb lol but i got it to work now. ... but if i want to add more info how can i get the strings like now it shows the current song but i would like to add things like stream title like Stations Name Previous Songs Stream Url Stream Genre Things like dat |
| | |
| | #11 (permalink) | |
| SUPER BANNED ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
Auratusnaut
| Quote:
It *may* be possible to parse the Shoutcast status page, but llHTTPRequest() has a low limit of 2048 bytes for a document. Anything beyond that is truncated, and the status page is far larger than that. The best tools I've seen for this first capture the data using a separate, web-based tool (such as a PHP script) that transforms the status page into something they can better target (say an XML or CSV document) for use with llHTTPRequest(). | |
| | |
| | #12 (permalink) | |
| Junior Member ![]() Join Date: Aug 2009
Posts: 7
| Quote:
can you help me out a bit? with a sample cuz i dont really know java that much im more of a vb6 guy | |
| | |
| | #13 (permalink) | |
| SUPER BANNED ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
Auratusnaut
| Quote:
I can write it and test it, but I cannot host it. | |
| | |
| | #14 (permalink) | |
| Junior Member ![]() Join Date: Aug 2009
Posts: 7
| Quote:
| |
| | |
| | #15 (permalink) | |
| SUPER BANNED ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
Auratusnaut
| Quote:
![]() So... here's two PHP scripts I whipped up. The first deals with the general status page on a Shoutcast server, and the second talks to the "played.html" page. You could combine them, but 2 points to consider: 1. To make the data as normalized as I could for LSL scripting, they output to the "standard" SL notecard config format, where each bit of data is on its own line: Code: Server Status: Server is currently up and public. Stream Status: Stream is up at 96 kbps with 11 of 25 listeners (8 unique) Listener Peak: 14 Average Listen Time: 0m 42s Stream Title: DJ SLU Content Type: audio/mpeg Stream Genre: Punk/Techno/Waltz Stream URL: http://shout.sluniverse.com:12345 Stream AIM: N/A Stream IRC: #shoutcast Current Song: Green Day - Basket Case 2. Again, the issue of requested documents getting truncated at 2K I think makes a good case to handle them separately. ... I didn't tackle the parser on the LSL side. Don't really have the time; but there's lots of LSL scripts floating around that handle notecard (config) reading that can be adapted. Anyway, the fun in all this is when it gets to be collaborative, right? ![]() So... PHP scripts, finally! shout2notecard.php: Code: <?php
// user-configurable var: Shoutcast server URL
$shoutcast_url = 'http://shout.sluniverse.com:12345';
error_reporting(0);
ini_set('user_agent', 'Mozilla');
header('Content-type: text/plain; charset=utf-8');
$html = file_get_contents($shoutcast_url);
$dom = new domDocument;
$dom->loadHTML($html);
$tables = $dom->getElementsByTagName('table');
$rows = $tables->item(3)->getElementsByTagName('tr');
foreach($rows as $row)
{
$cols = $row->getElementsByTagName('td');
echo $cols->item(0)->nodeValue;
echo $cols->item(1)->nodeValue."\n";
}
?> Code: <?php
// user-configurable var: Shoutcast server URL
$shoutcast_url = 'http://shout.sluniverse.com:12345';
error_reporting(0);
ini_set('user_agent', 'Mozilla');
header('Content-type: text/plain; charset=utf-8');
$html = file_get_contents(rtrim($shoutcast_url, '/').'/played.html');
$dom = new domDocument;
$dom->loadHTML($html);
$tables = $dom->getElementsByTagName('table');
$rows = $tables->item(2)->getElementsByTagName('tr');
foreach($rows as $row)
{
$cols = $row->getElementsByTagName('td');
if(!strstr($cols->item(0)->nodeValue,'@'))
{
echo $cols->item(0)->nodeValue . ': ';
echo $cols->item(1)->nodeValue;
if($cols->item(2)->nodeValue)
echo '*'.$cols->item(2)->nodeValue.'*';
echo "\n";
}
}
?> I wrote and tested both on a PHP5 setup (5.2.9). I strip out the column headers in played.html (Played @ and Song Title), but these can easily be left in if wanted. Error reporting is turned off because... well, the DOMDocument class loadHTML() function has issues with badly formed HTML, something Shoutcast server pages are littered with. ![]() Ok, any questions about the code, have at the asking thing! | |
| | |
| | #16 (permalink) | |
| Junior Member ![]() Join Date: Aug 2009
Posts: 7
| Quote:
| |
| | |
| | #19 (permalink) |
| dorkasaurus ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]()
good looking ullu di patthi
Join Date: Mar 2008 Location: N.E. United States
Posts: 2,651
My Mood: SL Join Date: Nov 2007
Business: Pocket Gardens & Madhu's Cafe Client: Viewer 2.x Blog Entries: 4 | Hey - I just wanted to say, I finally got around to trying the script Free posted and it worked like a dream! And it's simple enough that I was able to hack it to add a few more features I wanted. Thanks so much to everyone who helped me with this! |
| | |
| 1 User Said Yay!: |
| | #20 (permalink) |
| Proud 1920s Berliner ![]() ![]()
Traveling trough time.
Join Date: Oct 2009 Location: 1920s Berlin
Posts: 296
My Mood: SL Join Date: 2/20/2009
Business: Weimar! Client: Phoenix | Hello all. I hope you dont mind me joining this discussion. I am looking for something similar, something that announces the song playing and the artist, etc. I tried the scripts here and they work. But I would like them to do something more, my apalogies if this was actually mentioned earlier, but I would want the script to say the information in chat. I have a little radio in my club that I would like to 'chat' this information when there is no DJ or anyone else. So automatically when a new song starts it chats ;the next song is, and then the information it gets from shoutcast, etc. |
| | |
| | #21 (permalink) | |
| dorkasaurus ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]()
good looking ullu di patthi
Join Date: Mar 2008 Location: N.E. United States
Posts: 2,651
My Mood: SL Join Date: Nov 2007
Business: Pocket Gardens & Madhu's Cafe Client: Viewer 2.x Blog Entries: 4 | Quote:
I'll be happy to drop my version of the script on you in world when I get in a bit later. Is Fraulein Yardley your SL name? | |
| | |
| | #23 (permalink) |
| Junior Member ![]() Join Date: Dec 2009 Location: Atlanta, GA
Posts: 12
My Mood: SL Join Date: 11/5/2009 (I started a new 2nd Life) | I've been using the above (closer to the top) bit of code to pull the song info from the stream. I've got the script set in a little ball I made and added a few extra lines of code so when you click it, it will shout the song title. What I'm currently using: Code: // leave music_url blank if set in object's description
string music_url = "";
key HTTPRequest;
string feed;
string URL;
string currSongTitle;
string lastSongTitle;
list feedList;
default
{
state_entry()
{
llSetText(" ",<1,0,0>,1);
llSetTimerEvent(5.0);
if(music_url)
{
URL = music_url;
} else {
URL = llGetObjectDesc();
}
}
timer()
{
HTTPRequest=llHTTPRequest(URL + "/7.html HTTP/1.0\nUser-Agent: LSL Script (Mozilla Compatible)\n\n",[],"");
}
http_response(key k,integer status, list meta, string body)
{
if(k != HTTPRequest) return;
feed = llGetSubString(body,llSubStringIndex(body, "<body>") + llStringLength("<body>"), llSubStringIndex(body,"</body>") - 1);
feedList = llParseString2List(feed,[","],[]);
currSongTitle = llList2String(feedList,6);
integer length = llGetListLength(feedList);
if(llList2String(feedList,7))
{
integer a = 7;
for(; a<length; ++a)
{
currSongTitle += ", " + llList2String(feedList,a);
}
}
if (currSongTitle != lastSongTitle)
{
llSetText(currSongTitle + "\n\nClick anywhere to shout track information",<1,1,1>,0.75);
lastSongTitle = currSongTitle;
}
}
touch_start(integer num_detected)
{
llShout(0, "You're listening to '" + currSongTitle + "'");
}
} What I would like is to add a / command or even a menu script or something that would allow me to change the stream URL without having the URL listed in the Description as some URLs I would like to keep hidden. I am kind of new at scripting so any guidance would be greatly appreciated. Thank you |
| | |
| | #24 (permalink) |
| SUPER BANNED ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() *SLU Supporter* ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
Auratusnaut
| Code: integer Channel = 123;
float Time = 5.0;
key HTTPRequest;
string feed;
string URL;
string currSongTitle;
string lastSongTitle;
list feedList;
default
{
state_entry()
{
llSetText(" ",<1,0,0>,1);
llListen(Channel, "", llGetOwner(), "");
llOwnerSay("Starting. Change stream on channel " + (string)Channel );
if( URL != "" )
{
llSetTimerEvent(Time);
}
else
{
llOwnerSay("Stream has not yet been set!");
}
}
timer()
{
HTTPRequest=llHTTPRequest(URL + "/7.html HTTP/1.0\nUser-Agent: LSL Script (Mozilla Compatible)\n\n",[],"");
}
http_response(key k,integer status, list meta, string body)
{
if(k != HTTPRequest) return;
feed = llGetSubString(body,llSubStringIndex(body, "<body>") + llStringLength("<body>"), llSubStringIndex(body,"</body>") - 1);
feedList = llParseString2List(feed,[","],[]);
currSongTitle = llList2String(feedList,6);
integer length = llGetListLength(feedList);
if(llList2String(feedList,7))
{
integer a = 7;
for(; a<length; ++a)
{
currSongTitle += ", " + llList2String(feedList,a);
}
}
if (currSongTitle != lastSongTitle)
{
llSetText(currSongTitle + "\n\nClick anywhere to shout track information",<1,1,1>,0.75);
lastSongTitle = currSongTitle;
}
}
touch_start(integer num_detected)
{
llShout(0, "You're listening to '" + currSongTitle + "'");
}
listen (integer channel, string name, key id, string message)
{
if( llGetSubString(message,0,6) == "http://" )
{
URL = llStringTrim(message,STRING_TRIM);
if( llGetSubString(URL,-1,-1) == "/" )
URL = llDeleteSubString(URL,-1,-1);
llSetTimerEvent(Time);
llOwnerSay("Stream changed to : " + URL);
}
else
{
llOwnerSay("Address appears invalid. Stream was not changed.");
}
}
} Does a tiny bit of validation on the URL you enter (just makes sure it starts with http://), as well as stripping off any trailing slash. |
| | |
| | #25 (permalink) |
| Junior Member ![]() Join Date: Dec 2009 Location: Atlanta, GA
Posts: 12
My Mood: SL Join Date: 11/5/2009 (I started a new 2nd Life) | Thank you, that actually worked out pretty good. I got to messing around a bit and improved my little ball prim and made into a box and drew a little radio picture for the front of it. I added a 2nd prim to it and added the following script into it: Code: string music_url1 = "http://mystream1.net:12345";
string music_url2 = "http://mystream2.net:54321";
integer CHANNEL = 99;
list MENU_MAIN = ["Main", "Backup"];
default
{
state_entry()
{
llListen(CHANNEL, "", NULL_KEY, "");
}
touch_start(integer total_number)
{
llDialog(llDetectedKey(0), "Select a stream:", MENU_MAIN, CHANNEL);
}
listen(integer channel, string name, key id, string message)
{
if (llListFindList(MENU_MAIN, [message]) != -1)
{
if (message == "Main")
{
llOwnerSay("Main Stream - " + music_url1);
llSetParcelMusicURL(music_url1);
}
else if (message == "Backup")
{
llOwnerSay("Backup Stream - " + music_url2);
llSetParcelMusicURL(music_url2);
}
}
else
{
llOwnerSay("There was an error!");
}
}
} Again, thank you for any help. |
| | |
![]() |
| Thread Tools | |
| Display Modes | |
| |
| |