Advertisement
Guest User

Untitled

a guest
Sep 29th, 2019
389
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //FC's Parcel Music Manager
  2.  
  3. //version 4.0 for Mesh SoundMate (but works with every arbitrary prim)
  4.  
  5. //by Franklyn Constantine, 2009-2017 all rights reserved.
  6.  
  7. //this radio set reads music station URLs from a notecard and sets the parcel music appropriately.
  8.  
  9. // written under use of free LSL examples
  10.  
  11.  
  12. // Terms of use:
  13. // this program must not be sold alone, it may be copied or resold as a part of a new product,
  14. // as long as it is not the main purpose of the new creation.
  15.  
  16. // example: put it into a self made radio, or any other unique own creation and sell it - it's OK!
  17. //          put it in a freebie, or any other 3rd party stuff and sell it - this is NOT OK!
  18.  
  19.  
  20. // if reused, Franklyn Constantine  shall be mentioned in the credits.
  21.  
  22.  
  23. string VERSION = "4.0 SoundMate Edition"; //the current version
  24.  
  25. float freeURL_reset_time = 10800.0; // edit this to choose any wanted reset time to last station
  26.  
  27. integer CHANNEL = 6583; //the base channel
  28. integer channel; //the actual channel
  29.  
  30. // integer FACE_LED=3; //this is only needed to light the LED of my soundmate radio; leave it inactive for any other use (except your build has a face which shall turn red/ green.
  31.  
  32. integer UPDATE_PIN = 17433; //PINs the hosting Prim, allowing future updates
  33. list station_list = [];
  34. list menu_list = [];
  35.  
  36. list menu_page = []; // a subset of the menu list
  37. list station_page = []; // the same for the station URLs
  38.  
  39. string now_playing;
  40.  
  41. integer selected_index;
  42. string current_station;
  43. string freeURL_last_station;
  44.  
  45.  
  46. integer is_twinkle = FALSE; //twinkle extension
  47. integer is_grouponly=FALSE; //Group access rights
  48. integer is_owneronly=FALSE; //Owner access right
  49.  
  50. key toucher; // the avatar who touched the hosting prim
  51.  
  52. integer no_of_stations;
  53.  
  54. integer no_of_pages;
  55.  
  56. integer current_page = 0; // the current menu page (a part of the index number)
  57.  
  58. integer l_handle; // the listener handle for radio stations selection
  59.  
  60. // Read out a complete notecard from the object's inventory.
  61. string gName;    // name of a notecard in the object's inventory
  62. integer gLine = 0;        // current line number
  63. key gQueryID; // id used to identify dataserver queries
  64.  
  65. buildMenu(integer page)
  66. {
  67.     integer page_index;
  68.  
  69.     menu_page = llList2List(menu_list, (page*7), (page*7)+6); //extract a portion of the stations
  70.  
  71.     station_page = llList2List(station_list, (page*7), (page*8)+6); // dito, for the URL indices
  72.  
  73.     //add some buttons which appear on any menu page
  74.     menu_page += ["Options"]; // channel and access
  75.     // comment out end
  76.  
  77.     menu_page += ["Free URL"]; // add any custom URL
  78.  
  79.     menu_page += ["Off"]; // add an "off" button (enters a 'void' into the parcel URL field)
  80.  
  81.     menu_page += ["Next"];
  82.  
  83.     menu_page += ["Back"];
  84.  
  85. }
  86.  
  87. //** added with 4.0 - multi system stream channel identification **
  88. string GetCurrentChannel() // gets and identifies the current played parcel sound URL
  89. {
  90.     string current_url = llGetParcelMusicURL(); //read the parcel stream URL
  91.  
  92.     integer found_url_index;
  93.     string current_stream;
  94.  
  95.  
  96.     found_url_index = llListFindList( station_list, [current_url] ); // compare the parcel stream with radio entries (stations)
  97.  
  98.     if (found_url_index < 0) // if there is no match
  99.     {
  100.       current_stream  = "<not identified>"; //report this back
  101.     }
  102.     else
  103.     {
  104.         current_stream = llList2String(menu_list, found_url_index); //otherwise lookup for the station name (same index!)
  105.     }
  106.  
  107.     return current_stream; // tell the result
  108.  
  109.  }
  110.  
  111. default
  112. {
  113.     state_entry()
  114.     {
  115.         llSay(0, "FC's Web Radio Tuner Version" + VERSION);
  116.  
  117.         llSetRemoteScriptAccessPin(UPDATE_PIN);
  118.  
  119.         channel = CHANNEL;
  120.  
  121.  
  122.  
  123.         state read_card;
  124.     }
  125.  
  126.  
  127. }
  128.  
  129. state radio
  130. {
  131.     state_entry()
  132.     {
  133.         // nothing
  134.     }
  135.  
  136.  
  137.     touch_start(integer total_number)
  138.     {
  139.  
  140.         toucher = llDetectedKey(0);
  141.  
  142.         if (toucher != llGetOwner())
  143.         {
  144.  
  145.             if (is_grouponly && llSameGroup(toucher) == FALSE)
  146.             {
  147.                 llInstantMessage(toucher, "Sorry, operation is only allowed for group members.");
  148.  
  149.                 return;
  150.             }
  151.  
  152.             if (is_owneronly && toucher != llGetOwner())
  153.             {
  154.                 llInstantMessage(toucher, "Sorry, operation is only allowed for the owner.");
  155.  
  156.                 return;
  157.             }
  158.  
  159.  
  160.         }
  161.  
  162.         l_handle = llListen(channel, "", NULL_KEY, "");
  163.  
  164.         buildMenu(current_page);
  165.  
  166.         now_playing = GetCurrentChannel();
  167.  
  168.         llDialog(toucher, "Currently playing " + now_playing +  ".\nSelect a radio station:", menu_page, channel);
  169.        llSay(0, "<click>");
  170.  
  171.     }
  172.  
  173.     listen(integer channel, string name, key id, string selected)
  174.     {
  175.         //llOwnerSay("debug - entered non-twinkle section");
  176.  
  177.         if (selected == "Next")
  178.         {
  179.             current_page++;
  180.  
  181.             if (current_page > no_of_pages-1) current_page = 0; //reroll
  182.  
  183.             //llSay(0, "debug - current page = " + (string)current_page);
  184.  
  185.             buildMenu(current_page);
  186.  
  187.             llDialog(toucher, "Currently playing " + now_playing +  ".\nSelect a radio station:", menu_page, channel);
  188.  
  189.             return;
  190.         }
  191.  
  192.         if (selected == "Back")
  193.         {
  194.             //llSay(0, "debug - current page = " + (string)current_page);
  195.  
  196.             if (current_page == 0) current_page = no_of_pages;
  197.             else current_page--;
  198.  
  199.             buildMenu(current_page);
  200.  
  201.             llDialog(toucher, "Currently playing " + now_playing +  ".\nSelect a radio station:", menu_page, channel);
  202.  
  203.             return;
  204.         }
  205.  
  206.         if (selected == "Free URL")
  207.         {
  208.             state free_url;
  209.  
  210.             return;
  211.         }
  212.  
  213.         if (selected == "Options")
  214.         {
  215.             if (toucher == llGetOwner())
  216.             {
  217.                 state options;
  218.  
  219.             }
  220.             else
  221.             {
  222.                 llWhisper(0, "Options are only available for the owner.");
  223.             }
  224.  
  225.             return;
  226.         }
  227.  
  228.  
  229.         now_playing = selected;
  230.  
  231.         selected_index = llListFindList( menu_page, [selected] );
  232.  
  233.         //llOwnerSay("Debug - index for " + selected + " is " + (string)selected_index);
  234.  
  235.         current_station = llList2String(station_page, selected_index);
  236.  
  237.         //llOwnerSay("Debug - selected station is " + current_station);
  238.  
  239.  
  240.         llSetParcelMusicURL(current_station);
  241.         llSay(0, "FM station was changed to "+ selected);
  242.  
  243.         //*** ON/ OFF LED (new for Mesh Radio, leave it off for any other build, it will turn a face green or red, and you may not want that?!)
  244.         //if (selected == "Off")
  245.         //{
  246.         //    llSetColor(<135, 0, 0>, FACE_LED); // red
  247.         //}
  248.         //else
  249.         //{
  250.         //    llSetColor(<0, 255, 0>,  FACE_LED); // green
  251.         //}
  252.  
  253.         //llOwnerSay("debug: llsetparcelmusic reached, playing " + current_station);
  254.  
  255.         llSetTimerEvent(0.0); // stop the "last URL" timer, if any
  256.  
  257.         llListenRemove(l_handle);
  258.  
  259.     }
  260.  
  261.     timer()
  262.     {
  263.         llSetTimerEvent(0.0); // stop the "last URL" timer
  264.  
  265.         current_station = freeURL_last_station; //retrieve the last listed URL
  266.  
  267.         llSetParcelMusicURL(current_station);
  268.  
  269.         llSay(0, "FM station was reset");
  270.     }
  271.  
  272.     on_rez(integer start_param)
  273.     {
  274.         llResetScript();
  275.     }
  276.  
  277.     changed(integer change)
  278.     {
  279.         if(change & CHANGED_OWNER)  llResetScript();
  280.  
  281.         if (change & CHANGED_INVENTORY) llResetScript();
  282.     }
  283. }
  284.  
  285. state read_card //this is executed in the beginning, read a user defined notecard
  286. {
  287.     state_entry()
  288.     {
  289.  
  290.         station_list = [];
  291.         menu_list = [];
  292.         no_of_stations = 0;
  293.  
  294.         gName = "stations";
  295.         llOwnerSay("Loading station list...");
  296.         gQueryID = llGetNotecardLine(gName, gLine);    // request first line
  297.     }
  298.  
  299.     dataserver(key query_id, string data)
  300.     {
  301.  
  302.         if (query_id == gQueryID) {
  303.             if (data != EOF)
  304.             {    // not at the end of the notecard
  305.                 string station_line;
  306.                 string menu_line;
  307.  
  308.                 //llOwnerSay("Debug: line " + (string)gLine  + " reads: " + data);
  309.  
  310.  
  311.                 if (llGetSubString(data, 0,0) == "#" || llGetSubString(data, 0,0) == "") //skip this line, it's a comment or nothing
  312.                 {
  313.                     ++gLine;
  314.                     //llOwnerSay("Debug: comment skipped");
  315.                 }
  316.                 else // parse the line and divide in two sections: menu button and action (plus particle names?)
  317.                 {
  318.                     integer line_length = llStringLength(data);
  319.                     integer i = 1;
  320.  
  321.                     i = llSubStringIndex(data, ";"); //find the ; delimiter
  322.  
  323.                     menu_line = llGetSubString(data, 0, i-1); // part 1 is the menu button
  324.  
  325.                     // llOwnerSay( "Debug line 80: menu_line = " +  menu_line);
  326.                     if (llStringLength(menu_line) > 12) menu_line = llDeleteSubString(menu_line, 12, -1); // shorten menu_list to 12!
  327.                     menu_list += [menu_line];
  328.  
  329.                     //llOwnerSay("Debug - menu item: " + llGetSubString(menu_line, 0, i-1));
  330.  
  331.  
  332.  
  333.                     station_list += [llGetSubString(data, i+1, -1)]; // part two is the chat entry
  334.  
  335.  
  336.  
  337.                     //llOwnerSay("Debug: menu: " + llList2String(menu_list, no_of_stations) + " action: " + llList2String(station_list, no_of_stations));
  338.                     llOwnerSay("Station #" + (string)(no_of_stations+1) + ": " + llList2String(menu_list, no_of_stations) +   " found");
  339.  
  340.                     no_of_stations++;
  341.  
  342.                     ++gLine;
  343.  
  344.                 }
  345.  
  346.                              // increase line count
  347.                 gQueryID = llGetNotecardLine(gName, gLine);    // request next line
  348.             }
  349.             else
  350.             {
  351.                 no_of_stations= llGetListLength(station_list);
  352.  
  353.                 llOwnerSay("Loading complete, " + (string)no_of_stations + " stations ready to use.");
  354.  
  355.                 no_of_pages = 1 + no_of_stations/7;
  356.  
  357.                 //llSay(0, "debug: no_of_pages = " + (string)no_of_pages);
  358.  
  359.                 state radio;
  360.             }
  361.         }
  362.     }
  363.  
  364.     on_rez(integer start_param)
  365.     {
  366.         llResetScript();
  367.     }
  368.  
  369.     changed(integer change)
  370.     {
  371.         if(change & CHANGED_OWNER)  llResetScript();
  372.  
  373.         if (change & CHANGED_INVENTORY) llResetScript();
  374.     }
  375. }
  376.  
  377. state options
  378. {
  379.     state_entry()
  380.     {
  381.         string HELPTEXT = "\nAcess: Group or everybody\nChannel: Change control channel";
  382.  
  383.         l_handle = llListen(channel, "", NULL_KEY, "");
  384.  
  385.         llDialog(toucher, "Select an option:" + HELPTEXT, ["Access", "Channel"], channel);
  386.     }
  387.  
  388.     listen(integer channel, string name, key id, string message)
  389.     {
  390.  
  391.  
  392.         if (message == "Access")
  393.         {
  394.             llDialog(toucher, "Select access rights:", ["Owner", "Group", "All"], channel);
  395.  
  396.             return;
  397.         }
  398.  
  399.  
  400.         if (message == "Owner")
  401.         {
  402.             is_owneronly = TRUE;
  403.             is_grouponly = FALSE;
  404.  
  405.             llWhisper(0, "Access rights are set to owner only.");
  406.  
  407.         }
  408.         if (message == "Group")
  409.         {
  410.             is_grouponly = TRUE;
  411.             is_owneronly = FALSE;
  412.  
  413.             llWhisper(0, "Access rights are set to Group only.");
  414.  
  415.         }
  416.  
  417.         if (message == "All")
  418.         {
  419.             is_grouponly = FALSE;
  420.             is_owneronly = FALSE;
  421.  
  422.             llWhisper(0, "Access rights are set to everybody.");
  423.  
  424.         }
  425.  
  426.         if (message == "Channel")
  427.         {
  428.             channel = CHANNEL + (integer)llFrand(20);
  429.  
  430.             llWhisper(0, "Control channel was set to " + (string)channel);
  431.         }
  432.  
  433.         llListenRemove(l_handle);
  434.  
  435.         state radio;
  436.     }
  437.  
  438.     touch_start(integer total_number)
  439.     {
  440.         llWhisper(0, "Options aborted, returning to radio mode.");
  441.  
  442.         llListenRemove(l_handle);
  443.  
  444.         state radio;
  445.     }
  446.  
  447.  
  448.  
  449. }
  450.  
  451. state free_url
  452. {
  453.     state_entry()
  454.     {
  455.         llSetTimerEvent(30.0);
  456.  
  457.         llSay(0, "You now have 30 seconds time to enter a custom stream URL into the public chat.");
  458.  
  459.         llListen(0, "", toucher, "");
  460.     }
  461.  
  462.     listen(integer channel, string name, key id, string message)
  463.     {
  464.         if (llGetSubString(message, 0, 6) == "http://")
  465.         {
  466.             //this is a valid mp3 url heading, continue
  467.  
  468.             freeURL_last_station = current_station; // save last station before it is overwritten
  469.  
  470.             current_station = message;
  471.  
  472.             now_playing = "Custom stream URL";
  473.  
  474.             //llOwnerSay("Debug - selected station is " + current_station);
  475.  
  476.  
  477.             llSetParcelMusicURL(current_station);
  478.             llSay(0, "FM station was changed to a custom URL.");
  479.  
  480.  
  481.  
  482.             integer hours = llFloor(freeURL_reset_time/3600);
  483.             integer rest = (integer)freeURL_reset_time - hours*3600;
  484.             integer minutes = llFloor(rest/60);
  485.             rest = rest - minutes*60;
  486.             integer seconds = rest;
  487.  
  488.             llSay(0, "This station will be reset in " + (string)hours + " hour(s), "+ (string)minutes + " minute(s) and " + (string)seconds + " seconds.");
  489.  
  490.             llSetTimerEvent (freeURL_reset_time); // set timeout clock to a defined return time to last station.
  491.  
  492.  
  493.  
  494.         }
  495.         else
  496.         {
  497.             llSay(0, "This is no valid http:// URL, please repeat.");
  498.         }
  499.  
  500.         state radio;
  501.     }
  502.  
  503.         timer()
  504.         {
  505.             llSay(0, "Entering a custom URL was timed out. Please repeat.");
  506.  
  507.             llSetTimerEvent (0.0); // stop the timeout clock
  508.  
  509.             state radio; // return to normal operation
  510.  
  511.     }
  512.  
  513.  
  514.  
  515.     touch_start(integer total_number)
  516.     {
  517.         llSetTimerEvent(0.0);
  518.         llSay(0, "Entering of a free URL aborted.");
  519.  
  520.         state radio;
  521.     }
  522. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement