iPhone OS 4.0:NSFileHandleDataAvailableNotification 未在文件末尾提供回调

发布于 2024-09-09 22:12:04 字数 2687 浏览 3 评论 0原文

我对 iPhone 开发有点陌生,所以要温柔!我支持一个应用程序,它从 URL 文件流加载 wav 文件,并通过 AudioQueue 播放它。

我们在另一个线程中运行连续循环,如果我们检测到队列没有正在使用的缓冲区,并且输入 FileStream 已到达末尾,则停止队列。反过来,我们通过检查 availableData 的长度是否为 0 来检测 FileStream 是否已在流的 NSFileHandleDataAvailableNotificationwaitForDataInBackgroundAndNotify 回调中结束这

适用于 iOS 3.0 - 我们在文件末尾收到 0 个可用数据的通知 - 但在 iOS 4.0 上,我们似乎没有在文件末尾收到回调。无论目标操作系统版本如何,这种情况都会发生在 OS 4.0 设备上。

两个版本之间的 API 是否发生了变化?现在如何检测文件结尾?

希望相关代码:

数据可用回调:

- (void)readFileData:(NSNotification *)notification
{
  @try
  {
    NSData *data = [[notification object] availableData];

    if ([data length] == 0 && self.audioQueueState != AQS_END)
    {
      /***********************************************************************/
      /* We've hit the end of the data but it's possible that more may be    */
      /* appended to the file (if we're still downloading it) so we need to  */
      /* wait for the availability of more data.                             */
      /***********************************************************************/
      [self setFileStreamerState:FSS_END];
      [[notification object] waitForDataInBackgroundAndNotify];
    }
    else if (self.audioQueueState == AQS_END)
    {
      TRC_DBG(@"ignore read data as ending");
    }
    else
    {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

      TRC_DBG(@"Read %d bytes", [data length]);

      [self setFileStreamerState:FSS_DATA];

      if (discontinuous)
      {
        TRC_DBG(@"AudioFileStreamParseBytes %d bytes, discontinuous", [data length]);
        err = AudioFileStreamParseBytes(audioFileStream, [data length], [data bytes], kAudioFileStreamParseFlag_Discontinuity);
        discontinuous = NO;
      }
      else
      {
        TRC_DBG(@"AudioFileStreamParseBytes %d bytes, continuous", [data length]);
        err = AudioFileStreamParseBytes(audioFileStream, [data length], [data bytes], 0);
      }

      /***********************************************************************/
      /* If error then get out, otherwise wait again for more data.          */
      /***********************************************************************/
      if (err != 0)
      {
        [self failWithErrorCode:AS_FILE_STREAM_PARSE_BYTES_FAILED];
      }
      else
      {
        [[notification object] waitForDataInBackgroundAndNotify];
      }

      [pool release];
    }
  }
  @catch (NSException *exception)
  {
    TRC_ERR(@"Exception: %@", exception);
    TRC_ERR(@"Exception reason: %@", [exception reason]);
    //[self failWithErrorCode:AS_FILE_AVAILABLE_DATA_FAILED];
  }
}

I'm a bit new to iPhone development, so be gentle! I'm supporting an app which loads a wav file from a URL file-stream, and plays it back through an AudioQueue.

We run a continual loop in another thread, and stop the Queue if we detect that it has no buffers in use, and the input FileStream has reached its end. In turn, we detect if the FileStream has ended within the waitForDataInBackgroundAndNotify callback on the NSFileHandleDataAvailableNotification for the stream, by checking whether the availableData has length 0.

This works under iOS 3.0 - we get a notification of 0 available data at the end of the file - but on iOS 4.0, we don't seem to receive the callback at file end. This happens on an OS 4.0 device, regardless of the target OS version.

Has the API changed between the two versions? How can I detect the end of the file now?

Hopefully-relevant code:

data-available callback:

- (void)readFileData:(NSNotification *)notification
{
  @try
  {
    NSData *data = [[notification object] availableData];

    if ([data length] == 0 && self.audioQueueState != AQS_END)
    {
      /***********************************************************************/
      /* We've hit the end of the data but it's possible that more may be    */
      /* appended to the file (if we're still downloading it) so we need to  */
      /* wait for the availability of more data.                             */
      /***********************************************************************/
      [self setFileStreamerState:FSS_END];
      [[notification object] waitForDataInBackgroundAndNotify];
    }
    else if (self.audioQueueState == AQS_END)
    {
      TRC_DBG(@"ignore read data as ending");
    }
    else
    {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

      TRC_DBG(@"Read %d bytes", [data length]);

      [self setFileStreamerState:FSS_DATA];

      if (discontinuous)
      {
        TRC_DBG(@"AudioFileStreamParseBytes %d bytes, discontinuous", [data length]);
        err = AudioFileStreamParseBytes(audioFileStream, [data length], [data bytes], kAudioFileStreamParseFlag_Discontinuity);
        discontinuous = NO;
      }
      else
      {
        TRC_DBG(@"AudioFileStreamParseBytes %d bytes, continuous", [data length]);
        err = AudioFileStreamParseBytes(audioFileStream, [data length], [data bytes], 0);
      }

      /***********************************************************************/
      /* If error then get out, otherwise wait again for more data.          */
      /***********************************************************************/
      if (err != 0)
      {
        [self failWithErrorCode:AS_FILE_STREAM_PARSE_BYTES_FAILED];
      }
      else
      {
        [[notification object] waitForDataInBackgroundAndNotify];
      }

      [pool release];
    }
  }
  @catch (NSException *exception)
  {
    TRC_ERR(@"Exception: %@", exception);
    TRC_ERR(@"Exception reason: %@", [exception reason]);
    //[self failWithErrorCode:AS_FILE_AVAILABLE_DATA_FAILED];
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文