audiostreamer初识(二)
来源:互联网 发布:龙腾世纪3优化差 编辑:程序博客网 时间:2024/06/05 04:43
让我们看一下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 alloc] initWithString:@""];
#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 defaultCenter] retain];
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)url, kCFHTTPVersion1_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 = {0, self, NULL, NULL, NULL};
CFReadStreamSetClient(
stream,
kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
ASReadStreamCallBack,
&context);
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), 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];
}
- audiostreamer初识(二)
- audiostreamer初识(二)
- audiostreamer.m的初识(一)
- audiostreamer.m的初识(一)
- AudioStreamer
- 初识jbpm(二)
- 初识Volley(二)
- 初识JavaFX(二)
- 初识AS3(二)
- ant初识(二)
- 初识EF(二)
- 初识capwap(二)
- 初识Spring(二)
- 初识python(二)
- Redis初识(二)
- 初识JavaCC(二)
- XAMPP初识(二)
- Linux初识(二)
- EXTJS combo下拉框插入脚本生成的数据
- 查看基于Android 系统单个进程内存、CPU使用情况的几种方法
- Xcode中使用SVN (SCM) 管理自己的source code
- Xcode中使用SVN (SCM) 管理自己的source code
- WRFV3.3 安装记录
- audiostreamer初识(二)
- 2009-05-27 18:05 fopen 文本文件与二进制文件区别
- Hibernate 表自身映射多对多关系,用户对多朋友
- 项目 从Myclipse web 转为 Eclipse web
- cygwin syntax error near unexpected token `$'do\r''
- 谁贪占了我的系统资源 php-fpm
- Xcode4.2+SVN代码管理研究(一)
- Xcode4.2+SVN代码管理研究(二)
- 二维数组与new/delete