现在的位置: 首页 > 综合 > 正文

流媒体播放-在线音乐播放(2)

2013年02月16日 ⁄ 综合 ⁄ 共 6123字 ⁄ 字号 评论关闭

// MyFindQueueBuffer

//

// Returns the index of the specified buffer in the audioQueueBuffer array.

//

// This function is unchanged from Apple's example in AudioFileStreamExample.

//

int MyFindQueueBuffer(xxxxx* myData,
AudioQueueBufferRef inBuffer)

{

   
for (unsigned
int i = 0; i < kNumAQBufs; ++i) {

       
if (inBuffer == myData->buffers)

           
return i;

    }

   
return -1;

}



//

// MyAudioQueueOutputCallback

//

// Called from the AudioQueue when playback of specific buffers completes. This

// function signals from the AudioQueue thread to the AudioStream thread that

// the buffer is idle and available for copying data.

//

// This function is unchanged from Apple's example in AudioFileStreamExample.

//

void MyAudioQueueOutputCallback(void* inClientData,
AudioQueueRef inAQ,
AudioQueueBufferRef
inBuffer)

{

    // this is called by the audio queue when it has finished decoding our data.

    // The buffer is now free to be reused.

    xxxxx* myData = (xxxxx*)inClientData;

   
unsigned int bufIndex = MyFindQueueBuffer(myData, inBuffer);

    

    // signal waiting thread that the buffer is free.

    pthread_mutex_lock(&myData->mutex);

    myData->inuse[bufIndex] =
false;

    pthread_cond_signal(&myData->cond);

    pthread_mutex_unlock(&myData->mutex);

}



//

// MyAudioQueueIsRunningCallback

//

// Called from the AudioQueue when playback is started or stopped. This

// information is used to toggle the observable "isPlaying" property and

// set the "finished" flag.

//

void MyAudioQueueIsRunningCallback(void *inUserData,
AudioQueueRef inAQ,
AudioQueuePropertyID
inID)

{

    xxxxx *myData = (xxxxx *)inUserData;

    NSAutoreleasePool *pool = [[NSAutoreleasePool
alloc]
init];

    

   
if (myData.isPlaying)

    {

        myData->trackEnded =
true;

        myData.isPlaying =
false;

        

#ifdef TARGET_OS_IPHONE

        AudioSessionSetActive(false);

#endif

    }

   
else

    {

        myData.isPlaying =
true;

       
if (myData->trackEnded)

        {

            myData.isPlaying =
false;

        }

        

       
//

        // Note about this bug avoidance quirk:

       
//

        // On cleanup of the AudioQueue thread, on rare occasions, there would

        // be a crash in CFSetContainsValue as a CFRunLoopObserver was getting

        // removed from the CFRunLoop.

       
//

        // After lots of testing, it appeared that the audio thread was

        // attempting to remove CFRunLoop observers from the CFRunLoop after the

        // thread had already deallocated the run loop.

       
//

        // By creating an NSRunLoop for the AudioQueue thread, it changes the

        // thread destruction order and seems to avoid this crash bug -- or

        // at least I haven't had it since (nasty hard to reproduce error!)

       
//

        [NSRunLoop currentRunLoop];

    }

    

    [pool
release];

}



#ifdef TARGET_OS_IPHONE

//

// MyAudioSessionInterruptionListener

//

// Invoked if the audio session is interrupted (like when the phone rings)

//

void MyAudioSessionInterruptionListener(void *inClientData,
UInt32 inInterruptionState)

{

}

#endif



#pragma mark -

#pragma mark CFReadStream Callback Function Implementations



//

// ReadStreamCallBack

//

// This is the callback for the CFReadStream from the network connection. This

// is where all network data is passed to the AudioFileStream.

//

// Invoked when an error occurs, the stream ends or we have data to read.

//

void ReadStreamCallBack(CFReadStreamRef stream,
CFStreamEventType eventType,
void
* dataIn)

