audiostreamer初识(二)

让我们看一下audiostreamer.m的init:

- (id)initWithURL:(NSURL *)aURL

{

self = [super init];

if (self != nil)

{

if (url){

url = nil;

[url release];

}

url = [aURL copy];

#ifdef SHOUTCAST_METADATA

if (metaDataString){

metaDataString = nil;

[metaDataString release];

}

//NSLog(@"%d", [metaDataString retainCount]);

metaDataString = [[NSMutableString allocinitWithString:@""];

#endif

        seekTime = 0;

}

return self;

}

这里将url,metaDataString,seekTime初始化。

再看最重要的 start方法:

- (void)start

{

@synchronized (self)

{

if (state == AS_PAUSED)

{

[self pause];

}

else if (state == AS_INITIALIZED)

{

NSAssert([[NSThread currentThread] isEqual:[NSThread mainThread]],

@"Playback can only be started from the main thread.");

notificationCenter =

[[NSNotificationCenter defaultCenterretain];

self.state = AS_STARTING_FILE_THREAD;

internalThread =

[[NSThread alloc]

initWithTarget:self

selector:@selector(startInternal)

object:nil];

[internalThread setName:@"InternalThread"];

[internalThread start];

}

}

}

这里主要是重点注意

internalThread =[[NSThread alloc]initWithTarget:self selector:@selector(startInternal) object:nil];中的方法startInternal:


里面有几段代码特重要:

#if TARGET_OS_IPHONE

//

// Set the audio session category so that we continue to play if the

// iPhone/iPod auto-locks.

//

AudioSessionInitialize (

NULL,                          // 'NULL' to use the default (main) run loop

NULL,                          // 'NULL' to use the default run loop mode

MyAudioSessionInterruptionListener,  // a reference to your interruption callback

self                       // data to pass to your interruption listener callback

);

UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;

AudioSessionSetProperty (

kAudioSessionProperty_AudioCategory,

sizeof (sessionCategory),

&sessionCategory

);

AudioSessionSetActive(true);

__streamer = self;

#endif

相信大家都看懂,这是让播放器后台运行的代码。

接下来我们要看一句代码,让我们的思绪继续走下去:

if (![self openReadStream])

{

goto cleanup;

}

//

// Process the run loop until playback is finished or failed.

//

BOOL isRunning = YES;

do

{

isRunning = [[NSRunLoop currentRunLoop]

runMode:NSDefaultRunLoopMode

beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];

@synchronized(self) {

if (seekWasRequested) {

[self internalSeekToTime:requestedSeekTime];

seekWasRequested = NO;

}

}

//

// If there are no queued buffers, we need to check here since the

// handleBufferCompleteForQueue:buffer: should not change the state

// (may not enter the synchronized section).

//

if (buffersUsed == 0 && self.state == AS_PLAYING)

{

err = AudioQueuePause(audioQueue);

if (err)

{

[self failWithErrorCode:AS_AUDIO_QUEUE_PAUSE_FAILED];

return;

}

self.state = AS_BUFFERING;

}

while (isRunning && ![self runLoopShouldExit]);


这里第一步会调用 openReadStream方法,第二步当返回yes时,就会继续执行do-while语句,这里会碰到runloop循环:

- (BOOL)openReadStream

{

@synchronized(self)

{

NSAssert([[NSThread currentThread] isEqual:internalThread],

@"File stream download must be started on the internalThread");

NSAssert(stream == nil@"Download stream already initialized");

        NSLog(@"opopop   %@",url.absoluteString);

        if (url !=nil && [url.absoluteString rangeOfString:@"file"].location == NSNotFound){

//

// Create the HTTP GET request

//  

            isLocalFile = NO;


。。。。。。

}

如果url不是空,而且不是本地文件的时候,设置isLocalFile = NO;

剩下的几句重要的代码就是:

1.set useful headers

            CFHTTPMessageRef message= CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"GET", (CFURLRef)urlkCFHTTPVersion1_1);

    #ifdef SHOUTCAST_METADATA

            CFHTTPMessageSetHeaderFieldValue(message, CFSTR("icy-metadata"), CFSTR("1"));

    #endif

2.create the CFReadStreamRef:

            stream = CFReadStreamCreateForHTTPRequest(NULL, message);

            CFRelease(message);

           if (CFReadStreamSetProperty(

                                        stream,

                                        kCFStreamPropertyAppendToFile,

                                        kCFBooleanTrue) == false)

            {

                [self presentAlertWithTitle:NSLocalizedStringFromTable(@"File Error"@"Errors"nil)

                                    message:NSLocalizedStringFromTable(@"Unable to configure network read stream."@"Errors"nil)];

                return NO;

            }

    if (!CFReadStreamOpen(stream))

            {

CFRelease(stream);

[self presentAlertWithTitle:NSLocalizedStringFromTable(@"File Error"@"Errors"nil) message:NSLocalizedStringFromTable(@"Unable to configure network read stream."@"Errors"nil)];

return NO;

    }

    CFStreamClientContext context = {0selfNULLNULLNULL};

            CFReadStreamSetClient(

stream,

kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,

ASReadStreamCallBack,

&context);

    CFReadStreamScheduleWithRunLoop(streamCFRunLoopGetCurrent(), kCFRunLoopCommonModes);

这几句主要是CFHTTPMessage网络请求,与nsurl的get请求有几分相似,可以一起比较一下。

这时候会回调ASReadStreamCallBack 方法。

#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 ASReadStreamCallBack

(

   CFReadStreamRef aStream,

   CFStreamEventType eventType,

   void* inClientInfo

)

{

AudioStreamer* streamer = (AudioStreamer *)inClientInfo;

[streamer handleReadFromStream:aStream eventType:eventType];

}







  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值