Last Sound System

From Second Life Wiki
Jump to navigation Jump to search
// Last Sound System by Babbage Linden
//
// An Open Source last.fm radio client for Second Life
// based on lastFMProxy by Vidar Madsen
//
// Available under the Creative Commons Attribution-ShareAlike 2.5 license
// http://creativecommons.org/licenses/by-sa/2.5/

integer gDialogChannel = 7777;
list gInfo;
integer gDialogHandle;
key gDialogKey;
key gHandshakeRequestKey;
string gStationURL;

list parseLine(string line)
{
    list tokens;
    integer lineIndex = llSubStringIndex(line, "=");
    tokens += llGetSubString(line, 0, lineIndex - 1);
    tokens += llGetSubString(line, lineIndex + 1, -1);
    return tokens;
}

list parseLines(string lines)
{
    list tokens;
    integer index = llSubStringIndex(lines, "\n");
    while(index != -1)
    {
        string line = llGetSubString(lines, 0, index - 1);        
        tokens += parseLine(line);
        lines = llDeleteSubString(lines, 0, index);
        index = llSubStringIndex(lines, "\n");
    }
    tokens += parseLine(lines);
    return tokens;
}

string getValue(list pairs, string name)
{
    integer length = llGetListLength(pairs);
    integer i;
    for(i = 0; i < length; i += 2)
    {
        if(llList2String(pairs, i) == name)
        {
            return llList2String(pairs, i + 1);
        }
    }
    return "";
}

reset()
{
    if(llGetInventoryType("Config") != INVENTORY_NOTECARD)
    {
        llSay(0, "ERROR: Config notecard not found");   
    }
    else
    {
        llGetNotecardLine("Config", 0);
    }
}

default
{
    state_entry()
    {
        gDialogHandle = llListen(gDialogChannel, "", NULL_KEY, "");
    }
    
    state_exit()
    {
        llListenRemove(gDialogHandle);
    }
    
    touch_start(integer num)
    {
        key gDialogKey = llDetectedKey(0);
        llDialog(gDialogKey, "Last Sound System Control", ["skip", "love", "ban", "reset"], gDialogChannel);
    }
    
    listen(integer channel, string name, key id, string message)
    {
        if(channel == gDialogChannel)
        {
            if(message == "reset")
            {
                reset();
            }
            else
            {   
                // Send command.
                string url = "http://" + getValue(gInfo, "base_url");
                url += "/" + getValue(gInfo, "base_path");
                url += "/control.php?command=" + message + "&session=" + getValue(gInfo, "session");
                llHTTPRequest(url, [], "");
            }
        }
    }
    
    dataserver(key id, string data)
    {
        list values = llCSV2List(data);
        if(llGetListLength(values) != 3)
        {
            llSay(0, "ERROR: Config notecard must contain \"<user>,<md5 password>,<last.fm station URL>\"");
        }
        else
        {
            string username = llList2String(values, 0);
            string md5password = llToLower(llList2String(values, 1));
            gStationURL = llList2String(values, 2);
            
            // Create session.
            string url = "http://ws.audioscrobbler.com/radio/handshake.php?";
            url += "version=1.0.1&platform=linux&username=" + username;
            url += "&passwordmd5=" + md5password + "&debug=0";
            gHandshakeRequestKey = llHTTPRequest(url, [], "");
        }
    }
    
    http_response(key id, integer status, list metadata, string body)
    {
        if(status == 200)
        {
            if(id == gHandshakeRequestKey)
            {
                gInfo = parseLines(body);
                
                llSetParcelMusicURL(getValue(gInfo, "stream_url"));
                
                // Set station.
                string url = "http://" + getValue(gInfo, "base_url");
                url += "/" + getValue(gInfo, "base_path");
                url += "/adjust.php?session=" + getValue(gInfo, "session");
                url += "&url=" + gStationURL;
                llHTTPRequest(url, [], "");
            }
        }
        else
        {
            llSay(0, "ERROR:" + (string)status + ":" + body);
        }
    }
}