comparison ALmixer.c @ 37:b346b6608eab

Fixed memory leak in Quit due to changes related to background thread removal. FreeData was quick escaping because it checked for ALmixer_Initialized which is now false by the time the code is reached. Code was refactored to introduce an Internal_FreeData which skips this check. Also, I think there is another 'bug' where I should actually be able to delete buffers even though the context is NULL as long as there is a device. But this is all really ugly corner case stuff.
author Eric Wing <ewing@anscamobile.com>
date Mon, 11 Apr 2011 17:19:24 -0700
parents b65ad8b6ccf3
children 2b0b55b7f8cf
comparison
equal deleted inserted replaced
36:b65ad8b6ccf3 37:b346b6608eab
4767 ALmixer_SetError("Cannot query source: %s", ALmixer_GetError()); 4767 ALmixer_SetError("Cannot query source: %s", ALmixer_GetError());
4768 return -1; 4768 return -1;
4769 } 4769 }
4770 4770
4771 return Internal_PausedChannel(channel); 4771 return Internal_PausedChannel(channel);
4772 }
4773
4774
4775
4776 static void Internal_FreeData(ALmixer_Data* data)
4777 {
4778 ALenum error;
4779 if(NULL == data)
4780 {
4781 return;
4782 }
4783
4784 if(data->decoded_all)
4785 {
4786 /* If access_data was enabled, then the Sound_Sample*
4787 * still exists. We need to free it
4788 */
4789 if(data->sample != NULL)
4790 {
4791 Sound_FreeSample(data->sample);
4792 }
4793 alDeleteBuffers(1, data->buffer);
4794 if((error = alGetError()) != AL_NO_ERROR)
4795 {
4796 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));
4797 }
4798 }
4799 else
4800 {
4801 ALuint i;
4802
4803 /* Delete buffer copies if access_data was enabled */
4804 if(data->buffer_map_list != NULL)
4805 {
4806 for(i=0; i<data->max_queue_buffers; i++)
4807 {
4808 free(data->buffer_map_list[i].data);
4809 }
4810 free(data->buffer_map_list);
4811 }
4812 if(data->circular_buffer_queue != NULL)
4813 {
4814 CircularQueueUnsignedInt_FreeQueue(data->circular_buffer_queue);
4815 }
4816
4817 Sound_FreeSample(data->sample);
4818 alDeleteBuffers(data->max_queue_buffers, data->buffer);
4819 if((error = alGetError()) != AL_NO_ERROR)
4820 {
4821 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));
4822 }
4823 }
4824 free(data->buffer);
4825
4826 LinkedList_Remove(s_listOfALmixerData,
4827 LinkedList_Find(s_listOfALmixerData, data, NULL)
4828 );
4829
4830 free(data);
4772 } 4831 }
4773 4832
4774 4833
4775 4834
4776 4835
7515 */ 7574 */
7516 while(LinkedList_Size(s_listOfALmixerData) > 0) 7575 while(LinkedList_Size(s_listOfALmixerData) > 0)
7517 { 7576 {
7518 /* Note that ALmixer_FreeData will remove the data from the linked list for us so don't pop the list here. */ 7577 /* Note that ALmixer_FreeData will remove the data from the linked list for us so don't pop the list here. */
7519 ALmixer_Data* almixer_data = LinkedList_PopBack(s_listOfALmixerData); 7578 ALmixer_Data* almixer_data = LinkedList_PopBack(s_listOfALmixerData);
7520 ALmixer_FreeData(almixer_data); 7579 /* Watch out: ALmixer_FreeData used to escape because ALmixer_Initialized is now false. */
7580 Internal_FreeData(almixer_data);
7521 } 7581 }
7522 LinkedList_Free(s_listOfALmixerData); 7582 LinkedList_Free(s_listOfALmixerData);
7523 s_listOfALmixerData = NULL; 7583 s_listOfALmixerData = NULL;
7524 7584
7525 7585
8538 } 8598 }
8539 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data)); 8599 return( DoLoad(sample, buffersize, decode_mode_is_predecoded, max_queue_buffers, num_startup_buffers, access_data));
8540 } 8600 }
8541 8601
8542 8602
8543
8544
8545 void ALmixer_FreeData(ALmixer_Data* data) 8603 void ALmixer_FreeData(ALmixer_Data* data)
8546 { 8604 {
8547 ALenum error; 8605 if(AL_FALSE == ALmixer_Initialized)
8548 if(NULL == data)
8549 { 8606 {
8550 return; 8607 return;
8551 } 8608 }
8552 8609
8553 if(AL_FALSE == ALmixer_Initialized)
8554 {
8555 return;
8556 }
8557
8558 /* Bypass if in interruption event */ 8610 /* Bypass if in interruption event */
8611 /* FIXME: Buffers are connected to devices, sources are connected to contexts. I should still be able to delete the buffers even if there is no context. */
8559 if(NULL == alcGetCurrentContext()) 8612 if(NULL == alcGetCurrentContext())
8560 { 8613 {
8561 fprintf(stderr, "ALmixer_FreeData: Programmer Error. You cannot delete data when the OpenAL content is currently NULL. You may have already called ALmixer_Quit() or are in an interruption event\n"); 8614 fprintf(stderr, "ALmixer_FreeData: Programmer Error. You cannot delete data when the OpenAL content is currently NULL. You may have already called ALmixer_Quit() or are in an interruption event\n");
8562 return; 8615 return;
8563 } 8616 }
8564 8617
8565 if(data->decoded_all) 8618 Internal_FreeData(data);
8566 {
8567 /* If access_data was enabled, then the Sound_Sample*
8568 * still exists. We need to free it
8569 */
8570 if(data->sample != NULL)
8571 {
8572 Sound_FreeSample(data->sample);
8573 }
8574 alDeleteBuffers(1, data->buffer);
8575 if((error = alGetError()) != AL_NO_ERROR)
8576 {
8577 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));
8578 }
8579 }
8580 else
8581 {
8582 ALuint i;
8583
8584 /* Delete buffer copies if access_data was enabled */
8585 if(data->buffer_map_list != NULL)
8586 {
8587 for(i=0; i<data->max_queue_buffers; i++)
8588 {
8589 free(data->buffer_map_list[i].data);
8590 }
8591 free(data->buffer_map_list);
8592 }
8593 if(data->circular_buffer_queue != NULL)
8594 {
8595 CircularQueueUnsignedInt_FreeQueue(data->circular_buffer_queue);
8596 }
8597
8598 Sound_FreeSample(data->sample);
8599 alDeleteBuffers(data->max_queue_buffers, data->buffer);
8600 if((error = alGetError()) != AL_NO_ERROR)
8601 {
8602 fprintf(stderr, "ALmixer_FreeData: alDeleteBuffers failed. %s\n", alGetString(error));
8603 }
8604 }
8605 free(data->buffer);
8606
8607 LinkedList_Remove(s_listOfALmixerData,
8608 LinkedList_Find(s_listOfALmixerData, data, NULL)
8609 );
8610
8611 free(data);
8612 } 8619 }
8613 8620
8614 ALint ALmixer_GetTotalTime(ALmixer_Data* data) 8621 ALint ALmixer_GetTotalTime(ALmixer_Data* data)
8615 { 8622 {
8616 if(NULL == data) 8623 if(NULL == data)