Change font size
It is currently Tue Dec 18, 2018 1:08 pm

Forum rules


{L_IMAGE}



Post a new topicPost a reply Page 1 of 1   [ 4 posts ]
Author Message
 Post subject: Shoutcast - radio controller
PostPosted: Fri Mar 16, 2012 3:36 pm 
OSG Elite

Joined: Wed Aug 05, 2009 1:59 am
Posts: 417
This script (and a controller notecard) makes a nice parcel music player.
Menu driven, multiple categories, you can set permissions on who can use it and more.

First the script. Drop it in a prim.

{L_CODE}:
// Script:  Shoutcast - radio controller
// Version: 0.3 - released 10-2-2011
// Logic Scripts (Flennan Roffo)
// (c) 2010 - Flennan Roffo (Logic Scripts)
//
// This script is a remake of a couple of similar script:
// + LandOwnersRadio V2.0 by Scripter Coba  (( menu driven / notecard config script to select the radio station and sets parcel music url ))
// + Raven radio infoboard by Jamie Otis    (( worked at the basis of sis service [sis.slserver.com/sis.php] used Xy text display         ))
// + currentPlaying by Darkie Minotaur      (( used the /7.html info to fetch current song title info, displayed as float text            ))
//
// Purpose:
// * Sets the parcel audio URL and displays the channel info
// * Uses Xytext to display the info.
// * Fetches song title info from the shoutcast url
///////////////////////////////////////////////////////////////////////////////////////
// Extra Features -- 0.1 release
// * On/Off option
// * Allows multiple menus (if options per menu > 12) using a prev/next button
// * Checks if your url is well-formatted
// * Will delete genres for which no stations exist
// * Will skip stations that have same url and same genre (you can however have an identical station url under different genres).
// * New notecard format
//////////////////////////////////////////////////////////////////////////////////////////
// Extra Features -- 0.2 release
// * Configurable button text
// * Gets parcel URL and automatically sets the genre/station and on/off status accordingly (<-- doesn't work)
//////////////////////////////////////////////////////////////////////////////////////////
// Update -- 0.3 release
// * Fixed bug (only first station in genre displayed in menu)
// * Auto reset script when config card updated
// Notes:
// * Expects url to be in the format: <ip>:<port>, where <ip> has the format: xxx.xxx.xxx.xxx  (0 <= xxx <= 255)
// * Deletes entries in category (genre) for which no stations are configured with notice.
// * Skips stations which have identical url AND same category (genre).
//////////////////////////////////////////////////////////////////////////////////////////
// Upcoming release -- 0.4
// * Will add functions for remote controller(s) and remote display(s) using llRegionSay to communicate over a channel.
// * Should relax on the constraints about the input format of URL's (currently requires that URL has format: xxx.xxx.xxx.xxx/yyyy).
// * Fix button placement. Control buttons should be on the first line.
// * Implement script reset on change of owner.
// * Permit station to be put under multiple genres, using a comma-seperated list of genres in the section [STATION]
//   (currently this is only possible by duplicating the entire line and change the genre.)
/////////////////////////////////////////////////////////////////////////////////////////
// Future plans:
// * Individual user preferences that can be stored on seperate note cards. A user has access to his own list of genres and stations and the system available genres/stations.
// * Feature for accessing online playlists (M3U, PLS, other formats) to play a list of songs provided by that playlist.
// * User provided url.
/////////////////////////////////////////////////////////////////////////////////////////
// BUGS & FEATURE REQUESTS
//
// Please inform the author, Logic Scripts (flennan.roffo) about any bugs or annoyances.
// Feature requests can also be submitted to the author.
/////////////////////////////////////////////////////////////////////////////////////////
// LICENCE INFO
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
///////////////////////////////////////////////////////////////////////////////////////////

string info_notecard="Radio Control info";              ///////    EDITABLE  \\\\\\
string config_notecard="Radio Control config";          ///////    EDITABLE  \\\\\\
string comment_char="#";                                ///////    EDITABLE  \\\\\\
list sep_char_list= ["|"];                              ///////    EDITABLE  \\\\\\
float update_time=5.0;                                  ///////    EDITABLE  \\\\\\
string no_title_info="(no title info available)";       ///////    EDITABLE  \\\\\\

