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
20 #include "audioOutput.h"
23 #include "sig_handlers.h"
25 #include "playerData.h"
27 #include "state_file.h"
34 #include <sys/param.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)
67 ConfigParam *param = NULL;
69 while ((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param)))
72 nr = 1; /* we'll always have at least one device */
76 void copyAudioFormat(AudioFormat * dest, AudioFormat * src)
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))
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;
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];
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)) {
132 FATAL("problems configuring output device "
133 "defined at line %i\n", param->line);
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);
159 copyAudioFormat(outAudioFormat, inAudioFormat);
162 void initAudioConfig(void)
164 ConfigParam *param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT);
166 if (NULL == param || NULL == param->value)
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)
181 memset(audioFormat, 0, sizeof(AudioFormat));
183 audioFormat->sampleRate = strtol(conf, &test, 10);
186 ERROR("error parsing audio output format: %s\n", conf);
190 /*switch(audioFormat->sampleRate) {
197 ERROR("sample rate %i can not be used for audio output\n",
198 (int)audioFormat->sampleRate);
202 if (audioFormat->sampleRate <= 0) {
203 ERROR("sample rate %i is not >= 0\n",
204 (int)audioFormat->sampleRate);
208 audioFormat->bits = strtol(test + 1, &test, 10);
211 ERROR("error parsing audio output format: %s\n", conf);
215 switch (audioFormat->bits) {
219 ERROR("bits %i can not be used for audio output\n",
220 (int)audioFormat->bits);
224 audioFormat->channels = strtol(test + 1, &test, 10);
227 ERROR("error parsing audio output format: %s\n", conf);
231 switch (audioFormat->channels) {
236 ERROR("channels %i can not be used for audio output\n",
237 (int)audioFormat->channels);
244 void finishAudioConfig(void)
246 if (audio_configFormat)
247 free(audio_configFormat);
250 void finishAudioDriver(void)
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)
268 if (cmpAudioFormat(audioFormat, &audio_format) != 0)
274 static void syncAudioDeviceStates(void)
276 AudioOutput *audioOutput;
279 if (!audio_format.channels)
282 for (i = 0; i < audioOutputArraySize; ++i) {
283 audioOutput = &audioOutputArray[i];
284 switch (audioDeviceStates[i]) {
286 /* This will reopen only if the audio format changed */
287 if (openAudioOutput(audioOutput, &audio_format) < 0)
288 audioDeviceStates[i] = DEVICE_ENABLE;
291 if (openAudioOutput(audioOutput, &audio_format) == 0)
292 audioDeviceStates[i] = DEVICE_ON;
295 dropBufferedAudioOutput(audioOutput);
296 closeAudioOutput(audioOutput);
297 audioDeviceStates[i] = DEVICE_OFF;
303 static int flushAudioBuffer(void)
308 if (audioBufferPos == 0)
311 syncAudioDeviceStates();
313 for (i = 0; i < audioOutputArraySize; ++i) {
314 if (audioDeviceStates[i] != DEVICE_ON)
316 err = playAudioOutput(&audioOutputArray[i], audioBuffer,
321 /* device should already be closed if the play
322 * func returned an error */
323 audioDeviceStates[i] = DEVICE_ENABLE;
331 int openAudioDevice(AudioFormat * audioFormat)
336 if (!audioOutputArray)
339 if (!audioOpened || !isCurrentAudioFormat(audioFormat)) {
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)
358 /* close all devices if there was an error */
359 for (i = 0; i < audioOutputArraySize; ++i) {
360 closeAudioOutput(&audioOutputArray[i]);
369 int playAudio(char *playChunk, int size)
374 send = audioBufferSize - audioBufferPos;
375 send = send < size ? send : size;
377 memcpy(audioBuffer + audioBufferPos, playChunk, send);
378 audioBufferPos += send;
382 if (audioBufferPos == audioBufferSize) {
383 if (flushAudioBuffer() < 0)
391 int isAudioDeviceOpen(void)
396 void dropBufferedAudio(void)
400 syncAudioDeviceStates();
403 for (i = 0; i < audioOutputArraySize; ++i) {
404 if (audioDeviceStates[i] == DEVICE_ON)
405 dropBufferedAudioOutput(&audioOutputArray[i]);
409 void closeAudioDevice(void)
419 for (i = 0; i < audioOutputArraySize; ++i) {
420 if (audioDeviceStates[i] == DEVICE_ON)
421 audioDeviceStates[i] = DEVICE_ENABLE;
422 closeAudioOutput(&audioOutputArray[i]);
428 void sendMetadataToAudioDevice(MpdTag * tag)
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);
445 if (!(audioDeviceStates[device] & 0x01))
446 audioDeviceStates[device] = DEVICE_ENABLE;
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);
458 if (audioDeviceStates[device] & 0x01)
459 audioDeviceStates[device] = DEVICE_DISABLE;
464 void printAudioDevices(int fd)
468 for (i = 0; i < audioOutputArraySize; i++) {
470 "outputid: %i\noutputname: %s\noutputenabled: %i\n",
472 audioOutputArray[i].name,
473 audioDeviceStates[i] & 0x01);
477 void saveAudioDevicesState(FILE *fp)
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];
494 assert(audioOutputArraySize != 0);
496 while (myFgets(buffer, AUDIO_BUFFER_SIZE, fp)) {
499 if (strncmp(buffer, AUDIO_DEVICE_STATE, AUDIO_DEVICE_STATE_LEN))
502 c = strchr(buffer, ':');
506 name = strchr(c, ':');
507 if (!name || !(++name))
510 for (i = 0; i < audioOutputArraySize; ++i) {
511 if (!strcmp(name, audioOutputArray[i].name)) {
512 /* devices default to on */
514 audioDeviceStates[i] = DEVICE_DISABLE;
521 ERROR("invalid line in state_file: %s\n", buffer);