{

    xxxxx *myData = (xxxxx *)dataIn;

    

    if (eventType ==
kCFStreamEventErrorOccurred)

    {

        myData->failed =
YES;

    }

    else
if (eventType ==
kCFStreamEventEndEncountered)

    {

       
if (myData->failed || myData->trackEnded)

        {

           
return;

        }

        

       
//

        // If there is a partially filled buffer, pass it to the AudioQueue for

        // processing

       
//

       
if (myData->bytesFilled)

        {

            MyEnqueueBuffer(myData);

        }

        

       
//

        // If the AudioQueue started, then flush it (to make certain everything

        // sent thus far will be processed) and subsequently stop the queue.

       
//

       
if (myData->started)

        {

            OSStatus err = AudioQueueFlush(myData->queue);

           
if (err) { NSLog(@"AudioQueueFlush");
return; }

            

            err = AudioQueueStop(myData->queue,
false);

           
if (err) { NSLog(@"AudioQueueStop");
return; }

            

            CFReadStreamClose(stream);

            CFRelease(stream);

            myData->stream =
nil;

        }

       
else

        {

           
//

            // If we have reached the end of the file without starting, then we

            // have failed to find any audio in the file. Abort.

           
//

            myData->failed =
YES;

        }

    }

    else
if (eventType ==
kCFStreamEventHasBytesAvailable)

    {

       
if (myData->failed || myData->trackEnded)

        {

           
return;

        }

        

       
//

        // Read the bytes from the stream

       
//

        UInt8 bytes[kAQBufSize];

       
CFIndex length = CFReadStreamRead(stream, bytes, kAQBufSize);

        

       
if (length == -1)

        {

            myData->failed =
YES;

           
return;

        }

        

       
//

        // Parse the bytes read by sending them through the AudioFileStream

       
//

       
if (length > 0)

        {

           
if (myData->discontinuous)

            {

                OSStatus err = AudioFileStreamParseBytes(myData->audioFileStream, length, bytes, kAudioFileStreamParseFlag_Discontinuity);

               
if (err) { NSLog(@"AudioFileStreamParseBytes"); myData->failed =
true;}

            }

           
else

            {

                OSStatus err = AudioFileStreamParseBytes(myData->audioFileStream, length, bytes,
0);

               
if (err) { NSLog(@"AudioFileStreamParseBytes"); myData->failed =
true; }

            }

        }

    }

}



@interface xxxxx (private)



static
void propertyListenerCallback(void *inUserData,
AudioQueueRef queueObject,
AudioQueuePropertyID
propertyID);

- (void) playBackIsRunningStateChanged;



static
void BufferCallback(void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef
buffer);

- (void) callbackForBuffer:(AudioQueueBufferRef)buffer;

- (UInt32) readPacketsIntoBuffer:(AudioQueueBufferRef)buffer;



@end



@implementation xxxxx



@synthesize isPlaying, trackClosed;



#pragma mark -

#pragma mark xxxxx



- (void)dealloc

{

    [self
close];

   
if (packetDescs !=
nil
)

        free(packetDescs);

    [url release];

    [super dealloc];

}



- (void)close

{

    // it is preferrable to call close first, if there is a problem waiting for an autorelease

   
if (trackClosed)

       
return;

    trackClosed =
YES;

    AudioQueueStop(queue,
YES);
// <-- YES means stop immediately

    AudioQueueDispose(queue,
YES);

    AudioFileClose(audioFile);

    kxxxTrackActive =
NO;

}



- (id)initWithURL:(NSURL*)newUrl

{

   
self = [super init];

   
if (self !=
nil)

    {

        url = [newUrl retain];

    }

    return
self;

}



- (id)initWithPath:(NSString*)path

{

   
UInt32 size, maxPacketSize;

   
char *cookie;

   
int i;

    

   
if (kxxxTrackActive)

    {

        NSLog(@"Other music is playing.");

       
return nil;

    }

    

   
if (path == nil)
return nil;

   
if(!(self = [super init]))
return nil;

    

    // try to open up the file using the specified path

   
if (noErr != AudioFileOpenURL((CFURLRef)[NSURL fileURLWithPath:path],
0x01, 0, &audioFile))

    {

        NSLog(@"File can not be opened!");

       
return nil;

    }

抱歉!评论已关闭.