OutputThread.cxx 13.4 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2014 The Music Player Daemon Project
3
 * http://www.musicpd.org
4 5 6 7 8 9 10 11 12 13
 *
 * 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.
14 15 16 17
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 19
 */

20
#include "config.h"
21
#include "Internal.hxx"
22
#include "OutputAPI.hxx"
23
#include "Domain.hxx"
Max Kellermann's avatar
Max Kellermann committed
24
#include "pcm/PcmMix.hxx"
Max Kellermann's avatar
Max Kellermann committed
25
#include "notify.hxx"
26 27 28
#include "filter/FilterInternal.hxx"
#include "filter/plugins/ConvertFilterPlugin.hxx"
#include "filter/plugins/ReplayGainFilterPlugin.hxx"
29
#include "PlayerControl.hxx"
30 31
#include "MusicPipe.hxx"
#include "MusicChunk.hxx"
32
#include "thread/Util.hxx"
33
#include "thread/Slack.hxx"
34
#include "thread/Name.hxx"
35
#include "system/FatalError.hxx"
36
#include "util/Error.hxx"
37
#include "Log.hxx"
38
#include "Compiler.h"
39

40
#include <assert.h>
Max Kellermann's avatar
Max Kellermann committed
41
#include <string.h>
42

43 44
void
AudioOutput::CommandFinished()
45
{
46 47
	assert(command != AO_COMMAND_NONE);
	command = AO_COMMAND_NONE;
48

49
	mutex.unlock();
Max Kellermann's avatar
Max Kellermann committed
50
	audio_output_client_notify.Signal();
51
	mutex.lock();
52 53
}

54 55
inline bool
AudioOutput::Enable()
56
{
57
	if (really_enabled)
58 59
		return true;

60 61 62 63
	mutex.unlock();
	Error error;
	bool success = ao_plugin_enable(this, error);
	mutex.lock();
64
	if (!success) {
65 66
		FormatError(error,
			    "Failed to enable \"%s\" [%s]",
67
			    name, plugin.name);
68 69 70
		return false;
	}

71
	really_enabled = true;
72 73 74
	return true;
}

75 76
inline void
AudioOutput::Disable()
77
{
78 79
	if (open)
		Close(false);
80

81 82
	if (really_enabled) {
		really_enabled = false;
83

84 85 86
		mutex.unlock();
		ao_plugin_disable(this);
		mutex.lock();
87 88 89
	}
}

90 91
inline AudioFormat
AudioOutput::OpenFilter(AudioFormat &format, Error &error_r)
92
{
93
	assert(format.IsValid());
94

95
	/* the replay_gain filter cannot fail here */
96 97
	if (replay_gain_filter != nullptr &&
	    !replay_gain_filter->Open(format, error_r).IsDefined())
98 99
		return AudioFormat::Undefined();

100 101 102 103
	if (other_replay_gain_filter != nullptr &&
	    !other_replay_gain_filter->Open(format, error_r).IsDefined()) {
		if (replay_gain_filter != nullptr)
			replay_gain_filter->Close();
104 105
		return AudioFormat::Undefined();
	}
106

107
	const AudioFormat af = filter->Open(format, error_r);
108
	if (!af.IsDefined()) {
109 110 111 112
		if (replay_gain_filter != nullptr)
			replay_gain_filter->Close();
		if (other_replay_gain_filter != nullptr)
			other_replay_gain_filter->Close();
113 114 115
	}

	return af;
116 117
}

118 119
void
AudioOutput::CloseFilter()
120
{
121 122 123 124
	if (replay_gain_filter != nullptr)
		replay_gain_filter->Close();
	if (other_replay_gain_filter != nullptr)
		other_replay_gain_filter->Close();
125

126
	filter->Close();
127 128
}

