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/>.
23 #include "ActiveAESink.h"
24 #include "cores/AudioEngine/Utils/AEUtil.h"
25 #include "utils/EndianSwap.h"
28 #include "settings/Settings.h"
30 using namespace ActiveAE;
32 CActiveAESink::CActiveAESink(CEvent *inMsgEvent) :
34 m_controlPort("SinkControlPort", inMsgEvent, &m_outMsgEvent),
35 m_dataPort("SinkDataPort", inMsgEvent, &m_outMsgEvent)
37 m_inMsgEvent = inMsgEvent;
40 m_convertBuffer = NULL;
44 void CActiveAESink::Start()
49 SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
53 void CActiveAESink::Dispose()
58 m_controlPort.Purge();
64 m_sink->Deinitialize();
69 delete m_sampleOfSilence.pkt;
70 m_sampleOfSilence.pkt = NULL;
74 _aligned_free(m_convertBuffer);
75 m_convertBuffer = NULL;
79 AEDeviceType CActiveAESink::GetDeviceType(const std::string &device)
81 std::string dev = device;
83 CAESinkFactory::ParseDevice(dev, dri);
84 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
86 for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
88 CAEDeviceInfo& info = *itt2;
89 if (info.m_deviceName == dev)
90 return info.m_deviceType;
93 return AE_DEVTYPE_PCM;
96 bool CActiveAESink::HasPassthroughDevice()
98 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
100 for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
102 CAEDeviceInfo& info = *itt2;
103 if (info.m_deviceType != AE_DEVTYPE_PCM)
113 S_TOP_UNCONFIGURED, // 1
114 S_TOP_CONFIGURED, // 2
115 S_TOP_CONFIGURED_SUSPEND, // 3
116 S_TOP_CONFIGURED_IDLE, // 4
117 S_TOP_CONFIGURED_PLAY, // 5
118 S_TOP_CONFIGURED_SILENCE, // 6
121 int SINK_parentStates[] = {
123 0, //TOP_UNCONFIGURED
125 2, //TOP_CONFIGURED_SUSPEND
126 2, //TOP_CONFIGURED_IDLE
127 2, //TOP_CONFIGURED_PLAY
128 2, //TOP_CONFIGURED_SILENCE
131 void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
133 for (int state = m_state; ; state = SINK_parentStates[state])
138 if (port == &m_controlPort)
142 case CSinkControlProtocol::CONFIGURE:
144 data = (SinkConfig*)msg->data;
147 m_requestedFormat = data->format;
148 m_stats = data->stats;
149 m_device = *(data->device);
152 m_extSilenceTimer = 0;
159 reply.format = m_sinkFormat;
160 reply.cacheTotal = m_sink->GetCacheTotal();
161 reply.latency = m_sink->GetLatency();
162 reply.hasVolume = m_sink->HasVolume();
163 m_state = S_TOP_CONFIGURED_IDLE;
164 m_extTimeout = 10000;
165 msg->Reply(CSinkControlProtocol::ACC, &reply, sizeof(SinkReply));
169 m_state = S_TOP_UNCONFIGURED;
170 msg->Reply(CSinkControlProtocol::ERR);
174 case CSinkControlProtocol::UNCONFIGURE:
179 m_sink->Deinitialize();
183 m_state = S_TOP_UNCONFIGURED;
184 msg->Reply(CSinkControlProtocol::ACC);
187 case CSinkControlProtocol::FLUSH:
189 msg->Reply(CSinkControlProtocol::ACC);
196 else if (port == &m_dataPort)
200 case CSinkDataProtocol::DRAIN:
201 msg->Reply(CSinkDataProtocol::ACC);
202 m_state = S_TOP_UNCONFIGURED;
210 std::string portName = port == NULL ? "timer" : port->portName;
211 CLog::Log(LOGWARNING, "CActiveAESink::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
215 case S_TOP_UNCONFIGURED:
216 if (port == NULL) // timeout
220 case CSinkControlProtocol::TIMEOUT:
227 else if (port == &m_dataPort)
231 case CSinkDataProtocol::SAMPLE:
232 CSampleBuffer *samples;
234 samples = *((CSampleBuffer**)msg->data);
235 timeout = 1000*samples->pkt->nb_samples/samples->pkt->config.sample_rate;
237 msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
246 case S_TOP_CONFIGURED:
247 if (port == &m_controlPort)
251 case CSinkControlProtocol::SILENCEMODE:
253 silencemode = *(bool*)msg->data;
255 m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
257 m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
258 m_extSilenceTimer.Set(m_extSilenceTimeout);
259 if (!m_extSilenceTimer.IsTimePast())
261 m_state = S_TOP_CONFIGURED_SILENCE;
265 case CSinkControlProtocol::VOLUME:
266 m_volume = *(float*)msg->data;
267 m_sink->SetVolume(m_volume);
273 else if (port == &m_dataPort)
277 case CSinkDataProtocol::DRAIN:
279 msg->Reply(CSinkDataProtocol::ACC);
280 m_state = S_TOP_CONFIGURED_IDLE;
281 m_extTimeout = 10000;
283 case CSinkDataProtocol::SAMPLE:
284 CSampleBuffer *samples;
286 samples = *((CSampleBuffer**)msg->data);
287 delay = OutputSamples(samples);
288 msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
291 m_sink->Deinitialize();
294 m_state = S_TOP_CONFIGURED_SUSPEND;
299 m_state = S_TOP_CONFIGURED_PLAY;
300 m_extTimeout = delay / 2;
301 m_extSilenceTimer.Set(m_extSilenceTimeout);
310 case S_TOP_CONFIGURED_SUSPEND:
311 if (port == &m_controlPort)
315 case CSinkControlProtocol::SILENCEMODE:
317 case CSinkControlProtocol::VOLUME:
318 m_volume = *(float*)msg->data;
324 else if (port == &m_dataPort)
328 case CSinkDataProtocol::SAMPLE:
331 OutputSamples(&m_sampleOfSilence);
332 m_state = S_TOP_CONFIGURED_PLAY;
334 m_bStateMachineSelfTrigger = true;
336 case CSinkDataProtocol::DRAIN:
337 msg->Reply(CSinkDataProtocol::ACC);
343 else if (port == NULL) // timeout
347 case CSinkControlProtocol::TIMEOUT:
348 m_extTimeout = 10000;
356 case S_TOP_CONFIGURED_IDLE:
357 if (port == &m_dataPort)
361 case CSinkDataProtocol::SAMPLE:
362 OutputSamples(&m_sampleOfSilence);
363 m_state = S_TOP_CONFIGURED_PLAY;
365 m_bStateMachineSelfTrigger = true;
371 else if (port == NULL) // timeout
375 case CSinkControlProtocol::TIMEOUT:
376 m_sink->Deinitialize();
379 m_state = S_TOP_CONFIGURED_SUSPEND;
380 m_extTimeout = 10000;
388 case S_TOP_CONFIGURED_PLAY:
389 if (port == NULL) // timeout
393 case CSinkControlProtocol::TIMEOUT:
394 if (!m_extSilenceTimer.IsTimePast())
396 m_state = S_TOP_CONFIGURED_SILENCE;
402 m_state = S_TOP_CONFIGURED_IDLE;
403 m_extTimeout = 10000;
412 case S_TOP_CONFIGURED_SILENCE:
413 if (port == NULL) // timeout
417 case CSinkControlProtocol::TIMEOUT:
418 OutputSamples(&m_sampleOfSilence);
421 m_sink->Deinitialize();
424 m_state = S_TOP_CONFIGURED_SUSPEND;
427 m_state = S_TOP_CONFIGURED_PLAY;
436 default: // we are in no state, should not happen
437 CLog::Log(LOGERROR, "CActiveAESink::%s - no valid state: %d", __FUNCTION__, m_state);
443 void CActiveAESink::Process()
446 Protocol *port = NULL;
448 XbmcThreads::EndTime timer;
450 m_state = S_TOP_UNCONFIGURED;
452 m_bStateMachineSelfTrigger = false;
457 timer.Set(m_extTimeout);
459 if (m_bStateMachineSelfTrigger)
461 m_bStateMachineSelfTrigger = false;
462 // self trigger state machine
463 StateMachine(msg->signal, port, msg);
464 if (!m_bStateMachineSelfTrigger)
471 // check control port
472 else if (m_controlPort.ReceiveOutMessage(&msg))
475 port = &m_controlPort;
478 else if (m_dataPort.ReceiveOutMessage(&msg))
486 StateMachine(msg->signal, port, msg);
487 if (!m_bStateMachineSelfTrigger)
496 else if (m_outMsgEvent.WaitMSec(m_extTimeout))
498 m_extTimeout = timer.MillisLeft();
504 msg = m_controlPort.GetMessage();
505 msg->signal = CSinkControlProtocol::TIMEOUT;
507 // signal timeout to state machine
508 StateMachine(msg->signal, port, msg);
509 if (!m_bStateMachineSelfTrigger)
518 void CActiveAESink::EnumerateSinkList(bool force)
520 if (!m_sinkInfoList.empty() && !force)
523 unsigned int c_retry = 5;
524 m_sinkInfoList.clear();
525 CAESinkFactory::EnumerateEx(m_sinkInfoList);
526 while(m_sinkInfoList.size() == 0 && c_retry > 0)
528 CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
531 // retry the enumeration
532 CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
534 CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
538 void CActiveAESink::PrintSinks()
540 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
542 CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
544 for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
546 CLog::Log(LOGNOTICE, " Device %d", ++count);
547 CAEDeviceInfo& info = *itt2;
548 std::stringstream ss((std::string)info);
550 while(std::getline(ss, line, '\n'))
551 CLog::Log(LOGNOTICE, " %s", line.c_str());
556 void CActiveAESink::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
558 EnumerateSinkList(false);
560 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
562 AESinkInfo sinkInfo = *itt;
563 for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
565 CAEDeviceInfo devInfo = *itt2;
566 if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
569 std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
571 std::stringstream ss;
573 /* add the sink name if we have more then one sink type */
574 if (m_sinkInfoList.size() > 1)
575 ss << sinkInfo.m_sinkName << ": ";
577 ss << devInfo.m_displayName;
578 if (!devInfo.m_displayNameExtra.empty())
579 ss << ", " << devInfo.m_displayNameExtra;
581 devices.push_back(AEDevice(ss.str(), device));
586 std::string CActiveAESink::GetDefaultDevice(bool passthrough)
588 EnumerateSinkList(false);
590 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
592 AESinkInfo sinkInfo = *itt;
593 for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
595 CAEDeviceInfo devInfo = *itt2;
596 if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
599 std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
606 void CActiveAESink::GetDeviceFriendlyName(std::string &device)
608 m_deviceFriendlyName = "Device not found";
609 /* Match the device and find its friendly name */
610 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
612 AESinkInfo sinkInfo = *itt;
613 for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
615 CAEDeviceInfo& devInfo = *itt2;
616 if (devInfo.m_deviceName == device)
618 m_deviceFriendlyName = devInfo.m_displayName;
626 void CActiveAESink::OpenSink()
628 // we need a copy of m_device here because ParseDevice and CreateDevice write back
629 // into this variable
630 std::string device = m_device;
632 bool passthrough = AE_IS_RAW(m_requestedFormat.m_dataFormat);
634 CAESinkFactory::ParseDevice(device, driver);
635 if (driver.empty() && m_sink)
636 driver = m_sink->GetName();
638 CLog::Log(LOGINFO, "CActiveAESink::OpenSink - initialize sink");
643 m_sink->Deinitialize();
648 // get the display name of the device
649 GetDeviceFriendlyName(device);
651 // if we already have a driver, prepend it to the device string
653 device = driver + ":" + device;
655 // WARNING: this changes format and does not use passthrough
656 m_sinkFormat = m_requestedFormat;
657 CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
658 m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
662 CLog::Log(LOGERROR, "CActiveAESink::OpenSink - no sink was returned");
667 m_sink->SetVolume(m_volume);
669 #ifdef WORDS_BIGENDIAN
670 if (m_sinkFormat.m_dataFormat == AE_FMT_S16BE)
671 m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
672 else if (m_sinkFormat.m_dataFormat == AE_FMT_S32BE)
673 m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
675 if (m_sinkFormat.m_dataFormat == AE_FMT_S16LE)
676 m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
677 else if (m_sinkFormat.m_dataFormat == AE_FMT_S32LE)
678 m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
681 CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - %s Initialized:", m_sink->GetName());
682 CLog::Log(LOGDEBUG, " Output Device : %s", m_deviceFriendlyName.c_str());
683 CLog::Log(LOGDEBUG, " Sample Rate : %d", m_sinkFormat.m_sampleRate);
684 CLog::Log(LOGDEBUG, " Sample Format : %s", CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat));
685 CLog::Log(LOGDEBUG, " Channel Count : %d", m_sinkFormat.m_channelLayout.Count());
686 CLog::Log(LOGDEBUG, " Channel Layout: %s", ((std::string)m_sinkFormat.m_channelLayout).c_str());
687 CLog::Log(LOGDEBUG, " Frames : %d", m_sinkFormat.m_frames);
688 CLog::Log(LOGDEBUG, " Frame Samples : %d", m_sinkFormat.m_frameSamples);
689 CLog::Log(LOGDEBUG, " Frame Size : %d", m_sinkFormat.m_frameSize);
691 // init sample of silence
693 config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
694 config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
695 config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
696 config.channels = m_sinkFormat.m_channelLayout.Count();
697 config.sample_rate = m_sinkFormat.m_sampleRate;
699 // init sample of silence/noise
700 delete m_sampleOfSilence.pkt;
701 m_sampleOfSilence.pkt = new CSoundPacket(config, m_sinkFormat.m_frames);
702 m_sampleOfSilence.pkt->nb_samples = m_sampleOfSilence.pkt->max_nb_samples;
708 _aligned_free(m_convertBuffer);
709 m_convertBuffer = NULL;
712 m_convertState = CHECK_CONVERT;
715 void CActiveAESink::ReturnBuffers()
718 CSampleBuffer *samples;
719 while (m_dataPort.ReceiveOutMessage(&msg))
721 if (msg->signal == CSinkDataProtocol::SAMPLE)
723 samples = *((CSampleBuffer**)msg->data);
724 msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
729 unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
731 uint8_t *buffer = samples->pkt->data[0];
732 unsigned int frames = samples->pkt->nb_samples;
733 unsigned int maxFrames;
735 unsigned int written = 0;
736 double sinkDelay = 0.0;
738 switch(m_convertState)
743 EnsureConvertBuffer(samples);
744 buffer = Convert(samples);
747 Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
750 ConvertInit(samples);
751 if (m_convertState == NEED_CONVERT)
752 buffer = Convert(samples);
753 else if (m_convertState == NEED_BYTESWAP)
754 Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
762 maxFrames = std::min(frames, m_sinkFormat.m_frames);
763 written = m_sink->AddPackets(buffer, maxFrames, true, true);
766 Sleep(500*m_sinkFormat.m_frames/m_sinkFormat.m_sampleRate);
771 CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed");
772 m_stats->UpdateSinkDelay(0, frames);
778 else if (written > maxFrames)
781 CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error");
782 m_stats->UpdateSinkDelay(0, samples->pool ? maxFrames : 0);
786 buffer += written*m_sinkFormat.m_frameSize;
787 sinkDelay = m_sink->GetDelay();
788 m_stats->UpdateSinkDelay(sinkDelay, samples->pool ? written : 0);
790 return sinkDelay*1000;
793 void CActiveAESink::ConvertInit(CSampleBuffer* samples)
795 if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat)
797 m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat);
799 _aligned_free(m_convertBuffer);
800 m_convertBufferSampleSize = samples->pkt->max_nb_samples;
801 m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
802 memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
803 m_convertState = NEED_CONVERT;
805 else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
807 m_convertState = NEED_BYTESWAP;
810 m_convertState = SKIP_CONVERT;
813 void CActiveAESink::EnsureConvertBuffer(CSampleBuffer* samples)
815 if (!m_convertBuffer)
818 if (samples->pkt->max_nb_samples <= m_convertBufferSampleSize)
821 _aligned_free(m_convertBuffer);
822 m_convertBufferSampleSize = samples->pkt->max_nb_samples;
823 m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
824 memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
827 uint8_t* CActiveAESink::Convert(CSampleBuffer* samples)
829 m_convertFn((float*)samples->pkt->data[0], samples->pkt->nb_samples * samples->pkt->config.channels, m_convertBuffer);
830 return m_convertBuffer;
833 #define PI 3.1415926536f
835 void CActiveAESink::GenerateNoise()
837 int nb_floats = m_sinkFormat.m_frames*m_sinkFormat.m_channelLayout.Count();
838 float *noise = (float*)_aligned_malloc(nb_floats*sizeof(float), 16);
841 for(int i=0; i<nb_floats;i++)
845 R1 = (float) rand() / (float) RAND_MAX;
846 R2 = (float) rand() / (float) RAND_MAX;
850 noise[i] = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ) * 0.00001f;
853 AEDataFormat fmt = CActiveAEResample::GetAESampleFormat(m_sampleOfSilence.pkt->config.fmt, m_sampleOfSilence.pkt->config.bits_per_sample);
854 CAEConvert::AEConvertFrFn convertFn = CAEConvert::FrFloat(fmt);
855 convertFn(noise, nb_floats, m_sampleOfSilence.pkt->data[0]);
856 _aligned_free(noise);