Невозможно установить Bluetooth-гарнитуру в качестве устройства вывода по умолчанию в OS X с помощью API CoreAudio.

У меня возникли трудности с программной настройкой моей Bluetooth-гарнитуры (Apple Airpods) в качестве устройства вывода звука по умолчанию на моей OSX. Я попытался использовать API CoreAudio, чтобы установить устройство по умолчанию, но, похоже, оно не работает.

В своей программе записи звука я создаю совокупное аудиоустройство, включающее в себя гарнитуру Bluetooth и устройство «черная дыра». Программа правильно запоминает имя устройства Bluetooth-гарнитуры и получает из этого имени AudioDeviceID. После записи программа удаляет созданное совокупное аудиоустройство, а затем пытается установить устройство гарнитуры Bluetooth в качестве устройства вывода по умолчанию с помощью AudioObjectSetPropertyData(). Однако, несмотря на то, что функция возвращает успешный результат (noErr), устройство не устанавливается по умолчанию.

Прежде чем прекратить запись, я еще раз проверяю, совпадает ли устройство вывода по умолчанию с предыдущим. Если отображается по-другому, я пытаюсь установить его еще раз. Однако он снова возвращает успех, но еще не устанавливает его по умолчанию.

Я не уверен, является ли это проблемой реализации функции или сама функция не работает. Если у кого-то есть предложения или кто-то сталкивался с подобной проблемой, буду очень признателен за любую помощь или совет.

      #include <CoreAudio/AudioHardware.h>
#include <CoreAudio/AudioServerPlugIn.h>

OSStatus SetDefaultOutputDeviceFromName(const char *_name = nullptr)
{
    OSStatus err = noErr;
    if(_name != nullptr)
    {
        std::string log_ = "[Destroy Aggregate Device]: Selected loopback device name: " + std::string(_name) +  "\n";
        synchronized_logger_function(log_);
        AudioDeviceID deviceID = findDeviceIDFromDeviceName(_name);
        if(deviceID == kAudioObjectUnknown) {
           std::cerr << "Error in getting Device Id from name\n";
        }
        else 
        {
            AudioObjectPropertyAddress defaultDeviceAOPA;
            defaultDeviceAOPA.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
            defaultDeviceAOPA.mScope = kAudioObjectPropertyScopeGlobal;
            defaultDeviceAOPA.mElement = kAudioObjectPropertyElementMain;

            err = AudioObjectSetPropertyData(kAudioObjectSystemObject, &defaultDeviceAOPA, 0, NULL, sizeof(AudioDeviceID), &deviceID);
            // pause again to give the changes time to take effect
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

            if (err)
            {
                // printf("[Remove Aggregate Device]: Error setting default output device: %d\n", err);
            }           
            else
            {
                // printf("[Create Aggregate Device]: Previous device set as default output device.\n");
            }
        }
        // MA_ASSERT(deviceID != kAudioObjectUnknown);
    }
    return noErr;
}

OSStatus DestroyAggregateDevice(AudioDeviceID inDeviceToDestroy, const char *_name = nullptr)
{
    OSStatus osErr = noErr;

    //-----------------------
    // Start by getting the base audio hardware plugin
    //-----------------------

    // UInt32 outSize;
    // Boolean outWritable;
    // osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
    // if (osErr != noErr) return osErr;

    AudioObjectPropertyAddress propertyAddress = {
        kAudioHardwarePropertyPlugInForBundleID,
        kAudioObjectPropertyScopeGlobal,
        kAudioObjectPropertyElementMain};

    UInt32 outSize = 0;
    // Boolean writable = false;

    OSStatus err = AudioObjectGetPropertyDataSize(
        kAudioObjectSystemObject,
        &propertyAddress,
        0,
        NULL,
        &outSize);

    if (err != noErr)
    {
        // Handle error
        synchronized_logger_function(std::string("[Destroy aggregate device]: Error occured in removing aggregate device\n"));
    }

    AudioValueTranslation pluginAVT;

    CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
    AudioObjectID pluginID;

    pluginAVT.mInputData = &inBundleRef;
    pluginAVT.mInputDataSize = sizeof(inBundleRef);
    pluginAVT.mOutputData = &pluginID;
    pluginAVT.mOutputDataSize = sizeof(pluginID);
    osErr = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &outSize, &pluginAVT);
    // osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
    if (osErr != noErr)
        return osErr;

    //-----------------------
    // Feed the AudioDeviceID to the plugin, to destroy the aggregate device
    //-----------------------

    AudioObjectPropertyAddress pluginAOPA;
    pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
    pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
    pluginAOPA.mElement = kAudioObjectPropertyElementMain;
    UInt32 outDataSize;

    osErr = AudioObjectGetPropertyDataSize(pluginID, &pluginAOPA, 0, NULL, &outDataSize);
    if (osErr != noErr)
    {
        return osErr;
    }

    osErr = AudioObjectGetPropertyData(pluginID, &pluginAOPA, 0, NULL, &outDataSize, &inDeviceToDestroy);
    if (osErr != noErr)
    {
        return osErr;
    }
    // pause again to give the changes time to take effect
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

    SetDefaultOutputDeviceFromName(_name);

    return noErr;
}

0 ответов

Другие вопросы по тегам