129 130
inline void
AudioOutput::Open()
131 132
{
	bool success;
133
	Error error;
134
	struct audio_format_string af_string;
135

136 137 138 139
	assert(!open);
	assert(pipe != nullptr);
	assert(current_chunk == nullptr);
	assert(in_audio_format.IsValid());
140

141
	fail_timer.Reset();
142

143 144
	/* enable the device (just in case the last enable has failed) */

145
	if (!Enable())
146 147 148
		/* still no luck */
		return;

149 150
	/* open the filter */

151
	const AudioFormat filter_audio_format =
152
		OpenFilter(in_audio_format, error);
153
	if (!filter_audio_format.IsDefined()) {
154
		FormatError(error, "Failed to open filter for \"%s\" [%s]",
155
			    name, plugin.name);
156

157
		fail_timer.Update();
158 159 160
		return;
	}

161
	assert(filter_audio_format.IsValid());
162

163 164
	out_audio_format = filter_audio_format;
	out_audio_format.ApplyMask(config_audio_format);
165

166 167 168
	mutex.unlock();
	success = ao_plugin_open(this, out_audio_format, error);
	mutex.lock();
169

170
	assert(!open);
171 172

	if (!success) {
173
		FormatError(error, "Failed to open \"%s\" [%s]",
174
			    name, plugin.name);
175

176 177
		CloseFilter();
		fail_timer.Update();
178 179 180
		return;
	}

181
	if (!convert_filter_set(convert_filter, out_audio_format,
182 183
				error)) {
		FormatError(error, "Failed to convert for \"%s\" [%s]",
184
			    name, plugin.name);
185

186 187
		CloseFilter();
		fail_timer.Update();
188 189
		return;
	}
190

191
	open = true;
192

193 194
	FormatDebug(output_domain,
		    "opened plugin=%s name=\"%s\" audio_format=%s",
195 196
		    plugin.name, name,
		    audio_format_to_string(out_audio_format, &af_string));
197

198
	if (in_audio_format != out_audio_format)
199
		FormatDebug(output_domain, "converting from %s",
200
			    audio_format_to_string(in_audio_format,
201
						   &af_string));
202 203
}

204 205
void
AudioOutput::Close(bool drain)
206
{
207
	assert(open);
208

209
	pipe = nullptr;
210

211 212
	current_chunk = nullptr;
	open = false;
213

214
	mutex.unlock();
215

216
	if (drain)
217
		ao_plugin_drain(this);
218
	else
219
		ao_plugin_cancel(this);
220

221 222
	ao_plugin_close(this);
	CloseFilter();
223

224
	mutex.lock();
225

226
	FormatDebug(output_domain, "closed plugin=%s name=\"%s\"",
227
		    plugin.name, name);
228 229
}

230 231
void
AudioOutput::ReopenFilter()
232
{
233
	Error error;
234

235
	CloseFilter();
236
	const AudioFormat filter_audio_format =
237
		OpenFilter(in_audio_format, error);
238
	if (!filter_audio_format.IsDefined() ||
239
	    !convert_filter_set(convert_filter, out_audio_format,
240
				error)) {
241 242
		FormatError(error,
			    "Failed to open filter for \"%s\" [%s]",
243
			    name, plugin.name);
244

245
		/* this is a little code duplication from Close(),
246
		   but we cannot call this function because we must
247
		   not call filter_close(filter) again */
248

249
		pipe = nullptr;
250

251 252 253
		current_chunk = nullptr;
		open = false;
		fail_timer.Update();
254

255 256 257
		mutex.unlock();
		ao_plugin_close(this);
		mutex.lock();
258 259 260 261 262

		return;
	}
}

263 264
void
AudioOutput::Reopen()
265
{
266 267 268 269 270
	if (!config_audio_format.IsFullyDefined()) {
		if (open) {
			const MusicPipe *mp = pipe;
			Close(true);
			pipe = mp;
271 272 273 274 275
		}

		/* no audio format is configured: copy in->out, let
		   the output's open() method determine the effective
		   out_audio_format */
276 277
		out_audio_format = in_audio_format;
		out_audio_format.ApplyMask(config_audio_format);
278 279
	}

280
	if (open)
281 282
		/* the audio format has changed, and all filters have
		   to be reconfigured */
283
		ReopenFilter();
284
	else
285
		Open();
286 287
}

288 289 290 291 292 293
/**
 * Wait until the output's delay reaches zero.
 *
 * @return true if playback should be continued, false if a command
 * was issued
 */
294 295
inline bool
AudioOutput::WaitForDelay()
296 297
{
	while (true) {
298
		unsigned delay = ao_plugin_delay(this);
299 300 301
		if (delay == 0)
			return true;

302
		(void)cond.timed_wait(mutex, delay);
303

304
		if (command != AO_COMMAND_NONE)
305 306 307 308
			return false;
	}
}

309
static const void *
310
ao_chunk_data(AudioOutput *ao, const struct music_chunk *chunk,
311
	      Filter *replay_gain_filter,
312
	      unsigned *replay_gain_serial_p,
313
	      size_t *length_r)
314
{
315
	assert(chunk != nullptr);
316 317
	assert(!chunk->IsEmpty());
	assert(chunk->CheckFormat(ao->in_audio_format));
318

319
	const void *data = chunk->data;
320 321 322 323
	size_t length = chunk->length;

	(void)ao;

324
	assert(length % ao->in_audio_format.GetFrameSize() == 0);
325

326
	if (length > 0 && replay_gain_filter != nullptr) {
327 328 329 330
		if (chunk->replay_gain_serial != *replay_gain_serial_p) {
			replay_gain_filter_set_info(replay_gain_filter,
						    chunk->replay_gain_serial != 0
						    ? &chunk->replay_gain_info
331
						    : nullptr);
332 333 334
			*replay_gain_serial_p = chunk->replay_gain_serial;
		}

335
		Error error;
336
		data = replay_gain_filter->FilterPCM(data, length,
337
						     &length, error);
338
		if (data == nullptr) {
339
			FormatError(error, "\"%s\" [%s] failed to filter",
340
				    ao->name, ao->plugin.name);
341
			return nullptr;
342 343 344
		}
	}

345 346 347 348
	*length_r = length;
	return data;
}

