summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_coreaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/ao_coreaudio.c')
-rw-r--r--audio/out/ao_coreaudio.c259
1 files changed, 4 insertions, 255 deletions
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index a91ba95c2f..09ca4fa8cd 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -25,8 +25,9 @@
#include "options/m_option.h"
#include "misc/ring.h"
#include "common/msg.h"
-#include "audio/out/ao_coreaudio_properties.h"
-#include "audio/out/ao_coreaudio_utils.h"
+#include "ao_coreaudio_chmap.h"
+#include "ao_coreaudio_properties.h"
+#include "ao_coreaudio_utils.h"
struct priv {
AudioDeviceID device;
@@ -37,9 +38,6 @@ struct priv {
int change_physical_format;
};
-bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
- struct mp_chmap *chmap);
-
static int64_t ca_get_hardware_latency(struct ao *ao) {
struct priv *p = ao->priv;
@@ -123,7 +121,6 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
return CONTROL_UNKNOWN;
}
-static bool init_chmap(struct ao *ao);
static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd);
static void init_physical_format(struct ao *ao);
@@ -160,7 +157,7 @@ static int init(struct ao *ao)
if (p->change_physical_format)
init_physical_format(ao);
- if (!init_chmap(ao))
+ if (!ca_init_chmap(ao, p->device))
goto coreaudio_error;
ao->format = af_fmt_from_planar(ao->format);
@@ -177,97 +174,6 @@ coreaudio_error:
return CONTROL_ERROR;
}
-static AudioChannelLayout* ca_query_layout(struct ao *ao, void *talloc_ctx)
-{
- struct priv *p = ao->priv;
- OSStatus err;
- uint32_t psize;
- AudioChannelLayout *r = NULL;
-
- AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {
- .mSelector = kAudioDevicePropertyPreferredChannelLayout,
- .mScope = kAudioDevicePropertyScopeOutput,
- .mElement = kAudioObjectPropertyElementWildcard,
- };
-
- err = AudioObjectGetPropertyDataSize(p->device, &p_addr, 0, NULL, &psize);
- CHECK_CA_ERROR("could not get device preferred layout (size)");
-
- r = talloc_size(talloc_ctx, psize);
-
- err = AudioObjectGetPropertyData(p->device, &p_addr, 0, NULL, &psize, r);
- CHECK_CA_ERROR("could not get device preferred layout (get)");
-
-coreaudio_error:
- return r;
-}
-
-static AudioChannelLayout* ca_query_stereo_layout(struct ao *ao, void *talloc_ctx)
-{
- struct priv *p = ao->priv;
- OSStatus err;
- const int nch = 2;
- uint32_t channels[nch];
- AudioChannelLayout *r = NULL;
-
- AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {
- .mSelector = kAudioDevicePropertyPreferredChannelsForStereo,
- .mScope = kAudioDevicePropertyScopeOutput,
- .mElement = kAudioObjectPropertyElementWildcard,
- };
-
- uint32_t psize = sizeof(channels);
- err = AudioObjectGetPropertyData(p->device, &p_addr, 0, NULL, &psize, channels);
- CHECK_CA_ERROR("could not get device preferred stereo layout");
-
- psize = sizeof(AudioChannelLayout) + nch * sizeof(AudioChannelDescription);
- r = talloc_zero_size(talloc_ctx, psize);
- r->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
- r->mNumberChannelDescriptions = nch;
-
- AudioChannelDescription desc = {0};
- desc.mChannelFlags = kAudioChannelFlags_AllOff;
-
- for(int i = 0; i < nch; i++) {
- desc.mChannelLabel = channels[i];
- r->mChannelDescriptions[i] = desc;
- }
-
-coreaudio_error:
- return r;
-}
-
-static bool init_chmap(struct ao *ao)
-{
- struct priv *p = ao->priv;
- void *ta_ctx = talloc_new(NULL);
-
- struct mp_chmap_sel chmap_sel = {.tmp = p};
- struct mp_chmap chmap = {0};
-
- AudioChannelLayout *ml = ca_query_layout(ao, ta_ctx);
- if (ml && ca_layout_to_mp_chmap(ao, ml, &chmap))
- mp_chmap_sel_add_map(&chmap_sel, &chmap);
-
- AudioChannelLayout *sl = ca_query_stereo_layout(ao, ta_ctx);
- if (sl && ca_layout_to_mp_chmap(ao, sl, &chmap))
- mp_chmap_sel_add_map(&chmap_sel, &chmap);
-
- talloc_free(ta_ctx);
-
- if (!ao_chmap_sel_adjust(ao, &chmap_sel, &ao->channels)) {
- MP_ERR(ao, "could not select a suitable channel map among the "
- "hardware supported ones. Make sure to configure your "
- "output device correctly in 'Audio MIDI Setup.app'\n");
- goto coreaudio_error;
- }
-
- return true;
-
-coreaudio_error:
- return false;
-}
-
static void init_physical_format(struct ao *ao)
{
struct priv *p = ao->priv;
@@ -469,163 +375,6 @@ static void hotplug_uninit(struct ao *ao)
}
}
-
-// Channel Mapping functions
-static const int speaker_map[][2] = {
- { kAudioChannelLabel_Left, MP_SPEAKER_ID_FL },
- { kAudioChannelLabel_Right, MP_SPEAKER_ID_FR },
- { kAudioChannelLabel_Center, MP_SPEAKER_ID_FC },
- { kAudioChannelLabel_LFEScreen, MP_SPEAKER_ID_LFE },
- { kAudioChannelLabel_LeftSurround, MP_SPEAKER_ID_BL },
- { kAudioChannelLabel_RightSurround, MP_SPEAKER_ID_BR },
- { kAudioChannelLabel_LeftCenter, MP_SPEAKER_ID_FLC },
- { kAudioChannelLabel_RightCenter, MP_SPEAKER_ID_FRC },
- { kAudioChannelLabel_CenterSurround, MP_SPEAKER_ID_BC },
- { kAudioChannelLabel_LeftSurroundDirect, MP_SPEAKER_ID_SL },
- { kAudioChannelLabel_RightSurroundDirect, MP_SPEAKER_ID_SR },
- { kAudioChannelLabel_TopCenterSurround, MP_SPEAKER_ID_TC },
- { kAudioChannelLabel_VerticalHeightLeft, MP_SPEAKER_ID_TFL },
- { kAudioChannelLabel_VerticalHeightCenter, MP_SPEAKER_ID_TFC },
- { kAudioChannelLabel_VerticalHeightRight, MP_SPEAKER_ID_TFR },
- { kAudioChannelLabel_TopBackLeft, MP_SPEAKER_ID_TBL },
- { kAudioChannelLabel_TopBackCenter, MP_SPEAKER_ID_TBC },
- { kAudioChannelLabel_TopBackRight, MP_SPEAKER_ID_TBR },
-
- // unofficial extensions
- { kAudioChannelLabel_RearSurroundLeft, MP_SPEAKER_ID_SDL },
- { kAudioChannelLabel_RearSurroundRight, MP_SPEAKER_ID_SDR },
- { kAudioChannelLabel_LeftWide, MP_SPEAKER_ID_WL },
- { kAudioChannelLabel_RightWide, MP_SPEAKER_ID_WR },
- { kAudioChannelLabel_LFE2, MP_SPEAKER_ID_LFE2 },
-
- { kAudioChannelLabel_HeadphonesLeft, MP_SPEAKER_ID_DL },
- { kAudioChannelLabel_HeadphonesRight, MP_SPEAKER_ID_DR },
-
- { kAudioChannelLabel_Unknown, MP_SPEAKER_ID_NA0 },
-
- { 0, -1 },
-};
-
-static int ca_label_to_mp_speaker_id(AudioChannelLabel label)
-{
- for (int i = 0; speaker_map[i][1] >= 0; i++)
- if (speaker_map[i][0] == label)
- return speaker_map[i][1];
- return -1;
-}
-
-static void ca_log_layout(struct ao *ao, int l, AudioChannelLayout *layout)
-{
- if (!mp_msg_test(ao->log, l))
- return;
-
- AudioChannelDescription *descs = layout->mChannelDescriptions;
-
- mp_msg(ao->log, l, "layout: tag: <%u>, bitmap: <%u>, "
- "descriptions <%u>\n",
- (unsigned) layout->mChannelLayoutTag,
- (unsigned) layout->mChannelBitmap,
- (unsigned) layout->mNumberChannelDescriptions);
-
- for (int i = 0; i < layout->mNumberChannelDescriptions; i++) {
- AudioChannelDescription d = descs[i];
- mp_msg(ao->log, l, " - description %d: label <%u, %u>, "
- " flags: <%u>, coords: <%f, %f, %f>\n", i,
- (unsigned) d.mChannelLabel,
- (unsigned) ca_label_to_mp_speaker_id(d.mChannelLabel),
- (unsigned) d.mChannelFlags,
- d.mCoordinates[0],
- d.mCoordinates[1],
- d.mCoordinates[2]);
- }
-}
-
-static AudioChannelLayout *ca_layout_to_custom_layout(
- struct ao *ao, void *talloc_ctx, AudioChannelLayout *l)
-{
- AudioChannelLayoutTag tag = l->mChannelLayoutTag;
- AudioChannelLayout *r;
- OSStatus err;
-
- if (tag == kAudioChannelLayoutTag_UseChannelBitmap) {
- uint32_t psize;
- err = AudioFormatGetPropertyInfo(
- kAudioFormatProperty_ChannelLayoutForBitmap,
- sizeof(uint32_t), &l->mChannelBitmap, &psize);
- CHECK_CA_ERROR("failed to convert channel bitmap to descriptions (info)");
- r = talloc_size(NULL, psize);
- err = AudioFormatGetProperty(
- kAudioFormatProperty_ChannelLayoutForBitmap,
- sizeof(uint32_t), &l->mChannelBitmap, &psize, r);
- CHECK_CA_ERROR("failed to convert channel bitmap to descriptions (get)");
- } else if (tag != kAudioChannelLayoutTag_UseChannelDescriptions) {
- uint32_t psize;
- err = AudioFormatGetPropertyInfo(
- kAudioFormatProperty_ChannelLayoutForTag,
- sizeof(AudioChannelLayoutTag), &l->mChannelLayoutTag, &psize);
- r = talloc_size(NULL, psize);
- CHECK_CA_ERROR("failed to convert channel tag to descriptions (info)");
- err = AudioFormatGetProperty(
- kAudioFormatProperty_ChannelLayoutForTag,
- sizeof(AudioChannelLayoutTag), &l->mChannelLayoutTag, &psize, r);
- CHECK_CA_ERROR("failed to convert channel tag to descriptions (get)");
- } else {
- r = l;
- }
-
- return r;
-coreaudio_error:
- return NULL;
-}
-
-bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
- struct mp_chmap *chmap)
-{
- void *talloc_ctx = talloc_new(NULL);
-
- MP_DBG(ao, "input channel layout:\n");
- ca_log_layout(ao, MSGL_DEBUG, layout);
-
- AudioChannelLayout *l = ca_layout_to_custom_layout(ao, talloc_ctx, layout);
- if (!l)
- goto coreaudio_error;
-
- MP_VERBOSE(ao, "converted input channel layout:\n");
- ca_log_layout(ao, MSGL_V, l);
-
- if (l->mNumberChannelDescriptions > MP_NUM_CHANNELS) {
- MP_VERBOSE(ao, "layout has too many descriptions (%u, max: %d)\n",
- (unsigned) l->mNumberChannelDescriptions, MP_NUM_CHANNELS);
- return false;
- }
-
- int next_na = MP_SPEAKER_ID_NA0;
- for (int n = 0; n < l->mNumberChannelDescriptions; n++) {
- AudioChannelLabel label = l->mChannelDescriptions[n].mChannelLabel;
- uint8_t speaker = ca_label_to_mp_speaker_id(label);
- if (speaker == MP_SPEAKER_ID_NA0 && next_na < MP_SPEAKER_ID_NA_LAST)
- {
- speaker = next_na++;
- }
- if (speaker < 0) {
- MP_VERBOSE(ao, "channel label=%u unusable to build channel "
- "bitmap, skipping layout\n", (unsigned) label);
- goto coreaudio_error;
- } else {
- chmap->speaker[n] = speaker;
- chmap->num = n + 1;
- }
- }
-
- talloc_free(talloc_ctx);
- return chmap->num > 0;
-coreaudio_error:
- MP_VERBOSE(ao, "converted input channel layout (failed):\n");
- ca_log_layout(ao, MSGL_V, layout);
- talloc_free(talloc_ctx);
- return false;
-}
-
#define OPT_BASE_STRUCT struct priv
const struct ao_driver audio_out_coreaudio = {