Skip to content

Commit

Permalink
Add the option of infinitely buffering a stream.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Jun 15, 2012
1 parent 56d4bf5 commit 96d9c82
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 19 deletions.
2 changes: 2 additions & 0 deletions AudioStreamer/AudioStreamer.h
Expand Up @@ -85,6 +85,7 @@ struct queued_packet;
AudioFileTypeID fileType;
UInt32 bufferSize; /* attempted to be guessed, but fallback here */
UInt32 bufferCnt;
BOOL bufferInfinite;

/* Creates as part of the [start] method */
CFReadStreamRef stream;
Expand Down Expand Up @@ -152,6 +153,7 @@ struct queued_packet;
@property (readwrite) UInt32 bufferCnt;
@property (readwrite) UInt32 bufferSize;
@property (readwrite) AudioFileTypeID fileType;
@property (readwrite) BOOL bufferInfinite;

+ (NSString*) stringForErrorCode:(AudioStreamerErrorCode)anErrorCode;

Expand Down
54 changes: 35 additions & 19 deletions AudioStreamer/AudioStreamer.m
Expand Up @@ -170,7 +170,7 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream
@implementation AudioStreamer

@synthesize errorCode, networkError, httpHeaders, url, bufferCnt, bufferSize,
fileType;
fileType, bufferInfinite;
@synthesize state = state_;

/* AudioFileStream callback when properties are available */
Expand Down Expand Up @@ -868,7 +868,7 @@ - (BOOL)openReadStream {
- (void)handleReadFromStream:(CFReadStreamRef)aStream
eventType:(CFStreamEventType)eventType {
assert(aStream == stream);
assert(!waitingOnBuffer);
assert(!waitingOnBuffer || bufferInfinite);
events++;

switch (eventType) {
Expand All @@ -880,6 +880,8 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream

case kCFStreamEventEndEncountered:
LOG(@"end");
[timeout invalidate];
timeout = nil;

/* Flush out extra data if necessary */
if (bytesFilled) {
Expand All @@ -891,16 +893,6 @@ - (void)handleReadFromStream:(CFReadStreamRef)aStream
/* If we never received any packets, then we fail */
if (state_ == AS_WAITING_FOR_DATA) {
[self failWithErrorCode:AS_AUDIO_DATA_NOT_FOUND];

/* Flush an asynchronously stop the audio queue now that it won't be
receiving any more data */
} else {
if (audioQueue) {
err = AudioQueueFlush(audioQueue);
CHECK_ERR(err, AS_AUDIO_QUEUE_FLUSH_FAILED);
err = AudioQueueStop(audioQueue, false);
CHECK_ERR(err, AS_AUDIO_QUEUE_STOP_FAILED);
}
}
return;

Expand Down Expand Up @@ -1012,14 +1004,36 @@ - (int) enqueueBuffer {
bytesFilled = 0; // reset bytes filled
packetsFilled = 0; // reset packets filled

/* If we have no more queued data, and the stream has reached its end, then
we're not going to be enqueueing any more buffers to the audio stream. In
this case flush it out and asynchronously stop it */
if (queued_head == NULL &&
CFReadStreamGetStatus(stream) == kCFStreamStatusAtEnd) {
err = AudioQueueFlush(audioQueue);
if (err) {
[self failWithErrorCode:AS_AUDIO_QUEUE_FLUSH_FAILED];
return -1;
}
err = AudioQueueStop(audioQueue, false);
if (err) {
[self failWithErrorCode:AS_AUDIO_QUEUE_STOP_FAILED];
return -1;
}
}

/* The inuse array is also managed by a separate AudioQueue internal thread,
so we need to synchronize around unscheduling the read stream to ensure
that our state is always coherent */
@synchronized(self) {
if (inuse[fillBufferIndex]) {
LOG(@"waiting for buffer %d", fillBufferIndex);
CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
/* Make sure we don't have ourselves marked as rescheduled */
unscheduled = YES;
rescheduled = NO;
if (!bufferInfinite) {
CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
/* Make sure we don't have ourselves marked as rescheduled */
unscheduled = YES;
rescheduled = NO;
}
waitingOnBuffer = true;
return 0;

Expand Down Expand Up @@ -1337,8 +1351,10 @@ - (void) enqueueCachedData {
if (cur == NULL) {
queued_tail = NULL;
rescheduled = YES;
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
if (!bufferInfinite) {
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
}
}
}

Expand Down

0 comments on commit 96d9c82

Please sign in to comment.