349
static const void *
350
ao_filter_chunk(AudioOutput *ao, const struct music_chunk *chunk,
351 352 353
		size_t *length_r)
{
	size_t length;
354
	const void *data = ao_chunk_data(ao, chunk, ao->replay_gain_filter,
355
					 &ao->replay_gain_serial, &length);
356 357
	if (data == nullptr)
		return nullptr;
358

359 360 361 362
	if (length == 0) {
		/* empty chunk, nothing to do */
		*length_r = 0;
		return data;
363
	}
364

365 366
	/* cross-fade */

367
	if (chunk->other != nullptr) {
368
		size_t other_length;
369
		const void *other_data =
370 371 372 373
			ao_chunk_data(ao, chunk->other,
				      ao->other_replay_gain_filter,
				      &ao->other_replay_gain_serial,
				      &other_length);
374 375
		if (other_data == nullptr)
			return nullptr;
376

377 378 379 380 381 382 383 384 385 386 387 388 389
		if (other_length == 0) {
			*length_r = 0;
			return data;
		}

		/* if the "other" chunk is longer, then that trailer
		   is used as-is, without mixing; it is part of the
		   "next" song being faded in, and if there's a rest,
		   it means cross-fading ends here */

		if (length > other_length)
			length = other_length;

390
		void *dest = ao->cross_fade_buffer.Get(other_length);
391
		memcpy(dest, other_data, other_length);
392
		if (!pcm_mix(ao->cross_fade_dither, dest, data, length,
393
			     ao->in_audio_format.format,
394
			     1.0 - chunk->mix_ratio)) {
395 396 397
			FormatError(output_domain,
				    "Cannot cross-fade format %s",
				    sample_format_to_string(ao->in_audio_format.format));
398
			return nullptr;
399
		}
400 401 402 403 404

		data = dest;
		length = other_length;
	}

405
	/* apply filter chain */
406

407 408
	Error error;
	data = ao->filter->FilterPCM(data, length, &length, error);
409
	if (data == nullptr) {
410
		FormatError(error, "\"%s\" [%s] failed to filter",
411
			    ao->name, ao->plugin.name);
412
		return nullptr;
413 414 415 416 417 418
	}

	*length_r = length;
	return data;
}

419 420
inline bool
AudioOutput::PlayChunk(const music_chunk *chunk)
421
{
422
	assert(filter != nullptr);
423

424 425 426 427
	if (tags && gcc_unlikely(chunk->tag != nullptr)) {
		mutex.unlock();
		ao_plugin_send_tag(this, chunk->tag);
		mutex.lock();
428 429 430
	}

	size_t size;
431 432 433 434
#if GCC_CHECK_VERSION(4,7)
	/* workaround -Wmaybe-uninitialized false positive */
	size = 0;
#endif
435
	const char *data = (const char *)ao_filter_chunk(this, chunk, &size);
436
	if (data == nullptr) {
437
		Close(false);
438 439 440

		/* don't automatically reopen this device for 10
		   seconds */
441
		fail_timer.Update();
442
		return false;
443 444
	}

445 446
	Error error;

447
	while (size > 0 && command == AO_COMMAND_NONE) {
448 449
		size_t nbytes;

450
		if (!WaitForDelay())
451 452
			break;

453 454 455
		mutex.unlock();
		nbytes = ao_plugin_play(this, data, size, error);
		mutex.lock();
456 457
		if (nbytes == 0) {
			/* play()==0 means failure */
458
			FormatError(error, "\"%s\" [%s] failed to play",
459
				    name, plugin.name);
460

461
			Close(false);
462 463 464

			/* don't automatically reopen this device for
			   10 seconds */
465 466
			assert(!fail_timer.IsDefined());
			fail_timer.Update();
467

468
			return false;
469 470 471
		}

		assert(nbytes <= size);
472
		assert(nbytes % out_audio_format.GetFrameSize() == 0);
473 474 475

		data += nbytes;
		size -= nbytes;
476 477
	}

478 479 480
	return true;
}

481 482
inline const music_chunk *
AudioOutput::GetNextChunk() const
483
{
484
	return current_chunk != nullptr
485
		/* continue the previous play() call */
486
		? current_chunk->next
487
		/* get the first chunk from the pipe */
488
		: pipe->Peek();
489 490
}

