audio.c 11.4 KB
Newer Older
Warren Dukes's avatar
Warren Dukes committed
1
/* the Music Player Daemon (MPD)
2
 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
Warren Dukes's avatar
Warren Dukes committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * This project's homepage is: http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "audio.h"
20
#include "audioOutput.h"
Warren Dukes's avatar
Warren Dukes committed
21
#include "log.h"
22
#include "command.h"
Max Kellermann's avatar
Max Kellermann committed
23 24 25
#include "path.h"
#include "ack.h"
#include "myfprintf.h"
26
#include "os_compat.h"
27

28
#define AUDIO_DEVICE_STATE	"audio_device_state:"
29
#define AUDIO_DEVICE_STATE_LEN	(sizeof(AUDIO_DEVICE_STATE)-1)
Eric Wong's avatar
Eric Wong committed
30
#define AUDIO_BUFFER_SIZE	2*MPD_PATH_MAX
Warren Dukes's avatar
Warren Dukes committed
31

32
static AudioFormat audio_format;
Warren Dukes's avatar
Warren Dukes committed
33

34
static AudioFormat *audio_configFormat;
35

36
static AudioOutput *audioOutputArray;
37
static unsigned int audioOutputArraySize;
38

39 40 41 42 43 44
enum ad_state {
	DEVICE_OFF = 0x00,
	DEVICE_ENABLE = 0x01,  /* currently off, but to be turned on */
	DEVICE_ON = 0x03,
	DEVICE_DISABLE = 0x04   /* currently on, but to be turned off */
};
45

46 47
/* the audioEnabledArray should be stuck into shared memory, and then disable
   and enable in playAudio() routine */
48
static enum ad_state *audioDeviceStates;
49

50
static mpd_uint8 audioOpened;
51

Max Kellermann's avatar
Max Kellermann committed
52
static size_t audioBufferSize;
53
static char *audioBuffer;
Max Kellermann's avatar
Max Kellermann committed
54
static size_t audioBufferPos;
55

56
static unsigned int audio_output_count(void)
57
{
58
	unsigned int nr = 0;
59 60 61 62 63 64 65 66 67
	ConfigParam *param = NULL;

	while ((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param)))
		nr++;
	if (!nr)
		nr = 1; /* we'll always have at least one device  */
	return nr;
}

68
void copyAudioFormat(AudioFormat * dest, const AudioFormat * src)
Avuton Olrich's avatar
Avuton Olrich committed
69 70 71
{
	if (!src)
		return;
Warren Dukes's avatar
Warren Dukes committed
72

73 74 75
	memcpy(dest, src, sizeof(AudioFormat));
}

76
int cmpAudioFormat(const AudioFormat * f1, const AudioFormat * f2)
77
{
78 79
	if (f1 && f2 && (f1->sampleRate == f2->sampleRate) &&
	    (f1->bits == f2->bits) && (f1->channels == f2->channels))
80 81
		return 0;
	return 1;
82 83
}

Avuton Olrich's avatar
Avuton Olrich committed
84 85
void loadAudioDrivers(void)
{
86
	initAudioOutputPlugins();
87
	loadAudioOutputPlugin(&shoutPlugin);
88
	loadAudioOutputPlugin(&nullPlugin);
89
	loadAudioOutputPlugin(&fifoPlugin);
90
	loadAudioOutputPlugin(&alsaPlugin);
91
	loadAudioOutputPlugin(&aoPlugin);
92
	loadAudioOutputPlugin(&ossPlugin);
93
	loadAudioOutputPlugin(&osxPlugin);
94
	loadAudioOutputPlugin(&pulsePlugin);
95
	loadAudioOutputPlugin(&mvpPlugin);
96
	loadAudioOutputPlugin(&jackPlugin);
97 98 99
}

/* make sure initPlayerData is called before this function!! */
Avuton Olrich's avatar
Avuton Olrich committed
100 101 102
void initAudioDriver(void)
{
	ConfigParam *param = NULL;
103
	unsigned int i;
104 105

	loadAudioDrivers();
Warren Dukes's avatar
Warren Dukes committed
106

107 108 109
	audioOutputArraySize = audio_output_count();
	audioDeviceStates = xmalloc(sizeof(enum ad_state) *
	                            audioOutputArraySize);
110
	audioOutputArray = xmalloc(sizeof(AudioOutput) * audioOutputArraySize);
111

112 113
	for (i = 0; i < audioOutputArraySize; i++)
	{
Eric Wong's avatar
Eric Wong committed
114
		AudioOutput *output = &audioOutputArray[i];
115
		unsigned int j;
116

117 118
		param = getNextConfigParam(CONF_AUDIO_OUTPUT, param);

Warren Dukes's avatar
Warren Dukes committed
119 120 121
		/* only allow param to be NULL if there just one audioOutput */
		assert(param || (audioOutputArraySize == 1));

122 123 124
		if (!initAudioOutput(output, param)) {
			if (param)
			{
125
				FATAL("problems configuring output device "
126 127 128 129
				      "defined at line %i\n", param->line);
			}
			else
			{
130
				FATAL("No audio_output specified and unable to "
131 132
				      "detect a default audio output device\n");
			}
133
		}
134 135

		/* require output names to be unique: */
136
		for (j = 0; j < i; j++) {
Eric Wong's avatar
Eric Wong committed
137
			if (!strcmp(output->name, audioOutputArray[j].name)) {
138
				FATAL("output devices with identical "
Avuton Olrich's avatar
Avuton Olrich committed
139
				      "names: %s\n", output->name);
140 141
			}
		}
142 143
		audioDeviceStates[i] = DEVICE_ENABLE;
	}
Warren Dukes's avatar
Warren Dukes committed
144 145
}

146
void getOutputAudioFormat(const AudioFormat * inAudioFormat,
Avuton Olrich's avatar
Avuton Olrich committed
147
			  AudioFormat * outAudioFormat)
148
{
Avuton Olrich's avatar
Avuton Olrich committed
149 150 151 152
	if (audio_configFormat) {
		copyAudioFormat(outAudioFormat, audio_configFormat);
	} else
		copyAudioFormat(outAudioFormat, inAudioFormat);
153 154
}

Avuton Olrich's avatar
Avuton Olrich committed
155 156 157
void initAudioConfig(void)
{
	ConfigParam *param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT);
158

Avuton Olrich's avatar
Avuton Olrich committed
159 160
	if (NULL == param || NULL == param->value)
		return;
161

162
	audio_configFormat = xmalloc(sizeof(AudioFormat));
163

Avuton Olrich's avatar
Avuton Olrich committed
164
	if (0 != parseAudioConfig(audio_configFormat, param->value)) {
165
		FATAL("error parsing \"%s\" at line %i\n",
Avuton Olrich's avatar
Avuton Olrich committed
166
		      CONF_AUDIO_OUTPUT_FORMAT, param->line);
167
	}
168 169
}

Avuton Olrich's avatar
Avuton Olrich committed
170 171 172 173 174
int parseAudioConfig(AudioFormat * audioFormat, char *conf)
{
	char *test;

	memset(audioFormat, 0, sizeof(AudioFormat));
175

Avuton Olrich's avatar
Avuton Olrich committed
176
	audioFormat->sampleRate = strtol(conf, &test, 10);
177

Avuton Olrich's avatar
Avuton Olrich committed
178 179
	if (*test != ':') {
		ERROR("error parsing audio output format: %s\n", conf);
180
		return -1;
Avuton Olrich's avatar
Avuton Olrich committed
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
	}

	/*switch(audioFormat->sampleRate) {
	   case 48000:
	   case 44100:
	   case 32000:
	   case 16000:
	   break;
	   default:
	   ERROR("sample rate %i can not be used for audio output\n",
	   (int)audioFormat->sampleRate);
	   return -1
	   } */

	if (audioFormat->sampleRate <= 0) {
		ERROR("sample rate %i is not >= 0\n",
		      (int)audioFormat->sampleRate);
198
		return -1;
Avuton Olrich's avatar
Avuton Olrich committed
199 200
	}

Max Kellermann's avatar
Max Kellermann committed
201
	audioFormat->bits = (mpd_sint8)strtol(test + 1, &test, 10);
202

Avuton Olrich's avatar
Avuton Olrich committed
203 204
	if (*test != ':') {
		ERROR("error parsing audio output format: %s\n", conf);
205
		return -1;
Avuton Olrich's avatar
Avuton Olrich committed
206 207 208 209 210 211 212 213
	}

	switch (audioFormat->bits) {
	case 16:
		break;
	default:
		ERROR("bits %i can not be used for audio output\n",
		      (int)audioFormat->bits);
214
		return -1;
Avuton Olrich's avatar
Avuton Olrich committed
215
	}
216

Max Kellermann's avatar
Max Kellermann committed
217
	audioFormat->channels = (mpd_sint8)strtol(test + 1, &test, 10);
Avuton Olrich's avatar
Avuton Olrich committed
218 219 220

	if (*test != '\0') {
		ERROR("error parsing audio output format: %s\n", conf);
221
		return -1;
Avuton Olrich's avatar
Avuton Olrich committed
222
	}
223

Avuton Olrich's avatar
Avuton Olrich committed
224
	switch (audioFormat->channels) {
225
	case 1:
Avuton Olrich's avatar
Avuton Olrich committed
226 227 228 229 230
	case 2:
		break;
	default:
		ERROR("channels %i can not be used for audio output\n",
		      (int)audioFormat->channels);
231
		return -1;
Avuton Olrich's avatar
Avuton Olrich committed
232
	}
233 234

	return 0;
235 236
}