// not used currently - for showing info on current song title elsewhere in the region
integer broadcast_channel=-1234;                        ///////    EDITABLE  \\\\\\

// Buttons

string button_MAIN = "MAIN";                            ///////    EDITABLE  \\\\\\
string button_HELP = "HELP";                            ///////    EDITABLE  \\\\\\
string button_NEXT = ">>";                              ///////    EDITABLE  \\\\\\
string button_PREV = "<<";                              ///////    EDITABLE  \\\\\\
string button_ON   = "ON";                              ///////    EDITABLE  \\\\\\ 
string button_OFF  = "OFF";                             ///////    EDITABLE  \\\\\\

//////////////////////////////////
// Don't touch the variables below
/////////////////////////////////

// List of categories (=genres)

list category_list=[];

// List of stations. KEEP THESE LISTS IN SYNCH!

list station_category=[];
list station_name=[];
list station_desc=[];
list station_url=[];

// Last song title played
string last_title_info="";

integer radio_status=0;    // 0 - OFF   1 - ON
string parcel_url="";
integer lineno=0;
key reqid=NULL_KEY;
key httpreq_id=NULL_KEY;
integer config_error=FALSE;
integer flag;
integer section=0;

// Access values. Note that users who are banned can not access the device even when access is public
integer owner_access=TRUE;
integer group_access=FALSE;
integer public_access=TRUE;
list banned_keys=[];

// Channels for menu and user input
integer menu_channel;
integer listen_handle;

// Menu
integer menu_type=0;         // 0 - Main menu (genres)   1 - Station menu (stations)
integer menu_num=0;          // When more menu options need to be selectable then can be displayed on a menu (12), this is the menu number - menu number 0 is the first menu.

// Genres and stations

integer category_index=0;    // Current index in category_list  (genre)
integer station_index=0;     // Current index in station_*      (station)

integer num_categories=0;
integer num_stations=0;

// Make request for title info using HTTP request
retrieve_titelinfo()
{
    string url=llList2String(station_url,station_index);
    httpreq_id=llHTTPRequest(url + "/7.html  HTTP/1.0\nUser-Agent: LSL Script (Mozilla Compatible)\n\n",[],"");
}

// Display a line on an Xytext device linked in
display_line(string line, string message)
{
    // Setup XYtext Variables
    integer DISPLAY_STRING      = 204000;
//    integer DISPLAY_EXTENDED    = 204001;     (not used)
//    integer REMAP_INDICES       = 204002;     (not used)
//    integer RESET_INDICES       = 204003;     (not used)
//    integer SET_CELL_INFO       = 204004;     (not used)
//    integer SET_FONT_TEXTURE    = 204005;     (not used)
//    integer SET_THICKNESS       = 204006;     (not used)
//    integer SET_COLOR           = 204007;     (not used)

    llMessageLinked(LINK_SET,DISPLAY_STRING,message,line);
}

// Clear the Xytext display
clear_display()
{
    // Clears the display
    display_line("1","Radio Station ID");
    display_line("2","Music Genre....");
    display_line("3","Now Playing....");
}

// Make a menu / dialog
make_menu(key id)
{
     menu_channel=random_channel();

    if (radio_status == 0)
    {
        menu_type=0;
        menu_num=0;
        llDialog(id,"Menu: Status\n\nRadio is OFF", [ "ON", "HELP" ],menu_channel);
    }
    else
    {
        if (menu_type ==0)
        {
            llDialog(id,"Menu: Genres", category_menu(menu_num),menu_channel);
        }
        else
        {
            llDialog(id,"Menu: Stations\nGenre: " + llList2String(category_list,category_index), station_menu(menu_num),menu_channel);
        }
    }

    if (listen_handle != 0)    llListenRemove(listen_handle);
    listen_handle=llListen(menu_channel,"",id,"");
}

