AudioQueue PropertyListener IsRunning只回调一次

时间:2012-11-13 06:48:41

标签: iphone objective-c ios audioqueue

 OSStatus err = AudioQueueNewOutput(&audioDescription, AudioPlayerAQOutputCallback, ( void* )self, nil, nil, 0, &audioQueue);
    if( err != noErr )
        NSLog(@"Couldn't open AudioFile.");

    err = AudioQueueAddPropertyListener(audioQueue, kAudioQueueProperty_IsRunning, isRunningProc, self);
    if( err != noErr )
        NSLog(@"Couldn't register for playback state changes.");

此回调函数仅在AudioQueueStart(audioQueue,NULL)之后调用一次;

我称之为AudioQueuePause(audioQueue);

或音频到达结束。

static void isRunningProc(void *              inUserData,
                      AudioQueueRef           inAQ,
                      AudioQueuePropertyID    inID)

我错过了什么?

1 个答案:

答案 0 :(得分:1)

我做了一个简短的测试:

当你恢复暂停时,确实看起来它不会被称为暂停或开始。

但这不是你无法解决的。你以某种方式开始了这首歌。这将触发属性侦听器。同样,如果歌曲停止。或者你阻止它。您可能必须在游戏例程中使用类似的东西以某种方式触发属性侦听器:

if (bytesRead == 0) {
    //This will trigger the property listener
    AudioQueueStop(inAQ, false);
}
else {
    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}

就AudioQueue而言,只要您继续使用音频缓冲区进行播放,它仍在播放。 (我还测试过根本没有提供任何缓冲区,它们没有触发停止,所以你必须明确地调用stop来触发属性监听器。)

这意味着您已经知道您的歌曲是否正在播放。单击按钮可请求暂停或取消暂停。如果歌曲没有播放,请不要做任何事情。如果正在播放歌曲,请拨打AudioQueuePause并设置一个暂停音乐的标志。请记住检查错误代码。 (见下文(1))。如果该标志表示您已暂停音乐,请致电AudioQueueStart,并清除指示您是否已暂停的标志。再次检查错误代码。

(1)为什么要检查错误代码?

首先,虽然不太可能,但可能会出现错误,因为它是一个蓝色的月亮。

然而,我关心的是多线程。 AudioQueue显然运行在与GUI不同的线程上。这意味着如果你测试一个标志是否正在播放音乐,这个状态就不能完全被信任,因为它可能在你测试状态后发生了变化。根据该测试,另一个线程可能会在您的测试和您的操作之间悄悄泄漏。

假设您检查该歌曲是否已播放。 (它是。) 然后你要求这首歌暂停,但是这首歌真的停止了,因为在你要求歌曲暂停之前它已经到了最后。 然后你要求暂停这首歌。但它已经停止了。

那会怎么样?我真的不知道。在这种情况下它甚至可能不是问题,但这样的事情值得考虑。它需要测试,或者至少需要咨询文档。

另一种情况怎么样?如果歌曲停止并且您要求再次启动该怎么办?我认为这是一个更糟糕的情况,但它可能不是一个问题。再次考虑这些情况并检查文档,甚至自己测试。