Avuton Olrich's avatar
Avuton Olrich committed
237 238 239 240
void finishAudioConfig(void)
{
	if (audio_configFormat)
		free(audio_configFormat);
241 242
}

Avuton Olrich's avatar
Avuton Olrich committed
243 244
void finishAudioDriver(void)
{
245
	unsigned int i;
246

Avuton Olrich's avatar
Avuton Olrich committed
247
	for (i = 0; i < audioOutputArraySize; i++) {
Eric Wong's avatar
Eric Wong committed
248
		finishAudioOutput(&audioOutputArray[i]);
249 250 251 252
	}

	free(audioOutputArray);
	audioOutputArray = NULL;
253
	audioOutputArraySize = 0;
Warren Dukes's avatar
Warren Dukes committed
254 255
}

256
int isCurrentAudioFormat(const AudioFormat * audioFormat)
Avuton Olrich's avatar
Avuton Olrich committed
257 258 259
{
	if (!audioFormat)
		return 1;
Warren Dukes's avatar
Warren Dukes committed
260

Avuton Olrich's avatar
Avuton Olrich committed
261 262
	if (cmpAudioFormat(audioFormat, &audio_format) != 0)
		return 0;
Warren Dukes's avatar
Warren Dukes committed
263

Warren Dukes's avatar
Warren Dukes committed
264 265 266
	return 1;
}

267
static void syncAudioDeviceStates(void)
Avuton Olrich's avatar
Avuton Olrich committed
268
{
269
	AudioOutput *audioOutput;
270
	unsigned int i;
271

272 273
	if (!audio_format.channels)
		return;
274 275 276

	for (i = 0; i < audioOutputArraySize; ++i) {
		audioOutput = &audioOutputArray[i];
277
		switch (audioDeviceStates[i]) {
278 279
		case DEVICE_OFF:
			break;
280 281
		case DEVICE_ON:
			/* This will reopen only if the audio format changed */
282 283
			if (openAudioOutput(audioOutput, &audio_format) < 0)
				audioDeviceStates[i] = DEVICE_ENABLE;
284
			break;
285
		case DEVICE_ENABLE:
286 287
			if (openAudioOutput(audioOutput, &audio_format) == 0)
				audioDeviceStates[i] = DEVICE_ON;
288 289
			break;
		case DEVICE_DISABLE:
290 291
			dropBufferedAudioOutput(audioOutput);
			closeAudioOutput(audioOutput);
292 293
			audioDeviceStates[i] = DEVICE_OFF;
		}
294
	}
295 296 297 298
}

static int flushAudioBuffer(void)
{
299 300
	int ret = -1, err;
	unsigned int i;
301 302 303 304 305 306

	if (audioBufferPos == 0)
		return 0;

	syncAudioDeviceStates();

307
	for (i = 0; i < audioOutputArraySize; ++i) {
308 309 310 311 312 313 314 315 316 317 318
		if (audioDeviceStates[i] != DEVICE_ON)
			continue;
		err = playAudioOutput(&audioOutputArray[i], audioBuffer,
				      audioBufferPos);
		if (!err)
			ret = 0;
		else if (err < 0)
			/* device should already be closed if the play
			 * func returned an error */
			audioDeviceStates[i] = DEVICE_ENABLE;
	}
319 320 321 322 323 324

	audioBufferPos = 0;

	return ret;
}

