mirror of
https://github.com/mpv-player/mpv
synced 2025-03-25 04:38:01 +00:00
ao_coreaudio: move device related functions to the new AO
This commit is contained in:
parent
a8ef70b0f8
commit
f317d24a39
@ -50,6 +50,261 @@ static void audio_pause(struct ao *ao);
|
|||||||
static void audio_resume(struct ao *ao);
|
static void audio_resume(struct ao *ao);
|
||||||
static void reset(struct ao *ao);
|
static void reset(struct ao *ao);
|
||||||
|
|
||||||
|
static bool ca_format_is_digital(AudioStreamBasicDescription asbd)
|
||||||
|
{
|
||||||
|
switch (asbd.mFormatID)
|
||||||
|
case 'IAC3':
|
||||||
|
case 'iac3':
|
||||||
|
case kAudioFormat60958AC3:
|
||||||
|
case kAudioFormatAC3:
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ca_stream_supports_digital(struct ao *ao, AudioStreamID stream)
|
||||||
|
{
|
||||||
|
AudioStreamRangedDescription *formats = NULL;
|
||||||
|
size_t n_formats;
|
||||||
|
|
||||||
|
OSStatus err =
|
||||||
|
CA_GET_ARY(stream, kAudioStreamPropertyAvailablePhysicalFormats,
|
||||||
|
&formats, &n_formats);
|
||||||
|
|
||||||
|
CHECK_CA_ERROR("Could not get number of stream formats.");
|
||||||
|
|
||||||
|
for (int i = 0; i < n_formats; i++) {
|
||||||
|
AudioStreamBasicDescription asbd = formats[i].mFormat;
|
||||||
|
ca_print_asbd(ao, "supported format:", &(asbd));
|
||||||
|
if (ca_format_is_digital(asbd)) {
|
||||||
|
talloc_free(formats);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
talloc_free(formats);
|
||||||
|
coreaudio_error:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ca_device_supports_digital(struct ao *ao, AudioDeviceID device)
|
||||||
|
{
|
||||||
|
AudioStreamID *streams = NULL;
|
||||||
|
size_t n_streams;
|
||||||
|
|
||||||
|
/* Retrieve all the output streams. */
|
||||||
|
OSStatus err =
|
||||||
|
CA_GET_ARY_O(device, kAudioDevicePropertyStreams, &streams, &n_streams);
|
||||||
|
|
||||||
|
CHECK_CA_ERROR("could not get number of streams.");
|
||||||
|
|
||||||
|
for (int i = 0; i < n_streams; i++) {
|
||||||
|
if (ca_stream_supports_digital(ao, streams[i])) {
|
||||||
|
talloc_free(streams);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
talloc_free(streams);
|
||||||
|
|
||||||
|
coreaudio_error:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_property_listener(
|
||||||
|
AudioObjectPropertySelector selector,
|
||||||
|
AudioObjectID object, uint32_t n_addresses,
|
||||||
|
const AudioObjectPropertyAddress addresses[],
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
void *talloc_ctx = talloc_new(NULL);
|
||||||
|
|
||||||
|
for (int i = 0; i < n_addresses; i++) {
|
||||||
|
if (addresses[i].mSelector == selector) {
|
||||||
|
if (data) *(volatile int *)data = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
talloc_free(talloc_ctx);
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_stream_listener(
|
||||||
|
AudioObjectID object, uint32_t n_addresses,
|
||||||
|
const AudioObjectPropertyAddress addresses[],
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
return ca_property_listener(kAudioStreamPropertyPhysicalFormat,
|
||||||
|
object, n_addresses, addresses, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_device_listener(
|
||||||
|
AudioObjectID object, uint32_t n_addresses,
|
||||||
|
const AudioObjectPropertyAddress addresses[],
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
return ca_property_listener(kAudioDevicePropertyDeviceHasChanged,
|
||||||
|
object, n_addresses, addresses, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid) {
|
||||||
|
*pid = getpid();
|
||||||
|
OSStatus err = CA_SET(device, kAudioDevicePropertyHogMode, pid);
|
||||||
|
if (err != noErr)
|
||||||
|
*pid = -1;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid) {
|
||||||
|
if (*pid == getpid()) {
|
||||||
|
*pid = -1;
|
||||||
|
return CA_SET(device, kAudioDevicePropertyHogMode, &pid);
|
||||||
|
}
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_change_mixing(struct ao *ao, AudioDeviceID device,
|
||||||
|
uint32_t val, bool *changed) {
|
||||||
|
*changed = false;
|
||||||
|
|
||||||
|
AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {
|
||||||
|
.mSelector = kAudioDevicePropertySupportsMixing,
|
||||||
|
.mScope = kAudioObjectPropertyScopeGlobal,
|
||||||
|
.mElement = kAudioObjectPropertyElementMaster,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (AudioObjectHasProperty(device, &p_addr)) {
|
||||||
|
OSStatus err;
|
||||||
|
Boolean writeable = 0;
|
||||||
|
err = CA_SETTABLE(device, kAudioDevicePropertySupportsMixing,
|
||||||
|
&writeable);
|
||||||
|
|
||||||
|
if (!CHECK_CA_WARN("can't tell if mixing property is settable")) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!writeable)
|
||||||
|
return noErr;
|
||||||
|
|
||||||
|
err = CA_SET(device, kAudioDevicePropertySupportsMixing, &val);
|
||||||
|
if (err != noErr)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!CHECK_CA_WARN("can't set mix mode")) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_disable_mixing(struct ao *ao,
|
||||||
|
AudioDeviceID device, bool *changed) {
|
||||||
|
return ca_change_mixing(ao, device, 0, changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_enable_mixing(struct ao *ao,
|
||||||
|
AudioDeviceID device, bool changed) {
|
||||||
|
if (changed) {
|
||||||
|
bool dont_care = false;
|
||||||
|
return ca_change_mixing(ao, device, 1, &dont_care);
|
||||||
|
}
|
||||||
|
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_change_device_listening(AudioDeviceID device,
|
||||||
|
void *flag, bool enabled)
|
||||||
|
{
|
||||||
|
AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {
|
||||||
|
.mSelector = kAudioDevicePropertyDeviceHasChanged,
|
||||||
|
.mScope = kAudioObjectPropertyScopeGlobal,
|
||||||
|
.mElement = kAudioObjectPropertyElementMaster,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
return AudioObjectAddPropertyListener(
|
||||||
|
device, &p_addr, ca_device_listener, flag);
|
||||||
|
} else {
|
||||||
|
return AudioObjectRemovePropertyListener(
|
||||||
|
device, &p_addr, ca_device_listener, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_enable_device_listener(AudioDeviceID device, void *flag) {
|
||||||
|
return ca_change_device_listening(device, flag, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OSStatus ca_disable_device_listener(AudioDeviceID device, void *flag) {
|
||||||
|
return ca_change_device_listening(device, flag, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ca_change_format(struct ao *ao, AudioStreamID stream,
|
||||||
|
AudioStreamBasicDescription change_format)
|
||||||
|
{
|
||||||
|
OSStatus err = noErr;
|
||||||
|
AudioObjectPropertyAddress p_addr;
|
||||||
|
volatile int stream_format_changed = 0;
|
||||||
|
|
||||||
|
ca_print_asbd(ao, "setting stream format:", &change_format);
|
||||||
|
|
||||||
|
/* Install the callback. */
|
||||||
|
p_addr = (AudioObjectPropertyAddress) {
|
||||||
|
.mSelector = kAudioStreamPropertyPhysicalFormat,
|
||||||
|
.mScope = kAudioObjectPropertyScopeGlobal,
|
||||||
|
.mElement = kAudioObjectPropertyElementMaster,
|
||||||
|
};
|
||||||
|
|
||||||
|
err = AudioObjectAddPropertyListener(stream, &p_addr, ca_stream_listener,
|
||||||
|
(void *)&stream_format_changed);
|
||||||
|
if (!CHECK_CA_WARN("can't add property listener during format change")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change the format. */
|
||||||
|
err = CA_SET(stream, kAudioStreamPropertyPhysicalFormat, &change_format);
|
||||||
|
if (!CHECK_CA_WARN("error changing physical format")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The AudioStreamSetProperty is not only asynchronious,
|
||||||
|
* it is also not Atomic, in its behaviour.
|
||||||
|
* Therefore we check 5 times before we really give up. */
|
||||||
|
bool format_set = false;
|
||||||
|
for (int i = 0; !format_set && i < 5; i++) {
|
||||||
|
for (int j = 0; !stream_format_changed && j < 50; j++)
|
||||||
|
mp_sleep_us(10000);
|
||||||
|
|
||||||
|
if (stream_format_changed) {
|
||||||
|
stream_format_changed = 0;
|
||||||
|
} else {
|
||||||
|
MP_VERBOSE(ao, "reached timeout\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioStreamBasicDescription actual_format;
|
||||||
|
err = CA_GET(stream, kAudioStreamPropertyPhysicalFormat, &actual_format);
|
||||||
|
|
||||||
|
ca_print_asbd(ao, "actual format in use:", &actual_format);
|
||||||
|
if (actual_format.mSampleRate == change_format.mSampleRate &&
|
||||||
|
actual_format.mFormatID == change_format.mFormatID &&
|
||||||
|
actual_format.mFramesPerPacket == change_format.mFramesPerPacket) {
|
||||||
|
format_set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = AudioObjectRemovePropertyListener(stream, &p_addr, ca_stream_listener,
|
||||||
|
(void *)&stream_format_changed);
|
||||||
|
|
||||||
|
if (!CHECK_CA_WARN("can't remove property listener")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return format_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct priv {
|
struct priv {
|
||||||
AudioDeviceID device; // selected device
|
AudioDeviceID device; // selected device
|
||||||
|
|
||||||
|
@ -149,255 +149,6 @@ void ca_print_asbd(struct ao *ao, const char *description,
|
|||||||
talloc_free(format);
|
talloc_free(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ca_format_is_digital(AudioStreamBasicDescription asbd)
|
|
||||||
{
|
|
||||||
switch (asbd.mFormatID)
|
|
||||||
case 'IAC3':
|
|
||||||
case 'iac3':
|
|
||||||
case kAudioFormat60958AC3:
|
|
||||||
case kAudioFormatAC3:
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ca_stream_supports_digital(struct ao *ao, AudioStreamID stream)
|
|
||||||
{
|
|
||||||
AudioStreamRangedDescription *formats = NULL;
|
|
||||||
size_t n_formats;
|
|
||||||
|
|
||||||
OSStatus err =
|
|
||||||
CA_GET_ARY(stream, kAudioStreamPropertyAvailablePhysicalFormats,
|
|
||||||
&formats, &n_formats);
|
|
||||||
|
|
||||||
CHECK_CA_ERROR("Could not get number of stream formats.");
|
|
||||||
|
|
||||||
for (int i = 0; i < n_formats; i++) {
|
|
||||||
AudioStreamBasicDescription asbd = formats[i].mFormat;
|
|
||||||
ca_print_asbd(ao, "supported format:", &(asbd));
|
|
||||||
if (ca_format_is_digital(asbd)) {
|
|
||||||
talloc_free(formats);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
talloc_free(formats);
|
|
||||||
coreaudio_error:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ca_device_supports_digital(struct ao *ao, AudioDeviceID device)
|
|
||||||
{
|
|
||||||
AudioStreamID *streams = NULL;
|
|
||||||
size_t n_streams;
|
|
||||||
|
|
||||||
/* Retrieve all the output streams. */
|
|
||||||
OSStatus err =
|
|
||||||
CA_GET_ARY_O(device, kAudioDevicePropertyStreams, &streams, &n_streams);
|
|
||||||
|
|
||||||
CHECK_CA_ERROR("could not get number of streams.");
|
|
||||||
|
|
||||||
for (int i = 0; i < n_streams; i++) {
|
|
||||||
if (ca_stream_supports_digital(ao, streams[i])) {
|
|
||||||
talloc_free(streams);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
talloc_free(streams);
|
|
||||||
|
|
||||||
coreaudio_error:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_property_listener(AudioObjectPropertySelector selector,
|
|
||||||
AudioObjectID object, uint32_t n_addresses,
|
|
||||||
const AudioObjectPropertyAddress addresses[],
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
void *talloc_ctx = talloc_new(NULL);
|
|
||||||
|
|
||||||
for (int i = 0; i < n_addresses; i++) {
|
|
||||||
if (addresses[i].mSelector == selector) {
|
|
||||||
if (data) *(volatile int *)data = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
talloc_free(talloc_ctx);
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_stream_listener(AudioObjectID object, uint32_t n_addresses,
|
|
||||||
const AudioObjectPropertyAddress addresses[],
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
return ca_property_listener(kAudioStreamPropertyPhysicalFormat,
|
|
||||||
object, n_addresses, addresses, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_device_listener(AudioObjectID object, uint32_t n_addresses,
|
|
||||||
const AudioObjectPropertyAddress addresses[],
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
return ca_property_listener(kAudioDevicePropertyDeviceHasChanged,
|
|
||||||
object, n_addresses, addresses, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid) {
|
|
||||||
*pid = getpid();
|
|
||||||
OSStatus err = CA_SET(device, kAudioDevicePropertyHogMode, pid);
|
|
||||||
if (err != noErr)
|
|
||||||
*pid = -1;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid) {
|
|
||||||
if (*pid == getpid()) {
|
|
||||||
*pid = -1;
|
|
||||||
return CA_SET(device, kAudioDevicePropertyHogMode, &pid);
|
|
||||||
}
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static OSStatus ca_change_mixing(struct ao *ao, AudioDeviceID device,
|
|
||||||
uint32_t val, bool *changed) {
|
|
||||||
*changed = false;
|
|
||||||
|
|
||||||
AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {
|
|
||||||
.mSelector = kAudioDevicePropertySupportsMixing,
|
|
||||||
.mScope = kAudioObjectPropertyScopeGlobal,
|
|
||||||
.mElement = kAudioObjectPropertyElementMaster,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (AudioObjectHasProperty(device, &p_addr)) {
|
|
||||||
OSStatus err;
|
|
||||||
Boolean writeable = 0;
|
|
||||||
err = CA_SETTABLE(device, kAudioDevicePropertySupportsMixing,
|
|
||||||
&writeable);
|
|
||||||
|
|
||||||
if (!CHECK_CA_WARN("can't tell if mixing property is settable")) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!writeable)
|
|
||||||
return noErr;
|
|
||||||
|
|
||||||
err = CA_SET(device, kAudioDevicePropertySupportsMixing, &val);
|
|
||||||
if (err != noErr)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (!CHECK_CA_WARN("can't set mix mode")) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
*changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_disable_mixing(struct ao *ao, AudioDeviceID device, bool *changed) {
|
|
||||||
return ca_change_mixing(ao, device, 0, changed);
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_enable_mixing(struct ao *ao, AudioDeviceID device, bool changed) {
|
|
||||||
if (changed) {
|
|
||||||
bool dont_care = false;
|
|
||||||
return ca_change_mixing(ao, device, 1, &dont_care);
|
|
||||||
}
|
|
||||||
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static OSStatus ca_change_device_listening(AudioDeviceID device,
|
|
||||||
void *flag, bool enabled)
|
|
||||||
{
|
|
||||||
AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {
|
|
||||||
.mSelector = kAudioDevicePropertyDeviceHasChanged,
|
|
||||||
.mScope = kAudioObjectPropertyScopeGlobal,
|
|
||||||
.mElement = kAudioObjectPropertyElementMaster,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
return AudioObjectAddPropertyListener(
|
|
||||||
device, &p_addr, ca_device_listener, flag);
|
|
||||||
} else {
|
|
||||||
return AudioObjectRemovePropertyListener(
|
|
||||||
device, &p_addr, ca_device_listener, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_enable_device_listener(AudioDeviceID device, void *flag) {
|
|
||||||
return ca_change_device_listening(device, flag, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus ca_disable_device_listener(AudioDeviceID device, void *flag) {
|
|
||||||
return ca_change_device_listening(device, flag, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ca_change_format(struct ao *ao, AudioStreamID stream,
|
|
||||||
AudioStreamBasicDescription change_format)
|
|
||||||
{
|
|
||||||
OSStatus err = noErr;
|
|
||||||
AudioObjectPropertyAddress p_addr;
|
|
||||||
volatile int stream_format_changed = 0;
|
|
||||||
|
|
||||||
ca_print_asbd(ao, "setting stream format:", &change_format);
|
|
||||||
|
|
||||||
/* Install the callback. */
|
|
||||||
p_addr = (AudioObjectPropertyAddress) {
|
|
||||||
.mSelector = kAudioStreamPropertyPhysicalFormat,
|
|
||||||
.mScope = kAudioObjectPropertyScopeGlobal,
|
|
||||||
.mElement = kAudioObjectPropertyElementMaster,
|
|
||||||
};
|
|
||||||
|
|
||||||
err = AudioObjectAddPropertyListener(stream, &p_addr, ca_stream_listener,
|
|
||||||
(void *)&stream_format_changed);
|
|
||||||
if (!CHECK_CA_WARN("can't add property listener during format change")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Change the format. */
|
|
||||||
err = CA_SET(stream, kAudioStreamPropertyPhysicalFormat, &change_format);
|
|
||||||
if (!CHECK_CA_WARN("error changing physical format")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The AudioStreamSetProperty is not only asynchronious,
|
|
||||||
* it is also not Atomic, in its behaviour.
|
|
||||||
* Therefore we check 5 times before we really give up. */
|
|
||||||
bool format_set = false;
|
|
||||||
for (int i = 0; !format_set && i < 5; i++) {
|
|
||||||
for (int j = 0; !stream_format_changed && j < 50; j++)
|
|
||||||
mp_sleep_us(10000);
|
|
||||||
|
|
||||||
if (stream_format_changed) {
|
|
||||||
stream_format_changed = 0;
|
|
||||||
} else {
|
|
||||||
MP_VERBOSE(ao, "reached timeout\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioStreamBasicDescription actual_format;
|
|
||||||
err = CA_GET(stream, kAudioStreamPropertyPhysicalFormat, &actual_format);
|
|
||||||
|
|
||||||
ca_print_asbd(ao, "actual format in use:", &actual_format);
|
|
||||||
if (actual_format.mSampleRate == change_format.mSampleRate &&
|
|
||||||
actual_format.mFormatID == change_format.mFormatID &&
|
|
||||||
actual_format.mFramesPerPacket == change_format.mFramesPerPacket) {
|
|
||||||
format_set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = AudioObjectRemovePropertyListener(stream, &p_addr, ca_stream_listener,
|
|
||||||
(void *)&stream_format_changed);
|
|
||||||
|
|
||||||
if (!CHECK_CA_WARN("can't remove property listener")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return format_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int speaker_map[][2] = {
|
static const int speaker_map[][2] = {
|
||||||
{ kAudioChannelLabel_Left, MP_SPEAKER_ID_FL },
|
{ kAudioChannelLabel_Left, MP_SPEAKER_ID_FL },
|
||||||
{ kAudioChannelLabel_Right, MP_SPEAKER_ID_FR },
|
{ kAudioChannelLabel_Right, MP_SPEAKER_ID_FR },
|
||||||
|
@ -52,34 +52,6 @@ OSStatus ca_select_device(struct ao *ao, int selection, AudioDeviceID *device);
|
|||||||
void ca_print_asbd(struct ao *ao, const char *description,
|
void ca_print_asbd(struct ao *ao, const char *description,
|
||||||
const AudioStreamBasicDescription *asbd);
|
const AudioStreamBasicDescription *asbd);
|
||||||
|
|
||||||
bool ca_format_is_digital(AudioStreamBasicDescription asbd);
|
|
||||||
bool ca_stream_supports_digital(struct ao *ao, AudioStreamID stream);
|
|
||||||
bool ca_device_supports_digital(struct ao *ao, AudioDeviceID device);
|
|
||||||
|
|
||||||
OSStatus ca_property_listener(AudioObjectPropertySelector selector,
|
|
||||||
AudioObjectID object, uint32_t n_addresses,
|
|
||||||
const AudioObjectPropertyAddress addresses[],
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
OSStatus ca_stream_listener(AudioObjectID object, uint32_t n_addresses,
|
|
||||||
const AudioObjectPropertyAddress addresses[],
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
OSStatus ca_device_listener(AudioObjectID object, uint32_t n_addresses,
|
|
||||||
const AudioObjectPropertyAddress addresses[],
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid);
|
|
||||||
OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid);
|
|
||||||
OSStatus ca_disable_mixing(struct ao *ao, AudioDeviceID device, bool *changed);
|
|
||||||
OSStatus ca_enable_mixing(struct ao *ao, AudioDeviceID device, bool changed);
|
|
||||||
|
|
||||||
OSStatus ca_enable_device_listener(AudioDeviceID device, void *flag);
|
|
||||||
OSStatus ca_disable_device_listener(AudioDeviceID device, void *flag);
|
|
||||||
|
|
||||||
bool ca_change_format(struct ao *ao, AudioStreamID stream,
|
|
||||||
AudioStreamBasicDescription change_format);
|
|
||||||
|
|
||||||
bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
|
bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
|
||||||
struct mp_chmap *chmap);
|
struct mp_chmap *chmap);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user