491 492
inline bool
AudioOutput::Play()
493
{
494
	assert(pipe != nullptr);
495

496
	const music_chunk *chunk = GetNextChunk();
497
	if (chunk == nullptr)
498 499
		/* no chunk available */
		return false;
500

501
	current_chunk_finished = false;
502

503 504
	assert(!in_playback_loop);
	in_playback_loop = true;
505

506 507
	while (chunk != nullptr && command == AO_COMMAND_NONE) {
		assert(!current_chunk_finished);
508

509
		current_chunk = chunk;
510

511 512
		if (!PlayChunk(chunk)) {
			assert(current_chunk == nullptr);
513 514 515
			break;
		}

516
		assert(current_chunk == chunk);
517 518 519
		chunk = chunk->next;
	}

520 521
	assert(in_playback_loop);
	in_playback_loop = false;
522

523
	current_chunk_finished = true;
524

525 526 527
	mutex.unlock();
	player_control->LockSignal();
	mutex.lock();
528 529

	return true;
530 531
}

532 533
inline void
AudioOutput::Pause()
534
{
535 536 537
	mutex.unlock();
	ao_plugin_cancel(this);
	mutex.lock();
538

539 540
	pause = true;
	CommandFinished();
541 542

	do {
543
		if (!WaitForDelay())
544 545
			break;

546 547 548
		mutex.unlock();
		bool success = ao_plugin_pause(this);
		mutex.lock();
549

550 551
		if (!success) {
			Close(false);
552 553
			break;
		}
554
	} while (command == AO_COMMAND_NONE);
555

556
	pause = false;
557 558
}

559 560
inline void
AudioOutput::Task()
561
{
562
	FormatThreadName("output:%s", name);
563

564
	SetThreadRealtime();
565
	SetThreadTimerSlackUS(100);
566

567
	mutex.lock();
568

569
	while (1) {
570
		switch (command) {
571 572 573
		case AO_COMMAND_NONE:
			break;

574
		case AO_COMMAND_ENABLE:
575 576
			Enable();
			CommandFinished();
577 578 579
			break;

		case AO_COMMAND_DISABLE:
580 581
			Disable();
			CommandFinished();
582 583
			break;

584
		case AO_COMMAND_OPEN:
585 586
			Open();
			CommandFinished();
587 588
			break;

589
		case AO_COMMAND_REOPEN:
590 591
			Reopen();
			CommandFinished();
592 593
			break;

594
		case AO_COMMAND_CLOSE:
595 596
			assert(open);
			assert(pipe != nullptr);
597

598 599
			Close(false);
			CommandFinished();
600 601
			break;

602
		case AO_COMMAND_PAUSE:
603
			if (!open) {
604 605 606 607
				/* the output has failed after
				   audio_output_all_pause() has
				   submitted the PAUSE command; bail
				   out */
608
				CommandFinished();
609 610 611
				break;
			}

612
			Pause();
613
			/* don't "break" here: this might cause
614
			   Play() to be called when command==CLOSE
615 616 617
			   ends the paused state - "continue" checks
			   the new command first */
			continue;
618

619
		case AO_COMMAND_DRAIN:
620 621 622
			if (open) {
				assert(current_chunk == nullptr);
				assert(pipe->Peek() == nullptr);
623

624 625 626
				mutex.unlock();
				ao_plugin_drain(this);
				mutex.lock();
627 628
			}

629
			CommandFinished();
630 631
			continue;

632
		case AO_COMMAND_CANCEL:
633
			current_chunk = nullptr;
634

635 636 637 638
			if (open) {
				mutex.unlock();
				ao_plugin_cancel(this);
				mutex.lock();
639 640
			}

641
			CommandFinished();
642
			continue;
643 644

		case AO_COMMAND_KILL:
645 646 647
			current_chunk = nullptr;
			CommandFinished();
			mutex.unlock();
648
			return;
649 650
		}

651
		if (open && allow_play && Play())
652 653 654
			/* don't wait for an event if there are more
			   chunks in the pipe */
			continue;
655

656 657 658
		if (command == AO_COMMAND_NONE) {
			woken_for_play = false;
			cond.wait(mutex);
659
		}
660 661 662
	}
}

663 664 665 666 667 668 669
void
AudioOutput::Task(void *arg)
{
	AudioOutput *ao = (AudioOutput *)arg;
	ao->Task();
}

670 671
void
AudioOutput::StartThread()
672
{
673
	assert(command == AO_COMMAND_NONE);
674

675
	Error error;
676
	if (!thread.Start(Task, this, error))
677
		FatalError(error);
678
}