325
int openAudioDevice(const AudioFormat * audioFormat)
Avuton Olrich's avatar
Avuton Olrich committed
326
{
327
	int ret = -1;
328
	unsigned int i;
329

Avuton Olrich's avatar
Avuton Olrich committed
330 331
	if (!audioOutputArray)
		return -1;
332

333
	if (!audioOpened || !isCurrentAudioFormat(audioFormat)) {
334
		flushAudioBuffer();
335
		copyAudioFormat(&audio_format, audioFormat);
Avuton Olrich's avatar
Avuton Olrich committed
336 337 338
		audioBufferSize = (audio_format.bits >> 3) *
		    audio_format.channels;
		audioBufferSize *= audio_format.sampleRate >> 5;
339
		audioBuffer = xrealloc(audioBuffer, audioBufferSize);
Warren Dukes's avatar
Warren Dukes committed
340 341
	}

342 343
	syncAudioDeviceStates();

344
	for (i = 0; i < audioOutputArraySize; ++i) {
345
		if (audioOutputArray[i].open)
Avuton Olrich's avatar
Avuton Olrich committed
346
			ret = 0;
347 348
	}

Avuton Olrich's avatar
Avuton Olrich committed
349 350
	if (ret == 0)
		audioOpened = 1;
351 352
	else {
		/* close all devices if there was an error */
353
		for (i = 0; i < audioOutputArraySize; ++i) {
Eric Wong's avatar
Eric Wong committed
354
			closeAudioOutput(&audioOutputArray[i]);
355 356 357 358 359
		}

		audioOpened = 0;
	}

360
	return ret;
361
}
Warren Dukes's avatar
Warren Dukes committed
362

Max Kellermann's avatar
Max Kellermann committed
363
int playAudio(const char *playChunk, size_t size)
Avuton Olrich's avatar
Avuton Olrich committed
364
{
Max Kellermann's avatar
Max Kellermann committed
365
	size_t send_size;
Avuton Olrich's avatar
Avuton Olrich committed
366 367

	while (size > 0) {
Max Kellermann's avatar
Max Kellermann committed
368 369
		send_size = audioBufferSize - audioBufferPos;
		send_size = send_size < size ? send_size : size;
370

Max Kellermann's avatar
Max Kellermann committed
371 372 373 374
		memcpy(audioBuffer + audioBufferPos, playChunk, send_size);
		audioBufferPos += send_size;
		size -= send_size;
		playChunk += send_size;
375

Avuton Olrich's avatar
Avuton Olrich committed
376 377 378
		if (audioBufferPos == audioBufferSize) {
			if (flushAudioBuffer() < 0)
				return -1;
379 380 381
		}
	}

382
	return 0;
Warren Dukes's avatar
Warren Dukes committed
383 384
}

Avuton Olrich's avatar
Avuton Olrich committed
385 386
int isAudioDeviceOpen(void)
{
387
	return audioOpened;
388 389
}

Avuton Olrich's avatar
Avuton Olrich committed
390 391
void dropBufferedAudio(void)
{
392
	unsigned int i;
393

394
	syncAudioDeviceStates();
395
	audioBufferPos = 0;
396

397
	for (i = 0; i < audioOutputArraySize; ++i) {
398
		if (audioDeviceStates[i] == DEVICE_ON)
Eric Wong's avatar
Eric Wong committed
399
			dropBufferedAudioOutput(&audioOutputArray[i]);
400 401 402
	}
}

Avuton Olrich's avatar
Avuton Olrich committed
403 404
void closeAudioDevice(void)
{
405
	unsigned int i;
406

407 408 409 410 411 412
	flushAudioBuffer();

	free(audioBuffer);
	audioBuffer = NULL;
	audioBufferSize = 0;

413
	for (i = 0; i < audioOutputArraySize; ++i) {
414 415
		if (audioDeviceStates[i] == DEVICE_ON)
			audioDeviceStates[i] = DEVICE_ENABLE;
Eric Wong's avatar
Eric Wong committed
416
		closeAudioOutput(&audioOutputArray[i]);
417
	}
418 419

	audioOpened = 0;
Warren Dukes's avatar
Warren Dukes committed
420
}
421

