Path: blob/main/src/lwjgl/java/paulscode/sound/StreamThread.java
8644 views
package paulscode.sound;12import java.util.LinkedList;3import java.util.List;4import java.util.ListIterator;56/**7* The StreamThread class is used to process all streaming sources. This8* thread starts out asleep, and it sleeps when all streaming sources are9* finished playing, so it is necessary to call interrupt() after adding new10* streaming sources to the list.11*<br><br>12*<b><i> SoundSystem License:</b></i><br><b><br>13* You are free to use this library for any purpose, commercial or otherwise.14* You may modify this library or source code, and distribute it any way you15* like, provided the following conditions are met:16*<br>17* 1) You may not falsely claim to be the author of this library or any18* unmodified portion of it.19*<br>20* 2) You may not copyright this library or a modified version of it and then21* sue me for copyright infringement.22*<br>23* 3) If you modify the source code, you must clearly document the changes24* made before redistributing the modified source code, so other users know25* it is not the original code.26*<br>27* 4) You are not required to give me credit for this library in any derived28* work, but if you do, you must also mention my website:29* http://www.paulscode.com30*<br>31* 5) I the author will not be responsible for any damages (physical,32* financial, or otherwise) caused by the use if this library or any part33* of it.34*<br>35* 6) I the author do not guarantee, warrant, or make any representations,36* either expressed or implied, regarding the use of this library or any37* part of it.38* <br><br>39* Author: Paul Lamb40* <br>41* http://www.paulscode.com42* </b>43*44*/45public class StreamThread extends SimpleThread46{47/**48* Processes status messages, warnings, and error messages.49*/50private SoundSystemLogger logger;5152/**53* List of sources that are currently streaming.54*/55private List<Source> streamingSources;5657/**58* Used to synchronize access to the streaming sources list.59*/60private final Object listLock = new Object();6162/**63* Constructor: Grabs a handle to the message logger and instantiates the64* streaming sources list.65*/66public StreamThread()67{68// grab a handle to the message logger:69logger = SoundSystemConfig.getLogger();7071streamingSources = new LinkedList<Source>();72}7374/**75* Removes all references to instantiated objects, and changes the thread's76* state to "not alive". Method alive() returns false when the cleanup()77* method has completed.78*/79@Override80protected void cleanup()81{82kill();83super.cleanup(); // Important!!84}8586/**87* The main loop for processing commands. The thread sleeps when it finishes88* processing commands, and it must be interrupted to process more.89*/90@Override91public void run()92{93ListIterator<Source> iter;94Source src;9596// Start out asleep:97snooze( 3600000 );9899while( !dying() )100{101while( !dying() && !streamingSources.isEmpty() )102{103// Make sure noone else is accessing the list of sources:104synchronized( listLock )105{106iter = streamingSources.listIterator();107while( !dying() && iter.hasNext() )108{109src = iter.next();110// If this is a removed source, we cleanup here and then let normal cleanup run - https://github.com/MinecraftForge/MinecraftForge/pull/4765111if (src!=null && src.removed)112{113src.cleanup();114src = null;115}116if( src == null )117{118iter.remove();119}120else if( src.stopped() )121{122if( !src.rawDataStream )123iter.remove();124}125else if( !src.active() )126{127if( src.toLoop || src.rawDataStream )128src.toPlay = true;129iter.remove();130}131else if( !src.paused() )132{133src.checkFadeOut();134if( (!src.stream()) && (!src.rawDataStream) )135{136if( src.channel == null137|| !src.channel.processBuffer() )138{139if( src.nextCodec == null )140{141src.readBuffersFromNextSoundInSequence();142}143/*144if( src.getSoundSequenceQueueSize() > 0 )145{146src.incrementSoundSequence();147}148149// check if this is a looping source150else*/ if( src.toLoop )151{152// wait for stream to finish playing153if( !src.playing() )154{155// Generate an EOS event:156SoundSystemConfig.notifyEOS(157src.sourcename,158src.getSoundSequenceQueueSize()159);160// Check if the source is currently161// in the process of fading out.162if( src.checkFadeOut() )163{164// Source is fading out.165// Keep looping until it166// finishes.167src.preLoad = true;168}169else170{171// Source is not fading out.172// If there is another sound in173// the sequence, switch to it174// before replaying.175src.incrementSoundSequence();176src.preLoad = true; // replay177}178}179}180else181{182// wait for stream to finish playing183if( !src.playing() )184{185// Generate an EOS event:186SoundSystemConfig.notifyEOS(187src.sourcename,188src.getSoundSequenceQueueSize()189);190// Check if the source is currently191// in the process of fading out192if( !src.checkFadeOut() )193{194// Source is not fading out.195// Play anything else that is196// in the sound sequence queue.197if(198src.incrementSoundSequence() )199src.preLoad = true;200else201iter.remove(); // finished202}203}204}205}206}207}208}209}210if( !dying() && !streamingSources.isEmpty() )211snooze( 20 ); // sleep a bit so we don't peg the cpu212}213if( !dying() && streamingSources.isEmpty() )214snooze( 3600000 ); // sleep until there is more to do.215}216217cleanup(); // Important!!218}219220/**221* Adds a new streaming source to the list. If another source in the list is222* already playing on the same channel, it is stopped and removed from the223* list.224* @param source New source to stream.225*/226public void watch( Source source )227{228// make sure the source exists:229if( source == null )230return;231232// make sure we aren't already watching this source:233if( streamingSources.contains( source ) )234return;235236ListIterator<Source> iter;237Source src;238239// Make sure noone else is accessing the list of sources:240synchronized( listLock )241{242// Any currently watched source which is null or playing on the243// same channel as the new source should be stopped and removed244// from the list.245iter = streamingSources.listIterator();246while( iter.hasNext() )247{248src = iter.next();249if( src == null )250{251iter.remove();252}253else if( source.channel == src.channel )254{255src.stop();256iter.remove();257}258}259260// Add the new source to the list:261streamingSources.add( source );262}263}264265/**266* Prints a message.267* @param message Message to print.268*/269private void message( String message )270{271logger.message( message, 0 );272}273274/**275* Prints an important message.276* @param message Message to print.277*/278private void importantMessage( String message )279{280logger.importantMessage( message, 0 );281}282283/**284* Prints the specified message if error is true.285* @param error True or False.286* @param message Message to print if error is true.287* @return True if error is true.288*/289private boolean errorCheck( boolean error, String message )290{291return logger.errorCheck( error, "StreamThread", message, 0 );292}293294/**295* Prints an error message.296* @param message Message to print.297*/298private void errorMessage( String message )299{300logger.errorMessage( "StreamThread", message, 0 );301}302}303304305