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 "../audioOutput.h"
30 static int driverInitCount;
32 typedef struct _AoData {
39 static AoData *newAoData(void)
41 AoData *ret = xmalloc(sizeof(AoData));
48 static void audioOutputAo_error(void)
50 if (errno == AO_ENOTLIVE) {
51 ERROR("not a live ao device\n");
52 } else if (errno == AO_EOPENDEVICE) {
53 ERROR("not able to open audio device\n");
54 } else if (errno == AO_EBADOPTION) {
55 ERROR("bad driver option\n");
59 static int audioOutputAo_initDriver(AudioOutput * audioOutput,
70 AoData *ad = newAoData();
71 BlockParam *blockParam;
73 audioOutput->data = ad;
75 if ((blockParam = getBlockParam(param, "write_size"))) {
76 ad->writeSize = strtol(blockParam->value, &test, 10);
78 FATAL("\"%s\" is not a valid write size at line %i\n",
79 blockParam->value, blockParam->line);
84 if (driverInitCount == 0) {
89 blockParam = getBlockParam(param, "driver");
91 if (!blockParam || 0 == strcmp(blockParam->value, "default")) {
92 ad->driverId = ao_default_driver_id();
93 } else if ((ad->driverId = ao_driver_id(blockParam->value)) < 0) {
94 FATAL("\"%s\" is not a valid ao driver at line %i\n",
95 blockParam->value, blockParam->line);
98 if ((ai = ao_driver_info(ad->driverId)) == NULL) {
99 FATAL("problems getting driver info for device defined at line %i\n"
100 "you may not have permission to the audio device\n", param->line);
103 DEBUG("using ao driver \"%s\" for \"%s\"\n", ai->short_name,
106 blockParam = getBlockParam(param, "options");
109 dup = xstrdup(blockParam->value);
115 n1 = strtok_r(dup, ";", &stk1);
118 key = strtok_r(n1, "=", &stk2);
120 FATAL("problems parsing options \"%s\"\n", n1);
122 for(i=0;i<ai->option_count;i++) {
123 if(strcmp(ai->options[i],key)==0) {
129 FATAL("\"%s\" is not an option for "
130 "\"%s\" ao driver\n",key,
133 value = strtok_r(NULL, "", &stk2);
135 FATAL("problems parsing options \"%s\"\n", n1);
136 ao_append_option(&ad->options, key, value);
137 n1 = strtok_r(NULL, ";", &stk1);
145 static void freeAoData(AoData * ad)
147 ao_free_options(ad->options);
151 static void audioOutputAo_finishDriver(AudioOutput * audioOutput)
153 AoData *ad = (AoData *) audioOutput->data;
158 if (driverInitCount == 0)
162 static void audioOutputAo_dropBufferedAudio(AudioOutput * audioOutput)
164 /* not supported by libao */
167 static void audioOutputAo_closeDevice(AudioOutput * audioOutput)
169 AoData *ad = (AoData *) audioOutput->data;
172 ao_close(ad->device);
176 audioOutput->open = 0;
179 static int audioOutputAo_openDevice(AudioOutput * audioOutput)
181 ao_sample_format format;
182 AoData *ad = (AoData *) audioOutput->data;
185 audioOutputAo_closeDevice(audioOutput);
188 format.bits = audioOutput->outAudioFormat.bits;
189 format.rate = audioOutput->outAudioFormat.sampleRate;
190 format.byte_format = AO_FMT_NATIVE;
191 format.channels = audioOutput->outAudioFormat.channels;
193 ad->device = ao_open_live(ad->driverId, &format, ad->options);
195 if (ad->device == NULL)
198 audioOutput->open = 1;
203 static int audioOutputAo_play(AudioOutput * audioOutput, char *playChunk,
207 AoData *ad = (AoData *) audioOutput->data;
209 if (ad->device == NULL)
213 send = ad->writeSize > size ? size : ad->writeSize;
215 if (ao_play(ad->device, playChunk, send) == 0) {
216 audioOutputAo_error();
217 ERROR("closing audio device due to write error\n");
218 audioOutputAo_closeDevice(audioOutput);
229 AudioOutputPlugin aoPlugin = {
232 audioOutputAo_initDriver,
233 audioOutputAo_finishDriver,
234 audioOutputAo_openDevice,
236 audioOutputAo_dropBufferedAudio,
237 audioOutputAo_closeDevice,
238 NULL, /* sendMetadataFunc */
245 DISABLED_AUDIO_OUTPUT_PLUGIN(aoPlugin)