// Make the menu option list for menu: catagories (genres)
list category_menu(integer num)
{
    integer len=llGetListLength(category_list);
    list menu=[];

    if (len > 9)   // If more then 9 items (12 minus the 3 buttons for MAIN/HELP and PREV, NEXT)
    {
        integer last_sub=(len-1)/9;   // submenus start at 0. 9th entry is in submenu 0, 10th in 1, etc.

        if (num > last_sub)
        {
            llWhisper(0,"error: wrong submenu number: " + (string) num + ".");
            return [ "MAIN" ];
        }
        else
        {
             integer first=9*num;

             while (--len >= first)
                menu+=(list)llList2String(category_list,len);

             if (num == 0)
                menu+=(list)button_HELP;
             else
                 menu+=(list)button_MAIN;

             if (num == 0)
                menu+=(list)button_OFF;
             else
                menu+=(list)button_PREV;

             if (num != last_sub)
                menu+=(list)button_NEXT;       
        }           
    }
    else
    {
        while (--len >= 0)
            menu+=(list)llList2String(category_list,len);

        menu+=(list)button_OFF;
        menu+=(list)button_HELP;
    }       

    return menu;    // order_buttons(menu);
}

// Returns the number of stations in a certain category
integer stations_in_category(integer cat)
{
    integer count=0;
    integer i;
    integer len=llGetListLength(station_category);
    string category=llList2String(category_list,cat);

    for (i=0; i < len; i++)
        if (category == llList2String(category_list,i))
            count++;

    return count;
}

// Not used currently -- to fix button placement
//list order_buttons(list buttons)
//{
//    integer offset;
//    list fixt;
//    integer flag=0;
//
//    while((offset = llGetListLength(buttons)))
//   {
//       if (offset > 3)
//           flag=1;
//        else
//            flag=0;
//
//       fixt = llList2List(buttons, offset = -3 * flag, -1);
//        buttons = llDeleteSubList(buttons, offset, -1);
//   }

  //  return fixt;
//}

// Returns a list of station names in a certain category (genre)
list station_list(integer category)
{
    list s=[];
    integer i;
    string cname=llList2String(category_list,category_index);

    for (i = 0; i < llGetListLength(station_name); i++)
        if (llList2String(station_category,i) == cname)
            s+=(list)llList2String(station_name,i);

    return s;

}

// Returns the list of stations for the station menu, depending on the submenu number
list station_menu(integer num)
{
    list stations=station_list(category_index);
    integer len=llGetListLength(stations);
    list menu=[];

    if (len > 11)       // 12 - 1 for MAIN menu
    {
        integer last_sub=(len-1)/9;

        if (num >= last_sub)
        {
            llWhisper(0,"error: wrong submenu number: " + (string) num + ".");
            return [ "MAIN" ];
        }
        else
        {
             integer first=9*num;
             integer last=9*num+8;

             menu+=(list)button_MAIN;

             if (num > 0)
                menu+=(list)button_PREV;

             if (num < last_sub)
                menu+=(list)button_NEXT;                     

            if (len > last)
                len =last;

            while (--len >= first)
                menu+=(list)llList2String(stations,len);
        }
    }           
    else
    {
        menu+=(list)button_MAIN;

        while (--len >= 0)
            menu+=(list)llList2String(stations,len);
    }       

    return menu; // order_buttons(menu);
}

// Returns whether av with key id has access
integer has_access(key id)
{
    if (llListFindList(banned_keys,(list)id) != -1)
        return FALSE;

    if (owner_access && id == llGetOwner())
        return TRUE;

    if (group_access && llSameGroup(id))
        return TRUE;

    if (public_access)
        return TRUE;

    return FALSE;
}

// Gets a random channel -- uses a wide range of big negative channel numbers seldomly used
integer random_channel()
{
    integer min=-2147483647;
    integer max=-1000;

    return (integer) (min + llFrand(max-min));
}

// Check for the format of the url string  -- is very selective about url format
// expects:   xxx.xxx.xxx.xxx:xxxx    (ip adress in number notation with port adress)
// Next release will relax on this constraint.
integer check_url(string url)
{
    integer pos=0;

    if (llGetSubString(url,0,6) == "http://")
        pos=7;       
    if (llGetSubString(url,0,7) == "https://")
        pos=8;

    if (pos==0)   return FALSE;

    string str_ip_port=llGetSubString(url,pos,-1);
    list list_ip_port=llParseString2List(str_ip_port,[":"],[]);                 // split in ip-adress and port
    list list_ip=llParseString2List(llList2String(list_ip_port,0),["."],[]);    // split ip-adress elements

    if (llGetListLength(list_ip_port) != 2 || llGetListLength(list_ip) != 4)
        return FALSE;

    integer i;
    integer test;

    for (i=0;i<4;i++)
    {
        test=llList2Integer(list_ip,i);
        if (llList2String(list_ip,i) != (string)test)
            return FALSE;
        if (test < 0 || test > 255)
            return FALSE;
    }

    test=llList2Integer(list_ip_port,1);
    if (llList2String(list_ip_port,1) != (string)test)
        return FALSE;

    return TRUE;
}

// Returns a true value depending on the first character in input - anything else is assumed false.
integer true_value(string input)
{
    string value=llToLower(llGetSubString(input,0,0));

    if (value == "y" || value == "t" || value =="1")
        return TRUE;

    return FALSE;
}

// Return if more input should be processed (if not at EOF) - sets ConfigError if any config error found. Reading config card stops at the first error.
integer process_line(string dataline)
{
    string line=llStringTrim(dataline,STRING_TRIM);
    integer index=llSubStringIndex(line,comment_char);

    if (index==0)       // line starts with comment - ignore line
        return TRUE;

    if (index!=-1)
        line=llStringTrim(llGetSubString(line,0,index-1),STRING_TRIM_TAIL);   // skip everything after comment_char and trim tail

    if (line=="")       // Ignore blank lines
        return TRUE;

    if (llToLower(line) == "[access]")
    {
        section = 1;
        return TRUE;
    }
    else if (llToLower(line) == "[banned]")
    {
        section = 2;
        return TRUE;
    }
    else if (llToLower(line) == "[genre]")
    {
        section = 3;
        return TRUE;
    }
    else if (llToLower(line) == "[station]")
    {
        section = 4;
        return TRUE;
    }
    else if (llGetSubString(line,0,0) == "[" && llGetSubString(line,-1,-1) == "]")
    {
        llWhisper(0,"error: malformed section found at line " + (string)lineno + ".\n" + dataline);
        config_error=TRUE;
        return FALSE;
    }

    if (section == 0)
    {
        llWhisper(0,"error: no section found on line: " + (string) lineno);
        config_error = TRUE;
        return FALSE;
    }

    list breakup=llParseString2List(line,["="],[]);
    string field=llStringTrim(llList2String(breakup,0),STRING_TRIM);
    string values=llStringTrim(llList2String(breakup,1),STRING_TRIM);

    if (section == 1)            // access
    {
        field=llToLower(field);

        if (field=="owner")
        {
            owner_access=true_value(values);                       
            return TRUE;
        }
        else if (field=="group")
        {   
            group_access=true_value(values);
            return TRUE;
        }
        else if (field=="public")
        {
            public_access=true_value(values);
            return TRUE;
        }
        else
        {
            llWhisper(0,"error: invalid option on line: " + (string)lineno + ".\n" + dataline);
            config_error=TRUE;
            return FALSE;
        }

    }
    else if (section == 2)         // ban list
    {
        key try=(key) field;

        if (try)
        {
            banned_keys+=(list)((key) field);
            return TRUE;
        }
        else
            return FALSE;
    }
    else if (section == 3)           // categories
    {
        if (llListFindList(category_list,(list)field) == -1)
        {
            category_list+=(list)field;
        }
        else
            llWhisper(0,"genre: '" + field + "' already entered; double entry skipped.");

        return TRUE;
    }
    else if (section == 4)            // stations
    {
        list parse=llParseString2List(line,sep_char_list, []);
        string category=llStringTrim(llList2String(parse,0),STRING_TRIM);
        string name=llStringTrim(llList2String(parse,1),STRING_TRIM);
        string desc=llStringTrim(llList2String(parse,2),STRING_TRIM);
        string url=llStringTrim(llToLower(llList2String(parse,3)),STRING_TRIM);

        if (!available_category(category))
        {
            llWhisper(0,"error: unknown genre on line: " + (string)lineno + ".\n" + dataline);
            config_error=TRUE;
            return FALSE;
        }

        if (check_url(url))
        {
            if (llListFindList(station_url,(list)url) == -1 || llListFindList(station_category,(list)category) == -1)
            {
                num_stations++;
                station_category+=(list)category;
                station_name+=(list)name;
                station_desc+=(list)desc;
                station_url+=(list)url;
                return TRUE;
            }
            else
            {
                llWhisper(0,"This station is already entered under the same genre and same url and is skipped.\nStation: " + name + "\nGenre: '" + category + "'\nURL: " + url);
                return TRUE;
            }
        }
        else
        {
            llWhisper(0,"error: malformed url on line: " + (string)lineno + ".\n" + dataline);
            config_error=TRUE;
            return FALSE;
        }
    }

    return FALSE;
}