Avuton Olrich's avatar
Avuton Olrich committed
422 423
void sendMetadataToAudioDevice(MpdTag * tag)
{
424
	unsigned int i;
425

426
	for (i = 0; i < audioOutputArraySize; ++i) {
Eric Wong's avatar
Eric Wong committed
427
		sendMetadataToAudioOutput(&audioOutputArray[i], tag);
428
	}
429
}
430

431
int enableAudioDevice(int fd, unsigned int device)
Avuton Olrich's avatar
Avuton Olrich committed
432
{
Max Kellermann's avatar
Max Kellermann committed
433
	if (device >= audioOutputArraySize) {
434
		commandError(fd, ACK_ERROR_ARG, "audio output device id %i "
Avuton Olrich's avatar
Avuton Olrich committed
435
			     "doesn't exist\n", device);
436 437 438
		return -1;
	}

439 440
	if (!(audioDeviceStates[device] & 0x01))
		audioDeviceStates[device] = DEVICE_ENABLE;
441 442 443 444

	return 0;
}

445
int disableAudioDevice(int fd, unsigned int device)
Avuton Olrich's avatar
Avuton Olrich committed
446
{
Max Kellermann's avatar
Max Kellermann committed
447
	if (device >= audioOutputArraySize) {
448
		commandError(fd, ACK_ERROR_ARG, "audio output device id %i "
Avuton Olrich's avatar
Avuton Olrich committed
449
			     "doesn't exist\n", device);
450 451
		return -1;
	}
452 453
	if (audioDeviceStates[device] & 0x01)
		audioDeviceStates[device] = DEVICE_DISABLE;
454 455 456

	return 0;
}
457

458
void printAudioDevices(int fd)
Avuton Olrich's avatar
Avuton Olrich committed
459
{
460
	unsigned int i;
461

Avuton Olrich's avatar
Avuton Olrich committed
462
	for (i = 0; i < audioOutputArraySize; i++) {
463 464 465
		fdprintf(fd,
		         "outputid: %i\noutputname: %s\noutputenabled: %i\n",
			 i,
Eric Wong's avatar
Eric Wong committed
466
			 audioOutputArray[i].name,
467
			 audioDeviceStates[i] & 0x01);
468 469
	}
}
470

471
void saveAudioDevicesState(FILE *fp)
Avuton Olrich's avatar
Avuton Olrich committed
472
{
473
	unsigned int i;
474

475
	assert(audioOutputArraySize != 0);
476
	for (i = 0; i < audioOutputArraySize; i++) {
477
		fprintf(fp, AUDIO_DEVICE_STATE "%d:%s\n",
478
			audioDeviceStates[i] & 0x01,
Eric Wong's avatar
Eric Wong committed
479
		        audioOutputArray[i].name);
480 481 482
	}
}

483
void readAudioDevicesState(FILE *fp)
484 485
{
	char buffer[AUDIO_BUFFER_SIZE];
486
	unsigned int i;
487

488
	assert(audioOutputArraySize != 0);
489

Avuton Olrich's avatar
Avuton Olrich committed
490
	while (myFgets(buffer, AUDIO_BUFFER_SIZE, fp)) {
491
		char *c, *name;
492

Avuton Olrich's avatar
Avuton Olrich committed
493
		if (strncmp(buffer, AUDIO_DEVICE_STATE, AUDIO_DEVICE_STATE_LEN))
494
			continue;
495

Avuton Olrich's avatar
Avuton Olrich committed
496
		c = strchr(buffer, ':');
497 498
		if (!c || !(++c))
			goto errline;
499

Avuton Olrich's avatar
Avuton Olrich committed
500
		name = strchr(c, ':');
501 502
		if (!name || !(++name))
			goto errline;
503

504
		for (i = 0; i < audioOutputArraySize; ++i) {
Eric Wong's avatar
Eric Wong committed
505
			if (!strcmp(name, audioOutputArray[i].name)) {
506 507 508
				/* devices default to on */
				if (!atoi(c))
					audioDeviceStates[i] = DEVICE_DISABLE;
509
				break;
510 511
			}
		}
512
		continue;
513
errline:
514 515 516 517 518
		/* nonfatal */
		ERROR("invalid line in state_file: %s\n", buffer);
	}
}