Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lDEVinux
GitHub Repository: lDEVinux/eaglercraft
Path: blob/main/src/lwjgl/java/paulscode/sound/SoundSystem.java
8644 views
1
package paulscode.sound;
2
3
import java.net.URL;
4
import java.util.HashMap;
5
import java.util.Iterator;
6
import java.util.LinkedList;
7
import java.util.List;
8
import java.util.ListIterator;
9
import java.util.Random;
10
import java.util.Set;
11
import javax.sound.sampled.AudioFormat;
12
13
/**
14
* The SoundSystem class is the core class for the SoundSystem library. It is
15
* capable of interfacing with external sound library and codec library
16
* pluggins. This core class is stripped down to give it a smaller memory
17
* footprint and to make it more customizable. This library was created to
18
* provide a simple, common interface to a variety of 3rd-party sound and codec
19
* libraries, and to simplify switching between them on the fly. If no
20
* external pluggins are loaded, this core class by itself is only capable of
21
* playing MIDI files. Specific implementations (such as SoundSystemJPCT) will
22
* extend this core class. They will automatically link with popular
23
* external pluggins and provide extra methods for ease of use.
24
* There should be only one instance of this class in any program! The
25
* SoundSystem can be constructed by defining which sound library to use, or by
26
* allowing SoundSystem to perform its own library compatibility checking. See
27
* {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for information
28
* about changing default settings and linking with external pluggins.
29
*<br><br>
30
*<b><i> SoundSystem License:</b></i><br><b><br>
31
* You are free to use this library for any purpose, commercial or otherwise.
32
* You may modify this library or source code, and distribute it any way you
33
* like, provided the following conditions are met:
34
*<br>
35
* 1) You may not falsely claim to be the author of this library or any
36
* unmodified portion of it.
37
*<br>
38
* 2) You may not copyright this library or a modified version of it and then
39
* sue me for copyright infringement.
40
*<br>
41
* 3) If you modify the source code, you must clearly document the changes
42
* made before redistributing the modified source code, so other users know
43
* it is not the original code.
44
*<br>
45
* 4) You are not required to give me credit for this library in any derived
46
* work, but if you do, you must also mention my website:
47
* http://www.paulscode.com
48
*<br>
49
* 5) I the author will not be responsible for any damages (physical,
50
* financial, or otherwise) caused by the use if this library or any part
51
* of it.
52
*<br>
53
* 6) I the author do not guarantee, warrant, or make any representations,
54
* either expressed or implied, regarding the use of this library or any
55
* part of it.
56
* <br><br>
57
* Author: Paul Lamb
58
* <br>
59
* http://www.paulscode.com
60
* </b>
61
*/
62
public class SoundSystem
63
{
64
/**
65
* Used to return a current value from one of the synchronized
66
* boolean-interface methods.
67
*/
68
private static final boolean GET = false;
69
/**
70
* Used to set the value in one of the synchronized boolean-interface methods.
71
*/
72
private static final boolean SET = true;
73
/**
74
* Used when a parameter for one of the synchronized boolean-interface methods
75
* is not aplicable.
76
*/
77
private static final boolean XXX = false;
78
79
/**
80
* Processes status messages, warnings, and error messages.
81
*/
82
protected SoundSystemLogger logger;
83
84
/**
85
* Handle to the active sound library.
86
*/
87
protected Library soundLibrary;
88
89
/**
90
* List of queued commands to perform.
91
*/
92
protected List<CommandObject> commandQueue;
93
94
/**
95
* Used internally by SoundSystem to keep track of play/pause/stop/rewind
96
* commands. This prevents source management (culling and activating) from
97
* being adversely affected by the quickPlay, quickStream, and backgroundMusic
98
* methods.
99
*/
100
private List<CommandObject> sourcePlayList;
101
102
/**
103
* Processes queued commands in the background.
104
*/
105
protected CommandThread commandThread;
106
107
/**
108
* Generates random numbers.
109
*/
110
public Random randomNumberGenerator;
111
112
/**
113
* Name of this class.
114
*/
115
protected String className = "SoundSystem";
116
117
/**
118
* Indicates the currently loaded sound-library, or null if none.
119
*/
120
private static Class currentLibrary = null;
121
122
/**
123
* Becomes true when the sound library has been initialized.
124
*/
125
private static boolean initialized = false;
126
127
/**
128
* Indicates the last exception that was thrown.
129
*/
130
private static SoundSystemException lastException = null;
131
132
/**
133
* Constructor: Create the sound system using the default library. If the
134
* default library is not compatible, another library type will be loaded
135
* instead, in the order of library preference.
136
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for
137
* information about sound library types.
138
*/
139
public SoundSystem()
140
{
141
// create the message logger:
142
logger = SoundSystemConfig.getLogger();
143
// if the user didn't create one, then do it now:
144
if( logger == null )
145
{
146
logger = new SoundSystemLogger();
147
SoundSystemConfig.setLogger( logger );
148
}
149
150
linkDefaultLibrariesAndCodecs();
151
152
LinkedList<Class> libraries = SoundSystemConfig.getLibraries();
153
154
if( libraries != null )
155
{
156
ListIterator<Class> i = libraries.listIterator();
157
Class c;
158
while( i.hasNext() )
159
{
160
c = i.next();
161
try
162
{
163
init( c );
164
return;
165
}
166
catch( SoundSystemException sse )
167
{
168
logger.printExceptionMessage( sse, 1 );
169
}
170
}
171
}
172
try
173
{
174
init( Library.class );
175
return;
176
}
177
catch( SoundSystemException sse )
178
{
179
logger.printExceptionMessage( sse, 1 );
180
}
181
}
182
183
/**
184
* Constructor: Create the sound system using the specified library.
185
* @param libraryClass Library to use.
186
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for
187
* information about chosing a sound library.
188
*/
189
public SoundSystem( Class libraryClass ) throws SoundSystemException
190
{
191
// create the message logger:
192
logger = SoundSystemConfig.getLogger();
193
// if the user didn't create one, then do it now:
194
if( logger == null )
195
{
196
logger = new SoundSystemLogger();
197
SoundSystemConfig.setLogger( logger );
198
}
199
linkDefaultLibrariesAndCodecs();
200
201
init( libraryClass );
202
}
203
204
/**
205
* Links with any default libraries or codecs should be made in this method.
206
* This method is empty in the core SoundSystem class, and should be overriden
207
* by classes which extend SoundSystem.
208
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for
209
* information about linking with sound libraries and codecs.
210
*/
211
protected void linkDefaultLibrariesAndCodecs()
212
{
213
}
214
215
/**
216
* Loads the message logger, initializes the specified sound library, and
217
* starts the command thread. Also instantiates the random number generator
218
* and the command queue.
219
* @param libraryClass Library to initialize.
220
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for
221
* information about chosing a sound library.
222
*/
223
protected void init( Class libraryClass ) throws SoundSystemException
224
{
225
message( "", 0 );
226
message( "Starting up " + className + " version "+ SoundSystem.class.getPackage().getImplementationVersion()+"...", 0 );
227
228
// create the random number generator:
229
randomNumberGenerator = new Random();
230
// create the command queue:
231
commandQueue = new LinkedList<CommandObject>();
232
// create the working source playlist:
233
sourcePlayList = new LinkedList<CommandObject>();
234
235
// Instantiate and start the Command Processer thread:
236
commandThread = new CommandThread( this ); // Gets a SoundSystem handle
237
commandThread.start();
238
239
snooze( 200 );
240
241
newLibrary( libraryClass );
242
message( "", 0 );
243
}
244
245
/**
246
* Ends the command thread, shuts down the sound system, and removes references
247
* to all instantiated objects.
248
*/
249
public void cleanup()
250
{
251
boolean killException = false;
252
message( "", 0 );
253
message( className + " shutting down...", 0 );
254
255
// End the command thread:
256
try
257
{
258
commandThread.kill(); // end the command processor loop.
259
commandThread.interrupt(); // wake the thread up so it can end.
260
}
261
catch( Exception e )
262
{
263
killException = true;
264
}
265
266
if( !killException )
267
{
268
// wait up to 5 seconds for command thread to end:
269
for( int i = 0; i < 50; i++ )
270
{
271
if( !commandThread.alive() )
272
break;
273
snooze( 100 );
274
}
275
}
276
277
// Let user know if there was a problem ending the command thread
278
if( killException || commandThread.alive() )
279
{
280
errorMessage( "Command thread did not die!", 0 );
281
message( "Ignoring errors... continuing clean-up.", 0 );
282
}
283
284
initialized( SET, false );
285
currentLibrary( SET, null );
286
try
287
{
288
// Stop all sources and shut down the sound library:
289
if( soundLibrary != null )
290
soundLibrary.cleanup();
291
}
292
catch( Exception e )
293
{
294
errorMessage( "Problem during Library.cleanup()!", 0 );
295
message( "Ignoring errors... continuing clean-up.", 0 );
296
}
297
298
try
299
{
300
// remove any queued commands:
301
if( commandQueue != null )
302
commandQueue.clear();
303
}
304
catch( Exception e )
305
{
306
errorMessage( "Unable to clear the command queue!", 0 );
307
message( "Ignoring errors... continuing clean-up.", 0 );
308
}
309
310
try
311
{
312
// empty the source management list:
313
if( sourcePlayList != null )
314
sourcePlayList.clear();
315
}
316
catch( Exception e )
317
{
318
errorMessage( "Unable to clear the source management list!", 0 );
319
message( "Ignoring errors... continuing clean-up.", 0 );
320
}
321
322
// Remove references to all instantiated objects:
323
randomNumberGenerator = null;
324
soundLibrary = null;
325
commandQueue = null;
326
sourcePlayList = null;
327
commandThread = null;
328
329
importantMessage( "Author: Paul Lamb, www.paulscode.com", 1 );
330
message( "", 0 );
331
}
332
333
/**
334
* Wakes up the Command Thread to process commands. This method should be
335
* used if there is a need to call methods 'ManageSources' and 'CommandQueue'
336
* externally. In most cases, this method will not be needed, since
337
* SoundSystem automatically wakes the Command Thread every time commands are
338
* placed into either the ManageSources queue or CommandQueue to be processed.
339
*/
340
public void interruptCommandThread()
341
{
342
if( commandThread == null )
343
{
344
errorMessage( "Command Thread null in method " +
345
"'interruptCommandThread'", 0 );
346
return;
347
}
348
// Wake the command thread to process commands:
349
commandThread.interrupt();
350
}
351
352
/**
353
* Pre-loads a sound into memory. The file may either be located within the
354
* JAR or at an online location. If the file is online, filename must begin
355
* with "http://", since that is how SoundSystem recognizes URL's. If the file
356
* is located within the compiled JAR, the package in which sound files are
357
* located may be set by calling SoundSystemConfig.setSoundFilesPackage().
358
* @param filename Filename of the sound file to load.
359
*/
360
public void loadSound( String filename )
361
{
362
// Queue a command to load the sound file:
363
CommandQueue( new CommandObject( CommandObject.LOAD_SOUND,
364
new FilenameURL( filename ) ) );
365
// Wake the command thread to process commands:
366
commandThread.interrupt();
367
}
368
369
/**
370
* Pre-loads a sound specified by the given URL into memory. The second
371
* parameter 'identifier' should look like a filename, and it must have the
372
* correct extension so SoundSystem knows what codec to use for the file
373
* referenced by the URL instance.
374
* @param url URL handle to the sound file to load.
375
* @param identifier Filename/identifier of the file referenced by the URL.
376
*/
377
public void loadSound( URL url, String identifier )
378
{
379
// Queue a command to load the sound file from a URL:
380
CommandQueue( new CommandObject( CommandObject.LOAD_SOUND,
381
new FilenameURL( url, identifier ) ) );
382
// Wake the command thread to process commands:
383
commandThread.interrupt();
384
}
385
386
/**
387
* Saves raw PCM audio data in the specified audio format, under the specified
388
* identifier. This identifier can be later used in place of 'filename'
389
* parameters to reference the sample data.
390
* @param data The sample data
391
* @param format Format the sample data is stored in
392
* @param identifier What to call the sample.
393
*/
394
public void loadSound( byte[] data, AudioFormat format, String identifier )
395
{
396
// Queue a command to load the sound file from a URL:
397
CommandQueue( new CommandObject( CommandObject.LOAD_DATA,
398
identifier,
399
new SoundBuffer( data, format ) ) );
400
// Wake the command thread to process commands:
401
commandThread.interrupt();
402
}
403
404
405
/**
406
* Removes a pre-loaded sound from memory. This is a good method to use for
407
* freeing up memory after a large sound file is no longer needed. NOTE: the
408
* source will remain in memory after calling this method as long as the
409
* sound is attached to an existing source. When calling this method, calls
410
* should also be made to method removeSource( String ) for all sources which
411
* this sound is bound to.
412
* @param filename Filename/identifier of the sound file to unload.
413
*/
414
public void unloadSound( String filename )
415
{
416
// Queue a command to unload the sound file:
417
CommandQueue( new CommandObject( CommandObject.UNLOAD_SOUND, filename ) );
418
// Wake the command thread to process commands:
419
commandThread.interrupt();
420
}
421
422
/**
423
* If the specified source is a streaming source or MIDI source, this method
424
* queues up the next sound to play when the previous playback ends. The file
425
* may either be located within the JAR or at an online location. If the file
426
* is online, filename must begin with "http://", since that is how SoundSystem
427
* recognizes URL paths. If the file is located within the compiled JAR, the
428
* package in which sound files are located may be set by calling
429
* SoundSystemConfig.setSoundFilesPackage(). This method has no effect on
430
* non-streaming sources.
431
* @param sourcename Source identifier.
432
* @param filename Name of the sound file to play next.
433
*/
434
public void queueSound( String sourcename, String filename )
435
{
436
// Queue a command to queue the sound:
437
CommandQueue( new CommandObject( CommandObject.QUEUE_SOUND, sourcename,
438
new FilenameURL( filename ) ) );
439
// Wake the command thread to process commands:
440
commandThread.interrupt();
441
}
442
443
/**
444
* If the specified source is a streaming source or MIDI source, this method
445
* queues up the next sound to play when the previous playback ends. The third
446
* parameter 'identifier' should look like a filename, and it must have the
447
* correct extension so SoundSystem knows what codec to use for the file
448
* referenced by the URL instance. This method has no effect on non-streaming
449
* sources.
450
* @param sourcename Source identifier.
451
* @param url URL handle to the sound file to load.
452
* @param identifier Filename/identifier of the file referenced by the URL.
453
*/
454
public void queueSound( String sourcename, URL url, String identifier )
455
{
456
// Queue a command to queue the sound:
457
CommandQueue( new CommandObject( CommandObject.QUEUE_SOUND, sourcename,
458
new FilenameURL( url, identifier ) ) );
459
// Wake the command thread to process commands:
460
commandThread.interrupt();
461
}
462
463
/**
464
* Removes the first occurrence of the specified filename/identifier from the
465
* specified source's list of sounds to play when previous playback ends. This
466
* method has no effect on non-streaming sources.
467
* @param sourcename Source identifier.
468
* @param filename Filename/identifier of the sound file to play next.
469
*/
470
public void dequeueSound( String sourcename, String filename )
471
{
472
// Queue a command to dequeue the sound:
473
CommandQueue( new CommandObject( CommandObject.DEQUEUE_SOUND,
474
sourcename, filename ) );
475
// Wake the command thread to process commands:
476
commandThread.interrupt();
477
}
478
479
/**
480
* Fades out the volume of whatever the specified source is currently playing,
481
* then begins playing the specified file at the source's previously
482
* assigned volume level. The file may either be located within the JAR or at
483
* an online location. If the file is online, filename must begin with
484
* "http://", since that is how SoundSystem recognizes URL paths. If the file
485
* is located within the compiled JAR, the package in which sound files are
486
* located may be set by calling SoundSystemConfig.setSoundFilesPackage(). If
487
* the filename parameter is null or empty, the specified source will simply
488
* fade out and stop. The miliseconds parameter must be non-negative or zero.
489
* This method will remove anything that is currently in the specified source's
490
* list of queued sounds that would have played next when the current sound
491
* finished playing. This method may only be used for streaming and MIDI
492
* sources.
493
* @param sourcename Name of the source to fade out.
494
* @param filename Name of a sound file to play next, or null for none.
495
* @param milis Number of miliseconds the fadeout should take.
496
*/
497
public void fadeOut( String sourcename, String filename, long milis )
498
{
499
FilenameURL fu = null;
500
if( filename != null )
501
fu = new FilenameURL( filename );
502
// Queue a command to fade out:
503
CommandQueue( new CommandObject( CommandObject.FADE_OUT, sourcename, fu,
504
milis ) );
505
// Wake the command thread to process commands:
506
commandThread.interrupt();
507
}
508
509
/**
510
* Fades out the volume of whatever the specified source is currently playing,
511
* then begins playing the specified file at the source's previously
512
* assigned volume level. If the url parameter is null or empty, the
513
* specified source will simply fade out and stop. The third
514
* parameter 'identifier' should look like a filename, and it must have the
515
* correct extension so SoundSystem knows what codec to use for the file
516
* referenced by the URL instance. The miliseconds parameter must be
517
* non-negative or zero. This method will remove anything that is currently in
518
* the specified source's list of queued sounds that would have played next
519
* when the current sound finished playing. This method may only be used for
520
* streaming and MIDI sources.
521
* @param sourcename Name of the source to fade out.
522
* @param url URL handle to the sound file to play next, or null for none.
523
* @param identifier Filename/identifier of the file referenced by the URL.
524
* @param milis Number of miliseconds the fadeout should take.
525
*/
526
public void fadeOut( String sourcename, URL url, String identifier,
527
long milis )
528
{
529
FilenameURL fu = null;
530
if( url != null && identifier != null )
531
fu = new FilenameURL( url, identifier );
532
// Queue a command to fade out:
533
CommandQueue( new CommandObject( CommandObject.FADE_OUT, sourcename, fu,
534
milis ) );
535
// Wake the command thread to process commands:
536
commandThread.interrupt();
537
}
538
539
/**
540
* Fades out the volume of whatever the specified source is currently playing,
541
* then fades the volume back in playing the specified filename. Final volume
542
* after fade-in completes will be equal to the source's previously assigned
543
* volume level. The filename parameter may not be null or empty. The file
544
* may either be located within the JAR or at an online location. If the file
545
* is online, filename must begin with "http://", since that is how
546
* SoundSystem recognizes URL paths. If the file is located within the
547
* compiled JAR, the package in which sound files are located may be set by
548
* calling SoundSystemConfig.setSoundFilesPackage(). The miliseconds
549
* parameters must be non-negative or zero. This method will remove anything
550
* that is currently in the specified source's list of queued sounds that would
551
* have played next when the current sound finished playing. This method may
552
* only be used for streaming and MIDI sources.
553
* @param sourcename Name of the source to fade out/in.
554
* @param filename Name of a sound file to play next, or null for none.
555
* @param milisOut Number of miliseconds the fadeout should take.
556
* @param milisIn Number of miliseconds the fadein should take.
557
*/
558
public void fadeOutIn( String sourcename, String filename, long milisOut,
559
long milisIn )
560
{
561
// Queue a command to load the sound file:
562
CommandQueue( new CommandObject( CommandObject.FADE_OUT_IN,
563
sourcename,
564
new FilenameURL( filename ), milisOut,
565
milisIn ) );
566
// Wake the command thread to process commands:
567
commandThread.interrupt();
568
}
569
570
/**
571
* Fades out the volume of whatever the specified source is currently playing,
572
* then fades the volume back in playing the specified file. Final volume
573
* after fade-in completes will be equal to the source's previously assigned
574
* volume level. The url parameter may not be null or empty. The third
575
* parameter 'identifier' should look like a filename, and it must have the
576
* correct extension so SoundSystem knows what codec to use for the file
577
* referenced by the URL instance. The miliseconds parameters must be
578
* non-negative or zero. This method will remove anything that is currently
579
* in the specified source's list of queued sounds that would have played next
580
* when the current sound finished playing. This method may only be used for
581
* streaming and MIDI sources.
582
* @param sourcename Name of the source to fade out/in.
583
* @param url URL handle to the sound file to play next.
584
* @param identifier Filename/identifier of the file referenced by the URL.
585
* @param milisOut Number of miliseconds the fadeout should take.
586
* @param milisIn Number of miliseconds the fadein should take.
587
*/
588
public void fadeOutIn( String sourcename, URL url, String identifier,
589
long milisOut, long milisIn )
590
{
591
// Queue a command to load the sound file:
592
CommandQueue( new CommandObject( CommandObject.FADE_OUT_IN,
593
sourcename,
594
new FilenameURL( url, identifier ),
595
milisOut, milisIn ) );
596
// Wake the command thread to process commands:
597
commandThread.interrupt();
598
}
599
600
/**
601
* Makes sure the current volume levels of streaming sources and MIDI are
602
* correct. This method is designed to help reduce the "jerky" fading behavior
603
* that happens when using some library and codec pluggins (such as
604
* LibraryJavaSound and CodecJOrbis). This method has no effect on normal
605
* "non-streaming" sources. It would normally be called somewhere in the main
606
* "game loop". IMPORTANT: To optimize frame-rates, do not call this method
607
* for every frame. It is better to just call this method at some acceptable
608
* "granularity" (play around with different granularities to find what sounds
609
* acceptable for a particular situation).
610
*/
611
public void checkFadeVolumes()
612
{
613
// Queue a command to load check fading source volumes:
614
CommandQueue( new CommandObject( CommandObject.CHECK_FADE_VOLUMES ) );
615
// Wake the command thread to process commands:
616
commandThread.interrupt();
617
}
618
619
/**
620
* Creates a new permanant, streaming, priority source with zero attenuation.
621
* The file may either be located within the JAR or at an online location. If
622
* the file is online, filename must begin with "http://", since that is how
623
* SoundSystem recognizes URL paths. If the file is located within the
624
* compiled JAR, the package in which sound files are located may be set by
625
* calling SoundSystemConfig.setSoundFilesPackage().
626
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
627
* @param filename Filename of the sound file to stream at this source.
628
* @param toLoop Should this source loop, or play only once.
629
*/
630
public void backgroundMusic( String sourcename, String filename,
631
boolean toLoop )
632
{
633
// Queue a command to quick stream a new source:
634
CommandQueue( new CommandObject( CommandObject.QUICK_PLAY, true,
635
true, toLoop, sourcename,
636
new FilenameURL( filename ), 0, 0, 0,
637
SoundSystemConfig.ATTENUATION_NONE, 0, false ) );
638
CommandQueue( new CommandObject( CommandObject.PLAY, sourcename) );
639
640
commandThread.interrupt();
641
}
642
643
/**
644
* Creates a new permanant, streaming, priority source with zero attenuation.
645
* The third parameter 'identifier' should look like a filename, and it must
646
* have the correct extension so SoundSystem knows what codec to use for the
647
* file referenced by the URL instance.
648
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
649
* @param url URL handle to the sound file to stream at this source.
650
* @param identifier Filename/identifier of the file referenced by the URL.
651
* @param toLoop Should this source loop, or play only once.
652
*/
653
public void backgroundMusic( String sourcename, URL url, String identifier,
654
boolean toLoop )
655
{
656
// Queue a command to quick stream a new source:
657
CommandQueue( new CommandObject( CommandObject.QUICK_PLAY, true,
658
true, toLoop, sourcename,
659
new FilenameURL( url, identifier ),
660
0, 0, 0,
661
SoundSystemConfig.ATTENUATION_NONE,
662
0, false ) );
663
CommandQueue( new CommandObject( CommandObject.PLAY, sourcename) );
664
665
commandThread.interrupt();
666
}
667
668
/**
669
* Creates a new non-streaming source.
670
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
671
* information about Attenuation, fade distance, and rolloff factor.
672
* @param priority Setting this to true will prevent other sounds from overriding this one.
673
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
674
* @param filename Filename/identifier of the sound file to play at this source.
675
* @param toLoop Should this source loop, or play only once.
676
* @param x X position for this source.
677
* @param y Y position for this source.
678
* @param z Z position for this source.
679
* @param attmodel Attenuation model to use.
680
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
681
*/
682
public void newSource( boolean priority, String sourcename, String filename,
683
boolean toLoop, float x, float y, float z,
684
int attmodel, float distOrRoll )
685
{
686
CommandQueue( new CommandObject( CommandObject.NEW_SOURCE, priority,
687
false, toLoop, sourcename,
688
new FilenameURL( filename ), x, y, z,
689
attmodel, distOrRoll ) );
690
commandThread.interrupt();
691
}
692
693
/**
694
* Creates a new non-streaming source.
695
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
696
* information about Attenuation, fade distance, and rolloff factor.
697
* @param priority Setting this to true will prevent other sounds from overriding this one.
698
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
699
* @param url URL handle to the sound file to stream at this source.
700
* @param identifier Filename/identifier of the file referenced by the URL.
701
* @param toLoop Should this source loop, or play only once.
702
* @param x X position for this source.
703
* @param y Y position for this source.
704
* @param z Z position for this source.
705
* @param attmodel Attenuation model to use.
706
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
707
*/
708
public void newSource( boolean priority, String sourcename, URL url,
709
String identifier, boolean toLoop, float x, float y,
710
float z, int attmodel, float distOrRoll )
711
{
712
CommandQueue( new CommandObject( CommandObject.NEW_SOURCE, priority,
713
false, toLoop, sourcename,
714
new FilenameURL( url, identifier ),
715
x, y, z,
716
attmodel, distOrRoll ) );
717
commandThread.interrupt();
718
}
719
720
/**
721
* Creates a new streaming source. The file may either be located within the
722
* JAR or at an online location. If the file is online, filename must begin
723
* with "http://", since that is how SoundSystem recognizes URL paths. If the
724
* file is located within the compiled JAR, the package in which sound files
725
* are located may be set by calling SoundSystemConfig.setSoundFilesPackage().
726
* @param priority Setting this to true will prevent other sounds from overriding this one.
727
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
728
* @param filename The filename of the sound file to play at this source.
729
* @param toLoop Should this source loop, or play only once.
730
* @param x X position for this source.
731
* @param y Y position for this source.
732
* @param z Z position for this source.
733
* @param attmodel Attenuation model to use.
734
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
735
*/
736
public void newStreamingSource( boolean priority, String sourcename,
737
String filename, boolean toLoop, float x,
738
float y, float z, int attmodel,
739
float distOrRoll )
740
{
741
CommandQueue( new CommandObject( CommandObject.NEW_SOURCE, priority,
742
true, toLoop, sourcename,
743
new FilenameURL( filename ), x, y, z,
744
attmodel, distOrRoll ) );
745
commandThread.interrupt();
746
}
747
748
/**
749
* Creates a new streaming source. The fourth parameter 'identifier' should
750
* look like a filename, and it must have the correct extension so SoundSystem
751
* knows what codec to use for the file referenced by the URL instance.
752
* @param priority Setting this to true will prevent other sounds from overriding this one.
753
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
754
* @param url URL handle to the sound file to stream at this source.
755
* @param identifier Filename/identifier of the file referenced by the URL.
756
* @param toLoop Should this source loop, or play only once.
757
* @param x X position for this source.
758
* @param y Y position for this source.
759
* @param z Z position for this source.
760
* @param attmodel Attenuation model to use.
761
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
762
*/
763
public void newStreamingSource( boolean priority, String sourcename,
764
URL url, String identifier, boolean toLoop,
765
float x, float y, float z, int attmodel,
766
float distOrRoll )
767
{
768
CommandQueue( new CommandObject( CommandObject.NEW_SOURCE, priority,
769
true, toLoop, sourcename,
770
new FilenameURL( url, identifier ),
771
x, y, z, attmodel, distOrRoll ) );
772
commandThread.interrupt();
773
}
774
775
/**
776
* Opens a direct line for streaming audio data. This method creates a new
777
* streaming source to play the data at. The resulting streaming source can be
778
* manipulated the same as any other streaming source. Raw data can be sent to
779
* the new streaming source using the feedRawAudioData() method.
780
* @param audioFormat Format that the data will be in.
781
* @param priority Setting this to true will prevent other sounds from overriding this one.
782
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
783
* @param x X position for this source.
784
* @param y Y position for this source.
785
* @param z Z position for this source.
786
* @param attModel Attenuation model to use.
787
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
788
*/
789
public void rawDataStream( AudioFormat audioFormat, boolean priority,
790
String sourcename, float x, float y, float z,
791
int attModel, float distOrRoll )
792
{
793
CommandQueue( new CommandObject( CommandObject.RAW_DATA_STREAM,
794
audioFormat, priority, sourcename, x,
795
y, z, attModel, distOrRoll ) );
796
commandThread.interrupt();
797
}
798
799
/**
800
* Creates a temporary source and plays it. After the source finishes playing,
801
* it is removed. Returns a randomly generated name for the new source. NOTE:
802
* to make a source created by this method permanant, call the setActive()
803
* method using the return value for sourcename.
804
* @param priority Setting this to true will prevent other sounds from overriding this one.
805
* @param filename Filename/identifier of the sound file to play at this source.
806
* @param toLoop Should this source loop, or play only once.
807
* @param x X position for this source.
808
* @param y Y position for this source.
809
* @param z Z position for this source.
810
* @param attmodel Attenuation model to use.
811
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
812
* @return The new sorce's name.
813
*/
814
public String quickPlay( boolean priority, String filename, boolean toLoop,
815
float x, float y, float z, int attmodel,
816
float distOrRoll )
817
{
818
//generate a random name for this source:
819
String sourcename = "Source_"
820
+ randomNumberGenerator.nextInt()
821
+ "_" + randomNumberGenerator.nextInt();
822
823
// Queue a command to quick play this new source:
824
CommandQueue( new CommandObject( CommandObject.QUICK_PLAY, priority,
825
false, toLoop, sourcename,
826
new FilenameURL( filename ), x, y, z,
827
attmodel, distOrRoll, true ) );
828
CommandQueue( new CommandObject( CommandObject.PLAY, sourcename) );
829
// Wake the command thread to process commands:
830
commandThread.interrupt();
831
832
// return the new source name.
833
return sourcename;
834
}
835
836
/**
837
* Creates a temporary source and plays it. After the source finishes playing,
838
* it is removed. Returns a randomly generated name for the new source. NOTE:
839
* to make a source created by this method permanant, call the setActive()
840
* method using the return value for sourcename.
841
* @param priority Setting this to true will prevent other sounds from overriding this one.
842
* @param url URL handle to the sound file to stream at this source.
843
* @param identifier Filename/identifier of the file referenced by the URL.
844
* @param toLoop Should this source loop, or play only once.
845
* @param x X position for this source.
846
* @param y Y position for this source.
847
* @param z Z position for this source.
848
* @param attmodel Attenuation model to use.
849
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
850
* @return The new sorce's name.
851
*/
852
public String quickPlay( boolean priority, URL url, String identifier,
853
boolean toLoop, float x, float y, float z,
854
int attmodel, float distOrRoll )
855
{
856
//generate a random name for this source:
857
String sourcename = "Source_"
858
+ randomNumberGenerator.nextInt()
859
+ "_" + randomNumberGenerator.nextInt();
860
861
// Queue a command to quick play this new source:
862
CommandQueue( new CommandObject( CommandObject.QUICK_PLAY, priority,
863
false, toLoop, sourcename,
864
new FilenameURL( url, identifier ),
865
x, y, z, attmodel, distOrRoll,
866
true ) );
867
CommandQueue( new CommandObject( CommandObject.PLAY, sourcename) );
868
// Wake the command thread to process commands:
869
commandThread.interrupt();
870
871
// return the new source name.
872
return sourcename;
873
}
874
875
/**
876
* Creates a temporary source and streams it. After the source finishes
877
* playing, it is removed. The file may either be located within the
878
* JAR or at an online location. If the file is online, filename must begin
879
* with "http://", since that is how SoundSystem recognizes URL paths. If the
880
* file is located within the compiled JAR, the package in which sound files
881
* are located may be set by calling SoundSystemConfig.setSoundFilesPackage().
882
* Returns a randomly generated name for the new source. NOTE: to make a
883
* source created by this method permanant, call the setActive() method using
884
* the return value for sourcename.
885
* @param priority Setting this to true will prevent other sounds from overriding this one.
886
* @param filename Filename of the sound file to stream at this source.
887
* @param toLoop Should this source loop, or play only once.
888
* @param x X position for this source.
889
* @param y Y position for this source.
890
* @param z Z position for this source.
891
* @param attmodel Attenuation model to use.
892
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
893
* @return The new sorce's name.
894
*/
895
public String quickStream( boolean priority, String filename,
896
boolean toLoop, float x, float y, float z,
897
int attmodel, float distOrRoll )
898
{
899
//generate a random name for this source:
900
String sourcename = "Source_"
901
+ randomNumberGenerator.nextInt()
902
+ "_" + randomNumberGenerator.nextInt();
903
904
// Queue a command to quick stream this new source:
905
CommandQueue( new CommandObject( CommandObject.QUICK_PLAY, priority,
906
true, toLoop, sourcename,
907
new FilenameURL( filename ), x, y, z,
908
attmodel, distOrRoll, true ) );
909
CommandQueue( new CommandObject( CommandObject.PLAY, sourcename) );
910
// Wake the command thread to process commands:
911
commandThread.interrupt();
912
913
// return the new source name.
914
return sourcename;
915
}
916
/**
917
* Creates a temporary source and streams it. After the source finishes
918
* playing, it is removed. The third parameter 'identifier' should
919
* look like a filename, and it must have the correct extension so SoundSystem
920
* knows what codec to use for the file referenced by the URL instance.
921
* Returns a randomly generated name for the new source. NOTE: to make a
922
* source created by this method permanant, call the setActive() method using
923
* the return value for sourcename.
924
* @param priority Setting this to true will prevent other sounds from overriding this one.
925
* @param url URL handle to the sound file to stream at this source.
926
* @param identifier Filename/identifier of the file referenced by the URL.
927
* @param toLoop Should this source loop, or play only once.
928
* @param x X position for this source.
929
* @param y Y position for this source.
930
* @param z Z position for this source.
931
* @param attmodel Attenuation model to use.
932
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
933
* @return The new sorce's name.
934
*/
935
public String quickStream( boolean priority, URL url, String identifier,
936
boolean toLoop, float x, float y, float z,
937
int attmodel, float distOrRoll )
938
{
939
//generate a random name for this source:
940
String sourcename = "Source_"
941
+ randomNumberGenerator.nextInt()
942
+ "_" + randomNumberGenerator.nextInt();
943
944
// Queue a command to quick stream this new source:
945
CommandQueue( new CommandObject( CommandObject.QUICK_PLAY, priority,
946
true, toLoop, sourcename,
947
new FilenameURL( url, identifier ),
948
x, y, z, attmodel, distOrRoll,
949
true ) );
950
CommandQueue( new CommandObject( CommandObject.PLAY, sourcename) );
951
// Wake the command thread to process commands:
952
commandThread.interrupt();
953
954
// return the new source name.
955
return sourcename;
956
}
957
958
/**
959
* Move a source to the specified location.
960
* @param sourcename Identifier for the source.
961
* @param x destination X coordinate.
962
* @param y destination Y coordinate.
963
* @param z destination Z coordinate.
964
*/
965
public void setPosition( String sourcename, float x, float y, float z )
966
{
967
CommandQueue( new CommandObject( CommandObject.SET_POSITION,
968
sourcename, x, y, z ) );
969
commandThread.interrupt();
970
}
971
/**
972
* Manually sets the specified source's volume.
973
* @param sourcename Source to move.
974
* @param value New volume, float value ( 0.0f - 1.0f ).
975
*/
976
public void setVolume( String sourcename, float value )
977
{
978
CommandQueue( new CommandObject( CommandObject.SET_VOLUME,
979
sourcename, value ) );
980
commandThread.interrupt();
981
}
982
983
/**
984
* Returns the current volume of the specified source, or zero if the specified
985
* source was not found.
986
* @param sourcename Source to read volume from.
987
* @return Float value representing the source volume (0.0f - 1.0f).
988
*/
989
public float getVolume( String sourcename )
990
{
991
synchronized( SoundSystemConfig.THREAD_SYNC )
992
{
993
if( soundLibrary != null )
994
return soundLibrary.getVolume( sourcename );
995
else
996
return 0.0f;
997
}
998
}
999
1000
/**
1001
* Manually sets the specified source's pitch.
1002
* @param sourcename The source's name.
1003
* @param value A float value ( 0.5f - 2.0f ).
1004
*/
1005
public void setPitch( String sourcename, float value )
1006
{
1007
CommandQueue( new CommandObject( CommandObject.SET_PITCH,
1008
sourcename, value ) );
1009
commandThread.interrupt();
1010
}
1011
1012
/**
1013
* Returns the pitch of the specified source.
1014
* @param sourcename The source's name.
1015
* @return Float value representing the source pitch (0.5f - 2.0f).
1016
*/
1017
public float getPitch( String sourcename )
1018
{
1019
if( soundLibrary != null )
1020
return soundLibrary.getPitch( sourcename );
1021
else
1022
return 1.0f;
1023
}
1024
1025
/**
1026
* Set a source's priority factor. A priority source will not be overriden when
1027
* too many sources are playing at once.
1028
* @param sourcename Identifier for the source.
1029
* @param pri Setting this to true makes this source a priority source.
1030
*/
1031
public void setPriority( String sourcename, boolean pri )
1032
{
1033
CommandQueue( new CommandObject( CommandObject.SET_PRIORITY,
1034
sourcename, pri ) );
1035
commandThread.interrupt();
1036
}
1037
/**
1038
* Changes a source to looping or non-looping.
1039
* @param sourcename Identifier for the source.
1040
* @param lp This source should loop.
1041
*/
1042
public void setLooping( String sourcename, boolean lp )
1043
{
1044
CommandQueue( new CommandObject( CommandObject.SET_LOOPING,
1045
sourcename, lp ) );
1046
commandThread.interrupt();
1047
}
1048
/**
1049
* Changes a source's attenuation model.
1050
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1051
* information about Attenuation.
1052
* @param sourcename Identifier for the source.
1053
* @param model Attenuation model to use.
1054
*/
1055
public void setAttenuation( String sourcename, int model )
1056
{
1057
CommandQueue( new CommandObject( CommandObject.SET_ATTENUATION,
1058
sourcename, model ) );
1059
commandThread.interrupt();
1060
}
1061
/**
1062
* Changes a source's fade distance or rolloff factor.
1063
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1064
* information about fade distance and rolloff.
1065
* @param sourcename Identifier for the source.
1066
* @param dr Either the fading distance or rolloff factor, depending on the attenuation model used.
1067
*/
1068
public void setDistOrRoll( String sourcename, float dr)
1069
{
1070
CommandQueue( new CommandObject( CommandObject.SET_DIST_OR_ROLL,
1071
sourcename, dr ) );
1072
commandThread.interrupt();
1073
}
1074
1075
/**
1076
* Changes the Doppler factor, for determining Doppler effect scale.
1077
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1078
* information about Doppler effect.
1079
* @param dopplerFactor New value for Doppler factor.
1080
*/
1081
public void changeDopplerFactor( float dopplerFactor)
1082
{
1083
CommandQueue( new CommandObject( CommandObject.CHANGE_DOPPLER_FACTOR,
1084
dopplerFactor ) );
1085
commandThread.interrupt();
1086
}
1087
1088
/**
1089
* Changes the Doppler velocity, for use in Doppler effect.
1090
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1091
* information about Doppler effect.
1092
* @param dopplerVelocity New value for Doppler velocity.
1093
*/
1094
public void changeDopplerVelocity( float dopplerVelocity )
1095
{
1096
CommandQueue( new CommandObject( CommandObject.CHANGE_DOPPLER_VELOCITY,
1097
dopplerVelocity ) );
1098
commandThread.interrupt();
1099
}
1100
1101
/**
1102
* Sets the specified source's velocity, for use in Doppler effect.
1103
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1104
* information about Doppler effect.
1105
* @param sourcename The source's name.
1106
* @param x Velocity along world x-axis.
1107
* @param y Velocity along world y-axis.
1108
* @param z Velocity along world z-axis.
1109
*/
1110
public void setVelocity( String sourcename, float x, float y, float z )
1111
{
1112
CommandQueue( new CommandObject( CommandObject.SET_VELOCITY,
1113
sourcename, x, y, z ) );
1114
commandThread.interrupt();
1115
}
1116
1117
/**
1118
* Sets the listener's velocity, for use in Doppler effect.
1119
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1120
* information about Doppler effect.
1121
* @param x Velocity along world x-axis.
1122
* @param y Velocity along world y-axis.
1123
* @param z Velocity along world z-axis.
1124
*/
1125
public void setListenerVelocity( float x, float y, float z )
1126
{
1127
CommandQueue( new CommandObject( CommandObject.SET_LISTENER_VELOCITY,
1128
x, y, z ) );
1129
commandThread.interrupt();
1130
}
1131
1132
/**
1133
* Returns the number of miliseconds since the specified source began playing.
1134
* @return miliseconds, or -1 if not playing or unable to calculate
1135
*/
1136
public float millisecondsPlayed( String sourcename )
1137
{
1138
synchronized( SoundSystemConfig.THREAD_SYNC )
1139
{
1140
return soundLibrary.millisecondsPlayed( sourcename );
1141
}
1142
}
1143
1144
/**
1145
* Feeds raw data through the specified source. The source must be a
1146
* streaming source and it can not be already associated with a file or URL to
1147
* stream from. Only use this for streaming sources created with the
1148
* rawDataStream() method. NOTE: Be carefull how much data you send to a
1149
* source to stream. The data will be processed at playback speed, so if you
1150
* queue up 1 hour worth of data, it will take 1 hour to play (not to mention
1151
* hogging a ton of memory). To clear out all queued data from the source, use
1152
* the flush() method. Also note: if there is a break in the data stream,
1153
* you will hear clicks and studders, so ensure that the data flow is steady.
1154
* @param sourcename Name of the streaming source to play from.
1155
* @param buffer Byte buffer containing raw audio data to stream.
1156
*/
1157
public void feedRawAudioData( String sourcename, byte[] buffer )
1158
{
1159
CommandQueue( new CommandObject( CommandObject.FEED_RAW_AUDIO_DATA,
1160
sourcename, buffer ) );
1161
commandThread.interrupt();
1162
}
1163
/**
1164
* Plays the specified source.
1165
* @param sourcename Identifier for the source.
1166
*/
1167
public void play( String sourcename )
1168
{
1169
CommandQueue( new CommandObject( CommandObject.PLAY, sourcename) );
1170
commandThread.interrupt();
1171
}
1172
/**
1173
* Pauses the specified source.
1174
* @param sourcename Identifier for the source.
1175
*/
1176
public void pause( String sourcename )
1177
{
1178
CommandQueue( new CommandObject( CommandObject.PAUSE, sourcename) );
1179
commandThread.interrupt();
1180
}
1181
/**
1182
* Stops the specified source.
1183
* @param sourcename Identifier for the source.
1184
*/
1185
public void stop( String sourcename )
1186
{
1187
CommandQueue( new CommandObject( CommandObject.STOP, sourcename) );
1188
commandThread.interrupt();
1189
}
1190
/**
1191
* Rewinds the specified source.
1192
* @param sourcename Identifier for the source.
1193
*/
1194
public void rewind( String sourcename )
1195
{
1196
CommandQueue( new CommandObject( CommandObject.REWIND, sourcename) );
1197
commandThread.interrupt();
1198
}
1199
/**
1200
* Flushes all previously queued audio data from a streaming source.
1201
* @param sourcename Identifier for the source.
1202
*/
1203
public void flush( String sourcename )
1204
{
1205
CommandQueue( new CommandObject( CommandObject.FLUSH, sourcename) );
1206
commandThread.interrupt();
1207
}
1208
1209
/**
1210
* Culls the specified source. A culled source can not be played until it has
1211
* been activated again.
1212
* @param sourcename Identifier for the source.
1213
*/
1214
public void cull( String sourcename )
1215
{
1216
CommandQueue( new CommandObject( CommandObject.CULL, sourcename) );
1217
commandThread.interrupt();
1218
}
1219
1220
/**
1221
* Activates the specified source after it was culled, so it can be played
1222
* again.
1223
* @param sourcename Identifier for the source.
1224
*/
1225
public void activate( String sourcename )
1226
{
1227
CommandQueue( new CommandObject( CommandObject.ACTIVATE, sourcename) );
1228
commandThread.interrupt();
1229
}
1230
1231
/**
1232
* Sets a flag for a source indicating whether it should be used or if it
1233
* should be removed after it finishes playing. One possible use for this
1234
* method is to make temporary sources that were created with quickPlay()
1235
* permanant. Another use could be to have a source automatically removed
1236
* after it finishes playing. NOTE: Setting a source to temporary does not
1237
* stop it, and setting a source to permanant does not play it. It is also
1238
* important to note that a looping temporary source will not be removed as
1239
* long as it keeps playing.
1240
* @param sourcename Identifier for the source.
1241
* @param temporary True = temporary, False = permanant.
1242
*/
1243
public void setTemporary( String sourcename, boolean temporary )
1244
{
1245
CommandQueue( new CommandObject( CommandObject.SET_TEMPORARY,
1246
sourcename, temporary ) );
1247
commandThread.interrupt();
1248
}
1249
1250
/**
1251
* Removes the specified source and clears up any memory it used.
1252
* @param sourcename Identifier for the source.
1253
*/
1254
public void removeSource( String sourcename )
1255
{
1256
CommandQueue( new CommandObject( CommandObject.REMOVE_SOURCE,
1257
sourcename ) );
1258
commandThread.interrupt();
1259
}
1260
/**
1261
* Moves the listener relative to the current location.
1262
* @param x X offset.
1263
* @param y Y offset.
1264
* @param z Z offset.
1265
*/
1266
public void moveListener( float x, float y, float z )
1267
{
1268
CommandQueue( new CommandObject( CommandObject.MOVE_LISTENER,
1269
x, y, z ) );
1270
commandThread.interrupt();
1271
}
1272
/**
1273
* Moves the listener to the specified location.
1274
* @param x Destination X coordinate.
1275
* @param y Destination Y coordinate.
1276
* @param z Destination Z coordinate.
1277
*/
1278
public void setListenerPosition( float x, float y, float z )
1279
{
1280
CommandQueue( new CommandObject( CommandObject.SET_LISTENER_POSITION,
1281
x, y, z ) );
1282
commandThread.interrupt();
1283
}
1284
/**
1285
* Turns the listener counterclockwise by "angle" radians around the y-axis,
1286
* relative to the current angle.
1287
* @param angle radian offset.
1288
*/
1289
public void turnListener( float angle )
1290
{
1291
CommandQueue( new CommandObject( CommandObject.TURN_LISTENER,
1292
angle ) );
1293
commandThread.interrupt();
1294
}
1295
/**
1296
* Sets the listener's angle in radians around the y-axis.
1297
* @param angle radians.
1298
*/
1299
public void setListenerAngle( float angle )
1300
{
1301
CommandQueue( new CommandObject( CommandObject.SET_LISTENER_ANGLE,
1302
angle ) );
1303
commandThread.interrupt();
1304
}
1305
/**
1306
* Sets the listener's orientation.
1307
* @param lookX X coordinate of the (normalized) look-at vector.
1308
* @param lookY Y coordinate of the (normalized) look-at vector.
1309
* @param lookZ Z coordinate of the (normalized) look-at vector.
1310
* @param upX X coordinate of the (normalized) up-direction vector.
1311
* @param upY Y coordinate of the (normalized) up-direction vector.
1312
* @param upZ Z coordinate of the (normalized) up-direction vector.
1313
*/
1314
public void setListenerOrientation( float lookX, float lookY, float lookZ,
1315
float upX, float upY, float upZ )
1316
{
1317
CommandQueue( new CommandObject( CommandObject.SET_LISTENER_ORIENTATION,
1318
lookX, lookY, lookZ, upX, upY, upZ ) );
1319
commandThread.interrupt();
1320
}
1321
1322
/**
1323
* Sets the overall volume, affecting all sources.
1324
* @param value New volume, float value ( 0.0f - 1.0f ).
1325
*/
1326
public void setMasterVolume( float value )
1327
{
1328
CommandQueue( new CommandObject( CommandObject.SET_MASTER_VOLUME,
1329
value ) );
1330
commandThread.interrupt();
1331
}
1332
1333
/**
1334
* Returns the overall volume, affecting all sources.
1335
* @return Float value representing the master volume (0.0f - 1.0f).
1336
*/
1337
public float getMasterVolume()
1338
{
1339
return SoundSystemConfig.getMasterGain();
1340
}
1341
1342
/**
1343
* Method for obtaining information about the listener's position and
1344
* orientation.
1345
* @return a {@link paulscode.sound.ListenerData ListenerData} object.
1346
*/
1347
public ListenerData getListenerData()
1348
{
1349
synchronized( SoundSystemConfig.THREAD_SYNC )
1350
{
1351
return soundLibrary.getListenerData();
1352
}
1353
}
1354
/**
1355
* Switches to the specified library, and preserves all sources.
1356
* @param libraryClass Library to use.
1357
* @return True if switch was successful.
1358
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for
1359
* information about chosing a sound library.
1360
*/
1361
public boolean switchLibrary( Class libraryClass )
1362
throws SoundSystemException
1363
{
1364
synchronized( SoundSystemConfig.THREAD_SYNC )
1365
{
1366
initialized( SET, false );
1367
1368
HashMap<String, Source> sourceMap = null;
1369
ListenerData listenerData = null;
1370
1371
boolean wasMidiChannel = false;
1372
MidiChannel midiChannel = null;
1373
FilenameURL midiFilenameURL = null;
1374
String midiSourcename = "";
1375
boolean midiToLoop = true;
1376
1377
if( soundLibrary != null )
1378
{
1379
currentLibrary( SET, null );
1380
sourceMap = copySources( soundLibrary.getSources() );
1381
listenerData = soundLibrary.getListenerData();
1382
midiChannel = soundLibrary.getMidiChannel();
1383
if( midiChannel != null )
1384
{
1385
wasMidiChannel = true;
1386
midiToLoop = midiChannel.getLooping();
1387
midiSourcename = midiChannel.getSourcename();
1388
midiFilenameURL = midiChannel.getFilenameURL();
1389
}
1390
1391
soundLibrary.cleanup();
1392
soundLibrary = null;
1393
}
1394
message( "", 0 );
1395
message( "Switching to "
1396
+ SoundSystemConfig.getLibraryTitle( libraryClass ), 0 );
1397
message( "(" + SoundSystemConfig.getLibraryDescription( libraryClass )
1398
+ ")", 1 );
1399
1400
try
1401
{
1402
soundLibrary = (Library) libraryClass.newInstance();
1403
}
1404
catch( InstantiationException ie )
1405
{
1406
errorMessage( "The specified library did not load properly", 1 );
1407
}
1408
catch( IllegalAccessException iae )
1409
{
1410
errorMessage( "The specified library did not load properly", 1 );
1411
}
1412
catch( ExceptionInInitializerError eiie )
1413
{
1414
errorMessage( "The specified library did not load properly", 1 );
1415
}
1416
catch( SecurityException se )
1417
{
1418
errorMessage( "The specified library did not load properly", 1 );
1419
}
1420
1421
if( errorCheck( soundLibrary == null, "Library null after " +
1422
"initialization in method 'switchLibrary'", 1 ) )
1423
{
1424
SoundSystemException sse = new SoundSystemException(
1425
className + " did not load properly. " +
1426
"Library was null after initialization.",
1427
SoundSystemException.LIBRARY_NULL );
1428
lastException( SET, sse );
1429
initialized( SET, true );
1430
throw sse;
1431
}
1432
1433
try
1434
{
1435
soundLibrary.init();
1436
}
1437
catch( SoundSystemException sse )
1438
{
1439
lastException( SET, sse );
1440
initialized( SET, true );
1441
throw sse;
1442
}
1443
1444
soundLibrary.setListenerData( listenerData );
1445
if( wasMidiChannel )
1446
{
1447
if( midiChannel != null )
1448
midiChannel.cleanup();
1449
midiChannel = new MidiChannel( midiToLoop, midiSourcename,
1450
midiFilenameURL );
1451
soundLibrary.setMidiChannel( midiChannel );
1452
}
1453
soundLibrary.copySources( sourceMap );
1454
1455
message( "", 0 );
1456
1457
lastException( SET, null );
1458
initialized( SET, true );
1459
1460
return true;
1461
}
1462
}
1463
1464
/**
1465
* Switches to the specified library, loosing all sources.
1466
* @param libraryClass Library to use.
1467
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for
1468
* information about chosing a sound library.
1469
*/
1470
public boolean newLibrary( Class libraryClass )
1471
throws SoundSystemException
1472
{
1473
initialized( SET, false );
1474
1475
CommandQueue( new CommandObject( CommandObject.NEW_LIBRARY,
1476
libraryClass ) );
1477
commandThread.interrupt();
1478
1479
for( int x = 0; (!initialized( GET, XXX )) && (x < 100); x++ )
1480
{
1481
snooze( 400 );
1482
commandThread.interrupt();
1483
}
1484
1485
if( !initialized( GET, XXX ) )
1486
{
1487
SoundSystemException sse = new SoundSystemException(
1488
className +
1489
" did not load after 30 seconds.",
1490
SoundSystemException.LIBRARY_NULL );
1491
lastException( SET, sse );
1492
throw sse;
1493
}
1494
else
1495
{
1496
SoundSystemException sse = lastException( GET, null );
1497
if( sse != null )
1498
throw sse;
1499
}
1500
return true;
1501
}
1502
1503
/**
1504
* Switches to the specified library, loosing all sources. This method is used
1505
* internally by SoundSystem for thread synchronization, and it can not be
1506
* called directly - please use the newLibrary() method instead.
1507
* @param libraryClass Library to use.
1508
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for
1509
* information about chosing a sound library.
1510
*/
1511
private void CommandNewLibrary( Class libraryClass )
1512
{
1513
initialized( SET, false );
1514
1515
String headerMessage = "Initializing ";
1516
if( soundLibrary != null )
1517
{
1518
currentLibrary( SET, null );
1519
// we are switching libraries
1520
headerMessage = "Switching to ";
1521
soundLibrary.cleanup();
1522
soundLibrary = null;
1523
}
1524
message( headerMessage +
1525
SoundSystemConfig.getLibraryTitle( libraryClass ), 0 );
1526
message( "(" + SoundSystemConfig.getLibraryDescription( libraryClass )
1527
+ ")", 1 );
1528
1529
try
1530
{
1531
soundLibrary = (Library) libraryClass.newInstance();
1532
}
1533
catch( InstantiationException ie )
1534
{
1535
errorMessage( "The specified library did not load properly", 1 );
1536
}
1537
catch( IllegalAccessException iae )
1538
{
1539
errorMessage( "The specified library did not load properly", 1 );
1540
}
1541
catch( ExceptionInInitializerError eiie )
1542
{
1543
errorMessage( "The specified library did not load properly", 1 );
1544
}
1545
catch( SecurityException se )
1546
{
1547
errorMessage( "The specified library did not load properly", 1 );
1548
}
1549
1550
if( errorCheck( soundLibrary == null, "Library null after " +
1551
"initialization in method 'newLibrary'", 1 ) )
1552
{
1553
lastException( SET, new SoundSystemException(
1554
className + " did not load properly. " +
1555
"Library was null after initialization.",
1556
SoundSystemException.LIBRARY_NULL ) );
1557
importantMessage( "Switching to silent mode", 1 );
1558
1559
try
1560
{
1561
soundLibrary = new Library();
1562
}
1563
catch( SoundSystemException sse )
1564
{
1565
lastException( SET, new SoundSystemException(
1566
"Silent mode did not load properly. " +
1567
"Library was null after initialization.",
1568
SoundSystemException.LIBRARY_NULL ) );
1569
initialized( SET, true );
1570
return;
1571
}
1572
}
1573
1574
try
1575
{
1576
soundLibrary.init();
1577
}
1578
catch( SoundSystemException sse )
1579
{
1580
lastException( SET, sse );
1581
initialized( SET, true );
1582
return;
1583
}
1584
1585
lastException( SET, null );
1586
initialized( SET, true );
1587
1588
return;
1589
}
1590
/**
1591
* Calls the library's initialize() method. This method is used
1592
* internally by SoundSystem for thread synchronization, and it can not be
1593
* called directly.
1594
*/
1595
private void CommandInitialize()
1596
{
1597
try
1598
{
1599
if( errorCheck( soundLibrary == null, "Library null after " +
1600
"initialization in method 'CommandInitialize'",
1601
1 ) )
1602
{
1603
SoundSystemException sse = new SoundSystemException(
1604
className + " did not load properly. " +
1605
"Library was null after initialization.",
1606
SoundSystemException.LIBRARY_NULL );
1607
lastException( SET, sse );
1608
throw sse;
1609
}
1610
soundLibrary.init();
1611
}
1612
catch( SoundSystemException sse )
1613
{
1614
lastException( SET, sse );
1615
initialized( SET, true );
1616
}
1617
}
1618
/**
1619
* Loads sample data from a sound file or URL into memory. This method is used
1620
* internally by SoundSystem for thread synchronization, and it can not be
1621
* called directly - please use the loadSound() method instead.
1622
* @param filenameURL Filename/URL of the sound file to load.
1623
*/
1624
private void CommandLoadSound( FilenameURL filenameURL )
1625
{
1626
if( soundLibrary != null )
1627
soundLibrary.loadSound( filenameURL );
1628
else
1629
errorMessage(
1630
"Variable 'soundLibrary' null in method 'CommandLoadSound'", 0 );
1631
}
1632
/**
1633
* Saves the specified sample data, under the specified identifier. This
1634
* identifier can be later used in place of 'filename' parameters to reference
1635
* the sample data. This method is used internally by SoundSystem for thread
1636
* synchronization, and it can not be called directly - please use the
1637
* loadSound() method instead.
1638
* @param buffer the sample data and audio format to save.
1639
* @param identifier What to call the sample.
1640
*/
1641
private void CommandLoadSound( SoundBuffer buffer, String identifier )
1642
{
1643
if( soundLibrary != null )
1644
soundLibrary.loadSound( buffer, identifier );
1645
else
1646
errorMessage(
1647
"Variable 'soundLibrary' null in method 'CommandLoadSound'", 0 );
1648
}
1649
/**
1650
* Removes previously loaded sampled data from memory. This method is used
1651
* internally by SoundSystem for thread synchronization, and it can not be
1652
* called directly - please use the unloadSound() method instead.
1653
* @param filename Filename or string identifyer of sound to unload.
1654
*/
1655
private void CommandUnloadSound( String filename )
1656
{
1657
if( soundLibrary != null )
1658
soundLibrary.unloadSound( filename );
1659
else
1660
errorMessage(
1661
"Variable 'soundLibrary' null in method 'CommandLoadSound'", 0 );
1662
}
1663
/**
1664
* If the specified source is a streaming source or MIDI source, this method
1665
* queues up the next sound to play when the previous playback ends. This
1666
* method has no effect on non-streaming sources. This method is used
1667
* internally by SoundSystem for thread synchronization, and it can not be
1668
* called directly - please use the queueSound() method instead.
1669
* @param sourcename Source identifier.
1670
* @param filenameURL Filename/URL of the sound file to play next.
1671
*/
1672
private void CommandQueueSound( String sourcename,
1673
FilenameURL filenameURL )
1674
{
1675
if( soundLibrary != null )
1676
soundLibrary.queueSound( sourcename, filenameURL );
1677
else
1678
errorMessage(
1679
"Variable 'soundLibrary' null in method 'CommandQueueSound'", 0 );
1680
}
1681
/**
1682
* Removes the first occurrence of the specified filename/identifier from the
1683
* specified source's list of sounds to play when previous playback ends. This
1684
* method has no effect on non-streaming sources. This method is used
1685
* internally by SoundSystem for thread synchronization, and it can not be
1686
* called directly - please use the dequeueSound() method instead.
1687
* @param sourcename Source identifier.
1688
* @param filename Filename/identifier of the sound file to remove from the queue.
1689
*/
1690
private void CommandDequeueSound( String sourcename, String filename )
1691
{
1692
if( soundLibrary != null )
1693
soundLibrary.dequeueSound( sourcename, filename );
1694
else
1695
errorMessage(
1696
"Variable 'soundLibrary' null in method 'CommandDequeueSound'", 0 );
1697
}
1698
/**
1699
* Fades out the volume of whatever the specified source is currently playing,
1700
* then begins playing the specified file at the source's previously
1701
* assigned volume level. If the filenameURL parameter is null or empty, the
1702
* specified source will simply fade out and stop. The miliseconds parameter
1703
* must be non-negative or zero. This method will remove anything that is
1704
* currently in the specified source's list of queued sounds that would have
1705
* played next when the current sound finished playing. This method may only
1706
* be used for streaming and MIDI sources. This method is used
1707
* internally by SoundSystem for thread synchronization, and it can not be
1708
* called directly - please use the fadeOut() method instead.
1709
* @param sourcename Name of the source to fade out.
1710
* @param filenameURL Filename/URL of a sound file to play next, or null for none.
1711
* @param milis Number of miliseconds the fadeout should take.
1712
*/
1713
private void CommandFadeOut( String sourcename, FilenameURL filenameURL,
1714
long milis )
1715
{
1716
if( soundLibrary != null )
1717
soundLibrary.fadeOut( sourcename, filenameURL, milis );
1718
else
1719
errorMessage(
1720
"Variable 'soundLibrary' null in method 'CommandFadeOut'", 0 );
1721
}
1722
/**
1723
* Fades out the volume of whatever the specified source is currently playing,
1724
* then fades the volume back in playing the specified file. Final volume
1725
* after fade-in completes will be equal to the source's previously assigned
1726
* volume level. The filenameURL parameter may not be null or empty. The
1727
* miliseconds parameters must be non-negative or zero. This method will
1728
* remove anything that is currently in the specified source's list of queued
1729
* sounds that would have played next when the current sound finished playing.
1730
* This method may only be used for streaming and MIDI sources. This method is
1731
* used internally by SoundSystem for thread synchronization, and it can not be
1732
* called directly - please use the fadeOutIn() method instead.
1733
* @param sourcename Name of the source to fade out/in.
1734
* @param filenameURL Filename/URL of a sound file to play next, or null for none.
1735
* @param milisOut Number of miliseconds the fadeout should take.
1736
* @param milisIn Number of miliseconds the fadein should take.
1737
*/
1738
private void CommandFadeOutIn( String sourcename, FilenameURL filenameURL,
1739
long milisOut, long milisIn )
1740
{
1741
if( soundLibrary != null )
1742
soundLibrary.fadeOutIn( sourcename, filenameURL, milisOut,
1743
milisIn );
1744
else
1745
errorMessage(
1746
"Variable 'soundLibrary' null in method 'CommandFadeOutIn'", 0 );
1747
}
1748
/**
1749
* Makes sure the current volume levels of streaming sources and MIDI are
1750
* correct. This method is designed to help reduce the "jerky" fading behavior
1751
* that happens when using some library and codec pluggins (such as
1752
* LibraryJavaSound and CodecJOrbis). This method has no effect on normal
1753
* "non-streaming" sources. It would normally be called somewhere in the main
1754
* "game loop". IMPORTANT: To optimize frame-rates, do not call this method
1755
* for every frame. It is better to just call this method at some acceptable
1756
* "granularity" (play around with different granularities to find what sounds
1757
* acceptable for a particular situation). This method is used
1758
* internally by SoundSystem for thread synchronization, and it can not be
1759
* called directly - please use the checkFadeVolumes() method instead.
1760
*/
1761
private void CommandCheckFadeVolumes()
1762
{
1763
if( soundLibrary != null )
1764
soundLibrary.checkFadeVolumes();
1765
else
1766
errorMessage( "Variable 'soundLibrary' null in method " +
1767
"'CommandCheckFadeVolumes'", 0 );
1768
}
1769
/**
1770
* Loads a sound file into memory. This method is used internally by
1771
* SoundSystem for thread synchronization, and it can not be called directly -
1772
* please use the newSource() method instead.
1773
* @param priority Setting this to true will prevent other sounds from overriding this one.
1774
* @param toStream Whether or not to stream the source.
1775
* @param toLoop Whether or not to loop the source.
1776
* @param sourcename A unique identifier for the source.
1777
* @param filenameURL Filename/URL of the sound file to play at this source.
1778
* @param x X position for this source.
1779
* @param y Y position for this source.
1780
* @param z Z position for this source.
1781
* @param attModel Attenuation model to use.
1782
* @param distORroll Either the fading distance or rolloff factor, depending on the value of "attmodel".
1783
*/
1784
private void CommandNewSource( boolean priority, boolean toStream,
1785
boolean toLoop, String sourcename,
1786
FilenameURL filenameURL, float x,
1787
float y, float z, int attModel,
1788
float distORroll )
1789
{
1790
if( soundLibrary != null )
1791
{
1792
if( filenameURL.getFilename().matches(
1793
SoundSystemConfig.EXTENSION_MIDI )
1794
&& !SoundSystemConfig.midiCodec() )
1795
{
1796
soundLibrary.loadMidi( toLoop, sourcename, filenameURL );
1797
}
1798
else
1799
{
1800
soundLibrary.newSource( priority, toStream, toLoop, sourcename,
1801
filenameURL, x, y, z, attModel,
1802
distORroll );
1803
}
1804
}
1805
else
1806
errorMessage(
1807
"Variable 'soundLibrary' null in method 'CommandNewSource'", 0 );
1808
}
1809
/**
1810
* Opens a direct line for streaming audio data. This method is used
1811
* internally by SoundSystem, and it can not be called directly - please use
1812
* the rawDataStream() method instead.
1813
* @param audioFormat Format that the data will be in.
1814
* @param priority Setting this to true will prevent other sounds from overriding this one.
1815
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
1816
* @param x X position for this source.
1817
* @param y Y position for this source.
1818
* @param z Z position for this source.
1819
* @param attModel Attenuation model to use.
1820
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of "attmodel".
1821
*/
1822
private void CommandRawDataStream( AudioFormat audioFormat,
1823
boolean priority, String sourcename,
1824
float x, float y, float z,
1825
int attModel, float distOrRoll )
1826
{
1827
if( soundLibrary != null )
1828
soundLibrary.rawDataStream( audioFormat, priority, sourcename,
1829
x, y, z, attModel, distOrRoll );
1830
else
1831
errorMessage(
1832
"Variable 'soundLibrary' null in method 'CommandRawDataStream'", 0 );
1833
}
1834
/**
1835
* Creates a temporary source and either plays or streams it. After the source
1836
* finishes playing, it is removed. This method is used internally by
1837
* SoundSystem for thread synchronization, and it can not be called directly -
1838
* please use the quickPlay() method instead.
1839
* @param priority Setting this to true will prevent other sounds from overriding this one.
1840
* @param toStream Whether or not to stream the source.
1841
* @param toLoop Whether or not to loop the source.
1842
* @param sourcename A unique identifier for the source.
1843
* @param filenameURL Filename/URL of the sound file to play at this source.
1844
* @param x X position for this source.
1845
* @param y Y position for this source.
1846
* @param z Z position for this source.
1847
* @param attModel Attenuation model to use.
1848
* @param distORroll Either the fading distance or rolloff factor, depending on the value of "attmodel".
1849
* @param temporary Whether or not the source should be removed after it finishes playing.
1850
*/
1851
private void CommandQuickPlay( boolean priority, boolean toStream,
1852
boolean toLoop, String sourcename,
1853
FilenameURL filenameURL, float x, float y,
1854
float z, int attModel, float distORroll,
1855
boolean temporary )
1856
{
1857
if( soundLibrary != null )
1858
{
1859
if( filenameURL.getFilename().matches( SoundSystemConfig.EXTENSION_MIDI ) &&
1860
!SoundSystemConfig.midiCodec() )
1861
{
1862
soundLibrary.loadMidi( toLoop, sourcename, filenameURL );
1863
}
1864
else
1865
{
1866
soundLibrary.quickPlay( priority, toStream, toLoop, sourcename,
1867
filenameURL, x, y, z, attModel,
1868
distORroll, temporary );
1869
}
1870
}
1871
else
1872
errorMessage(
1873
"Variable 'soundLibrary' null in method 'CommandQuickPlay'", 0 );
1874
}
1875
/**
1876
* Moves a source to the specified coordinates. This method is used
1877
* internally by SoundSystem for thread synchronization, and it can not be
1878
* called directly - please use the setPosition() method instead.
1879
* @param sourcename Source to move.
1880
* @param x Destination X coordinate.
1881
* @param y Destination Y coordinate.
1882
* @param z Destination Z coordinate.
1883
*/
1884
private void CommandSetPosition( String sourcename, float x, float y,
1885
float z)
1886
{
1887
if( soundLibrary != null )
1888
soundLibrary.setPosition( sourcename, x, y, z );
1889
else
1890
errorMessage(
1891
"Variable 'soundLibrary' null in method 'CommandMoveSource'", 0 );
1892
}
1893
/**
1894
* Manually sets the specified source's volume. This method is used
1895
* internally by SoundSystem for thread synchronization, and it can not be
1896
* called directly - please use the setVolume() method instead.
1897
* @param sourcename Source to change the volume of.
1898
* @param value New volume, float value ( 0.0f - 1.0f ).
1899
*/
1900
private void CommandSetVolume( String sourcename, float value )
1901
{
1902
if( soundLibrary != null )
1903
soundLibrary.setVolume( sourcename, value );
1904
else
1905
errorMessage(
1906
"Variable 'soundLibrary' null in method 'CommandSetVolume'", 0 );
1907
}
1908
/**
1909
* Manually sets the specified source's pitch. This method is used
1910
* internally by SoundSystem for thread synchronization, and it can not be
1911
* called directly - please use the setPitch() method instead.
1912
* @param sourcename Source to change the pitch of.
1913
* @param value New pitch, float value ( 0.5f - 2.0f ).
1914
*/
1915
private void CommandSetPitch( String sourcename, float value )
1916
{
1917
if( soundLibrary != null )
1918
soundLibrary.setPitch( sourcename, value );
1919
else
1920
errorMessage(
1921
"Variable 'soundLibrary' null in method 'CommandSetPitch'", 0 );
1922
}
1923
/**
1924
* Set a source's priority factor. A priority source will not be overriden when
1925
* too many sources are playing at once. This method is used
1926
* internally by SoundSystem for thread synchronization, and it can not be
1927
* called directly - please use the setPriority() method instead.
1928
* @param sourcename Identifier for the source.
1929
* @param pri Setting this to true makes this source a priority source.
1930
*/
1931
private void CommandSetPriority( String sourcename, boolean pri )
1932
{
1933
if( soundLibrary != null )
1934
soundLibrary.setPriority( sourcename, pri );
1935
else
1936
errorMessage(
1937
"Variable 'soundLibrary' null in method 'CommandSetPriority'", 0 );
1938
}
1939
/**
1940
* Changes a source to looping or non-looping. This method is used
1941
* internally by SoundSystem for thread synchronization, and it can not be
1942
* called directly - please use the setLooping() method instead.
1943
* @param sourcename Identifier for the source.
1944
* @param lp This source should loop.
1945
*/
1946
private void CommandSetLooping( String sourcename, boolean lp )
1947
{
1948
if( soundLibrary != null )
1949
soundLibrary.setLooping( sourcename, lp );
1950
else
1951
errorMessage(
1952
"Variable 'soundLibrary' null in method 'CommandSetLooping'", 0 );
1953
}
1954
/**
1955
* Changes a source's attenuation model. This method is used
1956
* internally by SoundSystem for thread synchronization, and it can not be
1957
* called directly - please use the setAttenuation() method instead.
1958
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1959
* information about Attenuation.
1960
* @param sourcename Identifier for the source.
1961
* @param model Attenuation model to use.
1962
*/
1963
private void CommandSetAttenuation( String sourcename, int model )
1964
{
1965
if( soundLibrary != null )
1966
soundLibrary.setAttenuation( sourcename, model );
1967
else
1968
errorMessage(
1969
"Variable 'soundLibrary' null in method 'CommandSetAttenuation'",
1970
0 );
1971
}
1972
/**
1973
* Changes a source's fade distance or rolloff factor.
1974
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1975
* information about fade distance and rolloff.
1976
* @param sourcename Identifier for the source.
1977
* @param dr Either the fading distance or rolloff factor, depending on the attenuation model used.
1978
*/
1979
private void CommandSetDistOrRoll( String sourcename, float dr )
1980
{
1981
if( soundLibrary != null )
1982
soundLibrary.setDistOrRoll( sourcename, dr );
1983
else
1984
errorMessage(
1985
"Variable 'soundLibrary' null in method 'CommandSetDistOrRoll'",
1986
0 );
1987
}
1988
/**
1989
* Changes the Doppler factor. This method is used internally by SoundSystem
1990
* for thread synchronization, and it can not be called directly - please use
1991
* the setDopplerFactor() method instead.
1992
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
1993
* information about Doppler effect.
1994
* @param dopplerFactor New Doppler factor, for determining Doppler effect scale.
1995
*/
1996
private void CommandChangeDopplerFactor( float dopplerFactor )
1997
{
1998
if( soundLibrary != null )
1999
{
2000
SoundSystemConfig.setDopplerFactor( dopplerFactor );
2001
soundLibrary.dopplerChanged();
2002
}
2003
else
2004
errorMessage(
2005
"Variable 'soundLibrary' null in method 'CommandSetDopplerFactor'",
2006
0 );
2007
}
2008
/**
2009
* Changes the Doppler velocity. This method is used internally by SoundSystem
2010
* for thread synchronization, and it can not be called directly - please use
2011
* the setDopplerVelocity() method instead.
2012
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
2013
* information about Doppler effect.
2014
* @param dopplerVelocity New Doppler velocity, for use in Doppler effect.
2015
*/
2016
private void CommandChangeDopplerVelocity( float dopplerVelocity )
2017
{
2018
if( soundLibrary != null )
2019
{
2020
SoundSystemConfig.setDopplerVelocity( dopplerVelocity );
2021
soundLibrary.dopplerChanged();
2022
}
2023
else
2024
errorMessage(
2025
"Variable 'soundLibrary' null in method 'CommandSetDopplerFactor'",
2026
0 );
2027
}
2028
/**
2029
* Changes a source's velocity, for use in Doppler effect. This method is used
2030
* internally by SoundSystem for thread synchronization, and it can not be
2031
* called directly - please use the setVelocity() method instead.
2032
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
2033
* information about Doppler effect.
2034
* @param sourcename Identifier for the source.
2035
* @param x Source's velocity along the world x-axis.
2036
* @param y Source's velocity along the world y-axis.
2037
* @param z Source's velocity along the world z-axis.
2038
*/
2039
private void CommandSetVelocity( String sourcename, float x, float y, float z )
2040
{
2041
if( soundLibrary != null )
2042
soundLibrary.setVelocity( sourcename, x, y, z );
2043
else
2044
errorMessage(
2045
"Variable 'soundLibrary' null in method 'CommandVelocity'",
2046
0 );
2047
}
2048
/**
2049
* Changes the listener's velocity, for use in Doppler effect. This method is
2050
* used internally by SoundSystem for thread synchronization, and it can not be
2051
* called directly - please use the setListenerVelocity() method instead.
2052
* See {@link paulscode.sound.SoundSystemConfig SoundSystemConfig} for more
2053
* information about Doppler effect.
2054
* @param x Velocity along the world x-axis.
2055
* @param y Velocity along the world y-axis.
2056
* @param z Velocity along the world z-axis.
2057
*/
2058
private void CommandSetListenerVelocity( float x, float y, float z )
2059
{
2060
if( soundLibrary != null )
2061
soundLibrary.setListenerVelocity( x, y, z );
2062
else
2063
errorMessage(
2064
"Variable 'soundLibrary' null in method 'CommandSetListenerVelocity'",
2065
0 );
2066
}
2067
/**
2068
* Plays the specified source. This method is used
2069
* internally by SoundSystem for thread synchronization, and it can not be
2070
* called directly - please use the play() method instead.
2071
* @param sourcename Identifier for the source.
2072
*/
2073
private void CommandPlay( String sourcename )
2074
{
2075
if( soundLibrary != null )
2076
soundLibrary.play( sourcename );
2077
else
2078
errorMessage(
2079
"Variable 'soundLibrary' null in method 'CommandPlay'", 0 );
2080
}
2081
/**
2082
* Feeds raw data through the specified source. The source must be a
2083
* streaming source and it can not be already associated with a file or URL to
2084
* stream from. This method is used internally by SoundSystem for thread
2085
* synchronization, and it can not be called directly - please use the
2086
* feedRawAudioData() method instead.
2087
* @param sourcename Name of the streaming source to play from.
2088
* @param buffer Byte buffer containing raw audio data to stream.
2089
*/
2090
private void CommandFeedRawAudioData( String sourcename, byte[] buffer )
2091
{
2092
if( soundLibrary != null )
2093
soundLibrary.feedRawAudioData( sourcename, buffer );
2094
else
2095
errorMessage(
2096
"Variable 'soundLibrary' null in method 'CommandFeedRawAudioData'", 0 );
2097
}
2098
/**
2099
* Pauses the specified source. This method is used
2100
* internally by SoundSystem for thread synchronization, and it can not be
2101
* called directly - please use the pause() method instead.
2102
* @param sourcename Identifier for the source.
2103
*/
2104
private void CommandPause( String sourcename )
2105
{
2106
if( soundLibrary != null )
2107
soundLibrary.pause( sourcename );
2108
else
2109
errorMessage(
2110
"Variable 'soundLibrary' null in method 'CommandPause'", 0 );
2111
}
2112
/**
2113
* Stops the specified source. This method is used
2114
* internally by SoundSystem for thread synchronization, and it can not be
2115
* called directly - please use the stop() method instead.
2116
* @param sourcename Identifier for the source.
2117
*/
2118
private void CommandStop( String sourcename )
2119
{
2120
if( soundLibrary != null )
2121
soundLibrary.stop( sourcename );
2122
else
2123
errorMessage(
2124
"Variable 'soundLibrary' null in method 'CommandStop'", 0 );
2125
}
2126
/**
2127
* Rewinds the specified source. This method is used
2128
* internally by SoundSystem for thread synchronization, and it can not be
2129
* called directly - please use the rewind() method instead.
2130
* @param sourcename Identifier for the source.
2131
*/
2132
private void CommandRewind( String sourcename )
2133
{
2134
if( soundLibrary != null )
2135
soundLibrary.rewind( sourcename );
2136
else
2137
errorMessage(
2138
"Variable 'soundLibrary' null in method 'CommandRewind'", 0 );
2139
}
2140
/**
2141
* Flushes all previously queued audio data from a streaming source. This
2142
* method is used internally by SoundSystem for thread synchronization, and it
2143
* can not be called directly - please use the flush() method instead.
2144
* @param sourcename Identifier for the source.
2145
*/
2146
private void CommandFlush( String sourcename )
2147
{
2148
if( soundLibrary != null )
2149
soundLibrary.flush( sourcename );
2150
else
2151
errorMessage(
2152
"Variable 'soundLibrary' null in method 'CommandFlush'", 0 );
2153
}
2154
/**
2155
* Sets a flag for a source indicating whether it should be used or if it
2156
* should be removed after it finishes playing. One possible use for this
2157
* method is to make temporary sources that were created with quickPlay()
2158
* permanant. Another use could be to have a source automatically removed
2159
* after it finishes playing. NOTE: Setting a source to inactive does not stop
2160
* it, and setting a source to active does not play it. It is also important
2161
* to note that a looping inactive source will not be removed as long as
2162
* it keeps playing. This method is used
2163
* internally by SoundSystem for thread synchronization, and it can not be
2164
* called directly - please use the setTemporary() method instead.
2165
* @param sourcename Identifier for the source.
2166
* @param temporary True or False.
2167
*/
2168
private void CommandSetTemporary( String sourcename, boolean temporary )
2169
{
2170
if( soundLibrary != null )
2171
soundLibrary.setTemporary( sourcename, temporary );
2172
else
2173
errorMessage(
2174
"Variable 'soundLibrary' null in method 'CommandSetActive'", 0 );
2175
}
2176
/**
2177
* Removes the specified source and clears up any memory it used. This method
2178
* is used internally by SoundSystem for thread synchronization, and it can not
2179
* be called directly - please use the removeSource() method instead.
2180
* @param sourcename Identifier for the source.
2181
*/
2182
private void CommandRemoveSource( String sourcename )
2183
{
2184
if( soundLibrary != null )
2185
soundLibrary.removeSource( sourcename );
2186
else
2187
errorMessage(
2188
"Variable 'soundLibrary' null in method 'CommandRemoveSource'", 0 );
2189
}
2190
/**
2191
* Moves the listener relative to the current location. This method is used
2192
* internally by SoundSystem for thread synchronization, and it can not be
2193
* called directly - please use the moveListener() method instead.
2194
* @param x X offset.
2195
* @param y Y offset.
2196
* @param z Z offset.
2197
*/
2198
private void CommandMoveListener( float x, float y, float z )
2199
{
2200
if( soundLibrary != null )
2201
soundLibrary.moveListener( x, y, z );
2202
else
2203
errorMessage(
2204
"Variable 'soundLibrary' null in method 'CommandMoveListener'", 0 );
2205
}
2206
/**
2207
* Moves the listener to the specified location. This method is used
2208
* internally by SoundSystem for thread synchronization, and it can not be
2209
* called directly - please use the setListenerPosition() method instead.
2210
* @param x Destination X coordinate.
2211
* @param y Destination Y coordinate.
2212
* @param z Destination Z coordinate.
2213
*/
2214
private void CommandSetListenerPosition( float x, float y, float z )
2215
{
2216
if( soundLibrary != null )
2217
soundLibrary.setListenerPosition( x, y, z );
2218
else
2219
errorMessage(
2220
"Variable 'soundLibrary' null in method 'CommandSetListenerPosition'",
2221
0 );
2222
}
2223
/**
2224
* Turns the listener counterclockwise by "angle" radians around the y-axis,
2225
* relative to the current angle. This method is used
2226
* internally by SoundSystem for thread synchronization, and it can not be
2227
* called directly - please use the turnListener() method instead.
2228
* @param angle radian offset.
2229
*/
2230
private void CommandTurnListener( float angle )
2231
{
2232
if( soundLibrary != null )
2233
soundLibrary.turnListener( angle );
2234
else
2235
errorMessage(
2236
"Variable 'soundLibrary' null in method 'CommandTurnListener'",
2237
0 );
2238
}
2239
/**
2240
* Sets the listener's angle in radians around the y-axis. This method is used
2241
* internally by SoundSystem for thread synchronization, and it can not be
2242
* called directly - please use the setListenerAngle() method instead.
2243
* @param angle radians.
2244
*/
2245
private void CommandSetListenerAngle( float angle )
2246
{
2247
if( soundLibrary != null )
2248
soundLibrary.setListenerAngle( angle );
2249
else
2250
errorMessage(
2251
"Variable 'soundLibrary' null in method 'CommandSetListenerAngle'",
2252
0 );
2253
}
2254
/**
2255
* Sets the listener's orientation. This method is used
2256
* internally by SoundSystem for thread synchronization, and it can not be
2257
* called directly - please use the setListenerOrientation() method instead.
2258
* @param lookX X coordinate of the (normalized) look-at vector.
2259
* @param lookY Y coordinate of the (normalized) look-at vector.
2260
* @param lookZ Z coordinate of the (normalized) look-at vector.
2261
* @param upX X coordinate of the (normalized) look-at vector.
2262
* @param upY Y coordinate of the (normalized) look-at vector.
2263
* @param upZ Z coordinate of the (normalized) look-at vector.
2264
*/
2265
private void CommandSetListenerOrientation( float lookX, float lookY,
2266
float lookZ, float upX,
2267
float upY, float upZ )
2268
{
2269
if( soundLibrary != null )
2270
soundLibrary.setListenerOrientation( lookX, lookY, lookZ, upX, upY,
2271
upZ );
2272
else
2273
errorMessage(
2274
"Variable 'soundLibrary' null in method 'CommandSetListenerOrientation'",
2275
0 );
2276
}
2277
/**
2278
* Culls the specified source. A culled source can not be played until it has
2279
* been activated again. This method is used
2280
* internally by SoundSystem for thread synchronization, and it can not be
2281
* called directly - please use the cull() method instead.
2282
* @param sourcename Identifier for the source.
2283
*/
2284
private void CommandCull( String sourcename )
2285
{
2286
if( soundLibrary != null )
2287
soundLibrary.cull( sourcename );
2288
else
2289
errorMessage(
2290
"Variable 'soundLibrary' null in method 'CommandCull'", 0 );
2291
}
2292
/**
2293
* Activates a previously culled source, so it can be played again. This
2294
* method is used internally by SoundSystem for thread synchronization, and it
2295
* can not be called directly - please use the activate() method instead.
2296
* @param sourcename Identifier for the source.
2297
*/
2298
private void CommandActivate( String sourcename )
2299
{
2300
if( soundLibrary != null )
2301
soundLibrary.activate( sourcename );
2302
else
2303
errorMessage(
2304
"Variable 'soundLibrary' null in method 'CommandActivate'",
2305
0 );
2306
}
2307
/**
2308
* Sets the overall volume, affecting all sources. This method is used
2309
* internally by SoundSystem for thread synchronization, and it can not be
2310
* called directly - please use the setMasterVolume() method instead.
2311
* @param value New volume, float value ( 0.0f - 1.0f ).
2312
*/
2313
private void CommandSetMasterVolume( float value )
2314
{
2315
if( soundLibrary != null )
2316
soundLibrary.setMasterVolume( value );
2317
else
2318
errorMessage(
2319
"Variable 'soundLibrary' null in method 'CommandSetMasterVolume'",
2320
0 );
2321
}
2322
2323
/**
2324
* This method can be overridden by extended classes to be used for source
2325
* management (culling and activating sources based on established rules). One
2326
* possible use for this method is sorting sources by distance, culling the
2327
* furthest, and activating the closest.
2328
* This method is automatically called on the CommandThread before processing
2329
* queued commands, so you do not need to call it anywhere else. Note: use
2330
* methods cull() and activate() here, NOT CommandCull() and CommandActivate()
2331
* (thread safety issue).
2332
* IMPORTANT: Always use synchronized( SoundSystemConfig.THREAD_SYNC ) when
2333
* manually manipulating sources from outside the Command Thread!
2334
*/
2335
protected void ManageSources()
2336
{
2337
// OVERRIDDEN METHODS MUST USE THIS:
2338
2339
/*******
2340
synchronized( SoundSystemConfig.THREAD_SYNC )
2341
{
2342
// TODO: Sort the sources, cull and activate, etc.
2343
}
2344
********/
2345
}
2346
2347
/**
2348
* Queues a command.
2349
* If newCommand is null, all commands are dequeued and executed.
2350
* This is automatically used by the sound system, so it is not
2351
* likely that a user would ever need to use this method.
2352
* See {@link paulscode.sound.CommandObject CommandObject} for more information
2353
* about commands.
2354
* @param newCommand Command to queue, or null to execute commands.
2355
* @return True if more commands exist, false if queue is empty.
2356
*/
2357
public boolean CommandQueue( CommandObject newCommand )
2358
{
2359
synchronized( SoundSystemConfig.THREAD_SYNC )
2360
{
2361
if( newCommand == null )
2362
{
2363
// New command is null - that means execute all queued commands.
2364
boolean activations = false;
2365
CommandObject commandObject;
2366
2367
// Loop through the command queue:
2368
while( commandQueue != null && commandQueue.size() > 0 )
2369
{
2370
// Grab the oldest command in the queue:
2371
commandObject = commandQueue.remove( 0 );
2372
// See what it is, and execute the proper Command method:
2373
if( commandObject != null )
2374
{
2375
switch( commandObject.Command )
2376
{
2377
case CommandObject.INITIALIZE:
2378
CommandInitialize();
2379
break;
2380
case CommandObject.LOAD_SOUND:
2381
CommandLoadSound(
2382
(FilenameURL) commandObject.objectArgs[0] );
2383
break;
2384
case CommandObject.LOAD_DATA:
2385
CommandLoadSound(
2386
(SoundBuffer) commandObject.objectArgs[0],
2387
commandObject.stringArgs[0] );
2388
break;
2389
case CommandObject.UNLOAD_SOUND:
2390
CommandUnloadSound( commandObject.stringArgs[0] );
2391
break;
2392
case CommandObject.QUEUE_SOUND:
2393
CommandQueueSound( commandObject.stringArgs[0],
2394
(FilenameURL) commandObject.objectArgs[0] );
2395
break;
2396
case CommandObject.DEQUEUE_SOUND:
2397
CommandDequeueSound( commandObject.stringArgs[0],
2398
commandObject.stringArgs[1] );
2399
break;
2400
case CommandObject.FADE_OUT:
2401
CommandFadeOut( commandObject.stringArgs[0],
2402
(FilenameURL) commandObject.objectArgs[0],
2403
commandObject.longArgs[0] );
2404
break;
2405
case CommandObject.FADE_OUT_IN:
2406
CommandFadeOutIn( commandObject.stringArgs[0],
2407
(FilenameURL) commandObject.objectArgs[0],
2408
commandObject.longArgs[0],
2409
commandObject.longArgs[1] );
2410
break;
2411
case CommandObject.CHECK_FADE_VOLUMES:
2412
CommandCheckFadeVolumes();
2413
break;
2414
case CommandObject.NEW_SOURCE:
2415
CommandNewSource( commandObject.boolArgs[0],
2416
commandObject.boolArgs[1],
2417
commandObject.boolArgs[2],
2418
commandObject.stringArgs[0],
2419
(FilenameURL) commandObject.objectArgs[0],
2420
commandObject.floatArgs[0],
2421
commandObject.floatArgs[1],
2422
commandObject.floatArgs[2],
2423
commandObject.intArgs[0],
2424
commandObject.floatArgs[3] );
2425
break;
2426
case CommandObject.RAW_DATA_STREAM:
2427
CommandRawDataStream(
2428
(AudioFormat) commandObject.objectArgs[0],
2429
commandObject.boolArgs[0],
2430
commandObject.stringArgs[0],
2431
commandObject.floatArgs[0],
2432
commandObject.floatArgs[1],
2433
commandObject.floatArgs[2],
2434
commandObject.intArgs[0],
2435
commandObject.floatArgs[3] );
2436
break;
2437
case CommandObject.QUICK_PLAY:
2438
CommandQuickPlay( commandObject.boolArgs[0],
2439
commandObject.boolArgs[1],
2440
commandObject.boolArgs[2],
2441
commandObject.stringArgs[0],
2442
(FilenameURL) commandObject.objectArgs[0],
2443
commandObject.floatArgs[0],
2444
commandObject.floatArgs[1],
2445
commandObject.floatArgs[2],
2446
commandObject.intArgs[0],
2447
commandObject.floatArgs[3],
2448
commandObject.boolArgs[3] );
2449
break;
2450
case CommandObject.SET_POSITION:
2451
CommandSetPosition( commandObject.stringArgs[0],
2452
commandObject.floatArgs[0],
2453
commandObject.floatArgs[1],
2454
commandObject.floatArgs[2] );
2455
break;
2456
case CommandObject.SET_VOLUME:
2457
CommandSetVolume( commandObject.stringArgs[0],
2458
commandObject.floatArgs[0] );
2459
break;
2460
case CommandObject.SET_PITCH:
2461
CommandSetPitch( commandObject.stringArgs[0],
2462
commandObject.floatArgs[0] );
2463
break;
2464
case CommandObject.SET_PRIORITY:
2465
CommandSetPriority( commandObject.stringArgs[0],
2466
commandObject.boolArgs[0] );
2467
break;
2468
case CommandObject.SET_LOOPING:
2469
CommandSetLooping( commandObject.stringArgs[0],
2470
commandObject.boolArgs[0] );
2471
break;
2472
case CommandObject.SET_ATTENUATION:
2473
CommandSetAttenuation( commandObject.stringArgs[0],
2474
commandObject.intArgs[0] );
2475
break;
2476
case CommandObject.SET_DIST_OR_ROLL:
2477
CommandSetDistOrRoll( commandObject.stringArgs[0],
2478
commandObject.floatArgs[0] );
2479
break;
2480
case CommandObject.CHANGE_DOPPLER_FACTOR:
2481
CommandChangeDopplerFactor(
2482
commandObject.floatArgs[0] );
2483
break;
2484
case CommandObject.CHANGE_DOPPLER_VELOCITY:
2485
CommandChangeDopplerVelocity(
2486
commandObject.floatArgs[0] );
2487
break;
2488
case CommandObject.SET_VELOCITY:
2489
CommandSetVelocity( commandObject.stringArgs[0],
2490
commandObject.floatArgs[0],
2491
commandObject.floatArgs[1],
2492
commandObject.floatArgs[2]
2493
);
2494
break;
2495
case CommandObject.SET_LISTENER_VELOCITY:
2496
CommandSetListenerVelocity(
2497
commandObject.floatArgs[0],
2498
commandObject.floatArgs[1],
2499
commandObject.floatArgs[2]
2500
);
2501
break;
2502
// Methods related to playing sources must be processed
2503
// after cull/activate commands in order for source
2504
// management to work properly, so save them for
2505
// later:
2506
//------------------------------------------------------
2507
case CommandObject.PLAY:
2508
sourcePlayList.add( commandObject );
2509
break;
2510
case CommandObject.FEED_RAW_AUDIO_DATA:
2511
sourcePlayList.add( commandObject );
2512
break;
2513
//------------------------------------------------------
2514
case CommandObject.PAUSE:
2515
CommandPause( commandObject.stringArgs[0] );
2516
break;
2517
case CommandObject.STOP:
2518
CommandStop( commandObject.stringArgs[0] );
2519
break;
2520
case CommandObject.REWIND:
2521
CommandRewind( commandObject.stringArgs[0] );
2522
break;
2523
case CommandObject.FLUSH:
2524
CommandFlush( commandObject.stringArgs[0] );
2525
break;
2526
case CommandObject.CULL:
2527
CommandCull( commandObject.stringArgs[0] );
2528
break;
2529
case CommandObject.ACTIVATE:
2530
activations = true;
2531
CommandActivate( commandObject.stringArgs[0] );
2532
break;
2533
case CommandObject.SET_TEMPORARY:
2534
CommandSetTemporary( commandObject.stringArgs[0],
2535
commandObject.boolArgs[0] );
2536
break;
2537
case CommandObject.REMOVE_SOURCE:
2538
CommandRemoveSource( commandObject.stringArgs[0] );
2539
break;
2540
case CommandObject.MOVE_LISTENER:
2541
CommandMoveListener( commandObject.floatArgs[0],
2542
commandObject.floatArgs[1],
2543
commandObject.floatArgs[2]);
2544
break;
2545
case CommandObject.SET_LISTENER_POSITION:
2546
CommandSetListenerPosition(
2547
commandObject.floatArgs[0],
2548
commandObject.floatArgs[1],
2549
commandObject.floatArgs[2]);
2550
break;
2551
case CommandObject.TURN_LISTENER:
2552
CommandTurnListener( commandObject.floatArgs[0] );
2553
break;
2554
case CommandObject.SET_LISTENER_ANGLE:
2555
CommandSetListenerAngle(
2556
commandObject.floatArgs[0]);
2557
break;
2558
case CommandObject.SET_LISTENER_ORIENTATION:
2559
CommandSetListenerOrientation(
2560
commandObject.floatArgs[0],
2561
commandObject.floatArgs[1],
2562
commandObject.floatArgs[2],
2563
commandObject.floatArgs[3],
2564
commandObject.floatArgs[4],
2565
commandObject.floatArgs[5]);
2566
break;
2567
case CommandObject.SET_MASTER_VOLUME:
2568
CommandSetMasterVolume(
2569
commandObject.floatArgs[0] );
2570
break;
2571
case CommandObject.NEW_LIBRARY:
2572
CommandNewLibrary( commandObject.classArgs[0] );
2573
break;
2574
// If we don't recognize the command, just skip it:
2575
default:
2576
break;
2577
}
2578
}
2579
}
2580
2581
// If any sources were reactivated, check if they need to be
2582
// replayed:
2583
if( activations )
2584
soundLibrary.replaySources();
2585
2586
// Now that we have the correct sources culled and activated, we
2587
// can start playing sources. Loop through the playlist and
2588
// execute the commands:
2589
while( sourcePlayList != null && sourcePlayList.size() > 0 )
2590
{
2591
// Grab the oldest command in the queue:
2592
commandObject = sourcePlayList.remove( 0 );
2593
if( commandObject != null )
2594
{
2595
// See what it is, and execute the proper Command method:
2596
switch( commandObject.Command )
2597
{
2598
case CommandObject.PLAY:
2599
CommandPlay( commandObject.stringArgs[0] );
2600
break;
2601
case CommandObject.FEED_RAW_AUDIO_DATA:
2602
CommandFeedRawAudioData(
2603
commandObject.stringArgs[0],
2604
commandObject.buffer );
2605
break;
2606
}
2607
}
2608
}
2609
2610
return( commandQueue != null && commandQueue.size() > 0 );
2611
}
2612
else
2613
{
2614
// make sure the commandQueue exists:
2615
if( commandQueue == null )
2616
return false;
2617
// queue a new command
2618
commandQueue.add( newCommand );
2619
// Of course there is something in the list now, since we just
2620
// added it:
2621
return true;
2622
}
2623
}
2624
}
2625
2626
/**
2627
* Searches for and removes any temporary sources that have finished
2628
* playing. This method is used internally by SoundSystem, and it is
2629
* unlikely that the user will ever need to use it.
2630
*/
2631
public void removeTemporarySources()
2632
{
2633
synchronized( SoundSystemConfig.THREAD_SYNC )
2634
{
2635
if( soundLibrary != null )
2636
soundLibrary.removeTemporarySources();
2637
}
2638
}
2639
2640
/**
2641
* Returns true if the specified source is playing.
2642
* @param sourcename Unique identifier of the source to check.
2643
* @return True or false.
2644
*/
2645
public boolean playing( String sourcename )
2646
{
2647
synchronized( SoundSystemConfig.THREAD_SYNC )
2648
{
2649
if( soundLibrary == null )
2650
return false;
2651
2652
Source src = soundLibrary.getSources().get( sourcename );
2653
2654
if( src == null )
2655
return false;
2656
2657
return src.playing();
2658
}
2659
}
2660
2661
/**
2662
* Returns true if anything is currently playing.
2663
* @return True or false.
2664
*/
2665
public boolean playing()
2666
{
2667
synchronized( SoundSystemConfig.THREAD_SYNC )
2668
{
2669
if( soundLibrary == null )
2670
return false;
2671
2672
HashMap<String, Source> sourceMap = soundLibrary.getSources();
2673
if( sourceMap == null )
2674
return false;
2675
2676
Set<String> keys = sourceMap.keySet();
2677
Iterator<String> iter = keys.iterator();
2678
String sourcename;
2679
Source source;
2680
2681
while( iter.hasNext() )
2682
{
2683
sourcename = iter.next();
2684
source = sourceMap.get( sourcename );
2685
if( source != null )
2686
if( source.playing() )
2687
return true;
2688
}
2689
2690
return false;
2691
}
2692
}
2693
2694
/**
2695
* Copies and returns the peripheral information from a map of sources. This
2696
* method is used internally by SoundSystem, and it is unlikely that the user
2697
* will ever need to use it.
2698
* @param sourceMap Sources to copy.
2699
* @return New map of sources.
2700
*/
2701
private HashMap<String, Source> copySources( HashMap<String,
2702
Source> sourceMap )
2703
{
2704
Set<String> keys = sourceMap.keySet();
2705
Iterator<String> iter = keys.iterator();
2706
String sourcename;
2707
Source source;
2708
2709
// New map of generic source data:
2710
HashMap<String, Source> returnMap = new HashMap<String, Source>();
2711
2712
2713
// loop through and store information from all the sources:
2714
while( iter.hasNext() )
2715
{
2716
sourcename = iter.next();
2717
source = sourceMap.get( sourcename );
2718
if( source != null )
2719
returnMap.put( sourcename, new Source( source, null ) );
2720
}
2721
return returnMap;
2722
}
2723
2724
/**
2725
* Checks if the specified library type is compatible.
2726
* @param libraryClass Libary type to check.
2727
* @return True or false.
2728
*/
2729
public static boolean libraryCompatible( Class libraryClass )
2730
{
2731
// create the message logger:
2732
SoundSystemLogger logger = SoundSystemConfig.getLogger();
2733
// if the user didn't create one, then do it now:
2734
if( logger == null )
2735
{
2736
logger = new SoundSystemLogger();
2737
SoundSystemConfig.setLogger( logger );
2738
}
2739
logger.message( "", 0 );
2740
logger.message( "Checking if " +
2741
SoundSystemConfig.getLibraryTitle( libraryClass ) +
2742
" is compatible...", 0 );
2743
2744
boolean comp = SoundSystemConfig.libraryCompatible( libraryClass );
2745
2746
if( comp )
2747
logger.message( "...yes", 1 );
2748
else
2749
logger.message( "...no", 1 );
2750
2751
return comp;
2752
}
2753
2754
/**
2755
* Returns the currently loaded library, or -1 if none.
2756
* @return Global library identifier
2757
*/
2758
public static Class currentLibrary()
2759
{
2760
return( currentLibrary( GET, null ) );
2761
}
2762
2763
/**
2764
* Returns false if a sound library is busy initializing.
2765
* @return True or false.
2766
*/
2767
public static boolean initialized()
2768
{
2769
return( initialized( GET, XXX ) );
2770
}
2771
2772
/**
2773
* Returns the last SoundSystemException thrown, or null if none.
2774
* @return The last exception.
2775
*/
2776
public static SoundSystemException getLastException()
2777
{
2778
return( lastException( GET, null ) );
2779
}
2780
2781
/**
2782
* Stores a SoundSystemException which can be retreived later with the
2783
* 'getLastException' method.
2784
* @param e Exception to store.
2785
*/
2786
public static void setException( SoundSystemException e )
2787
{
2788
lastException( SET, e );
2789
}
2790
2791
/**
2792
* Sets or returns the value of boolean 'initialized'.
2793
* @param action Action to perform (GET or SET).
2794
* @param value New value if action is SET, otherwise XXX.
2795
* @return value of boolean 'initialized'.
2796
*/
2797
private static boolean initialized( boolean action, boolean value )
2798
{
2799
synchronized( SoundSystemConfig.THREAD_SYNC )
2800
{
2801
if( action == SET )
2802
initialized = value;
2803
return initialized;
2804
}
2805
}
2806
2807
/**
2808
* Sets or returns the value of boolean 'initialized'.
2809
* @param action Action to perform (GET or SET).
2810
* @param value New value if action is SET, otherwise XXX.
2811
* @return value of boolean 'initialized'.
2812
*/
2813
private static Class currentLibrary( boolean action,
2814
Class value )
2815
{
2816
synchronized( SoundSystemConfig.THREAD_SYNC )
2817
{
2818
if( action == SET )
2819
currentLibrary = value;
2820
return currentLibrary;
2821
}
2822
}
2823
2824
/**
2825
* Sets or returns the error code for the last error that occurred. If no
2826
* errors have occurred, returns SoundSystem.ERROR_NONE
2827
* @param action Action to perform (GET or SET).
2828
* @param e New exception if action is SET, otherwise XXX.
2829
* @return Last SoundSystemException thrown.
2830
*/
2831
private static SoundSystemException lastException( boolean action,
2832
SoundSystemException e )
2833
{
2834
synchronized( SoundSystemConfig.THREAD_SYNC )
2835
{
2836
if( action == SET )
2837
lastException = e;
2838
return lastException;
2839
}
2840
}
2841
2842
/**
2843
* Sleeps for the specified number of milliseconds.
2844
*/
2845
protected static void snooze( long milliseconds )
2846
{
2847
try
2848
{
2849
Thread.sleep( milliseconds );
2850
}
2851
catch( InterruptedException e ){}
2852
}
2853
2854
/**
2855
* Prints a message.
2856
* @param message Message to print.
2857
* @param indent Number of tabs to indent the message.
2858
*/
2859
protected void message( String message, int indent )
2860
{
2861
logger.message( message, indent );
2862
}
2863
2864
/**
2865
* Prints an important message.
2866
* @param message Message to print.
2867
* @param indent Number of tabs to indent the message.
2868
*/
2869
protected void importantMessage( String message, int indent )
2870
{
2871
logger.importantMessage( message, indent );
2872
}
2873
2874
/**
2875
* Prints the specified message if error is true.
2876
* @param error True or False.
2877
* @param message Message to print if error is true.
2878
* @param indent Number of tabs to indent the message.
2879
* @return True if error is true.
2880
*/
2881
protected boolean errorCheck( boolean error, String message, int indent )
2882
{
2883
return logger.errorCheck( error, className, message, indent );
2884
}
2885
2886
/**
2887
* Prints an error message.
2888
* @param message Message to print.
2889
* @param indent Number of tabs to indent the message.
2890
*/
2891
protected void errorMessage( String message, int indent )
2892
{
2893
logger.errorMessage( className, message, indent );
2894
}
2895
}
2896
2897