From: Richard Kettlewell Date: Sun, 22 Feb 2009 14:09:22 +0000 (+0000) Subject: Merge Core Audio fixes X-Git-Tag: 5.0~187 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/commitdiff_plain/e3002eb9f618d7498f21933a2e8552d42ffcc7fc?hp=093ec8103f8de58d890a77b458985ecf4293bfa7 Merge Core Audio fixes --- diff --git a/CHANGES.html b/CHANGES.html index 6dca25c..3722b61 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -58,6 +58,42 @@ span.command {

This file documents recent user-visible changes to DisOrder.

+

Changes up to version 4.4

+ +
+ +

Mac OS X

+ +
+ +

The device configuration option and --device option + to disorder-playrtp now work. Devices may be specified either + by UID or name. Fixes Issue + 27.

+ +
+ +

Bugs fixed

+ +
+ + + + + + + + + + + + +
IDDescription
#27Mac DisOrder uses wrong sound device
+ +
+
+

Changes up to version 4.3

diff --git a/clients/playrtp-coreaudio.c b/clients/playrtp-coreaudio.c index 809c89c..dae7027 100644 --- a/clients/playrtp-coreaudio.c +++ b/clients/playrtp-coreaudio.c @@ -23,13 +23,13 @@ #if HAVE_COREAUDIO_AUDIOHARDWARE_H #include -#include #include "mem.h" #include "log.h" #include "vector.h" #include "heap.h" #include "playrtp.h" +#include "coreaudio.h" /** @brief Callback from Core Audio */ static OSStatus adioproc @@ -112,13 +112,8 @@ void playrtp_coreaudio(void) { * excellent reason for that... */ /* TODO report errors as strings not numbers */ - propertySize = sizeof adid; - status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, - &propertySize, &adid); - if(status) - fatal(0, "AudioHardwareGetProperty: %d", (int)status); - if(adid == kAudioDeviceUnknown) - fatal(0, "no output device"); + /* Identify the device to use */ + adid = coreaudio_getdevice(device); propertySize = sizeof asbd; status = AudioDeviceGetProperty(adid, 0, false, kAudioDevicePropertyStreamFormat, diff --git a/configure.ac b/configure.ac index 1e465ab..e0de228 100644 --- a/configure.ac +++ b/configure.ac @@ -91,7 +91,7 @@ case "$host" in *-apple-darwin* ) AC_MSG_RESULT([Mac OS X]) if test $want_coreaudio = yes; then - COREAUDIO="-framework CoreAudio" + COREAUDIO="-framework CoreFoundation -framework CoreAudio" fi browser=open AC_MSG_CHECKING([Mac OS X target version]) diff --git a/doc/disorder-playrtp.1.in b/doc/disorder-playrtp.1.in index 5e0d091..b8147ad 100644 --- a/doc/disorder-playrtp.1.in +++ b/doc/disorder-playrtp.1.in @@ -51,8 +51,9 @@ Use Core Audio to play sound. .TP .B \-\-device \fIDEVICE\fR, \fB\-D \fIDEVICE\fR Specifies the audio device to use. -The exact meaning of this is platform-dependent; on Linux it is the -ALSA device name. +See +.B "DEVICE NAMES" +below for more information. .TP .B \-\-config \fIPATH\fR, \fB\-C \fIPATH Set the configuration file. @@ -113,6 +114,16 @@ After the first command the connection is closed. Only one connection at a time will be serviced. .PP This protocol is not guaranteed to be stable. +.SH "DEVICE NAMES" +.SS "Core Audio" +On a Mac, the device name can either be the human-readable name of the desired +output or its UID. +To get a list of the human-readable names, visit System Preferences -> Sound; +the Type column has the name you want. +.PP +For example, you might use "Built-in Output" for the built-in speaker +or "Built-in Line Output" if you have connected external speakers. +Remember to quote the name. .SH "SEE ALSO" .BR disobedience (1), .BR disorder_config (5), diff --git a/doc/disorder_config.5.in b/doc/disorder_config.5.in index e2f1ab0..0364126 100644 --- a/doc/disorder_config.5.in +++ b/doc/disorder_config.5.in @@ -386,7 +386,12 @@ will be tried. .IP For \fBapi alsa\fR this is the device name to use. .IP -For \fBapi coreaudio\fR this is currently ignored. +For \fBapi coreaudio\fR this can be either the UID or the human-readable +name of the desired device. +For a list of names, visit System Preferences -> Sound and look at the Type column. +For example, you might use "Built-in Output" for the built-in speaker +or "Built-in Line Output" if you have connected external speakers. +Remember to quote the name. .IP The default is \fBdefault\fR, which is intended to map to whatever the system's default is. diff --git a/lib/Makefile.am b/lib/Makefile.am index af4f8a6..9df1dfd 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -39,6 +39,7 @@ libdisorder_a_SOURCES=charset.c charset.h \ client-common.c client-common.h \ configuration.c configuration.h \ cookies.c cookies.h \ + coreaudio.c coreaudio.h \ dateparse.c dateparse.h xgetdate.c \ defs.c defs.h \ eclient.c eclient.h \ diff --git a/lib/coreaudio.c b/lib/coreaudio.c new file mode 100644 index 0000000..c8732d5 --- /dev/null +++ b/lib/coreaudio.c @@ -0,0 +1,152 @@ +/* + * This file is part of DisOrder + * Copyright (C) 2009 Richard Kettlewell + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ +/** @file lib/coreaudio.c + * @brief Support for @ref BACKEND_COREAUDIO + */ + +#include "common.h" + +#if HAVE_COREAUDIO_AUDIOHARDWARE_H + +#include "coreaudio.h" +#include "log.h" +#include + +/** @brief Return the default device ID */ +static AudioDeviceID coreaudio_use_default(void) { + OSStatus status; + UInt32 propertySize; + AudioDeviceID adid; + + /* TODO should we use kAudioHardwarePropertyDefaultSystemOutputDevice + * instead? It is listed in the enumeration but is not documented, so we + * leave it alone until better information is available. */ + propertySize = sizeof adid; + status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, + &propertySize, &adid); + if(status) + fatal(0, "AudioHardwareGetProperty kAudioHardwarePropertyDefaultOutputDevice: %d", (int)status); + if(adid == kAudioDeviceUnknown) + fatal(0, "no output device"); + return adid; +} + +/** @brief Find a device by some string + * @param selector Selector for property to look for + * @param description Property description + * @param devs List of device IDs + * @param ndevs Number of device IDs in @p devs + * @param resultp Where to put device ID + * @return 1 if found, 0 if not found + */ +static int coreaudio_find_device(AudioObjectPropertySelector selector, + //const char *description, + const AudioDeviceID *devs, + unsigned ndevs, + CFStringRef dev, + AudioDeviceID *resultp) { + OSStatus status; + UInt32 propertySize; + + for(unsigned n = 0; n < ndevs; ++n) { + CFStringRef name; + propertySize = sizeof name; + status = AudioDeviceGetProperty(devs[n], 0, FALSE, + selector, + &propertySize, &name); + if(status) + fatal(0, "AudioDeviceGetProperty: %d", (int)status); +#if 0 + UInt8 output[1024]; + CFIndex used; + CFRange r = { 0, CFStringGetLength(name) }; + CFStringGetBytes(name, r, kCFStringEncodingUTF8, + '?', FALSE, output, sizeof output, + &used); + output[used] = 0; + info("device %u %s: %s", n, description, (char *)output); +#endif + if(CFStringCompare(dev, name, + kCFCompareCaseInsensitive|kCFCompareNonliteral) + == kCFCompareEqualTo) { + *resultp = devs[n]; + CFRelease(name); + return 1; + } + CFRelease(name); + } + return 0; /* didn't find it */ +} + +/** @brief Identify audio device + * @param name Device name + * @return Device ID + */ +AudioDeviceID coreaudio_getdevice(const char *name) { + OSStatus status; + UInt32 propertySize; + int found; + AudioDeviceID adid; + + if(!name + || !*name + || !strcmp(name, "default")) + return coreaudio_use_default(); + /* Convert the configured device name to a CFString */ + CFStringRef dev; + dev = CFStringCreateWithCString(NULL/*default allocator*/, + name, + kCFStringEncodingUTF8); + if(!dev) + fatal(0, "CFStringCreateWithBytes failed"); + /* Get a list of available devices */ + AudioDeviceID devs[1024]; + unsigned ndevs; + + propertySize = sizeof devs; + status = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, + &propertySize, devs); + if(status) + fatal(0, "AudioHardwareGetProperty kAudioHardwarePropertyDevices: %d", + (int)status); + ndevs = propertySize / sizeof *devs; + if(!ndevs) + fatal(0, "no sound devices found"); + /* Try looking up by UID first */ + found = coreaudio_find_device(kAudioDevicePropertyDeviceUID, //"UID", + devs, ndevs, dev, &adid); + /* Failing that try looking up by name */ + if(!found) + found = coreaudio_find_device(kAudioObjectPropertyName, //"name", + devs, ndevs, dev, &adid); + CFRelease(dev); + if(!found) + fatal(0, "cannot find device '%s'", name); + return adid; +} + +#endif + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ diff --git a/lib/coreaudio.h b/lib/coreaudio.h new file mode 100644 index 0000000..6e62053 --- /dev/null +++ b/lib/coreaudio.h @@ -0,0 +1,38 @@ +/* + * This file is part of DisOrder + * Copyright (C) 2009 Richard Kettlewell + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ +/** @file lib/coreaudio.h + * @brief Support for @ref BACKEND_COREAUDIO + */ + +#ifndef COREAUDIO_H +#define COREAUDIO_H + +#include + +AudioDeviceID coreaudio_getdevice(const char *name); + +#endif /* COREAUDIO_H */ + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ diff --git a/server/Makefile.am b/server/Makefile.am index 62ad1c4..a35bd80 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -28,7 +28,7 @@ disorderd_SOURCES=disorderd.c api.c api-server.c daemonize.c play.c \ schedule.c exports.c ../lib/memgc.c disorder-server.h disorderd_LDADD=$(LIBOBJS) ../lib/libdisorder.a \ $(LIBPCRE) $(LIBDB) $(LIBAO) $(LIBGC) $(LIBGCRYPT) $(LIBICONV) \ - $(LIBASOUND) $(COREAUDIO) + $(LIBASOUND) disorderd_LDFLAGS=-export-dynamic disorderd_DEPENDENCIES=../lib/libdisorder.a diff --git a/server/speaker-coreaudio.c b/server/speaker-coreaudio.c index 42c3a36..ac4e7e7 100644 --- a/server/speaker-coreaudio.c +++ b/server/speaker-coreaudio.c @@ -37,13 +37,13 @@ #include #include #include -#include #include "configuration.h" #include "syscalls.h" #include "log.h" #include "speaker-protocol.h" #include "speaker.h" +#include "coreaudio.h" /** @brief Core Audio Device ID */ static AudioDeviceID adid; @@ -113,13 +113,7 @@ static void coreaudio_init(void) { UInt32 propertySize; AudioStreamBasicDescription asbd; - propertySize = sizeof adid; - status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, - &propertySize, &adid); - if(status) - fatal(0, "AudioHardwareGetProperty: %d", (int)status); - if(adid == kAudioDeviceUnknown) - fatal(0, "no output device"); + adid = coreaudio_getdevice(config->device); propertySize = sizeof asbd; status = AudioDeviceGetProperty(adid, 0, false, kAudioDevicePropertyStreamFormat,