adjusted a bit more
[feisty_meow.git] / huffware / huffotronic_scripts / JukeBox_v1.6.txt
1 
2 // jukebox script.  unknown provenance.
3 // modified for use in opensim by fred huffhines.
4 //
5 // this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html
6 // do not use it in objects without fully realizing you are implicitly accepting that license.
7 //
8
9 float INTERVAL = 9.00;
10
11 integer IS_OPENSIM = TRUE;
12     // this must be set to true to turn off the sound queuing.  opensim does not currently implement it.
13
14 float SOUND_OFFSET_PERIOD = 1.1;  // number of seconds to start the sound in advance.
15
16 integer LISTEN_CHAN = 2000;
17 integer SEND_CHAN = 2001;
18 float VOLUME = 1.0;
19
20 integer g_iSound;
21 integer total_tracks;
22 integer g_iListenCtrl = -1;
23 integer g_iPlaying;
24 integer g_iLinked;
25 integer g_iStop;
26 integer g_iPod;
27 string g_sLink;
28
29 // DEBUG
30 integer g_iWasLinked;
31 integer g_iFinished;
32
33 list song_names;
34     // hold onto the names of all the songs so we don't need to keep
35     // going back to inventory.
36
37 Initialize()
38 {
39     llSetText(llGetObjectName(), <0, 100, 100>, 10);
40     
41     // reset listeners
42     if ( g_iListenCtrl != -1 )
43     {
44         llListenRemove(g_iListenCtrl);
45     }
46     g_iListenCtrl = llListen(LISTEN_CHAN,"","","");
47     g_iPlaying = 0;
48     g_iLinked = 0;
49
50     integer i;
51     total_tracks = llGetInventoryNumber(INVENTORY_SOUND);
52     for ( i = 0; i < total_tracks; i++ ) {
53         string name = llGetInventoryName(INVENTORY_SOUND, i);
54         song_names += [ name ];
55         llPreloadSound(name);
56     }
57 //llOwnerSay("got song names list: " + (string)song_names);
58 }
59
60
61
62 PlaySong()
63 {
64     integer i;
65
66     g_iPlaying = 1;    
67     llWhisper(0, "Playing...");
68     if (!IS_OPENSIM) {
69         llSetSoundQueueing(TRUE);
70     }
71     llAdjustSoundVolume(1.0);
72     llPlaySound(llList2String(song_names, 0), VOLUME);
73     llPreloadSound(llList2String(song_names, 1));
74     // set the timer interval for just before the track chunk ends.
75     llSetTimerEvent(INTERVAL - SOUND_OFFSET_PERIOD);
76     g_iSound = 1;
77 }
78
79
80 StopSong()
81 {
82     g_iPlaying = 0;
83     llWhisper(0, "Stopping...");
84     llStopSound();
85     llAdjustSoundVolume(0);
86     llSetTimerEvent(0.0);
87 }
88
89
90 integer CheckLink()
91 {
92     string sLink;
93     
94     sLink = llGetLinkName(1);
95     g_sLink = sLink;
96     if ( llGetSubString(sLink,0,6) == "Jukebox" )
97     {
98         return TRUE;
99     }
100     return FALSE;
101 }
102
103
104 //////////////
105 // huffware script: auto-retire, by fred huffhines, version 2.8.
106 // distributed under BSD-like license.
107 //   !!  keep in mind that this code must be *copied* into another
108 //   !!  script that you wish to add auto-retirement capability to.
109 // when a script has auto_retire in it, it can be dropped into an
110 // object and the most recent version of the script will destroy
111 // all older versions.
112 //
113 // the version numbers are embedded into the script names themselves.
114 // the notation for versions uses a letter 'v', followed by two numbers
115 // in the form "major.minor".
116 // major and minor versions are implicitly considered as a floating point
117 // number that increases with each newer version of the script.  thus,
118 // "hazmap v0.1" might be the first script in the "hazmap" script continuum,
119 // and "hazmap v3.2" is a more recent version.
120 //
121 // example usage of the auto-retirement script:
122 //     default {
123 //         state_entry() {
124 //            auto_retire();  // make sure newest addition is only version of script.
125 //        }
126 //     }
127 // this script is partly based on the self-upgrading scripts from markov brodsky
128 // and jippen faddoul.
129 //////////////
130 auto_retire() {
131     string self = llGetScriptName();  // the name of this script.
132     list split = compute_basename_and_version(self);
133     if (llGetListLength(split) != 2) return;  // nothing to do for this script.
134     string basename = llList2String(split, 0);  // script name with no version attached.
135     string version_string = llList2String(split, 1);  // the version found.
136     integer posn;
137     // find any scripts that match the basename.  they are variants of this script.
138     for (posn = llGetInventoryNumber(INVENTORY_SCRIPT) - 1; posn >= 0; posn--) {
139         string curr_script = llGetInventoryName(INVENTORY_SCRIPT, posn);
140         if ( (curr_script != self) && (llSubStringIndex(curr_script, basename) == 0) ) {
141             // found a basic match at least.
142             list inv_split = compute_basename_and_version(curr_script);
143             if (llGetListLength(inv_split) == 2) {
144                 // see if this script is more ancient.
145                 string inv_version_string = llList2String(inv_split, 1);  // the version found.
146                 // must make sure that the retiring script is completely the identical basename;
147                 // just matching in the front doesn't make it a relative.
148                 if ( (llList2String(inv_split, 0) == basename)
149                     && ((float)inv_version_string < (float)version_string) ) {
150                     // remove script with same name from inventory that has inferior version.
151                     llRemoveInventory(curr_script);
152                 }
153             }
154         }
155     }
156 }
157 //
158 // separates the base script name and version number.  used by auto_retire.
159 list compute_basename_and_version(string to_chop_up)
160 {
161     // minimum script name is 2 characters plus a version.
162     integer space_v_posn;
163     // find the last useful space and 'v' combo.
164     for (space_v_posn = llStringLength(to_chop_up) - 3;
165         (space_v_posn >= 2) && (llGetSubString(to_chop_up, space_v_posn, space_v_posn + 1) != " v");
166         space_v_posn--) {
167         // look for space and v but do nothing else.
168     }
169     if (space_v_posn < 2) return [];  // no space found.
170     // now we zoom through the stuff after our beloved v character and find any evil
171     // space characters, which are most likely from SL having found a duplicate item
172     // name and not so helpfully renamed it for us.
173     integer indy;
174     for (indy = llStringLength(to_chop_up) - 1; indy > space_v_posn; indy--) {
175         if (llGetSubString(to_chop_up, indy, indy) == " ") {
176             // found one; zap it.  since we're going backwards we don't need to
177             // adjust the loop at all.
178             to_chop_up = llDeleteSubString(to_chop_up, indy, indy);
179         }
180     }
181     string full_suffix = llGetSubString(to_chop_up, space_v_posn, -1);
182     // ditch the space character for our numerical check.
183     string chop_suffix = llGetSubString(full_suffix, 1, llStringLength(full_suffix) - 1);
184     // strip out a 'v' if there is one.
185     if (llGetSubString(chop_suffix, 0, 0) == "v")
186         chop_suffix = llGetSubString(chop_suffix, 1, llStringLength(chop_suffix) - 1);
187     // if valid floating point number and greater than zero, that works for our version.
188     string basename = to_chop_up;  // script name with no version attached.
189     if ((float)chop_suffix > 0.0) {
190         // this is a big success right here.
191         basename = llGetSubString(to_chop_up, 0, -llStringLength(full_suffix) - 1);
192         return [ basename, chop_suffix ];
193     }
194     // seems like we found nothing useful.
195     return [];
196 }
197 //
198 //////////////
199
200 default {
201     state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; }
202     on_rez(integer parm) { state rerun; }
203 }
204 state rerun { state_entry() { state default; } }
205
206 state real_default
207 {
208     state_entry()
209     {
210         auto_retire();
211         Initialize();
212     }
213     
214     on_rez(integer start_param)
215     {
216         Initialize();
217         if ( start_param )
218         {
219             g_iPod = start_param - 1;
220             if ( g_iPod )
221             {
222                 llRequestPermissions(llGetOwner(),PERMISSION_ATTACH);
223             } else {
224                 // Tell the controller what the CD key is so it can link
225                 llWhisper(SEND_CHAN,"LINK " + (string)llGetKey());
226             }
227         }
228     }
229     
230     changed(integer change)
231     {
232         if ( change == CHANGED_LINK )
233         {
234             if ( llGetLinkNumber() == 0 )
235             {
236                 StopSong();
237                 llDie();
238             } else {
239                 if ( g_iStop )
240                 {
241                     llMessageLinked(1,llGetLinkNumber(),"UNLINK","");
242                 } else {
243                     llMessageLinked(1,llGetLinkNumber(),"LINKID","");
244                     g_iWasLinked = 1;
245                 }
246             }
247         }
248     }
249     
250     attach(key id)
251     {
252         if ( id == NULL_KEY )
253         {
254             llDie();
255         } else {
256             PlaySong();
257         }
258     }
259     
260     run_time_permissions(integer perm)
261     {
262         if ( perm == PERMISSION_ATTACH )
263         {
264             llAttachToAvatar(ATTACH_LSHOULDER);
265             llSetTexture("clear",ALL_SIDES);
266         }
267     }
268     
269     touch_start(integer total_number)
270     {
271         integer i;
272         
273         for ( i = 0; i < total_number; i++ )
274         {
275             if ( llDetectedKey(i) == llGetOwner() )
276             {
277 //llWhisper(0,"DEBUG: g_iPlaying=" + (string)g_iPlaying);
278 //llWhisper(0,"DEBUG: Link=" + (string)llGetLinkNumber());
279 //llWhisper(0,"DEBUG: g_iWasLinked=" + (string)g_iWasLinked);
280 //llWhisper(0,"DEBUG: g_iFinished=" + (string)g_iFinished);
281                 if ( g_iPlaying ) StopSong();
282                 else PlaySong();
283             }
284         }
285     }
286     
287     listen(integer channel, string name, key id, string message)
288     {
289         if ( message == "RESET" )
290         {
291             if ( llGetLinkNumber() == 0 )
292             {
293                 llDie();
294             } else {
295                 llMessageLinked(1,llGetLinkNumber(),"UNLINK","");
296             }
297         }
298         
299         if ( message == "STOP" )
300         {
301             if ( g_iPod )
302             {
303                 StopSong();
304                 llDetachFromAvatar();
305             }
306         }
307     }
308
309     link_message(integer sender_num, integer num, string str, key id)
310     {
311         if ( str == "PLAY" )
312         {
313             if ( !g_iPlaying )
314             {
315                 PlaySong();
316             }
317             return;
318         }
319         
320         if ( str == "STOP" )
321         {
322             g_iStop = 1;
323             StopSong();
324             llMessageLinked(1,llGetLinkNumber(),"UNLINK","");
325         }
326         
327         if ( str == "VOLUME" )
328         {
329             VOLUME = (float)num / 10.0;
330             llAdjustSoundVolume(VOLUME);
331         }
332     }
333     
334     timer()
335     {
336         if ( g_iPlaying )
337         {
338 //llWhisper(0, "playing song #" + (string)(g_iSound+1) + ": " +  llList2String(song_names, g_iSound));
339             llPlaySound(llList2String(song_names, g_iSound),VOLUME);
340             if ( g_iSound < (total_tracks - 1) )
341             {
342                 llPreloadSound(llList2String(song_names, g_iSound + 1));
343             }
344             g_iSound++;
345             if ( g_iSound >= total_tracks )
346             {
347                 llSetTimerEvent(INTERVAL + 5.0);
348                 g_iPlaying = 0;
349             } else {
350                 llSetTimerEvent(INTERVAL - SOUND_OFFSET_PERIOD);
351             }                
352         } else {
353             if ( llGetLinkNumber() != 0 )
354             {
355                 llSetTimerEvent(0.0);
356                 if ( g_iPod )
357                 {
358                     llWhisper(SEND_CHAN,"FINISH");
359                     llDetachFromAvatar();
360                 } else {
361                     llMessageLinked(1,0,"FINISH","");
362                     g_iFinished = 1;
363                 }
364             }
365         }
366     }
367 }