summaryrefslogtreecommitdiffstats
path: root/audio/out
diff options
context:
space:
mode:
authorStefano Pigozzi <stefano.pigozzi@gmail.com>2014-07-01 19:05:43 +0200
committerStefano Pigozzi <stefano.pigozzi@gmail.com>2014-07-02 21:43:07 +0200
commitf317d24a3972b65349d7860da48822fbd058f36c (patch)
treeff63e78cf4a7951db1cb4d9dcdeb7b3486bc4534 /audio/out
parenta8ef70b0f8a5d010be5810e52e4210967079e806 (diff)
downloadmpv-f317d24a3972b65349d7860da48822fbd058f36c.tar.bz2
mpv-f317d24a3972b65349d7860da48822fbd058f36c.tar.xz
ao_coreaudio: move device related functions to the new AO
Diffstat (limited to 'audio/out')
-rw-r--r--audio/out/ao_coreaudio_device.c255
-rw-r--r--audio/out/ao_coreaudio_utils.c249
-rw-r--r--audio/out/ao_coreaudio_utils.h28
3 files changed, 255 insertions, 277 deletions
diff --git a/audio/out/ao_coreaudio_device.c b/audio/out/ao_coreaudio_device.c
index 89fd9305f0..a0610a34d5 100644
--- a/audio/out/ao_coreaudio_device.c
+++ b/audio/out/ao_coreaudio_device.c
@@ -50,6 +50,261 @@ static void audio_pause(struct ao *ao);
static void audio_resume(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 {
AudioDeviceID device; // selected device
diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c
index 4656c2c508..f5cc43db0b 100644
--- a/audio/out/ao_coreaudio_utils.c
+++ b/audio/out/ao_coreaudio_utils.c
@@ -149,255 +149,6 @@ void ca_print_asbd(struct ao *ao, const char *description,
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] = {
{ kAudioChannelLabel_Left, MP_SPEAKER_ID_FL },
{ kAudioChannelLabel_Right, MP_SPEAKER_ID_FR },
diff --git a/audio/out/ao_coreaudio_utils.h b/audio/out/ao_coreaudio_utils.h
index f44ea28e82..b9b65eb5be 100644
--- a/audio/out/ao_coreaudio_utils.h
+++ b/audio/out/ao_coreaudio_utils.h
@@ -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,
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,
struct mp_chmap *chmap);