]>
Commit | Line | Data |
---|---|---|
cf8401db JL |
1 | /* |
2 | * Audio driver handler. This file is part of Shairport. | |
3 | * Copyright (c) James Laird 2013 | |
1f75fe4e | 4 | * Modifications (c) Mike Brady 2014 -- 2019 |
cf8401db JL |
5 | * All rights reserved. |
6 | * | |
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: | |
14 | * | |
15 | * The above copyright notice and this permission notice shall be | |
16 | * included in all copies or substantial portions of the Software. | |
17 | * | |
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. | |
26 | */ | |
27 | ||
9b33878c | 28 | #include "audio.h" |
e513e533 | 29 | #include "common.h" |
9b33878c | 30 | #include "config.h" |
064bd293 MB |
31 | #include <stdio.h> |
32 | #include <string.h> | |
9b33878c | 33 | |
8cabb16f MB |
34 | #ifdef CONFIG_JACK |
35 | extern audio_output audio_jack; | |
36 | #endif | |
629e202f DS |
37 | #ifdef CONFIG_SNDIO |
38 | extern audio_output audio_sndio; | |
39 | #endif | |
9b33878c JL |
40 | #ifdef CONFIG_AO |
41 | extern audio_output audio_ao; | |
42 | #endif | |
71fc1a2c | 43 | #ifdef CONFIG_SOUNDIO |
44 | extern audio_output audio_soundio; | |
45 | #endif | |
ec232363 LR |
46 | #ifdef CONFIG_PW |
47 | extern audio_output audio_pw; | |
48 | #endif | |
b3ae05ea MB |
49 | #ifdef CONFIG_PA |
50 | extern audio_output audio_pa; | |
51 | #endif | |
95035f33 M |
52 | #ifdef CONFIG_ALSA |
53 | extern audio_output audio_alsa; | |
54 | #endif | |
55f57c1f MB |
55 | #ifdef CONFIG_DUMMY |
56 | extern audio_output audio_dummy; | |
57 | #endif | |
58 | #ifdef CONFIG_PIPE | |
59 | extern audio_output audio_pipe; | |
60 | #endif | |
61 | #ifdef CONFIG_STDOUT | |
62 | extern audio_output audio_stdout; | |
63 | #endif | |
9b33878c JL |
64 | |
65 | static audio_output *outputs[] = { | |
95035f33 M |
66 | #ifdef CONFIG_ALSA |
67 | &audio_alsa, | |
68 | #endif | |
b7864b4e MB |
69 | #ifdef CONFIG_SNDIO |
70 | &audio_sndio, | |
a69c5f20 | 71 | #endif |
ec232363 LR |
72 | #ifdef CONFIG_PW |
73 | &audio_pw, | |
74 | #endif | |
b3ae05ea MB |
75 | #ifdef CONFIG_PA |
76 | &audio_pa, | |
77 | #endif | |
8cabb16f MB |
78 | #ifdef CONFIG_JACK |
79 | &audio_jack, | |
80 | #endif | |
9b33878c JL |
81 | #ifdef CONFIG_AO |
82 | &audio_ao, | |
83 | #endif | |
71fc1a2c | 84 | #ifdef CONFIG_SOUNDIO |
85 | &audio_soundio, | |
86 | #endif | |
064bd293 | 87 | #ifdef CONFIG_PIPE |
55f57c1f MB |
88 | &audio_pipe, |
89 | #endif | |
90 | #ifdef CONFIG_STDOUT | |
91 | &audio_stdout, | |
b7864b4e MB |
92 | #endif |
93 | #ifdef CONFIG_DUMMY | |
94 | &audio_dummy, | |
55f57c1f MB |
95 | #endif |
96 | NULL}; | |
9b33878c | 97 | |
ca562872 | 98 | audio_output *audio_get_output(const char *name) { |
87a0475c | 99 | audio_output **out; |
98da1d2f | 100 | |
87a0475c MB |
101 | // default to the first |
102 | if (!name) | |
103 | return outputs[0]; | |
9b33878c | 104 | |
87a0475c MB |
105 | for (out = outputs; *out; out++) |
106 | if (!strcasecmp(name, (*out)->name)) | |
107 | return *out; | |
9b33878c | 108 | |
87a0475c | 109 | return NULL; |
9b33878c JL |
110 | } |
111 | ||
112 | void audio_ls_outputs(void) { | |
87a0475c | 113 | audio_output **out; |
9b33878c | 114 | |
552218ab | 115 | printf("Available audio backends:\n"); |
87a0475c MB |
116 | for (out = outputs; *out; out++) |
117 | printf(" %s%s\n", (*out)->name, out == outputs ? " (default)" : ""); | |
82518dc3 | 118 | |
87a0475c MB |
119 | for (out = outputs; *out; out++) { |
120 | printf("\n"); | |
1ae7856d | 121 | if ((*out)->help) { |
552218ab | 122 | printf("Settings and options for the audio backend \"%s\":\n", (*out)->name); |
1ae7856d MB |
123 | (*out)->help(); |
124 | } else { | |
c8b0be30 | 125 | printf("There are no settings or options for the audio backend \"%s\".\n", (*out)->name); |
1ae7856d | 126 | } |
87a0475c | 127 | } |
9b33878c | 128 | } |
b7864b4e MB |
129 | |
130 | void parse_general_audio_options(void) { | |
e513e533 MB |
131 | /* this must be called after the output device has been initialised, so that the default values |
132 | * are set before any options are chosen */ | |
b7864b4e MB |
133 | int value; |
134 | double dvalue; | |
a4edc649 | 135 | const char *str = 0; |
b7864b4e MB |
136 | if (config.cfg != NULL) { |
137 | ||
138 | /* Get the desired buffer size setting (deprecated). */ | |
139 | if (config_lookup_int(config.cfg, "general.audio_backend_buffer_desired_length", &value)) { | |
140 | if ((value < 0) || (value > 66150)) { | |
141 | inform("The setting general.audio_backend_buffer_desired_length is deprecated. " | |
142 | "Use alsa.audio_backend_buffer_desired_length_in_seconds instead."); | |
143 | die("Invalid audio_backend_buffer_desired_length value: \"%d\". It " | |
144 | "should be between 0 and " | |
145 | "66150, default is %d", | |
e513e533 | 146 | value, (int)(config.audio_backend_buffer_desired_length * 44100)); |
b7864b4e MB |
147 | } else { |
148 | inform("The setting general.audio_backend_buffer_desired_length is deprecated. " | |
149 | "Use general.audio_backend_buffer_desired_length_in_seconds instead."); | |
150 | config.audio_backend_buffer_desired_length = 1.0 * value / 44100; | |
151 | } | |
152 | } | |
153 | ||
154 | /* Get the desired buffer size setting in seconds. */ | |
155 | if (config_lookup_float(config.cfg, "general.audio_backend_buffer_desired_length_in_seconds", | |
156 | &dvalue)) { | |
72d71535 | 157 | if (dvalue < 0) { |
b7864b4e | 158 | die("Invalid audio_backend_buffer_desired_length_in_seconds value: \"%f\". It " |
72d71535 MB |
159 | "should be 0.0 or greater." |
160 | " The default is %.3f seconds", | |
e513e533 | 161 | dvalue, config.audio_backend_buffer_desired_length); |
b7864b4e MB |
162 | } else { |
163 | config.audio_backend_buffer_desired_length = dvalue; | |
164 | } | |
165 | } | |
80f15e1f | 166 | |
b9cf91b2 | 167 | /* Get the minimum buffer size for fancy interpolation setting in seconds. */ |
80f15e1f MB |
168 | if (config_lookup_float(config.cfg, |
169 | "general.audio_backend_buffer_interpolation_threshold_in_seconds", | |
db0e718c MB |
170 | &dvalue)) { |
171 | if ((dvalue < 0) || (dvalue > config.audio_backend_buffer_desired_length)) { | |
172 | die("Invalid audio_backend_buffer_interpolation_threshold_in_seconds value: \"%f\". It " | |
173 | "should be between 0 and " | |
174 | "audio_backend_buffer_desired_length_in_seconds of %.3f, default is %.3f seconds", | |
80f15e1f MB |
175 | dvalue, config.audio_backend_buffer_desired_length, |
176 | config.audio_backend_buffer_interpolation_threshold_in_seconds); | |
db0e718c MB |
177 | } else { |
178 | config.audio_backend_buffer_interpolation_threshold_in_seconds = dvalue; | |
179 | } | |
180 | } | |
b7864b4e MB |
181 | |
182 | /* Get the latency offset (deprecated). */ | |
183 | if (config_lookup_int(config.cfg, "general.audio_backend_latency_offset", &value)) { | |
184 | if ((value < -66150) || (value > 66150)) { | |
185 | inform("The setting general.audio_backend_latency_offset is deprecated. " | |
186 | "Use general.audio_backend_latency_offset_in_seconds instead."); | |
187 | die("Invalid audio_backend_latency_offset value: \"%d\". It " | |
188 | "should be between -66150 and +66150, default is 0", | |
189 | value); | |
190 | } else { | |
191 | inform("The setting general.audio_backend_latency_offset is deprecated. " | |
192 | "Use general.audio_backend_latency_offset_in_seconds instead."); | |
193 | config.audio_backend_latency_offset = 1.0 * value / 44100; | |
194 | } | |
195 | } | |
196 | ||
197 | /* Get the latency offset in seconds. */ | |
e513e533 MB |
198 | if (config_lookup_float(config.cfg, "general.audio_backend_latency_offset_in_seconds", |
199 | &dvalue)) { | |
54d761ff | 200 | config.audio_backend_latency_offset = dvalue; |
b7864b4e MB |
201 | } |
202 | ||
a4edc649 MB |
203 | /* Check if the length of the silent lead-in ia set to \"auto\". */ |
204 | if (config_lookup_string(config.cfg, "general.audio_backend_silent_lead_in_time", &str)) { | |
205 | if (strcasecmp(str, "auto") == 0) { | |
206 | config.audio_backend_silent_lead_in_time_auto = 1; | |
207 | } else { | |
208 | if (config.audio_backend_silent_lead_in_time_auto == 1) | |
54d761ff MB |
209 | warn("Invalid audio_backend_silent_lead_in_time \"%s\". It should be \"auto\" or the " |
210 | "lead-in time in seconds. " | |
a4edc649 MB |
211 | "It remains set to \"auto\". Note: numbers should not be placed in quotes.", |
212 | str); | |
213 | else | |
214 | warn("Invalid output rate \"%s\". It should be \"auto\" or the lead-in time in seconds. " | |
215 | "It remains set to %f. Note: numbers should not be placed in quotes.", | |
216 | str, config.audio_backend_silent_lead_in_time); | |
217 | } | |
218 | } | |
219 | ||
b7864b4e | 220 | /* Get the desired length of the silent lead-in. */ |
e513e533 | 221 | if (config_lookup_float(config.cfg, "general.audio_backend_silent_lead_in_time", &dvalue)) { |
ede276d4 | 222 | if ((dvalue < 0.0) || (dvalue > 4)) { |
54d761ff MB |
223 | if (config.audio_backend_silent_lead_in_time_auto == 1) |
224 | warn("Invalid audio_backend_silent_lead_in_time \"%f\". It " | |
225 | "must be between 0.0 and 4.0 seconds. Omit the setting to use the automatic value. " | |
226 | "The setting remains at \"auto\".", | |
227 | dvalue); | |
a4edc649 | 228 | else |
54d761ff MB |
229 | warn("Invalid audio_backend_silent_lead_in_time \"%f\". It " |
230 | "must be between 0.0 and 4.0 seconds. Omit the setting to use the automatic value. " | |
231 | "It remains set to %f.", | |
232 | dvalue, config.audio_backend_silent_lead_in_time); | |
b7864b4e MB |
233 | } else { |
234 | config.audio_backend_silent_lead_in_time = dvalue; | |
a4edc649 | 235 | config.audio_backend_silent_lead_in_time_auto = 0; |
b7864b4e MB |
236 | } |
237 | } | |
238 | } | |
239 | } |