OSStatus ca_select_device(struct ao *ao, char* name, AudioDeviceID *device) { OSStatus err = noErr; int selection = name ? strtol(name, (char **)NULL, 10) : -1; if (errno == EINVAL || errno == ERANGE) { selection = -1; MP_WARN(ao, "device identifier '%s' is invalid\n", name); } *device = 0; if (selection < 0) { // device not set by user, get the default one err = CA_GET(kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice, device); CHECK_CA_ERROR("could not get default audio device"); } else { *device = selection; } if (mp_msg_test(ao->log, MSGL_V)) { char *desc; err = CA_GET_STR(*device, kAudioObjectPropertyName, &desc); CHECK_CA_ERROR("could not get selected audio device name"); MP_VERBOSE(ao, "selected audio output device: %s (%" PRIu32 ")\n", desc, *device); talloc_free(desc); } coreaudio_error: return err; }
static void init_physical_format(struct ao *ao) { struct priv *p = ao->priv; OSErr err; AudioStreamBasicDescription asbd; ca_fill_asbd(ao, &asbd); AudioStreamID *streams; size_t n_streams; err = CA_GET_ARY_O(p->device, kAudioDevicePropertyStreams, &streams, &n_streams); CHECK_CA_ERROR("could not get number of streams"); for (int i = 0; i < n_streams; i++) { AudioStreamRangedDescription *formats; size_t n_formats; err = CA_GET_ARY(streams[i], kAudioStreamPropertyAvailablePhysicalFormats, &formats, &n_formats); if (!CHECK_CA_WARN("could not get number of stream formats")) continue; // try next one MP_VERBOSE(ao, "Looking at formats in substream %d...\n", i); AudioStreamBasicDescription best_asbd = {0}; for (int j = 0; j < n_formats; j++) { AudioStreamBasicDescription *stream_asbd = &formats[j].mFormat; ca_print_asbd(ao, "- ", stream_asbd); if (!best_asbd.mFormatID || ca_asbd_is_better(&asbd, &best_asbd, stream_asbd)) best_asbd = *stream_asbd; } if (best_asbd.mFormatID) { p->original_asbd_stream = streams[i]; err = CA_GET(p->original_asbd_stream, kAudioStreamPropertyPhysicalFormat, &p->original_asbd); CHECK_CA_WARN("could not get current physical stream format"); ca_change_physical_format_sync(ao, streams[i], best_asbd); break; } } coreaudio_error: return; }
.mOutputDataSize = sizeof(*device), }; uint32_t size = sizeof(AudioValueTranslation); AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) { .mSelector = kAudioHardwarePropertyDeviceForUID, .mScope = kAudioObjectPropertyScopeGlobal, .mElement = kAudioObjectPropertyElementMaster, }; err = AudioObjectGetPropertyData( kAudioObjectSystemObject, &p_addr, 0, 0, &size, &v); CFRelease(uid); CHECK_CA_ERROR("unable to query for device UID"); } else { // device not set by user, get the default one err = CA_GET(kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice, device); CHECK_CA_ERROR("could not get default audio device"); } if (mp_msg_test(ao->log, MSGL_V)) { char *desc; OSStatus err2 = CA_GET_STR(*device, kAudioObjectPropertyName, &desc); if (err2 == noErr) { MP_VERBOSE(ao, "selected audio output device: %s (%" PRIu32 ")\n", desc, *device); talloc_free(desc); } } coreaudio_error: