2 * Copyright (C) 2010-2013 Team XBMC
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, or (at your option)
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.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
24 #include "PulseAEStream.h"
25 #include "AEFactory.h"
26 #include "Utils/AEUtil.h"
27 #include "utils/log.h"
28 #include "utils/MathUtils.h"
29 #include "threads/SingleLock.h"
31 static const char *StreamStateToString(pa_stream_state s)
35 case PA_STREAM_UNCONNECTED:
37 case PA_STREAM_CREATING:
41 case PA_STREAM_FAILED:
43 case PA_STREAM_TERMINATED:
50 CPulseAEStream::CPulseAEStream(pa_context *context, pa_threaded_mainloop *mainLoop, enum AEDataFormat format, unsigned int sampleRate, CAEChannelInfo channelLayout, unsigned int options) : m_fader(this)
52 ASSERT(channelLayout.Count());
54 m_Initialized = false;
56 m_ResumeCallback = false;
60 m_MainLoop = mainLoop;
63 m_sampleRate = sampleRate;
64 m_channelLayout = channelLayout;
67 m_DrainOperation = NULL;
70 pa_threaded_mainloop_lock(m_MainLoop);
72 m_SampleSpec.channels = channelLayout.Count();
73 m_SampleSpec.rate = m_sampleRate;
77 case AE_FMT_U8 : m_SampleSpec.format = PA_SAMPLE_U8; break;
78 case AE_FMT_S16NE : m_SampleSpec.format = PA_SAMPLE_S16NE; break;
79 case AE_FMT_S16LE : m_SampleSpec.format = PA_SAMPLE_S16LE; break;
80 case AE_FMT_S16BE : m_SampleSpec.format = PA_SAMPLE_S16BE; break;
81 case AE_FMT_S24NE3: m_SampleSpec.format = PA_SAMPLE_S24NE; break;
82 case AE_FMT_S24NE4: m_SampleSpec.format = PA_SAMPLE_S24_32NE; break;
83 case AE_FMT_S32NE : m_SampleSpec.format = PA_SAMPLE_S32NE; break;
84 case AE_FMT_S32LE : m_SampleSpec.format = PA_SAMPLE_S32LE; break;
85 case AE_FMT_S32BE : m_SampleSpec.format = PA_SAMPLE_S32BE; break;
86 case AE_FMT_FLOAT : m_SampleSpec.format = PA_SAMPLE_FLOAT32NE; break;
87 #if PA_CHECK_VERSION(1,0,0)
90 case AE_FMT_AC3 : m_SampleSpec.format = PA_SAMPLE_S16NE; break;
94 CLog::Log(LOGERROR, "PulseAudio: Invalid format %i", format);
95 pa_threaded_mainloop_unlock(m_MainLoop);
96 m_format = AE_FMT_INVALID;
100 if (!pa_sample_spec_valid(&m_SampleSpec))
102 CLog::Log(LOGERROR, "PulseAudio: Invalid sample spec");
103 pa_threaded_mainloop_unlock(m_MainLoop);
108 m_frameSize = pa_frame_size(&m_SampleSpec);
110 struct pa_channel_map map;
111 map.channels = m_channelLayout.Count();
113 for (unsigned int ch = 0; ch < m_channelLayout.Count(); ++ch)
114 switch(m_channelLayout[ch])
116 case AE_CH_NULL: break;
117 case AE_CH_MAX : break;
118 case AE_CH_RAW : break;
119 case AE_CH_FL : map.map[ch] = PA_CHANNEL_POSITION_FRONT_LEFT ; break;
120 case AE_CH_FR : map.map[ch] = PA_CHANNEL_POSITION_FRONT_RIGHT ; break;
121 case AE_CH_FC : map.map[ch] = PA_CHANNEL_POSITION_FRONT_CENTER ; break;
122 case AE_CH_BC : map.map[ch] = PA_CHANNEL_POSITION_REAR_CENTER ; break;
123 case AE_CH_BL : map.map[ch] = PA_CHANNEL_POSITION_REAR_LEFT ; break;
124 case AE_CH_BR : map.map[ch] = PA_CHANNEL_POSITION_REAR_RIGHT ; break;
125 case AE_CH_LFE : map.map[ch] = PA_CHANNEL_POSITION_LFE ; break;
126 case AE_CH_FLOC: map.map[ch] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ; break;
127 case AE_CH_FROC: map.map[ch] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; break;
128 case AE_CH_SL : map.map[ch] = PA_CHANNEL_POSITION_SIDE_LEFT ; break;
129 case AE_CH_SR : map.map[ch] = PA_CHANNEL_POSITION_SIDE_RIGHT ; break;
130 case AE_CH_TC : map.map[ch] = PA_CHANNEL_POSITION_TOP_CENTER ; break;
131 case AE_CH_TFL : map.map[ch] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT ; break;
132 case AE_CH_TFR : map.map[ch] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ; break;
133 case AE_CH_TFC : map.map[ch] = PA_CHANNEL_POSITION_TOP_CENTER ; break;
134 case AE_CH_TBL : map.map[ch] = PA_CHANNEL_POSITION_TOP_REAR_LEFT ; break;
135 case AE_CH_TBR : map.map[ch] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT ; break;
136 case AE_CH_TBC : map.map[ch] = PA_CHANNEL_POSITION_TOP_REAR_CENTER ; break;
140 m_MaxVolume = CAEFactory::GetEngine()->GetVolume();
142 pa_volume_t paVolume = pa_sw_volume_from_linear((double)(m_Volume * m_MaxVolume));
143 pa_cvolume_set(&m_ChVolume, m_SampleSpec.channels, paVolume);
145 #if PA_CHECK_VERSION(1,0,0)
146 pa_format_info *info[1];
147 info[0] = pa_format_info_new();
150 case AE_FMT_DTS : info[0]->encoding = PA_ENCODING_DTS_IEC61937 ; break;
151 case AE_FMT_EAC3: info[0]->encoding = PA_ENCODING_EAC3_IEC61937; break;
152 case AE_FMT_AC3 : info[0]->encoding = PA_ENCODING_AC3_IEC61937 ; break;
153 default: info[0]->encoding = PA_ENCODING_PCM ; break;
155 pa_format_info_set_rate (info[0], m_SampleSpec.rate);
156 pa_format_info_set_channels (info[0], m_SampleSpec.channels);
157 pa_format_info_set_channel_map (info[0], &map);
158 pa_format_info_set_sample_format(info[0], m_SampleSpec.format);
159 m_Stream = pa_stream_new_extended(m_Context, "audio stream", info, 1, NULL);
160 pa_format_info_free(info[0]);
162 m_Stream = pa_stream_new(m_Context, "audio stream", &m_SampleSpec, &map);
165 if (m_Stream == NULL)
167 CLog::Log(LOGERROR, "PulseAudio: Could not create a stream");
168 pa_threaded_mainloop_unlock(m_MainLoop);
173 pa_stream_set_state_callback(m_Stream, CPulseAEStream::StreamStateCallback, this);
174 pa_stream_set_write_callback(m_Stream, CPulseAEStream::StreamRequestCallback, this);
175 pa_stream_set_latency_update_callback(m_Stream, CPulseAEStream::StreamLatencyUpdateCallback, this);
176 pa_stream_set_underflow_callback(m_Stream, CPulseAEStream::StreamUnderflowCallback, this);
178 int flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
179 if (options && AESTREAM_FORCE_RESAMPLE)
180 flags |= PA_STREAM_VARIABLE_RATE;
182 if (pa_stream_connect_playback(m_Stream, NULL, NULL, (pa_stream_flags)flags, &m_ChVolume, NULL) < 0)
184 CLog::Log(LOGERROR, "PulseAudio: Failed to connect stream to output");
185 pa_threaded_mainloop_unlock(m_MainLoop);
190 /* Wait until the stream is ready */
193 pa_threaded_mainloop_wait(m_MainLoop);
194 CLog::Log(LOGDEBUG, "PulseAudio: Stream %s", StreamStateToString(pa_stream_get_state(m_Stream)));
196 while (pa_stream_get_state(m_Stream) != PA_STREAM_READY && pa_stream_get_state(m_Stream) != PA_STREAM_FAILED);
198 if (pa_stream_get_state(m_Stream) == PA_STREAM_FAILED)
200 CLog::Log(LOGERROR, "PulseAudio: Waited for the stream but it failed");
201 pa_threaded_mainloop_unlock(m_MainLoop);
206 const pa_buffer_attr *streamBuffer;
207 streamBuffer = pa_stream_get_buffer_attr(m_Stream);
208 m_cacheSize = streamBuffer->maxlength;
210 pa_threaded_mainloop_unlock(m_MainLoop);
212 m_Initialized = true;
214 CLog::Log(LOGINFO, "PulseAEStream::Initialized");
215 CLog::Log(LOGINFO, " Sample Rate : %d", m_sampleRate);
216 CLog::Log(LOGINFO, " Sample Format : %s", CAEUtil::DataFormatToStr(m_format));
217 CLog::Log(LOGINFO, " Channel Count : %d", m_channelLayout.Count());
218 CLog::Log(LOGINFO, " Channel Layout: %s", ((std::string)m_channelLayout).c_str());
219 CLog::Log(LOGINFO, " Frame Size : %d", m_frameSize);
220 CLog::Log(LOGINFO, " Cache Size : %d", m_cacheSize);
227 CPulseAEStream::~CPulseAEStream()
233 this method may be called inside the pulse main loop,
234 so be VERY careful with locking
236 void CPulseAEStream::Destroy()
244 m_fader.StopThread(true);
246 pa_threaded_mainloop_lock(m_MainLoop);
248 if (m_DrainOperation)
250 pa_operation_cancel(m_DrainOperation);
251 pa_operation_unref(m_DrainOperation);
252 m_DrainOperation = NULL;
257 pa_stream_set_state_callback(m_Stream, NULL, NULL);
258 pa_stream_set_write_callback(m_Stream, NULL, NULL);
259 pa_stream_set_latency_update_callback(m_Stream, NULL, NULL);
260 pa_stream_set_underflow_callback(m_Stream, NULL, NULL);
261 pa_stream_disconnect(m_Stream);
262 pa_stream_unref(m_Stream);
266 /* signal CPulseAE to free us */
268 m_Initialized = false;
270 pa_threaded_mainloop_unlock(m_MainLoop);
273 unsigned int CPulseAEStream::GetSpace()
278 pa_threaded_mainloop_lock(m_MainLoop);
279 unsigned int size = pa_stream_writable_size(m_Stream);
280 pa_threaded_mainloop_unlock(m_MainLoop);
282 if(size > m_cacheSize)
288 unsigned int CPulseAEStream::AddData(void *data, unsigned int size)
293 pa_threaded_mainloop_lock(m_MainLoop);
295 int length = std::min((int)pa_stream_writable_size(m_Stream), (int)size);
298 pa_threaded_mainloop_unlock(m_MainLoop);
302 int written = pa_stream_write(m_Stream, data, length, NULL, 0, PA_SEEK_RELATIVE);
303 pa_threaded_mainloop_unlock(m_MainLoop);
307 CLog::Log(LOGERROR, "PulseAudio: AddPackets - pa_stream_write failed\n");
314 double CPulseAEStream::GetDelay()
319 pa_usec_t latency = 0;
320 pa_threaded_mainloop_lock(m_MainLoop);
322 if (pa_stream_get_latency(m_Stream, &latency, NULL) == PA_ERR_NODATA)
323 CLog::Log(LOGERROR, "PulseAudio: pa_stream_get_latency() failed");
325 pa_threaded_mainloop_unlock(m_MainLoop);
326 return (double)((double)latency / 1000000.0);
329 double CPulseAEStream::GetCacheTime()
334 return (double)(m_cacheSize - GetSpace()) / (double)(m_sampleRate * m_frameSize);
337 double CPulseAEStream::GetCacheTotal()
342 return (double)m_cacheSize / (double)(m_sampleRate * m_frameSize);
345 bool CPulseAEStream::IsPaused()
350 bool CPulseAEStream::IsDraining()
352 if (m_DrainOperation)
354 if (pa_operation_get_state(m_DrainOperation) == PA_OPERATION_RUNNING)
357 pa_operation_unref(m_DrainOperation);
358 m_DrainOperation = NULL;
364 bool CPulseAEStream::IsDrained()
366 bool ret = (m_DrainOperation == NULL);
372 bool CPulseAEStream::IsDestroyed()
377 void CPulseAEStream::Pause()
380 m_Paused = Cork(true);
383 void CPulseAEStream::Resume()
386 m_Paused = Cork(false);
389 void CPulseAEStream::Drain(bool wait)
394 if (m_DrainOperation)
397 pa_threaded_mainloop_lock(m_MainLoop);
398 m_DrainOperation = pa_stream_drain(m_Stream, CPulseAEStream::StreamDrainComplete, this);
399 pa_threaded_mainloop_unlock(m_MainLoop);
402 void CPulseAEStream::Flush()
407 pa_threaded_mainloop_lock(m_MainLoop);
408 pa_operation_unref(pa_stream_flush(m_Stream, NULL, NULL));
409 pa_threaded_mainloop_unlock(m_MainLoop);
412 float CPulseAEStream::GetVolume()
417 float CPulseAEStream::GetReplayGain()
422 void CPulseAEStream::SetVolume(float volume)
427 if (!pa_threaded_mainloop_in_thread(m_MainLoop))
428 pa_threaded_mainloop_lock(m_MainLoop);
433 pa_volume_t paVolume = pa_sw_volume_from_linear((double)(m_Volume * m_MaxVolume));
435 pa_cvolume_set(&m_ChVolume, m_SampleSpec.channels, paVolume);
438 pa_cvolume_mute(&m_ChVolume,m_SampleSpec.channels);
440 pa_operation *op = pa_context_set_sink_input_volume(m_Context, pa_stream_get_index(m_Stream), &m_ChVolume, NULL, NULL);
443 CLog::Log(LOGERROR, "PulseAudio: Failed to set volume");
445 pa_operation_unref(op);
447 if (!pa_threaded_mainloop_in_thread(m_MainLoop))
448 pa_threaded_mainloop_unlock(m_MainLoop);
451 void CPulseAEStream::UpdateVolume(float max)
460 void CPulseAEStream::SetMute(const bool mute)
468 void CPulseAEStream::SetReplayGain(float factor)
472 const unsigned int CPulseAEStream::GetFrameSize() const
477 const unsigned int CPulseAEStream::GetChannelCount() const
479 return m_channelLayout.Count();
482 const unsigned int CPulseAEStream::GetSampleRate() const
487 const enum AEDataFormat CPulseAEStream::GetDataFormat() const
492 double CPulseAEStream::GetResampleRatio()
497 bool CPulseAEStream::SetResampleRatio(double ratio)
502 void CPulseAEStream::RegisterAudioCallback(IAudioCallback* pCallback)
504 m_AudioCallback = pCallback;
507 void CPulseAEStream::UnRegisterAudioCallback()
509 m_AudioCallback = NULL;
512 void CPulseAEStream::FadeVolume(float from, float target, unsigned int time)
517 m_fader.SetupFader(from, target, time);
520 bool CPulseAEStream::IsFading()
522 return m_fader.IsRunning();
525 void CPulseAEStream::StreamRequestCallback(pa_stream *s, size_t length, void *userdata)
527 CPulseAEStream *stream = (CPulseAEStream *)userdata;
528 pa_threaded_mainloop_signal(stream->m_MainLoop, 0);
531 void CPulseAEStream::StreamLatencyUpdateCallback(pa_stream *s, void *userdata)
533 CPulseAEStream *stream = (CPulseAEStream *)userdata;
534 pa_threaded_mainloop_signal(stream->m_MainLoop, 0);
537 void CPulseAEStream::StreamStateCallback(pa_stream *s, void *userdata)
539 CPulseAEStream *stream = (CPulseAEStream *)userdata;
540 pa_stream_state_t state = pa_stream_get_state(s);
544 case PA_STREAM_UNCONNECTED:
545 case PA_STREAM_CREATING:
546 case PA_STREAM_READY:
547 case PA_STREAM_FAILED:
548 case PA_STREAM_TERMINATED:
549 pa_threaded_mainloop_signal(stream->m_MainLoop, 0);
554 void CPulseAEStream::StreamUnderflowCallback(pa_stream *s, void *userdata)
556 CPulseAEStream *stream = (CPulseAEStream *)userdata;
557 CLog::Log(LOGWARNING, "PulseAudio: Stream underflow");
558 pa_threaded_mainloop_signal(stream->m_MainLoop, 0);
561 void CPulseAEStream::StreamDrainComplete(pa_stream *s, int success, void *userdata)
563 CPulseAEStream *stream = (CPulseAEStream *)userdata;
566 stream->SetDrained();
567 pa_threaded_mainloop_signal(stream->m_MainLoop, 0);
571 void CPulseAEStream::ProcessCallbacks()
573 if(m_ResumeCallback && m_slave)
576 m_ResumeCallback = false;
579 inline bool CPulseAEStream::WaitForOperation(pa_operation *op, pa_threaded_mainloop *mainloop, const char *LogEntry = "")
585 ASSERT(!pa_threaded_mainloop_in_thread(mainloop));
587 while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
588 pa_threaded_mainloop_wait(mainloop);
590 if (pa_operation_get_state(op) != PA_OPERATION_DONE)
592 CLog::Log(LOGERROR, "PulseAudio: %s Operation failed", LogEntry);
596 pa_operation_unref(op);
600 bool CPulseAEStream::Cork(bool cork)
602 pa_threaded_mainloop_lock(m_MainLoop);
604 pa_operation *op = pa_stream_cork(m_Stream, cork ? 1 : 0, NULL, NULL);
605 if (!WaitForOperation(op, m_MainLoop, cork ? "Pause" : "Resume"))
608 pa_threaded_mainloop_unlock(m_MainLoop);
612 void CPulseAEStream::RegisterSlave(IAEStream *stream)
617 CPulseAEStream::CLinearFader::CLinearFader(IAEStream *stream) : CThread("AEStream"), m_stream(stream)
625 void CPulseAEStream::CLinearFader::SetupFader(float from, float target, unsigned int time)
636 m_stream->SetVolume(m_target);
639 void CPulseAEStream::CLinearFader::Process()
641 if (m_stream == NULL)
645 m_stream->SetVolume(m_from);
646 float k = m_target - m_from;
648 unsigned int begin = XbmcThreads::SystemClockMillis();
649 unsigned int end = begin + m_time;
650 unsigned int current = begin;
651 unsigned int step = std::max(1u, m_time / 100);
655 float x = ((float)current - (float)begin) / (float)m_time;
657 m_stream->SetVolume(m_from + k * x);
659 current = XbmcThreads::SystemClockMillis();
660 } while (current <= end && !m_bStop);
662 m_stream->SetVolume(m_target);
666 bool CPulseAEStream::CLinearFader::IsRunning()