Mercurial > almixer_isolated
comparison ALmixer.c @ 44:56855942fdc6
Split off background thread (threads only) termination and creation into separate functions from Interruption handling to make it easier to avoid race condition bug with Apple rdar://10081775 w.r.t. setting the OpenAL context. New APIs to suspend and resume update threads. Interruption handling calls these automatically.
Also partially regressed simplification with regards to getting the current playing state in the main update loop.
author | Eric Wing <ewing@anscamobile.com> |
---|---|
date | Tue, 13 Sep 2011 18:03:21 -0700 |
parents | 05e5dc4817a4 |
children | 9b772c81b550 |
comparison
equal
deleted
inserted
replaced
42:05e5dc4817a4 | 44:56855942fdc6 |
---|---|
2818 */ | 2818 */ |
2819 alGetSourcei( | 2819 alGetSourcei( |
2820 ALmixer_Channel_List[channel].alsource, | 2820 ALmixer_Channel_List[channel].alsource, |
2821 AL_SOURCE_STATE, &state | 2821 AL_SOURCE_STATE, &state |
2822 ); | 2822 ); |
2823 if((error = alGetError()) != AL_NO_ERROR) | 2823 if((error = alGetError()) != AL_NO_ERROR) |
2824 { | 2824 { |
2825 fprintf(stderr, "29Testing error: %s\n", | 2825 fprintf(stderr, "Internal_PauseChannel specific channel error: %s\n", |
2826 alGetString(error)); | 2826 alGetString(error)); |
2827 } | 2827 } |
2828 if(AL_PLAYING == state) | 2828 if(AL_PLAYING == state) |
2829 { | 2829 { |
2830 /* Count the actual number of channels being paused */ | 2830 /* Count the actual number of channels being paused */ |
2831 counter++; | 2831 counter++; |
2832 | 2832 |
2901 */ | 2901 */ |
2902 alGetSourcei( | 2902 alGetSourcei( |
2903 ALmixer_Channel_List[i].alsource, | 2903 ALmixer_Channel_List[i].alsource, |
2904 AL_SOURCE_STATE, &state | 2904 AL_SOURCE_STATE, &state |
2905 ); | 2905 ); |
2906 if((error = alGetError()) != AL_NO_ERROR) | 2906 if((error = alGetError()) != AL_NO_ERROR) |
2907 { | 2907 { |
2908 fprintf(stderr, "30Testing error: %s\n", | 2908 fprintf(stderr, "Internal_PauseChannel all channels error: %s\n", |
2909 alGetString(error)); | 2909 alGetString(error)); |
2910 } | 2910 } |
2911 if(AL_PLAYING == state) | 2911 if(AL_PLAYING == state) |
2912 { | 2912 { |
2913 /* Count the actual number of channels being paused */ | 2913 /* Count the actual number of channels being paused */ |
2914 counter++; | 2914 counter++; |
2915 | 2915 |
5230 | 5230 |
5231 ALuint unqueued_buffer_id; | 5231 ALuint unqueued_buffer_id; |
5232 ALuint number_of_buffers_to_queue_this_pass = ALmixer_Channel_List[i].almixer_data->num_target_buffers_per_pass; | 5232 ALuint number_of_buffers_to_queue_this_pass = ALmixer_Channel_List[i].almixer_data->num_target_buffers_per_pass; |
5233 ALuint current_count_of_buffer_queue_passes = 0; | 5233 ALuint current_count_of_buffer_queue_passes = 0; |
5234 | 5234 |
5235 #if 0 | 5235 /* fprintf(stderr, "For Streamed\n"); */ |
5236 /********* Remove this **********/ | |
5237 fprintf(stderr, "For Streamed\n"); | |
5238 | 5236 |
5239 alGetSourcei( | 5237 alGetSourcei( |
5240 ALmixer_Channel_List[i].alsource, | 5238 ALmixer_Channel_List[i].alsource, |
5241 AL_SOURCE_STATE, &state | 5239 AL_SOURCE_STATE, &state |
5242 ); | 5240 ); |
5243 switch(state) { | 5241 #if 0 |
5242 /********* Remove this **********/ | |
5243 switch(state) | |
5244 { | |
5244 case AL_PLAYING: | 5245 case AL_PLAYING: |
5245 fprintf(stderr, "Channel '%d' is PLAYING\n", i); | 5246 fprintf(stderr, "Channel '%d' is PLAYING\n", i); |
5246 break; | 5247 break; |
5247 case AL_PAUSED: | 5248 case AL_PAUSED: |
5248 fprintf(stderr, "Channel '%d' is PAUSED\n",i); | 5249 fprintf(stderr, "Channel '%d' is PAUSED\n",i); |
7460 { | 7461 { |
7461 if((AL_TRUE == g_inInterruption) || (AL_FALSE == ALmixer_Initialized)) | 7462 if((AL_TRUE == g_inInterruption) || (AL_FALSE == ALmixer_Initialized)) |
7462 { | 7463 { |
7463 return; | 7464 return; |
7464 } | 7465 } |
7465 #ifdef ENABLE_ALMIXER_THREADS | 7466 |
7466 /* Kill bookkeeping thread to help minimize wasted CPU resources */ | 7467 ALmixer_SuspendUpdates(); |
7467 | 7468 |
7468 /* Is locking really necessary here? */ | |
7469 /* SDL_LockMutex(s_simpleLock); */ | |
7470 g_StreamThreadEnabled = AL_FALSE; | |
7471 /* SDL_UnlockMutex(s_simpleLock); */ | |
7472 | |
7473 SDL_WaitThread(Stream_Thread_global, NULL); | |
7474 Stream_Thread_global = NULL; | |
7475 | |
7476 #endif | |
7477 s_interruptionContext = alcGetCurrentContext(); | 7469 s_interruptionContext = alcGetCurrentContext(); |
7478 if(NULL != s_interruptionContext) | 7470 if(NULL != s_interruptionContext) |
7479 { | 7471 { |
7480 /* iOS alcSuspendContext is a no-op */ | 7472 /* iOS alcSuspendContext is a no-op */ |
7481 alcSuspendContext(s_interruptionContext); | 7473 alcSuspendContext(s_interruptionContext); |
7511 { | 7503 { |
7512 alcMakeContextCurrent(s_interruptionContext); | 7504 alcMakeContextCurrent(s_interruptionContext); |
7513 alcProcessContext(s_interruptionContext); | 7505 alcProcessContext(s_interruptionContext); |
7514 s_interruptionContext = NULL; | 7506 s_interruptionContext = NULL; |
7515 } | 7507 } |
7516 #ifdef ENABLE_ALMIXER_THREADS | 7508 |
7509 ALmixer_ResumeUpdates(); | |
7510 g_inInterruption = AL_FALSE; | |
7511 } | |
7512 | |
7513 | |
7514 ALboolean ALmixer_IsInInterruption() | |
7515 { | |
7516 if(AL_FALSE == ALmixer_Initialized) | |
7517 { | |
7518 return AL_FALSE; | |
7519 } | |
7520 return g_inInterruption; | |
7521 } | |
7522 | |
7523 void ALmixer_SuspendUpdates() | |
7524 { | |
7525 if(AL_TRUE == ALmixer_AreUpdatesSuspended()) | |
7526 { | |
7527 return; | |
7528 } | |
7529 #ifdef ENABLE_ALMIXER_THREADS | |
7530 /* Kill bookkeeping thread to help minimize wasted CPU resources */ | |
7531 | |
7532 /* Is locking really necessary here? */ | |
7533 /* SDL_LockMutex(s_simpleLock); */ | |
7534 g_StreamThreadEnabled = AL_FALSE; | |
7535 /* SDL_UnlockMutex(s_simpleLock); */ | |
7536 | |
7537 SDL_WaitThread(Stream_Thread_global, NULL); | |
7538 Stream_Thread_global = NULL; | |
7539 #endif | |
7540 } | |
7541 | |
7542 void ALmixer_ResumeUpdates() | |
7543 { | |
7544 if(AL_FALSE == ALmixer_AreUpdatesSuspended()) | |
7545 { | |
7546 return; | |
7547 } | |
7548 | |
7549 #ifdef ENABLE_ALMIXER_THREADS | |
7550 /* This must be set before the thread is created to prevent the thread from exiting. */ | |
7517 g_StreamThreadEnabled = AL_TRUE; | 7551 g_StreamThreadEnabled = AL_TRUE; |
7518 | 7552 |
7519 Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL); | 7553 Stream_Thread_global = SDL_CreateThread(Stream_Data_Thread_Callback, NULL); |
7520 if(NULL == Stream_Thread_global) | 7554 if(NULL == Stream_Thread_global) |
7521 { | 7555 { |
7522 fprintf(stderr, "Critical Error: Could not create bookkeeping thread in EndInterruption\n"); | 7556 fprintf(stderr, "Critical Error: Could not create bookkeeping thread in EndInterruption\n"); |
7523 } | 7557 } |
7524 #endif | 7558 /* Note: Only a few platforms change the priority. See implementation for notes. */ |
7525 g_inInterruption = AL_FALSE; | 7559 Internal_LowerThreadPriority(Stream_Thread_global); |
7526 } | 7560 #endif |
7527 | 7561 } |
7528 | 7562 |
7529 ALboolean ALmixer_IsInInterruption() | 7563 ALboolean ALmixer_AreUpdatesSuspended() |
7530 { | 7564 { |
7531 if(AL_FALSE == ALmixer_Initialized) | 7565 #ifdef ENABLE_ALMIXER_THREADS |
7566 if(AL_FALSE == g_StreamThreadEnabled) | |
7567 { | |
7568 return AL_TRUE; | |
7569 } | |
7570 else | |
7532 { | 7571 { |
7533 return AL_FALSE; | 7572 return AL_FALSE; |
7534 } | 7573 } |
7535 return g_inInterruption; | 7574 #else |
7575 return AL_FALSE; | |
7576 #endif | |
7536 } | 7577 } |
7537 | 7578 |
7538 /* Keep the return value void to allow easy use with | 7579 /* Keep the return value void to allow easy use with |
7539 * atexit() | 7580 * atexit() |
7540 */ | 7581 */ |
8485 * 0 tells SDL_sound to use the "actual" values | 8526 * 0 tells SDL_sound to use the "actual" values |
8486 */ | 8527 */ |
8487 target.channels = 0; | 8528 target.channels = 0; |
8488 target.rate = 0; | 8529 target.rate = 0; |
8489 | 8530 |
8531 if(0 == buffersize) | |
8532 { | |
8533 buffersize = ALMIXER_DEFAULT_BUFFERSIZE; | |
8534 } | |
8490 #if 0 | 8535 #if 0 |
8491 /* This requires my new additions to SDL_sound. It will | 8536 /* This requires my new additions to SDL_sound. It will |
8492 * convert the sample to the proper endian order. | 8537 * convert the sample to the proper endian order. |
8493 * If the actual is 8-bit, it will do unsigned, if | 8538 * If the actual is 8-bit, it will do unsigned, if |
8494 * the actual is 16-bit, it will do signed. | 8539 * the actual is 16-bit, it will do signed. |