mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-05 13:29:57 -05:00
module-coreaudio-device: get channel name as CFString and convert to plain C string.
This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
The old code fetched the channel name via AudioObjectGetPropertyData()
and accessed the "returned" data as a plain char buffer.
This may or may not have worked at some point according to the Apple
CFString documentation, which warns that the actual data layout is an
implementation detail and subject to change at any time.
On recent OS X versions, this behavior led to "random data" channel
names like >H��{, H��{<.
We need to actually let AudioObjectGetPropertyData() populate a CFString
struct and convert this into a plain char buffer.
The conversion function will not free the CFString, so do that in the
caller.
Signed-off-by: Mihai Moldovan <ionic@ionic.de>
This commit is contained in:
parent
cf91aaa2b6
commit
403ba1e676
1 changed files with 44 additions and 2 deletions
|
|
@ -375,6 +375,30 @@ static int ca_sink_set_state(pa_sink *s, pa_sink_state_t state) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Caveat: The caller is responsible to get rid of the CFString(Ref). */
|
||||||
|
static bool CFString_to_cstr_n(CFStringRef cfstr, char *buf, long n) {
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
pa_assert (buf);
|
||||||
|
|
||||||
|
ret = false;
|
||||||
|
|
||||||
|
if (cfstr != NULL) {
|
||||||
|
const char *tmp = CFStringGetCStringPtr(cfstr, kCFStringEncodingUTF8);
|
||||||
|
|
||||||
|
if (tmp == NULL) {
|
||||||
|
if (CFStringGetCString(cfstr, buf, n, kCFStringEncodingUTF8))
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
strncpy(buf, tmp, n);
|
||||||
|
buf[n - 1] = 0;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int ca_device_create_sink(pa_module *m, AudioBuffer *buf, int channel_idx) {
|
static int ca_device_create_sink(pa_module *m, AudioBuffer *buf, int channel_idx) {
|
||||||
OSStatus err;
|
OSStatus err;
|
||||||
UInt32 size;
|
UInt32 size;
|
||||||
|
|
@ -387,6 +411,7 @@ static int ca_device_create_sink(pa_module *m, AudioBuffer *buf, int channel_idx
|
||||||
char tmp[255];
|
char tmp[255];
|
||||||
pa_strbuf *strbuf;
|
pa_strbuf *strbuf;
|
||||||
AudioObjectPropertyAddress property_address;
|
AudioObjectPropertyAddress property_address;
|
||||||
|
CFStringRef tmp_cfstr = NULL;
|
||||||
|
|
||||||
ca_sink = pa_xnew0(coreaudio_sink, 1);
|
ca_sink = pa_xnew0(coreaudio_sink, 1);
|
||||||
ca_sink->map.channels = buf->mNumberChannels;
|
ca_sink->map.channels = buf->mNumberChannels;
|
||||||
|
|
@ -401,7 +426,15 @@ static int ca_device_create_sink(pa_module *m, AudioBuffer *buf, int channel_idx
|
||||||
property_address.mScope = kAudioDevicePropertyScopeOutput;
|
property_address.mScope = kAudioDevicePropertyScopeOutput;
|
||||||
property_address.mElement = channel_idx + i + 1;
|
property_address.mElement = channel_idx + i + 1;
|
||||||
size = sizeof(tmp);
|
size = sizeof(tmp);
|
||||||
err = AudioObjectGetPropertyData(u->object_id, &property_address, 0, NULL, &size, tmp);
|
err = AudioObjectGetPropertyData(u->object_id, &property_address, 0, NULL, &size, &tmp_cfstr);
|
||||||
|
if (err == 0) {
|
||||||
|
err = !(CFString_to_cstr_n(tmp_cfstr, tmp, sizeof(tmp)));
|
||||||
|
|
||||||
|
if (tmp_cfstr) {
|
||||||
|
CFRelease(tmp_cfstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (err || !strlen(tmp))
|
if (err || !strlen(tmp))
|
||||||
snprintf(tmp, sizeof(tmp), "Channel %d", (int) property_address.mElement);
|
snprintf(tmp, sizeof(tmp), "Channel %d", (int) property_address.mElement);
|
||||||
|
|
||||||
|
|
@ -505,6 +538,7 @@ static int ca_device_create_source(pa_module *m, AudioBuffer *buf, int channel_i
|
||||||
char tmp[255];
|
char tmp[255];
|
||||||
pa_strbuf *strbuf;
|
pa_strbuf *strbuf;
|
||||||
AudioObjectPropertyAddress property_address;
|
AudioObjectPropertyAddress property_address;
|
||||||
|
CFStringRef tmp_cfstr = NULL;
|
||||||
|
|
||||||
ca_source = pa_xnew0(coreaudio_source, 1);
|
ca_source = pa_xnew0(coreaudio_source, 1);
|
||||||
ca_source->map.channels = buf->mNumberChannels;
|
ca_source->map.channels = buf->mNumberChannels;
|
||||||
|
|
@ -519,7 +553,15 @@ static int ca_device_create_source(pa_module *m, AudioBuffer *buf, int channel_i
|
||||||
property_address.mScope = kAudioDevicePropertyScopeInput;
|
property_address.mScope = kAudioDevicePropertyScopeInput;
|
||||||
property_address.mElement = channel_idx + i + 1;
|
property_address.mElement = channel_idx + i + 1;
|
||||||
size = sizeof(tmp);
|
size = sizeof(tmp);
|
||||||
err = AudioObjectGetPropertyData(u->object_id, &property_address, 0, NULL, &size, tmp);
|
err = AudioObjectGetPropertyData(u->object_id, &property_address, 0, NULL, &size, &tmp_cfstr);
|
||||||
|
if (err == 0) {
|
||||||
|
err = !(CFString_to_cstr_n(tmp_cfstr, tmp, sizeof(tmp)));
|
||||||
|
|
||||||
|
if (tmp_cfstr) {
|
||||||
|
CFRelease(tmp_cfstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (err || !strlen(tmp))
|
if (err || !strlen(tmp))
|
||||||
snprintf(tmp, sizeof(tmp), "Channel %d", (int) property_address.mElement);
|
snprintf(tmp, sizeof(tmp), "Channel %d", (int) property_address.mElement);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue