ao_coreaudio: split ao_coreaudio_common in two files

* ao_coreaudio_utils: contains several utility function
 * ao_coreaudio_properties: contains functions to set and get  audio object
   properties.

Conflicts:
	audio/out/ao_coreaudio.c
This commit is contained in:
Stefano Pigozzi 2013-07-13 09:48:10 +02:00
parent 5a195845e3
commit 1e37965597
6 changed files with 290 additions and 161 deletions

View File

@ -73,7 +73,9 @@ SOURCES-$(ALSA) += audio/out/ao_alsa.c
SOURCES-$(CACA) += video/out/vo_caca.c
SOURCES-$(SDL) += audio/out/ao_sdl.c
SOURCES-$(SDL2) += video/out/vo_sdl.c
SOURCES-$(COREAUDIO) += audio/out/ao_coreaudio.c
SOURCES-$(COREAUDIO) += audio/out/ao_coreaudio.c \
audio/out/ao_coreaudio_utils.c \
audio/out/ao_coreaudio_properties.c
SOURCES-$(COREVIDEO) += video/out/vo_corevideo.m
SOURCES-$(DIRECT3D) += video/out/vo_direct3d.c \
video/out/w32_common.c

View File

@ -33,14 +33,14 @@
*/
#include "config.h"
#include "audio/out/ao_coreaudio_common.c"
#include "ao.h"
#include "audio/format.h"
#include "osdep/timer.h"
#include "core/subopt-helper.h"
#include "core/mp_ring.h"
#include "core/mp_msg.h"
#include "audio/out/ao_coreaudio_properties.h"
#include "audio/out/ao_coreaudio_utils.h"
static void audio_pause(struct ao *ao);
static void audio_resume(struct ao *ao);
@ -281,9 +281,9 @@ static int init(struct ao *ao, char *params)
AudioDeviceID selected_device = 0;
if (device_opt < 0) {
// device not set by user, get the default one
err = GetAudioProperty(kAudioObjectSystemObject,
kAudioHardwarePropertyDefaultOutputDevice,
sizeof(uint32_t), &selected_device);
err = CA_GET(kAudioObjectSystemObject,
kAudioHardwarePropertyDefaultOutputDevice,
&selected_device);
CHECK_CA_ERROR("could not get default audio device");
} else {
selected_device = device_opt;
@ -551,10 +551,7 @@ static int init_digital(struct ao *ao, AudioStreamBasicDescription asbd)
uint32_t size;
uint32_t is_alive = 1;
err = GetAudioProperty(p->device,
kAudioDevicePropertyDeviceIsAlive,
sizeof(uint32_t), &is_alive);
err = CA_GET(p->device, kAudioDevicePropertyDeviceIsAlive, &is_alive);
CHECK_CA_WARN( "could not check whether device is alive");
if (!is_alive)

View File

@ -0,0 +1,126 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Abstractions on the CoreAudio API to make property setting/getting suck les
*/
#include "audio/out/ao_coreaudio_properties.h"
#include "audio/out/ao_coreaudio_utils.h"
OSStatus ca_get(AudioObjectID id, AudioObjectPropertySelector selector,
uint32_t size, void *data)
{
AudioObjectPropertyAddress p_addr = (AudioObjectPropertyAddress) {
.mSelector = selector,
.mScope = kAudioObjectPropertyScopeGlobal,
.mElement = kAudioObjectPropertyElementMaster,
};
return AudioObjectGetPropertyData(id, &p_addr, 0, NULL, &size, data);
}
uint32_t GetAudioPropertyArray(AudioObjectID id,
AudioObjectPropertySelector selector,
AudioObjectPropertyScope scope, void **data)
{
OSStatus err;
AudioObjectPropertyAddress p_addr;
UInt32 p_size;
p_addr.mSelector = selector;
p_addr.mScope = scope;
p_addr.mElement = kAudioObjectPropertyElementMaster;
err = AudioObjectGetPropertyDataSize(id, &p_addr, 0, NULL, &p_size);
CHECK_CA_ERROR("Can't fetch property size");
*data = malloc(p_size);
err = AudioObjectGetPropertyData(id, &p_addr, 0, NULL, &p_size, *data);
CHECK_CA_ERROR_L(coreaudio_error_free, "Can't fetch property data %s");
return p_size;
coreaudio_error_free:
free(*data);
coreaudio_error:
return 0;
}
uint32_t GetGlobalAudioPropertyArray(AudioObjectID id,
AudioObjectPropertySelector selector,
void **data)
{
return GetAudioPropertyArray(id, selector, kAudioObjectPropertyScopeGlobal,
data);
}
OSStatus GetAudioPropertyString(AudioObjectID id,
AudioObjectPropertySelector selector,
char **data)
{
OSStatus err;
AudioObjectPropertyAddress p_addr;
UInt32 p_size = sizeof(CFStringRef);
CFStringRef string;
p_addr.mSelector = selector;
p_addr.mScope = kAudioObjectPropertyScopeGlobal;
p_addr.mElement = kAudioObjectPropertyElementMaster;
err = AudioObjectGetPropertyData(id, &p_addr, 0, NULL, &p_size, &string);
CHECK_CA_ERROR("Can't fetch array property");
CFIndex size =
CFStringGetMaximumSizeForEncoding(
CFStringGetLength(string), CA_CFSTR_ENCODING) + 1;
*data = malloc(size);
CFStringGetCString(string, *data, size, CA_CFSTR_ENCODING);
CFRelease(string);
coreaudio_error:
return err;
}
OSStatus SetAudioProperty(AudioObjectID id,
AudioObjectPropertySelector selector,
uint32_t size, void *data)
{
AudioObjectPropertyAddress p_addr;
p_addr.mSelector = selector;
p_addr.mScope = kAudioObjectPropertyScopeGlobal;
p_addr.mElement = kAudioObjectPropertyElementMaster;
return AudioObjectSetPropertyData(id, &p_addr, 0, NULL,
size, data);
}
Boolean IsAudioPropertySettable(AudioObjectID id,
AudioObjectPropertySelector selector,
Boolean *data)
{
AudioObjectPropertyAddress p_addr;
p_addr.mSelector = selector;
p_addr.mScope = kAudioObjectPropertyScopeGlobal;
p_addr.mElement = kAudioObjectPropertyElementMaster;
return AudioObjectIsPropertySettable(id, &p_addr, data);
}

View File

@ -0,0 +1,49 @@
/*
* This file is part of mpv.
* Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MPV_COREAUDIO_PROPERTIES_H
#define MPV_COREAUDIO_PROPERTIES_H
#include <AudioToolbox/AudioToolbox.h>
OSStatus ca_get(AudioObjectID id, AudioObjectPropertySelector selector,
uint32_t size, void *data);
#define CA_GET(id, selector, data) ca_get(id, selector, sizeof(*(data)), data)
uint32_t GetAudioPropertyArray(AudioObjectID id,
AudioObjectPropertySelector selector,
AudioObjectPropertyScope scope, void **data);
uint32_t GetGlobalAudioPropertyArray(AudioObjectID id,
AudioObjectPropertySelector selector,
void **data);
OSStatus GetAudioPropertyString(AudioObjectID id,
AudioObjectPropertySelector selector,
char **data);
OSStatus SetAudioProperty(AudioObjectID id,
AudioObjectPropertySelector selector,
uint32_t size, void *data);
Boolean IsAudioPropertySettable(AudioObjectID id,
AudioObjectPropertySelector selector,
Boolean *outData);
#endif /* MPV_COREAUDIO_PROPERTIES_H */

View File

@ -22,17 +22,14 @@
* on CoreAudio but not the AUHAL (such as using AudioQueue services).
*/
#include <AudioToolbox/AudioToolbox.h>
#include <AudioUnit/AudioUnit.h>
#include <inttypes.h>
#include <stdbool.h>
#include "audio/out/ao_coreaudio_utils.h"
#include "audio/out/ao_coreaudio_properties.h"
#include "osdep/timer.h"
#include "core/mp_msg.h"
#define ca_msg(a, b ...) mp_msg(MSGT_AO, a, "AO: [coreaudio] " b)
#define CA_CFSTR_ENCODING kCFStringEncodingASCII
static char *fourcc_repr(void *talloc_ctx, uint32_t code)
char *fourcc_repr(void *talloc_ctx, uint32_t code)
{
// Extract FourCC letters from the uint32_t and finde out if it's a valid
// code that is made of letters.
@ -58,7 +55,7 @@ static char *fourcc_repr(void *talloc_ctx, uint32_t code)
return repr;
}
static bool check_ca_st(int level, OSStatus code, const char *message)
bool check_ca_st(int level, OSStatus code, const char *message)
{
if (code == noErr) return true;
@ -69,18 +66,8 @@ static bool check_ca_st(int level, OSStatus code, const char *message)
return false;
}
#define CHECK_CA_ERROR_L(label, message) \
do { \
if (!check_ca_st(MSGL_ERR, err, message)) { \
goto label; \
} \
} while (0)
#define CHECK_CA_ERROR(message) CHECK_CA_ERROR_L(coreaudio_error, message)
#define CHECK_CA_WARN(message) check_ca_st(MSGL_WARN, err, message)
static void ca_print_asbd(const char *description,
const AudioStreamBasicDescription *asbd)
void ca_print_asbd(const char *description,
const AudioStreamBasicDescription *asbd)
{
uint32_t flags = asbd->mFormatFlags;
char *format = fourcc_repr(NULL, asbd->mFormatID);
@ -103,112 +90,7 @@ static void ca_print_asbd(const char *description,
talloc_free(format);
}
static OSStatus GetAudioProperty(AudioObjectID id,
AudioObjectPropertySelector selector,
UInt32 outSize, void *outData)
{
AudioObjectPropertyAddress p_addr;
p_addr.mSelector = selector;
p_addr.mScope = kAudioObjectPropertyScopeGlobal;
p_addr.mElement = kAudioObjectPropertyElementMaster;
return AudioObjectGetPropertyData(id, &p_addr, 0, NULL, &outSize,
outData);
}
static UInt32 GetAudioPropertyArray(AudioObjectID id,
AudioObjectPropertySelector selector,
AudioObjectPropertyScope scope,
void **data)
{
OSStatus err;
AudioObjectPropertyAddress p_addr;
UInt32 p_size;
p_addr.mSelector = selector;
p_addr.mScope = scope;
p_addr.mElement = kAudioObjectPropertyElementMaster;
err = AudioObjectGetPropertyDataSize(id, &p_addr, 0, NULL, &p_size);
CHECK_CA_ERROR("Can't fetch property size");
*data = malloc(p_size);
err = AudioObjectGetPropertyData(id, &p_addr, 0, NULL, &p_size, *data);
CHECK_CA_ERROR_L(coreaudio_error_free, "Can't fetch property data %s");
return p_size;
coreaudio_error_free:
free(*data);
coreaudio_error:
return 0;
}
static UInt32 GetGlobalAudioPropertyArray(AudioObjectID id,
AudioObjectPropertySelector selector,
void **outData)
{
return GetAudioPropertyArray(id, selector, kAudioObjectPropertyScopeGlobal,
outData);
}
static OSStatus GetAudioPropertyString(AudioObjectID id,
AudioObjectPropertySelector selector,
char **data)
{
OSStatus err;
AudioObjectPropertyAddress p_addr;
UInt32 p_size = sizeof(CFStringRef);
CFStringRef string;
p_addr.mSelector = selector;
p_addr.mScope = kAudioObjectPropertyScopeGlobal;
p_addr.mElement = kAudioObjectPropertyElementMaster;
err = AudioObjectGetPropertyData(id, &p_addr, 0, NULL, &p_size, &string);
CHECK_CA_ERROR("Can't fetch array property");
CFIndex size =
CFStringGetMaximumSizeForEncoding(
CFStringGetLength(string), CA_CFSTR_ENCODING) + 1;
*data = malloc(size);
CFStringGetCString(string, *data, size, CA_CFSTR_ENCODING);
CFRelease(string);
coreaudio_error:
return err;
}
static OSStatus SetAudioProperty(AudioObjectID id,
AudioObjectPropertySelector selector,
UInt32 inDataSize, void *inData)
{
AudioObjectPropertyAddress p_addr;
p_addr.mSelector = selector;
p_addr.mScope = kAudioObjectPropertyScopeGlobal;
p_addr.mElement = kAudioObjectPropertyElementMaster;
return AudioObjectSetPropertyData(id, &p_addr, 0, NULL,
inDataSize, inData);
}
static Boolean IsAudioPropertySettable(AudioObjectID id,
AudioObjectPropertySelector selector,
Boolean *outData)
{
AudioObjectPropertyAddress p_addr;
p_addr.mSelector = selector;
p_addr.mScope = kAudioObjectPropertyScopeGlobal;
p_addr.mElement = kAudioObjectPropertyElementMaster;
return AudioObjectIsPropertySettable(id, &p_addr, outData);
}
static int AudioFormatIsDigital(AudioStreamBasicDescription asbd)
int AudioFormatIsDigital(AudioStreamBasicDescription asbd)
{
switch (asbd.mFormatID)
case 'IAC3':
@ -219,7 +101,7 @@ static int AudioFormatIsDigital(AudioStreamBasicDescription asbd)
return CONTROL_FALSE;
}
static int AudioStreamSupportsDigital(AudioStreamID stream)
int AudioStreamSupportsDigital(AudioStreamID stream)
{
AudioStreamRangedDescription *formats = NULL;
@ -248,7 +130,7 @@ static int AudioStreamSupportsDigital(AudioStreamID stream)
return CONTROL_FALSE;
}
static int AudioDeviceSupportsDigital(AudioDeviceID device)
int AudioDeviceSupportsDigital(AudioDeviceID device)
{
AudioStreamID *streams = NULL;
@ -275,10 +157,10 @@ static int AudioDeviceSupportsDigital(AudioDeviceID device)
return CONTROL_FALSE;
}
static OSStatus ca_property_listener(AudioObjectPropertySelector selector,
AudioObjectID object, uint32_t n_addresses,
const AudioObjectPropertyAddress addresses[],
void *data)
OSStatus ca_property_listener(AudioObjectPropertySelector selector,
AudioObjectID object, uint32_t n_addresses,
const AudioObjectPropertyAddress addresses[],
void *data)
{
void *talloc_ctx = talloc_new(NULL);
@ -294,23 +176,23 @@ static OSStatus ca_property_listener(AudioObjectPropertySelector selector,
return noErr;
}
static OSStatus ca_stream_listener(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)
{
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)
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) {
OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid) {
*pid = getpid();
OSStatus err = SetAudioProperty(device, kAudioDevicePropertyHogMode,
sizeof(*pid), pid);
@ -320,7 +202,7 @@ static OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid) {
return err;
}
static OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid) {
OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid) {
if (*pid == getpid()) {
*pid = -1;
return SetAudioProperty(device, kAudioDevicePropertyHogMode,
@ -367,11 +249,11 @@ static OSStatus ca_change_mixing(AudioDeviceID device, uint32_t val,
return noErr;
}
static OSStatus ca_disable_mixing(AudioDeviceID device, bool *changed) {
OSStatus ca_disable_mixing(AudioDeviceID device, bool *changed) {
return ca_change_mixing(device, 0, changed);
}
static OSStatus ca_enable_mixing(AudioDeviceID device, bool changed) {
OSStatus ca_enable_mixing(AudioDeviceID device, bool changed) {
if (changed) {
bool dont_care = false;
return ca_change_mixing(device, 1, &dont_care);
@ -398,16 +280,16 @@ static OSStatus ca_change_device_listening(AudioDeviceID device,
}
}
static OSStatus ca_enable_device_listener(AudioDeviceID device, void *flag) {
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) {
OSStatus ca_disable_device_listener(AudioDeviceID device, void *flag) {
return ca_change_device_listening(device, flag, false);
}
static int AudioStreamChangeFormat(AudioStreamID i_stream_id,
AudioStreamBasicDescription change_format)
int AudioStreamChangeFormat(AudioStreamID i_stream_id,
AudioStreamBasicDescription change_format)
{
OSStatus err = noErr;
AudioObjectPropertyAddress p_addr;
@ -453,10 +335,7 @@ static int AudioStreamChangeFormat(AudioStreamID i_stream_id,
}
AudioStreamBasicDescription actual_format;
err = GetAudioProperty(i_stream_id,
kAudioStreamPropertyPhysicalFormat,
sizeof(AudioStreamBasicDescription),
&actual_format);
err = CA_GET(i_stream_id, kAudioStreamPropertyPhysicalFormat, &actual_format);
ca_print_asbd("actual format in use:", &actual_format);
if (actual_format.mSampleRate == change_format.mSampleRate &&
@ -477,4 +356,3 @@ static int AudioStreamChangeFormat(AudioStreamID i_stream_id,
return format_set;
}

View File

@ -0,0 +1,77 @@
/*
* This file is part of mpv.
* Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
*
* mpv is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MPV_COREAUDIO_UTILS_H
#define MPV_COREAUDIO_UTILS_H
#include <AudioToolbox/AudioToolbox.h>
#include <inttypes.h>
#include <stdbool.h>
#include "core/mp_msg.h"
#define ca_msg(a, b ...) mp_msg(MSGT_AO, a, "AO: [coreaudio] " b)
#define CA_CFSTR_ENCODING kCFStringEncodingASCII
char *fourcc_repr(void *talloc_ctx, uint32_t code);
bool check_ca_st(int level, OSStatus code, const char *message);
#define CHECK_CA_ERROR_L(label, message) \
do { \
if (!check_ca_st(MSGL_ERR, err, message)) { \
goto label; \
} \
} while (0)
#define CHECK_CA_ERROR(message) CHECK_CA_ERROR_L(coreaudio_error, message)
#define CHECK_CA_WARN(message) check_ca_st(MSGL_WARN, err, message)
void ca_print_asbd(const char *description,
const AudioStreamBasicDescription *asbd);
int AudioFormatIsDigital(AudioStreamBasicDescription asbd);
int AudioStreamSupportsDigital(AudioStreamID stream);
int AudioDeviceSupportsDigital(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(AudioDeviceID device, bool *changed);
OSStatus ca_enable_mixing(AudioDeviceID device, bool changed);
OSStatus ca_enable_device_listener(AudioDeviceID device, void *flag);
OSStatus ca_disable_device_listener(AudioDeviceID device, void *flag);
int AudioStreamChangeFormat(AudioStreamID i_stream_id,
AudioStreamBasicDescription change_format);
bool ca_bitmap_from_ch_descriptions(AudioChannelLayout layout,
uint32_t *bitmap);
bool ca_bitmap_from_ch_tag(AudioChannelLayout layout, uint32_t *bitmap);
#endif /* MPV_COREAUDIO_UTILS_H */