| 
									
										
										
										
											2013-04-21 02:17:03 -04:00
										 |  |  | // Copyright 2013 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-31 08:19:27 +00:00
										 |  |  | #include <functional>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | #include "Common.h"
 | 
					
						
							|  |  |  | #include "Thread.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "PulseAudioStream.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | namespace | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | const size_t BUFFER_SAMPLES = 512; | 
					
						
							|  |  |  | const size_t CHANNEL_COUNT = 2; | 
					
						
							|  |  |  | const size_t BUFFER_SIZE = BUFFER_SAMPLES * CHANNEL_COUNT; | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | PulseAudio::PulseAudio(CMixer *mixer) | 
					
						
							|  |  |  | 	: SoundStream(mixer) | 
					
						
							|  |  |  | 	, mix_buffer(BUFFER_SIZE) | 
					
						
							|  |  |  | 	, thread() | 
					
						
							|  |  |  | 	, run_thread() | 
					
						
							|  |  |  | 	, pa() | 
					
						
							|  |  |  | {} | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool PulseAudio::Start() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	run_thread = true; | 
					
						
							| 
									
										
										
										
											2011-01-31 08:19:27 +00:00
										 |  |  | 	thread = std::thread(std::mem_fun(&PulseAudio::SoundLoop), this); | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PulseAudio::Stop() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	run_thread = false; | 
					
						
							| 
									
										
										
										
											2011-01-27 21:34:37 +00:00
										 |  |  | 	thread.join(); | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PulseAudio::Update() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// don't need to do anything here.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Called on audio thread.
 | 
					
						
							|  |  |  | void PulseAudio::SoundLoop() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-30 20:22:48 -08:00
										 |  |  | 	Common::SetCurrentThreadName("Audio thread - pulse"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	if (PulseInit()) | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 		while (run_thread) | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 			m_mixer->Mix(&mix_buffer[0], mix_buffer.size() / CHANNEL_COUNT); | 
					
						
							|  |  |  | 			Write(&mix_buffer[0], mix_buffer.size() * sizeof(s16)); | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 		PulseShutdown(); | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | bool PulseAudio::PulseInit() | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	pa_sample_spec ss = {}; | 
					
						
							|  |  |  | 	ss.format = PA_SAMPLE_S16LE; | 
					
						
							|  |  |  | 	ss.channels = 2; | 
					
						
							| 
									
										
										
										
											2013-01-13 22:20:33 -06:00
										 |  |  | 	ss.rate = m_mixer->GetSampleRate(); | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	int error; | 
					
						
							|  |  |  | 	pa = pa_simple_new(nullptr, "dolphin-emu", PA_STREAM_PLAYBACK, | 
					
						
							|  |  |  | 		nullptr, "audio", &ss, nullptr, nullptr, &error); | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	if (!pa) | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 		ERROR_LOG(AUDIO, "PulseAudio failed to initialize: %s", | 
					
						
							|  |  |  | 			pa_strerror(error)); | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2009-10-15 17:28:23 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 		NOTICE_LOG(AUDIO, "Pulse successfully initialized."); | 
					
						
							|  |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | void PulseAudio::PulseShutdown() | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	pa_simple_free(pa); | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | void PulseAudio::Write(const void *data, size_t length) | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 	int error; | 
					
						
							|  |  |  | 	if (pa_simple_write(pa, data, length, &error) < 0) | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-01-09 17:39:19 -06:00
										 |  |  | 		ERROR_LOG(AUDIO, "PulseAudio failed to write data: %s", | 
					
						
							|  |  |  | 			pa_strerror(error)); | 
					
						
							| 
									
										
										
										
											2010-08-17 02:14:04 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |