Initial revision 6759
[qball-mpd.git] / src / audio.c
blob96712d713ea341328c218ae79fdbbd7551f50a5d
1 /* the Music Player Daemon (MPD)
2 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3 * This project's homepage is: http://www.musicpd.org
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 2 of the License, or
8 * (at your option) any later version.
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 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "audio.h"
20 #include "audioOutput.h"
21 #include "conf.h"
22 #include "log.h"
23 #include "sig_handlers.h"
24 #include "command.h"
25 #include "playerData.h"
26 #include "utils.h"
27 #include "state_file.h"
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <signal.h>
33 #include <sys/stat.h>
34 #include <sys/param.h>
35 #include <errno.h>
36 #include <unistd.h>
38 #define AUDIO_DEVICE_STATE "audio_device_state:"
39 #define AUDIO_DEVICE_STATE_LEN 19 /* strlen(AUDIO_DEVICE_STATE) */
40 #define AUDIO_BUFFER_SIZE 2*MAXPATHLEN
42 static AudioFormat audio_format;
44 static AudioFormat *audio_configFormat;
46 static AudioOutput *audioOutputArray;
47 static mpd_uint8 audioOutputArraySize;
49 #define DEVICE_OFF 0x00
50 #define DEVICE_ENABLE 0x01 /* currently off, but to be turned on */
51 #define DEVICE_ON 0x03
52 #define DEVICE_DISABLE 0x04 /* currently on, but to be turned off */
54 /* the audioEnabledArray should be stuck into shared memory, and then disable
55 and enable in playAudio() routine */
56 static mpd_uint8 *audioDeviceStates;
58 static mpd_uint8 audioOpened;
60 static mpd_sint32 audioBufferSize;
61 static char *audioBuffer;
62 static mpd_sint32 audioBufferPos;
64 size_t audio_device_count(void)
66 size_t nr = 0;
67 ConfigParam *param = NULL;
69 while ((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param)))
70 nr++;
71 if (!nr)
72 nr = 1; /* we'll always have at least one device */
73 return nr;
76 void copyAudioFormat(AudioFormat * dest, AudioFormat * src)
78 if (!src)
79 return;
81 memcpy(dest, src, sizeof(AudioFormat));
84 int cmpAudioFormat(AudioFormat * f1, AudioFormat * f2)
86 if (f1 && f2 && (f1->sampleRate == f2->sampleRate) &&
87 (f1->bits == f2->bits) && (f1->channels == f2->channels))
88 return 0;
89 return 1;
92 void loadAudioDrivers(void)
94 initAudioOutputPlugins();
95 loadAudioOutputPlugin(&shoutPlugin);
96 loadAudioOutputPlugin(&nullPlugin);
97 loadAudioOutputPlugin(&fifoPlugin);
98 loadAudioOutputPlugin(&alsaPlugin);
99 loadAudioOutputPlugin(&aoPlugin);
100 loadAudioOutputPlugin(&ossPlugin);
101 loadAudioOutputPlugin(&osxPlugin);
102 loadAudioOutputPlugin(&pulsePlugin);
103 loadAudioOutputPlugin(&mvpPlugin);
104 loadAudioOutputPlugin(&jackPlugin);
107 /* make sure initPlayerData is called before this function!! */
108 void initAudioDriver(void)
110 ConfigParam *param = NULL;
111 int i;
113 loadAudioDrivers();
115 audioOutputArraySize = audio_device_count();
116 audioDeviceStates = (getPlayerData())->audioDeviceStates;
117 audioOutputArray = xmalloc(sizeof(AudioOutput) * audioOutputArraySize);
119 for (i = 0; i < audioOutputArraySize; i++)
121 AudioOutput *output = &audioOutputArray[i];
122 int j;
124 param = getNextConfigParam(CONF_AUDIO_OUTPUT, param);
126 /* only allow param to be NULL if there just one audioOutput */
127 assert(param || (audioOutputArraySize == 1));
129 if (!initAudioOutput(output, param)) {
130 if (param)
132 FATAL("problems configuring output device "
133 "defined at line %i\n", param->line);
135 else
137 FATAL("No audio_output specified and unable to "
138 "detect a default audio output device\n");
142 /* require output names to be unique: */
143 for (j = 0; j < i; j++) {
144 if (!strcmp(output->name, audioOutputArray[j].name)) {
145 FATAL("output devices with identical "
146 "names: %s\n", output->name);
149 audioDeviceStates[i] = DEVICE_ENABLE;
153 void getOutputAudioFormat(AudioFormat * inAudioFormat,
154 AudioFormat * outAudioFormat)
156 if (audio_configFormat) {
157 copyAudioFormat(outAudioFormat, audio_configFormat);
158 } else
159 copyAudioFormat(outAudioFormat, inAudioFormat);
162 void initAudioConfig(void)
164 ConfigParam *param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT);
166 if (NULL == param || NULL == param->value)
167 return;
169 audio_configFormat = xmalloc(sizeof(AudioFormat));
171 if (0 != parseAudioConfig(audio_configFormat, param->value)) {
172 FATAL("error parsing \"%s\" at line %i\n",
173 CONF_AUDIO_OUTPUT_FORMAT, param->line);
177 int parseAudioConfig(AudioFormat * audioFormat, char *conf)
179 char *test;
181 memset(audioFormat, 0, sizeof(AudioFormat));
183 audioFormat->sampleRate = strtol(conf, &test, 10);
185 if (*test != ':') {
186 ERROR("error parsing audio output format: %s\n", conf);
187 return -1;
190 /*switch(audioFormat->sampleRate) {
191 case 48000:
192 case 44100:
193 case 32000:
194 case 16000:
195 break;
196 default:
197 ERROR("sample rate %i can not be used for audio output\n",
198 (int)audioFormat->sampleRate);
199 return -1
200 } */
202 if (audioFormat->sampleRate <= 0) {
203 ERROR("sample rate %i is not >= 0\n",
204 (int)audioFormat->sampleRate);
205 return -1;
208 audioFormat->bits = strtol(test + 1, &test, 10);
210 if (*test != ':') {
211 ERROR("error parsing audio output format: %s\n", conf);
212 return -1;
215 switch (audioFormat->bits) {
216 case 16:
217 break;
218 default:
219 ERROR("bits %i can not be used for audio output\n",
220 (int)audioFormat->bits);
221 return -1;
224 audioFormat->channels = strtol(test + 1, &test, 10);
226 if (*test != '\0') {
227 ERROR("error parsing audio output format: %s\n", conf);
228 return -1;
231 switch (audioFormat->channels) {
232 case 1:
233 case 2:
234 break;
235 default:
236 ERROR("channels %i can not be used for audio output\n",
237 (int)audioFormat->channels);
238 return -1;
241 return 0;
244 void finishAudioConfig(void)
246 if (audio_configFormat)
247 free(audio_configFormat);
250 void finishAudioDriver(void)
252 int i;
254 for (i = 0; i < audioOutputArraySize; i++) {
255 finishAudioOutput(&audioOutputArray[i]);
258 free(audioOutputArray);
259 audioOutputArray = NULL;
260 audioOutputArraySize = 0;
263 int isCurrentAudioFormat(AudioFormat * audioFormat)
265 if (!audioFormat)
266 return 1;
268 if (cmpAudioFormat(audioFormat, &audio_format) != 0)
269 return 0;
271 return 1;
274 static void syncAudioDeviceStates(void)
276 AudioOutput *audioOutput;
277 int i;
279 if (!audio_format.channels)
280 return;
282 for (i = 0; i < audioOutputArraySize; ++i) {
283 audioOutput = &audioOutputArray[i];
284 switch (audioDeviceStates[i]) {
285 case DEVICE_ON:
286 /* This will reopen only if the audio format changed */
287 if (openAudioOutput(audioOutput, &audio_format) < 0)
288 audioDeviceStates[i] = DEVICE_ENABLE;
289 break;
290 case DEVICE_ENABLE:
291 if (openAudioOutput(audioOutput, &audio_format) == 0)
292 audioDeviceStates[i] = DEVICE_ON;
293 break;
294 case DEVICE_DISABLE:
295 dropBufferedAudioOutput(audioOutput);
296 closeAudioOutput(audioOutput);
297 audioDeviceStates[i] = DEVICE_OFF;
298 break;
303 static int flushAudioBuffer(void)
305 int ret = -1;
306 int i, err;
308 if (audioBufferPos == 0)
309 return 0;
311 syncAudioDeviceStates();
313 for (i = 0; i < audioOutputArraySize; ++i) {
314 if (audioDeviceStates[i] != DEVICE_ON)
315 continue;
316 err = playAudioOutput(&audioOutputArray[i], audioBuffer,
317 audioBufferPos);
318 if (!err)
319 ret = 0;
320 else if (err < 0)
321 /* device should already be closed if the play
322 * func returned an error */
323 audioDeviceStates[i] = DEVICE_ENABLE;
326 audioBufferPos = 0;
328 return ret;
331 int openAudioDevice(AudioFormat * audioFormat)
333 int ret = -1;
334 int i;
336 if (!audioOutputArray)
337 return -1;
339 if (!audioOpened || !isCurrentAudioFormat(audioFormat)) {
340 flushAudioBuffer();
341 copyAudioFormat(&audio_format, audioFormat);
342 audioBufferSize = (audio_format.bits >> 3) *
343 audio_format.channels;
344 audioBufferSize *= audio_format.sampleRate >> 5;
345 audioBuffer = xrealloc(audioBuffer, audioBufferSize);
348 syncAudioDeviceStates();
350 for (i = 0; i < audioOutputArraySize; ++i) {
351 if (audioOutputArray[i].open)
352 ret = 0;
355 if (ret == 0)
356 audioOpened = 1;
357 else {
358 /* close all devices if there was an error */
359 for (i = 0; i < audioOutputArraySize; ++i) {
360 closeAudioOutput(&audioOutputArray[i]);
363 audioOpened = 0;
366 return ret;
369 int playAudio(char *playChunk, int size)
371 int send;
373 while (size > 0) {
374 send = audioBufferSize - audioBufferPos;
375 send = send < size ? send : size;
377 memcpy(audioBuffer + audioBufferPos, playChunk, send);
378 audioBufferPos += send;
379 size -= send;
380 playChunk += send;
382 if (audioBufferPos == audioBufferSize) {
383 if (flushAudioBuffer() < 0)
384 return -1;
388 return 0;
391 int isAudioDeviceOpen(void)
393 return audioOpened;
396 void dropBufferedAudio(void)
398 int i;
400 syncAudioDeviceStates();
401 audioBufferPos = 0;
403 for (i = 0; i < audioOutputArraySize; ++i) {
404 if (audioDeviceStates[i] == DEVICE_ON)
405 dropBufferedAudioOutput(&audioOutputArray[i]);
409 void closeAudioDevice(void)
411 int i;
413 flushAudioBuffer();
415 free(audioBuffer);
416 audioBuffer = NULL;
417 audioBufferSize = 0;
419 for (i = 0; i < audioOutputArraySize; ++i) {
420 if (audioDeviceStates[i] == DEVICE_ON)
421 audioDeviceStates[i] = DEVICE_ENABLE;
422 closeAudioOutput(&audioOutputArray[i]);
425 audioOpened = 0;
428 void sendMetadataToAudioDevice(MpdTag * tag)
430 int i;
432 for (i = 0; i < audioOutputArraySize; ++i) {
433 sendMetadataToAudioOutput(&audioOutputArray[i], tag);
437 int enableAudioDevice(int fd, int device)
439 if (device < 0 || device >= audioOutputArraySize) {
440 commandError(fd, ACK_ERROR_ARG, "audio output device id %i "
441 "doesn't exist\n", device);
442 return -1;
445 if (!(audioDeviceStates[device] & 0x01))
446 audioDeviceStates[device] = DEVICE_ENABLE;
448 return 0;
451 int disableAudioDevice(int fd, int device)
453 if (device < 0 || device >= audioOutputArraySize) {
454 commandError(fd, ACK_ERROR_ARG, "audio output device id %i "
455 "doesn't exist\n", device);
456 return -1;
458 if (audioDeviceStates[device] & 0x01)
459 audioDeviceStates[device] = DEVICE_DISABLE;
461 return 0;
464 void printAudioDevices(int fd)
466 int i;
468 for (i = 0; i < audioOutputArraySize; i++) {
469 fdprintf(fd,
470 "outputid: %i\noutputname: %s\noutputenabled: %i\n",
472 audioOutputArray[i].name,
473 audioDeviceStates[i] & 0x01);
477 void saveAudioDevicesState(FILE *fp)
479 int i;
481 assert(audioOutputArraySize != 0);
482 for (i = 0; i < audioOutputArraySize; i++) {
483 fprintf(fp, AUDIO_DEVICE_STATE "%d:%s\n",
484 audioDeviceStates[i] & 0x01,
485 audioOutputArray[i].name);
489 void readAudioDevicesState(FILE *fp)
491 char buffer[AUDIO_BUFFER_SIZE];
492 int i;
494 assert(audioOutputArraySize != 0);
496 while (myFgets(buffer, AUDIO_BUFFER_SIZE, fp)) {
497 char *c, *name;
499 if (strncmp(buffer, AUDIO_DEVICE_STATE, AUDIO_DEVICE_STATE_LEN))
500 continue;
502 c = strchr(buffer, ':');
503 if (!c || !(++c))
504 goto errline;
506 name = strchr(c, ':');
507 if (!name || !(++name))
508 goto errline;
510 for (i = 0; i < audioOutputArraySize; ++i) {
511 if (!strcmp(name, audioOutputArray[i].name)) {
512 /* devices default to on */
513 if (!atoi(c))
514 audioDeviceStates[i] = DEVICE_DISABLE;
515 break;
518 continue;
519 errline:
520 /* nonfatal */
521 ERROR("invalid line in state_file: %s\n", buffer);