From a1e8198ed4fbffaf4d73f8b82333423652653156 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 13 Jun 2012 23:36:11 -0700 Subject: [PATCH] Clean up after ourselves when done streaming In addition to closing the read stream, clear out our "cache" of packets and don't flag ourselves as waiting any more so a spurious message won't wake things up. Also when finishing the stream, only set ourselves to AS_DONE when all packets have been fully consumed by the audio stream, not when the network stream finishes. --- AudioStreamer/AudioStreamer.m | 54 +++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/AudioStreamer/AudioStreamer.m b/AudioStreamer/AudioStreamer.m index b2ca92b..e8a9647 100644 --- a/AudioStreamer/AudioStreamer.m +++ b/AudioStreamer/AudioStreamer.m @@ -536,12 +536,7 @@ - (BOOL)seekToTime:(double)newSeekTime { } } - /* Close the old stream */ - if (stream) { - CFReadStreamClose(stream); - CFRelease(stream); - stream = nil; - } + [self closeReadStream]; /* Stop audio for now */ err = AudioQueueStop(audioQueue, true); @@ -568,12 +563,8 @@ - (double)progress { AudioTimeStamp queueTime; Boolean discontinuity; err = AudioQueueGetCurrentTime(audioQueue, NULL, &queueTime, &discontinuity); - - const OSStatus AudioQueueStopped = 0x73746F70; // 0x73746F70 is 'stop' - if (err == AudioQueueStopped) { + if (err) { return lastProgress; - } else if (err) { - [self failWithErrorCode:AS_GET_AUDIO_TIME_FAILED]; } double progress = seekTime + queueTime.mSampleTime / sampleRate; @@ -662,12 +653,12 @@ - (void) play { // back to false // - (void)stop { - if (stream) { - CFReadStreamClose(stream); - CFRelease(stream); - stream = nil; + if (![self isDone]) { + [self setState:AS_STOPPED]; } + [self closeReadStream]; + // // Close the audio file strea, // @@ -692,9 +683,25 @@ - (void)stop { packetsFilled = 0; seekByteOffset = 0; packetBufferSize = 0; +} - if (![self isDone]) { - [self setState:AS_STOPPED]; +/** + * @brief Closes the read stream and frees all queued data + */ +- (void) closeReadStream { + if (waitingOnBuffer) waitingOnBuffer = FALSE; + queued_packet_t *cur = queued_head; + while (cur != NULL) { + queued_packet_t *tmp = cur->next; + free(cur); + cur = tmp; + } + queued_head = queued_tail = NULL; + + if (stream) { + CFReadStreamClose(stream); + CFRelease(stream); + stream = nil; } } @@ -742,7 +749,6 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream err = AudioQueueStop(audioQueue, false); CHECK_ERR(err, AS_AUDIO_QUEUE_STOP_FAILED); } - [self setState:AS_DONE]; } return; @@ -1218,7 +1224,13 @@ - (void)handleBufferCompleteForQueue:(AudioQueueRef)inAQ @synchronized(self) { inuse[idx] = false; buffersUsed--; - if (waitingOnBuffer) { + if (buffersUsed == 0 && queued_head == NULL && stream != nil && + CFReadStreamGetStatus(stream) == kCFStreamStatusAtEnd) { + assert(!waitingOnBuffer); + [self performSelectorOnMainThread:@selector(setStateObj:) + withObject:[NSNumber numberWithInt:AS_DONE] + waitUntilDone:NO]; + } else if (waitingOnBuffer) { waitingOnBuffer = false; [self performSelectorOnMainThread:@selector(enqueueCachedData) withObject:nil @@ -1227,6 +1239,10 @@ - (void)handleBufferCompleteForQueue:(AudioQueueRef)inAQ } } +- (void) setStateObj:(NSNumber*) num { + [self setState:[num intValue]]; +} + // // handlePropertyChangeForQueue:propertyID: //