chiark / gitweb /
typo fix
[disorder] / lib / coreaudio.c
1 /*
2  * This file is part of DisOrder
3  * Copyright (C) 2009 Richard Kettlewell
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /** @file lib/coreaudio.c
19  * @brief Support for @ref BACKEND_COREAUDIO
20  */
21
22 #include "common.h"
23
24 #if HAVE_COREAUDIO_AUDIOHARDWARE_H
25
26 #include "coreaudio.h"
27 #include "log.h"
28 #include <CoreFoundation/CFString.h>
29
30 /** @brief Return the default device ID */
31 static AudioDeviceID coreaudio_use_default(void) {
32   OSStatus status;
33   UInt32 propertySize;
34   AudioDeviceID adid;
35
36   /* TODO should we use kAudioHardwarePropertyDefaultSystemOutputDevice
37    * instead?  It is listed in the enumeration but is not documented, so we
38    * leave it alone until better information is available. */
39   propertySize = sizeof adid;
40   status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
41                                     &propertySize, &adid);
42   if(status)
43     fatal(0, "AudioHardwareGetProperty kAudioHardwarePropertyDefaultOutputDevice: %d", (int)status);
44   if(adid == kAudioDeviceUnknown)
45     fatal(0, "no output device");
46   return adid;
47 }
48
49 /** @brief Find a device by some string
50  * @param selector Selector for property to look for
51  * @param description Property description
52  * @param devs List of device IDs
53  * @param ndevs Number of device IDs in @p devs
54  * @param resultp Where to put device ID
55  * @return 1 if found, 0 if not found
56  */
57 static int coreaudio_find_device(AudioObjectPropertySelector selector,
58                                  //const char *description,
59                                  const AudioDeviceID *devs,
60                                  unsigned ndevs,
61                                  CFStringRef dev,
62                                  AudioDeviceID *resultp) {
63   OSStatus status;
64   UInt32 propertySize;
65
66   for(unsigned n = 0; n < ndevs; ++n) {
67     CFStringRef name;
68     propertySize = sizeof name;
69     status = AudioDeviceGetProperty(devs[n], 0, FALSE,
70                                     selector,
71                                     &propertySize, &name);
72     if(status)
73       fatal(0, "AudioDeviceGetProperty: %d", (int)status);
74 #if 0
75     UInt8 output[1024];
76     CFIndex used;
77     CFRange r = { 0, CFStringGetLength(name) };
78     CFStringGetBytes(name, r, kCFStringEncodingUTF8,
79                      '?', FALSE, output, sizeof output,
80                      &used);
81     output[used] = 0;
82     info("device %u %s: %s", n, description, (char *)output);
83 #endif
84     if(CFStringCompare(dev, name,
85                        kCFCompareCaseInsensitive|kCFCompareNonliteral)
86        == kCFCompareEqualTo) {
87       *resultp = devs[n];
88       CFRelease(name);
89       return 1;
90     }
91     CFRelease(name);
92   }
93   return 0;                             /* didn't find it */
94 }
95
96 /** @brief Identify audio device
97  * @param name Device name
98  * @return Device ID
99  */
100 AudioDeviceID coreaudio_getdevice(const char *name) {
101   OSStatus status;
102   UInt32 propertySize;
103   int found;
104   AudioDeviceID adid;
105
106   if(!name
107      || !*name
108      || !strcmp(name, "default"))
109     return coreaudio_use_default();
110   /* Convert the configured device name to a CFString */
111   CFStringRef dev;
112   dev = CFStringCreateWithCString(NULL/*default allocator*/,
113                                   name,
114                                   kCFStringEncodingUTF8);
115   if(!dev)
116     fatal(0, "CFStringCreateWithBytes failed");
117   /* Get a list of available devices */
118   AudioDeviceID devs[1024];
119   unsigned ndevs;
120
121   propertySize = sizeof devs;
122   status = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
123                                     &propertySize, devs);
124   if(status)
125     fatal(0, "AudioHardwareGetProperty kAudioHardwarePropertyDevices: %d",
126           (int)status);
127   ndevs = propertySize / sizeof *devs;
128   if(!ndevs)
129     fatal(0, "no sound devices found");
130   /* Try looking up by UID first */
131   found = coreaudio_find_device(kAudioDevicePropertyDeviceUID, //"UID",
132                                 devs, ndevs, dev, &adid);
133   /* Failing that try looking up by name */
134   if(!found)
135     found = coreaudio_find_device(kAudioObjectPropertyName, //"name",
136                                   devs, ndevs, dev, &adid);
137   CFRelease(dev);
138   if(!found)
139     fatal(0, "cannot find device '%s'", name);
140   return adid;
141 }
142
143 #endif
144
145 /*
146 Local Variables:
147 c-basic-offset:2
148 comment-column:40
149 fill-column:79
150 indent-tabs-mode:nil
151 End:
152 */