// Sets the parcel URL and updates the display
set_parcel_url(string url)
{
    parcel_url=url;
    llSetParcelMusicURL(parcel_url);

    if (parcel_url=="")
    {
        clear_display();
        display_line("1","Radio is OFF");
        display_line("2","");
        display_line("3","");
    }
    else
    {
        llWhisper(0,"station now set to " + llList2String(station_desc,station_index) + ".");
        display_line("1","Station: " + llList2String(station_desc,station_index));
        display_line("2","Genre  : " + llList2String(category_list,category_index));
        display_line("3","Now playing.....");
        llSetTimerEvent(update_time);
    }
}

// Returns if a category (genre) exists.
integer available_category(string category)
{
    integer i;
    integer len=llGetListLength(category_list);

    for (i=0;i<len;i++)
        if (llToLower(category) == llToLower(llList2String(category_list,i)))
            return TRUE;

    return FALSE;
}

// Returns if a category (genre) is empty (i.e. there are no stations for this catagory (genre))
integer empty_category(string category)
{
    integer i;
    integer len=llGetListLength(station_category);

    for (i=0; i < len; i++)
        if (llToLower(category) == llToLower(llList2String(station_category,i)))
            return FALSE;

    return TRUE;
}

// Removes categories (genres) for which no station is known.
skip_empty_categories()
{
    integer i=0;

    while (i<llGetListLength(category_list))
    {
        if (empty_category(llList2String(category_list,i)))
        {
            llWhisper(0,"Warning: Genre '" + llList2String(category_list,i) + "' contains no stations and is deleted.");
            category_list=llDeleteSubList(category_list,i,i);
        }
        else
            i++;
    }

    num_categories=llGetListLength(category_list);
}

/////////////////////////////////////////////
// state default
////////////////////////////////////////////

default
{
    state_entry()
    {
        flag=FALSE;
        lineno=0;
        config_error=FALSE;
        num_stations=0;
        num_categories=0;
        radio_status=0;
        menu_num=0;
        menu_type=0;

        if (llGetInventoryType(config_notecard) == INVENTORY_NOTECARD)
        {
           reqid=llGetNotecardLine(config_notecard,lineno++);
           llWhisper(0, "Reading config notecard...");
           display_line("1","Reading configuration.");
           display_line("2","Wait....");
           display_line("3","");
        }
        else
        {
            llWhisper(0,"No config notecard '" +  config_notecard + "' present.");
            state offline;
        }
    }

    on_rez(integer param)
    {
        llResetScript();
    }

    dataserver(key id, string data)
    {
        if (reqid==id)
        {       
            if (data==EOF)
            {
                skip_empty_categories();
                llWhisper(0,"Configuration ok.\n" + (string)num_categories + " genres and " + (string)num_stations + " stations.");
                display_line("1","Configuration OK");
                display_line("2","Genres  : " + (string)num_categories);
                display_line("3","Stations: " + (string)num_stations);
                state menu;
            }
            else
            {
                if (process_line(data))
                    reqid=llGetNotecardLine(config_notecard,lineno++);
                else if (config_error)
                {
                    llWhisper(0,"errors found in configuration. please correct them.");
                    state offline;
                }
            }
        }
    }

    touch_start(integer total_num)
    {
    }

    changed(integer ch)
    {
        if (ch & CHANGED_INVENTORY)
            llResetScript();
    }
}

