bool AEDeviceEnumerationOSX::hasDataFormat(const AEDataFormatList &list, const enum AEDataFormat format) const
{
  for (size_t i = 0; i < list.size(); ++i)
  {
    if (list[i] == format)
      return true;
  }
  return false;
}
AEDataFormatList AEDeviceEnumerationOSX::getFormatListForStream(UInt32 streamIdx) const
{
  AEDataFormatList returnDataFormatList;
  if (streamIdx >= m_caStreamInfos.size())
    return returnDataFormatList;
  
  // check the streams
  const StreamFormatList &formatList = m_caStreamInfos[streamIdx].formatList;
  for(UInt32 formatIdx = 0; formatIdx < formatList.size(); formatIdx++)
  {
    AudioStreamBasicDescription formatDesc = formatList[formatIdx].mFormat;
    AEDataFormatList aeFormatList = caFormatToAE(formatDesc, m_caStreamInfos[streamIdx].isDigital);
    for (UInt32 formatListIdx = 0; formatListIdx < aeFormatList.size(); formatListIdx++)
    {
      if (!hasDataFormat(returnDataFormatList, aeFormatList[formatListIdx]))
        returnDataFormatList.push_back(aeFormatList[formatListIdx]);
    }
  }
  return returnDataFormatList;
}
AEDataFormatList AEDeviceEnumerationOSX::caFormatToAE(const AudioStreamBasicDescription &formatDesc, bool isDigital) const
{
  AEDataFormatList formatList;
  // add stream format info
  switch (formatDesc.mFormatID)
  {
    case kAudioFormatAC3:
    case kAudioFormat60958AC3:
      break;
    default:
      switch(formatDesc.mBitsPerChannel)
    {
      case 16:
        if (formatDesc.mFormatFlags & kAudioFormatFlagIsBigEndian)
          formatList.push_back(AE_FMT_S16BE);
        else
        {
          formatList.push_back(AE_FMT_S16LE);
        }
        break;
      case 24:
        if (formatDesc.mFormatFlags & kAudioFormatFlagIsBigEndian)
          formatList.push_back(AE_FMT_S24BE3);
        else
          formatList.push_back(AE_FMT_S24LE3);
        break;
      case 32:
        if (formatDesc.mFormatFlags & kAudioFormatFlagIsFloat)
          formatList.push_back(AE_FMT_FLOAT);
        else
        {
          if (formatDesc.mFormatFlags & kAudioFormatFlagIsBigEndian)
            formatList.push_back(AE_FMT_S32BE);
          else
            formatList.push_back(AE_FMT_S32LE);
        }
        break;
    }
      break;
  }
  return formatList;
}
AEDataFormatList AEDeviceEnumerationOSX::caFormatToAE(const AudioStreamBasicDescription &formatDesc, bool isDigital) const
{
  AEDataFormatList formatList;
  // add stream format info
  switch (formatDesc.mFormatID)
  {
    case kAudioFormatAC3:
    case kAudioFormat60958AC3:
      formatList.push_back(AE_FMT_AC3);
      formatList.push_back(AE_FMT_DTS);
      break;
    default:
      switch(formatDesc.mBitsPerChannel)
    {
      case 16:
        if (formatDesc.mFormatFlags & kAudioFormatFlagIsBigEndian)
          formatList.push_back(AE_FMT_S16BE);
        else
        {
          /* Passthrough is possible with a 2ch digital output */
          if (formatDesc.mChannelsPerFrame == 2 && isDigital)
          {
            if (formatDesc.mSampleRate == 48000)
            {
              formatList.push_back(AE_FMT_AC3);
              formatList.push_back(AE_FMT_DTS);
            }
            else if (formatDesc.mSampleRate == 192000)
            {
              formatList.push_back(AE_FMT_EAC3);
            }
          }
          formatList.push_back(AE_FMT_S16LE);
        }
        break;
      case 24:
        if (formatDesc.mFormatFlags & kAudioFormatFlagIsBigEndian)
          formatList.push_back(AE_FMT_S24BE3);
        else
          formatList.push_back(AE_FMT_S24LE3);
        break;
      case 32:
        if (formatDesc.mFormatFlags & kAudioFormatFlagIsFloat)
          formatList.push_back(AE_FMT_FLOAT);
        else
        {
          if (formatDesc.mFormatFlags & kAudioFormatFlagIsBigEndian)
            formatList.push_back(AE_FMT_S32BE);
          else
            formatList.push_back(AE_FMT_S32LE);
        }
        break;
    }
      break;
  }
  return formatList;
}