• R/O
  • HTTP
  • SSH
  • HTTPS

cinnamon: Commit

Cinnamon audio library


Commit MetaInfo

Revisionbda80654cb6d31f4039df18a228a738b61d90fe2 (tree)
Zeit2021-07-25 06:38:35
AutorAlaskanEmily <emily@alas...>
CommiterAlaskanEmily

Log Message

Add basic device enumeration API.

This is kind of sub-optimal though, OpenAL just says there is one "OpenAL Soft"
device which is clearly not what we really wanted. I need to investigate the
method OpenAL uses to choose devices, and possibly just tell it using an envvar.

Ändern Zusammenfassung

Diff

--- a/src/aucat.c
+++ b/src/aucat.c
@@ -119,16 +119,22 @@ int main(int argc, char **argv){
119119 char *const buffer = malloc(rate);
120120 unsigned num_read, total_read = 0;
121121
122- struct Cin_Driver *const driver = malloc(Cin_StructDriverSize());
123- struct Cin_Sound *const sound = malloc(Cin_StructSoundSize());
124- struct Cin_Loader *const loader = malloc(Cin_StructLoaderSize());
122+ struct Cin_Driver *const driver =
123+ malloc(Cin_StructDriverSize());
124+ struct Cin_Sound *const sound =
125+ malloc(Cin_StructSoundSize());
126+ struct Cin_Loader *const loader =
127+ malloc(Cin_StructLoaderSize());
125128
126- if(driver == NULL || Cin_CreateDriver(driver) != Cin_eDriverSuccess){
129+ if(driver == NULL ||
130+ Cin_CreateDriver(driver, NULL) != Cin_eDriverSuccess){
131+
127132 fputs("Could not create driver\n", stderr);
128133 return EXIT_FAILURE;
129134 }
130135
131- if(loader == NULL || Cin_CreateLoader(loader, driver, rate, channels, format) != Cin_eLoaderSuccess){
136+ if(loader == NULL ||
137+ Cin_CreateLoader(loader, driver, rate, channels, format) != Cin_eLoaderSuccess){
132138 fputs("Could not create loader\n", stderr);
133139 return EXIT_FAILURE;
134140 }
@@ -141,7 +147,8 @@ int main(int argc, char **argv){
141147 /* The buffer is no longer needed. */
142148 free(buffer);
143149
144- if(sound == NULL || Cin_LoaderFinalize(loader, sound) != Cin_eLoaderSuccess){
150+ if(sound == NULL ||
151+ Cin_LoaderFinalize(loader, sound) != Cin_eLoaderSuccess){
145152 fputs("Could not create sound\n", stderr);
146153 return EXIT_FAILURE;
147154 }
--- a/src/cinnamon.h
+++ b/src/cinnamon.h
@@ -36,6 +36,28 @@ enum Cin_DriverError {
3636 Cin_eDriverNoDevice
3737 };
3838
39+typedef const char **cin_device_list_t;
40+
41+/**
42+ * @brief Creates a list of all devices.
43+ *
44+ * The list is terminated with a NULL pointer, and each string is
45+ * NULL-terminated.
46+ *
47+ * There is no guarantee that any devices will be enumerated, in which case
48+ * only the default device (a NULL argument to Cin_CreateDriver) may be
49+ * available, or no devices at all may be available.
50+ *
51+ * @return A list of devices. This must be freed with Cin_FreeDeviceList
52+ * @sa Cin_FreeDeviceList
53+ */
54+CIN_EXPORT(cin_device_list_t) Cin_GetDeviceList(void);
55+
56+/**
57+ * @brief Frees the result of Cin_GetDeviceList
58+ */
59+CIN_EXPORT(void) Cin_FreeDeviceList(const char **list);
60+
3961 /**
4062 * @brief Returns the size of struct Cin_Driver
4163 *
@@ -52,11 +74,16 @@ CIN_EXPORT(unsigned) Cin_StructDriverSize(void);
5274 * @warning The data that is placed in drv must NOT be copied. Do not use
5375 * memcpy on @p sdrv, other structures may depend on the address of @p drv.
5476 *
77+ * @param drv Memory to place the driver in.
78+ * @param name Name of the device to open, or NULL for default.
79+ *
5580 * @sa Cin_StructDriverSize
5681 * @sa Cin_DestroyDriver
5782 * @todo There is currently no way to enumerate devices.
5883 */
59-CIN_EXPORT(enum Cin_DriverError) Cin_CreateDriver(struct Cin_Driver *drv);
84+CIN_EXPORT(enum Cin_DriverError) Cin_CreateDriver(
85+ struct Cin_Driver *drv,
86+ const char *name);
6087
6188 /**
6289 * @brief Destroys the Driver
@@ -196,6 +223,12 @@ CIN_EXPORT(enum Cin_LoaderError) Cin_LoaderFinalize(struct Cin_Loader *ld,
196223 struct Cin_Sound *out);
197224
198225 /** @} */ /* End Loader group. */
226+
227+/**
228+ * @brief Name of the environment variable to set the default device to use.
229+ */
230+#define CIN_DEFAULT_DEVICE_ENV "CINDEV"
231+
199232 #ifdef __cplusplus
200233 } // extern "C"
201234 #endif
--- a/src/openal/cin_openal.c
+++ b/src/openal/cin_openal.c
@@ -8,9 +8,22 @@
88 #include "cinnamon.h"
99 #include "cin_openal.h"
1010
11-#include <stddef.h>
11+#include <string.h>
12+#include <stdlib.h>
1213 #include <assert.h>
1314
15+#ifndef ALC_DEVICE_SPECIFIER
16+#define ALC_DEVICE_SPECIFIER 0x1005
17+#endif
18+
19+#ifndef ALC_DEFAULT_ALL_DEVICES_SPECIFIER
20+#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
21+#endif
22+
23+#ifndef ALC_ALL_DEVICES_SPECIFIER
24+#define ALC_ALL_DEVICES_SPECIFIER 0x1013
25+#endif
26+
1427 /*****************************************************************************/
1528 /* See gen_float_table.py for how this table was generated. */
1629 static const float char_to_float_table[0x100] = {
@@ -195,19 +208,82 @@ CIN_PRIVATE(int) Cin_CleanOpenALSound(ALuint snd, ALuint *out){
195208
196209 /*****************************************************************************/
197210
211+const char **Cin_GetDeviceList(void){
212+ static const char *nothing = NULL;
213+ /* OS X has a totally broken implementation of these extensions. */
214+#ifndef __APPLE__
215+ const char *strs = NULL, **list;
216+ if(alcIsExtensionPresent(NULL, "ALC_enumeration_all_EXT"))
217+ strs = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
218+
219+ if(strs == NULL && alcIsExtensionPresent(NULL, "ALC_enumeration_EXT"))
220+ strs = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
221+
222+ if(strs != NULL){
223+ /* Count the number of strings first. */
224+ unsigned n = 0, i = 0, l;
225+ while((l = strlen(strs + i)) != 0){
226+ n++;
227+ i += l + 1;
228+ }
229+ /* Allocate the list */
230+ list = malloc(sizeof(char*) * n + 1);
231+ if(list == NULL)
232+ return &nothing;
233+
234+ /* Copy each string. */
235+ n = i = 0;
236+ while((l = strlen(strs + i)) != 0){
237+ list[n] = malloc(l + 1);
238+ if(list[n] == NULL)
239+ break;
240+
241+ memcpy((char*)(list[n]), strs + i, l + 1);
242+
243+ i += l + 1;
244+ n++;
245+ }
246+ list[n] = NULL;
247+ return list;
248+ }
249+#endif
250+ return &nothing;
251+}
252+
253+/*****************************************************************************/
254+
255+void Cin_FreeDeviceList(const char **list){
256+#ifdef __APPLE__
257+ (void)list;
258+#else
259+ unsigned i;
260+ for(i = 0; list[i] != NULL; i++)
261+ free((char*)(list[i]));
262+ free(list);
263+#endif
264+}
265+
266+/*****************************************************************************/
267+
198268 unsigned Cin_StructDriverSize(){
199269 return sizeof(struct Cin_Driver);
200270 }
201271
202272 /*****************************************************************************/
203273
204-enum Cin_DriverError Cin_CreateDriver(struct Cin_Driver *drv){
274+enum Cin_DriverError Cin_CreateDriver(
275+ struct Cin_Driver *drv,
276+ const char *name){
277+
205278 ALCcontext *ctx;
206279 ALCdevice *dev;
207280
208281 assert(drv != NULL);
209282
210- dev = alcOpenDevice(NULL);
283+ if(name == NULL)
284+ name = getenv(CIN_DEFAULT_DEVICE_ENV);
285+
286+ dev = alcOpenDevice(name);
211287 if(dev == NULL){
212288 return Cin_eDriverNoDevice;
213289 }
--- a/src/sine_test.c
+++ b/src/sine_test.c
@@ -43,9 +43,13 @@ int main(int argc, char **argv){
4343 assert(Cin_StructLoaderSize() > 0);
4444 assert(Cin_StructSoundSize() > 0);
4545
46- if(driver == NULL || Cin_CreateDriver(driver) == Cin_eDriverSuccess){
47- struct Cin_Loader *const loader = malloc(Cin_StructLoaderSize());
48- struct Cin_Sound *const sound = malloc(Cin_StructSoundSize());
46+ if(driver == NULL ||
47+ Cin_CreateDriver(driver, NULL) == Cin_eDriverSuccess){
48+
49+ struct Cin_Loader *const loader =
50+ malloc(Cin_StructLoaderSize());
51+ struct Cin_Sound *const sound =
52+ malloc(Cin_StructSoundSize());
4953
5054 /* TODO: Make these configurable */
5155 unsigned num_channels = 2,
--- a/src/unix.mk
+++ b/src/unix.mk
@@ -1,7 +1,7 @@
11 # Any copyright is dedicated to the Public Domain.
22 # http://creativecommons.org/publicdomain/zero/1.0/
33
4-all: libcinnamon.a sine_test aucat
4+all: libcinnamon.a sine_test aucat list_dev
55
66 CIN_BACKEND?=$(BACKEND)
77
@@ -22,16 +22,22 @@ libcinnamon.a: $(CIN_BACKEND)_lib
2222
2323 sine_test.o: sine_test.c cinnamon.h cin_export.h cin_format.h
2424 $(CC) $(CFLAGS) -c sine_test.c -o sine_test.o
25-
25+
2626 aucat.o: aucat.c cinnamon.h cin_export.h cin_format.h
2727 $(CC) $(CFLAGS) -c aucat.c -o aucat.o
2828
29+list_dev.o: list_dev.c cinnamon.h cin_export.h cin_format.h
30+ $(CC) $(CFLAGS) -c list_dev.c -o list_dev.o
31+
2932 sine_test: libcinnamon.a sine_test.o
3033 $(LINK) sine_test.o libcinnamon.a $(EXTRALIBS) -lm -o sine_test
3134
3235 aucat: libcinnamon.a aucat.o
3336 $(LINK) aucat.o libcinnamon.a $(EXTRALIBS) -o aucat
3437
38+list_dev: libcinnamon.a list_dev.o
39+ $(LINK) list_dev.o libcinnamon.a $(EXTRALIBS) -o list_dev
40+
3541 clean:
3642 rm *.o 2> /dev/null || true
3743 rm *.a 2> /dev/null || true
Show on old repository browser