/////////////////////////////////////////////
// state offline
////////////////////////////////////////////

state offline
{
    state_entry()
    {
        llWhisper(0,"Reset on owner touch or when notecard updated.");
    }

    touch_start(integer t)
    {
        if (llDetectedKey(0)==llGetOwner())
            llResetScript();
    }

    changed(integer ch)
    {
        if (ch & CHANGED_INVENTORY)
            llResetScript();
    }
}

/////////////////////////////////////////////
// state menu
////////////////////////////////////////////

state menu
{
    state_entry()
    {
        menu_type=0;
        menu_num=0;
        listen_handle=0;
    }

    on_rez(integer param)
    {
        llResetScript();
    }

    touch_start(integer total_num)
    {
        key toucher=llDetectedKey(0);

        if (has_access(toucher))
        {
            make_menu(toucher);
        }
        else
            llWhisper(0,"sorry, no access.");
    }

    listen(integer chan, string name,key id,string msg)
    {
        integer index;

        if (menu_type == 0)          // main menu
        {
            if (msg == button_MAIN)
            {
                menu_type=0;
                menu_num =0;
                make_menu(id);
            }
            else if (msg == button_NEXT)
            {
                menu_num++;
                make_menu(id);
            }
            else if (msg == button_PREV)
            {
                menu_num--;
                make_menu(id);
            }
            else if (msg == button_ON)
            {
                radio_status=1;
                set_parcel_url(parcel_url);               
                display_line("1","Radio is ON");
                menu_num=0;
                llWhisper(0,"Radio now turned on.");
                make_menu(id);
            }
            else if (msg == button_OFF)
            {
                radio_status=0;
                set_parcel_url("");
                llSetTimerEvent(0.0);
                llWhisper(0,"Radio now turned off.");
            }
            else if (msg == button_HELP)
            {
                if (llGetInventoryType(info_notecard) == INVENTORY_NOTECARD)
                {
                    llGiveInventory(id,info_notecard);
                }
                else
                    llWhisper(0,"sorry, help not available.");
            }
            else if (radio_status == 1)
            {
                index = llListFindList(category_list, (list)msg);

                if (index == -1)
                    llWhisper(0,"error: genre not found: " + msg);
                else
                {
                    category_index=index;
                    llWhisper(0,"Genre now set to " + llList2String(category_list,category_index) + ".");
                    menu_type=1;
                    menu_num=0;
                    make_menu(id);
                }
            }
        }
        else if (menu_type == 1 && radio_status == 1)     // station menu
        {
            if (msg == button_MAIN)
            {
                menu_type=0;
                menu_num =0;
                make_menu(id);
            }
            else if (msg == button_NEXT)
            {
                menu_num++;
                make_menu(id);
            }
            else if (msg == button_PREV)
            {
                menu_num--;
                make_menu(id);
            }
            else
            {
                index = llListFindList(station_name, (list)msg);

                if (index == -1)
                    llWhisper(0,"error: station not found: " + msg);
                else
                {
                    station_index=index;
                    string new_url=llList2String(station_url,station_index);

                    if (new_url != parcel_url)
                    {
                        set_parcel_url(new_url);
                    }
                }
            }
        }
    }

    timer()
    {
        retrieve_titelinfo();
        llSetTimerEvent(update_time);
    }

    http_response(key id, integer status, list meta, string body)
    {
        if (id == httpreq_id)
        {
            if (status == 200)
            {
                string feed = llGetSubString(body,llSubStringIndex(body, "<body>") + llStringLength("<body>"), llSubStringIndex(body,"</body>") - 1);
                list feed_list = llParseString2List(feed,[","],[]);
                string current_title_info= llList2String(feed_list,6);
                integer length = llGetListLength(feed_list);

                if(llList2String(feed_list,7))
                {
                    integer a = 7;
                    for(; a<length; ++a)
                    {
                        current_title_info += ", " + llList2String(feed_list,a);
                    }
                }

                if (current_title_info != last_title_info)
                {
                    last_title_info = current_title_info;
                    display_line("3","Title  : " + current_title_info);
                }
            }
            else
            {
                display_line("3","Title  : " + no_title_info);
            }
        }   
    }

    changed(integer ch)
    {
        if (ch & CHANGED_INVENTORY)
            llResetScript();
    }
}

