Programmable Song Player ( V2 )

Written by Kitsune

Due the the 10 second limit on sounds we need to play whole songs as a sequence of clips. This does that.

    https://d1yjxggot69855.cloudfront.net/skins/monobook/bullet.gif); color: rgb(0, 0, 0); font-family: verdana, helvetica, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
  • You can add up to 11 (inclusive) complete songs (however many sound files there are per song) and select which to play.
  • If a song is playing you can select the next to play and a playlist is formed. The playlist can be added to at anytime during playback.
  • The volume is adjustable at anytime, including during playback.
  • Reads the song snippets from the sound files placed in the object inventory. They will be played in alphabetical/numerical order.
  • Follow the instructions at the top of the script. Very little editing is needed.
      https://d1yjxggot69855.cloudfront.net/skins/monobook/bullet.gif); ">
    • There is a chance that the memory will break if the playlist is made too long. V3 will include a measure against that but I have to sleep occasionally.
      // V2 //
       
      // This list is all you need to edit. List the names of the songs (each collection of sound files that makes one song)
      // followed by the length of those sound clips (each song should contain clips of equal length)
       
      // The list should be structured like so -
       
      // list songs = ["First Song", 9.0, "Second Song", 9.65, "Third Song", 9.45];
       
      // The names of the songs must be identical to some part of the sound files used for that song like so -
       
      //// In the prim inventory (along with this script) -
       
      ////// Box_Of_Rain_wav_1
      ////// Box_Of_Rain_wav_2
      ////// Box_Of_Rain_wav_3
      ////// Servant 1
      ////// Servant 2
      ////// Servant 3
       
      //// In the script -
       
      ////// list songs = ["Box_Of_Rain", 9.2, "Servant", 9.8];
       
      // The script will play the clips in alpha/numerical order so name them wisely.
       
      ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      ////////////////////////////////////////////////ONLY EDIT BELOW HERE///////////////////////////////////////////////////////////////
      ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
      list songs = ["Box_Of_Rain", 9.2, "Servant", 9.8]; // YUP! EDIT THIS BIT ;-)
       
      ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      ////////////////////////////////////////////////ONLY EDIT ABOVE HERE///////////////////////////////////////////////////////////////
      ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
      integer volume = 10;
       
      integer lis_count;
       
      integer playing;
       
      integer busy;
       
      integer part;
       
      integer lis;
       
      integer sl;
       
      float delay;
       
      list cancel = ["CANCEL"];
       
      list playlist;
       
      list waiting;
       
      list song;
       
      string vol_str = "Volume";
       
      string song_str = "Songs";
       
      string song_name;
       
      list StrideOfList(list src, integer stride, integer start, integer end)
      {
          list l = [];
          integer ll = llGetListLength(src);
          if(start < 0)start += ll;
          if(end < 0)end += ll;
          if(end < start) return llList2List(src, start, start);
          while(start <= end)
          {
              l += llList2List(src, start, start);
              start += stride;
          }
          return l;
      }
       
      list Volumes(integer vol)
      {
          integer v = 0;
          list l = [];
          do
          {
              if(v != vol)
              l += [((string)v)];
          }
          while((++v) <= 10);
          return l;
      }
       
      PageOne(key k, integer c)
      {
          llDialog(k, "\nAdjust the volume or select a song to play?", [vol_str, song_str] + cancel, c);
      }
       
      PlaySong(string n)
      {
          song = [];
          integer c = -1;
          string name = "";
          do
          {
              if(llSubStringIndex((name = llGetInventoryName(INVENTORY_SOUND, (++c))), n) != -1)
              song += [name];
          }
          while(name);
          delay = llList2Float(songs, (llListFindList(songs, [n]) + 1));
          if((sl = llGetListLength(song)))
          {
              llPreloadSound(llList2String(song, (part = 0)));
              if(sl > 1)
              llPreloadSound(llList2String(song, 1));
              playing = FALSE;
              llSetTimerEvent(0.01);
          }
      }
       
      integer Chan()
      {
          return llRound((llFrand(-5000000.0) + -500000.0));
      }
       
      float ScaleVol(integer v)
      {
          return (v * 0.1);
      }
       
      Listen(integer c, key a)
      {
          lis = llListen(c, "", a, "");
      }
       
      RemoveListen(integer b)
      {
          llListenRemove(lis);
          lis_count = 0;
          if(b)
          busy = FALSE;
          lis = 0;
      }
       
      SetListenTimer(integer p)
      {
          if(p)
          while(((++lis_count) * llRound(delay)) < 30);
          else
          {
              lis_count = 1;
              llSetTimerEvent(30.0);
          }
      }
       
      integer CheckWaitingRoom(integer c)
      {
          if(waiting)
          {
              key a = llList2Key(waiting, 0);
              if(!c)
              {
                  RemoveListen(0);
                  Listen((c = Chan()), a);
                  SetListenTimer(playing);
              }
              PageOne(a, c);
              waiting = llDeleteSubList(waiting, 0, 0);
              return 1;
          }
          return 0;
      }
       
      default
      {
          on_rez(integer param)
          {
              llStopSound();
              llResetScript();
          }
          changed(integer change)
          {
              if(change & CHANGED_INVENTORY)
              llResetScript();
          }
          touch_start(integer nd)
          {
              while(nd)
              {
                  key agent = llDetectedKey(--nd);
                  if(!busy)
                  {
                      busy = TRUE;
                      integer channel = Chan();
                      SetListenTimer(playing);
                      Listen(channel, agent);
                      PageOne(agent, channel);
                  }
                  else
                  {
                      list a = [agent];
                      if(llListFindList(waiting, a) == -1)
                      waiting += a;
                  }
              }
          }
          listen(integer chan, string name, key id, string msg)
          {
              if(msg != llList2String(cancel, 0))
              {
                  SetListenTimer(playing);
                  if(msg == vol_str)
                  {
                      llDialog(id, "\nChange the volume?\nThe current volume is set at \"" + ((string)volume) + "\"", cancel + Volumes(volume), chan);
                      return;
                  }
                  if(msg == song_str)
                  {
                      string current = "";
                      if(playlist)
                      {
                          current = "\n\nThe songs currently queued are\n\"" + llList2String(playlist, 0) + "\" (currently playing)";
                          if(llGetListLength(playlist) > 1)
                          current += "\n\"" + llDumpList2String(llList2List(playlist, 1, -1), "\"\n\"") + "\"";
                      }
                      llDialog(id, llGetSubString(("\nSelect a song to play?" + current), 0, 500), cancel + StrideOfList(songs, 2, 0, -1), chan);
                      return;
                  }
                  if(llListFindList(Volumes(volume), [msg]) != -1)
                  {
                      llAdjustSoundVolume(ScaleVol((volume = ((integer)msg))));
                      PageOne(id, chan);
                      return;
                  }
                  if(llGetListLength((playlist += [msg])) == 1)
                  PlaySong((song_name = msg));
              }
              if(CheckWaitingRoom(chan))
              return;
              RemoveListen(1);
          }
          timer()
          {
              if(playlist)
              {
                  if(!playing)
                  {
                      llSetTimerEvent(delay);
                      playing = TRUE;
                  }
                  llPlaySound(llList2String(song, part), ScaleVol(volume));
                  if((++part) == sl)
                  {
                      if(llGetListLength(playlist) > 1)
                      {
                          song_name = llList2String((playlist = llDeleteSubList(playlist, 0, 0)), 0);
                          llSleep(delay);
                          PlaySong(song_name);
                      }
                      else
                      {
                          llSetTimerEvent(0.0);
                          song_name = "";
                          playing = FALSE;
                          playlist = [];
                      }
                  }
                  else if(part == (sl - 1))
                  llPreloadSound(llList2String(song, 0));
                  else
                  llPreloadSound(llList2String(song, (part + 1)));
              }
              if(lis && (!(--lis_count)))
              {
                  if(!(CheckWaitingRoom(0)))
                  RemoveListen(1);
              }
          }
      }