2 * libao output driver. This file is part of Shairport.
3 * Copyright (c) James Laird 2013
4 * Copyright (c) Mike Brady 2014 -- 2022
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
35 ao_device
*dev
= NULL
;
36 ao_option
*ao_opts
= NULL
;
40 static void help(void) {
41 printf(" -d driver set the output driver\n"
42 " -o name=value set an arbitrary ao option\n"
43 " -i id shorthand for -o id=<id>\n"
44 " -n name shorthand for -o dev=<name> -o dsp=<name>\n");
45 // get a list of drivers available
47 int defaultDriver
= ao_default_driver_id();
48 if (defaultDriver
== -1) {
49 printf(" No usable drivers available.\n");
51 ao_info
*defaultDriverInfo
= ao_driver_info(defaultDriver
);
53 ao_info
**driver_list
= ao_driver_info_list(&driver_count
);
55 if (driver_count
== 0) {
56 printf(" Driver list unavailable.\n");
58 printf(" Drivers:\n");
59 for (i
= 0; i
< driver_count
; i
++) {
60 ao_info
*the_driver
= driver_list
[i
];
61 if (strcmp(the_driver
->short_name
, defaultDriverInfo
->short_name
) == 0)
62 printf(" \"%s\" (default)\n", the_driver
->short_name
);
64 printf(" \"%s\"\n", the_driver
->short_name
);
71 static int init(int argc
, char **argv
) {
73 driver
= ao_default_driver_id();
75 warn("libao can not find a usable driver!");
78 // set up default values first
80 config
.audio_backend_buffer_desired_length
= 1.0;
81 config
.audio_backend_latency_offset
= 0;
83 // get settings from settings file first, allow them to be overridden by
84 // command line options
86 // do the "general" audio options. Note, these options are in the "general" stanza!
87 parse_general_audio_options();
89 optind
= 1; // optind=0 is equivalent to optind=1 plus special behaviour
90 argv
--; // so we shift the arguments to satisfy getopt()
93 // some platforms apparently require optreset = 1; - which?
96 while ((opt
= getopt(argc
, argv
, "d:i:n:o:")) > 0) {
99 driver
= ao_driver_id(optarg
);
101 die("could not find ao driver %s", optarg
);
104 ao_append_option(&ao_opts
, "id", optarg
);
107 ao_append_option(&ao_opts
, "dev", optarg
);
108 // Old libao versions (for example, 0.8.8) only support
109 // "dsp" instead of "dev".
110 ao_append_option(&ao_opts
, "dsp", optarg
);
113 mid
= strchr(optarg
, '=');
115 die("Expected an = in audio option %s", optarg
);
117 ao_append_option(&ao_opts
, optarg
, mid
+ 1);
121 die("Invalid audio option -%c specified", opt
);
126 die("Invalid audio argument: %s", argv
[optind
]);
128 memset(&fmt
, 0, sizeof(fmt
));
133 fmt
.byte_format
= AO_FMT_NATIVE
;
134 fmt
.matrix
= strdup("L,R");
139 static void deinit(void) {
146 static void start(__attribute__((unused
)) int sample_rate
,
147 __attribute__((unused
)) int sample_format
) {
148 // debug(1,"libao start");
151 static int play(void *buf
, int samples
, __attribute__((unused
)) int sample_type
,
152 __attribute__((unused
)) uint32_t timestamp
,
153 __attribute__((unused
)) uint64_t playtime
) {
156 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &oldState
); // make this un-cancellable
159 dev
= ao_open_live(driver
, &fmt
, ao_opts
);
161 response
= ao_play(dev
, buf
, samples
* 4);
163 pthread_setcancelstate(oldState
, NULL
);
167 static void stop(void) {
168 // debug(1,"libao stop");
175 audio_output audio_ao
= {.name
= "ao",