//////////////////////////////
// end of script
//////////////////////////////


Now create a notecard, copy the (example) text below, past that in to the notecard and put the notecard in the prim.
Reset the script, and your done.
Enjoy.

{L_CODE}:
# New format Shoutcast - radio controller config notecard
# The format is divided in 4 sections:
# 1 - Access configuration
# 2 - Ban list (keys)
# 3 - Categories  (same as genres)
# 4 - Station info (category, name, desc, url)
# The '#' character defines the start of a comment and can be anywhere on a line.
# Everything after the '#' incuding the '#' itself is ignored.
# Case is not important (but information on display will show as entered)
# Spaces before and/or after fields are trimmed.
# Empty lines are ignored.

[ACCESS]
owner=yes       # yes, true,1      means owner has access. everything else not.
group=yes       #  ,,  ,,  ,,      means group has acess.    ,,        ,,   ,,
public=yes      #  ,,  ,,  ,,      means public has access.  ,,        ,,   ,,

[BANNED]
# keys of banned residents

[GENRE]
# genre name -- Use short genre names as the the length of menu buttons is short!
Hard Rock
Classic Rock
Oldies
Rap/Urban
Comedy
News
Dance
Country
Gothic
Classical
Blues
# etc.
[STATION]
# Shoutcast radio stations
# Use a '|' between each field - don't mind spaces before and after fields, they will be trimmed
# field1:genre, field2:station name, field3: station description, field4: station http://<ip>:<port> or https://<ip>:<port>
# Note that genre must match case-insensitive a value previously entered in section [GENRE]
Classical|  Mozart Piano | Piano music   | http://68.68.22.142:8030
Blues|  BellyUp4Blues|The Only Ass Kicking Blues Rocker  | http://72.13.82.82:5100
# etc.


Top
 Profile  
 
 Post subject: Re: Shoutcast - radio controller
PostPosted: Thu Jun 05, 2014 4:46 pm 
User avatar

Joined: Sat Nov 03, 2012 6:06 am
Posts: 8
{L_CODE}:
httpreq_id=llHTTPRequest(url + "/7.html  HTTP/1.0\nUser-Agent: LSL Script (Mozilla Compatible)\n\n",[],"");


Found this script again, just wanted to make sure I didn't forget something while fetching shoutcast's /7.html but... does anyone else have problems using this?
I'm getting 499 errors, whatever I try. Did shoutcast change their servers recently?

When I fetch html from one of my own servers, it works. /7.html just blocks requests like above.


Top
 Profile  
 
 Post subject: Re: Shoutcast - radio controller
PostPosted: Thu Jun 05, 2014 6:16 pm 
OSG Elite
User avatar

Joined: Thu Aug 06, 2009 7:07 am
Posts: 347
Location: B.C. Canada
Not sure if this is the cause of that error, but did you take the ";" out from
the " user_agent = "OpenSim LSL (Mozilla Compatible)" " line in opensim.ini?


Top
 Profile  
 
 Post subject: Re: Shoutcast - radio controller
PostPosted: Fri Jun 06, 2014 4:30 am 
User avatar

Joined: Sat Nov 03, 2012 6:06 am
Posts: 8
Jeeper, thanks for putting me on the right track here. It didn't work at once but when I changed the script above, it actually stopped giving me this very annoying
{L_CODE}:
<HTML><HEAD><TITLE>SHOUTcast Server</TITLE></HEAD><BODY><H3>Invalid resource</H3></BODY></HTML>
as result.

Besides taking that ';' in opensim.ini, also change this line in the script:

{L_CODE}:
httpreq_id=llHTTPRequest(url + "/7.html",[],"");


And then it will return you /7.html as expected. :mrgreen:

_________________
I'll be Peter Pan, and you just be pretty.
~IAMX


Top
 Profile  
 
Display posts from previous:  Sort by  
Post a new topicPost a reply Page 1 of 1   [ 4 posts ]


Who is online

Users browsing this forum: legacy_google [bot] and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
610nm Style by Daniel St. Jules of Gamexe.net