3 * Copyright (C) 2010-2012 Team XBMC
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with XBMC; see the file COPYING. If not, write to
18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19 * http://www.gnu.org/copyleft/gpl.html
28 #include "threads/Thread.h"
29 #include "threads/CriticalSection.h"
30 #include "threads/SharedSection.h"
32 #include "Interfaces/ThreadedAE.h"
33 #include "Interfaces/AESink.h"
34 #include "Interfaces/AEEncoder.h"
35 #include "Utils/AEConvert.h"
36 #include "Utils/AERemap.h"
37 #include "Utils/AEBuffer.h"
38 #include "AEAudioFormat.h"
39 #include "AESinkFactory.h"
41 #include "SoftAEStream.h"
42 #include "SoftAESound.h"
44 #include "cores/IAudioCallback.h"
46 /* forward declarations */
52 class CSoftAE : public IThreadedAE
55 friend class CAEFactory;
60 virtual void Shutdown();
61 virtual bool Initialize();
62 virtual void OnSettingsChange(std::string setting);
66 virtual double GetDelay();
68 virtual float GetVolume();
69 virtual void SetVolume(const float volume);
70 virtual void SetMute(const bool enabled) { m_muted = enabled; }
71 virtual bool IsMuted() { return m_muted; }
72 virtual void SetSoundMode(const int mode);
74 /* returns a new stream for data in the specified format */
75 virtual IAEStream *MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options = 0);
76 virtual IAEStream *FreeStream(IAEStream *stream);
78 /* returns a new sound object */
79 virtual IAESound *MakeSound(const std::string& file);
80 virtual void FreeSound(IAESound *sound);
81 void PlaySound(IAESound *sound);
82 void StopSound(IAESound *sound);
84 /* free's sounds that have expired */
85 virtual void GarbageCollect();
87 /* these are for the streams so they can provide compatible data */
88 unsigned int GetSampleRate ();
89 unsigned int GetChannelCount () {return m_chLayout.Count() ;}
90 CAEChannelInfo& GetChannelLayout() {return m_chLayout ;}
91 enum AEStdChLayout GetStdChLayout () {return m_stdChLayout ;}
92 unsigned int GetFrames () {return m_sinkFormat.m_frames ;}
93 unsigned int GetFrameSize () {return m_frameSize ;}
95 /* these are for streams that are in RAW mode */
96 const AEAudioFormat* GetSinkAudioFormat() {return &m_sinkFormat ;}
97 enum AEDataFormat GetSinkDataFormat () {return m_sinkFormat.m_dataFormat ;}
98 CAEChannelInfo& GetSinkChLayout () {return m_sinkFormat.m_channelLayout;}
99 unsigned int GetSinkFrameSize () {return m_sinkFormat.m_frameSize ;}
101 /* for streams so they can calc cachetimes correct */
102 double GetCacheTime();
103 double GetCacheTotal();
105 virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
106 virtual std::string GetDefaultDevice(bool passthrough);
107 virtual bool SupportsRaw();
109 /* internal stream methods */
110 void PauseStream (CSoftAEStream *stream);
111 void ResumeStream(CSoftAEStream *stream);
116 CSoftAEStream *GetMasterStream();
119 void VerifySoundDevice(std::string &device, bool passthrough);
122 void InternalOpenSink();
124 bool SetupEncoder(AEAudioFormat &format);
127 IAESink *GetSink(AEAudioFormat &desiredFormat, bool passthrough, std::string &device);
128 void StopAllSounds();
130 enum AEStdChLayout m_stdChLayout;
131 std::string m_device;
132 std::string m_passthroughDevice;
137 bool m_running, m_reOpen;
138 CEvent m_reOpenEvent;
140 CCriticalSection m_runningLock; /* released when the thread exits */
141 CCriticalSection m_streamLock; /* m_streams lock */
142 CCriticalSection m_soundLock; /* m_sounds lock */
143 CCriticalSection m_soundSampleLock; /* m_playing_sounds lock */
144 CSharedSection m_sinkLock; /* lock for m_sink on re-open */
146 /* the current configuration */
149 CAEChannelInfo m_chLayout;
150 unsigned int m_frameSize;
152 /* the sink, its format information, and conversion function */
153 AESinkInfoList m_sinkInfoList;
155 AEAudioFormat m_sinkFormat;
156 float m_sinkFormatSampleRateMul;
157 float m_sinkFormatFrameSizeMul;
158 unsigned int m_sinkBlockSize;
159 AEAudioFormat m_encoderFormat;
160 float m_encoderFrameSizeMul;
161 unsigned int m_bytesPerSample;
162 CAEConvert::AEConvertFrFn m_convertFn;
164 /* currently playing sounds */
168 unsigned int sampleCount;
171 typedef std::vector<CSoftAEStream*> StreamList;
172 typedef std::list <CSoftAESound* > SoundList;
173 typedef std::list <SoundState > SoundStateList;
175 /* the streams, sounds, output buffer and output buffer fill size */
177 bool m_rawPassthrough;
178 StreamList m_newStreams, m_streams, m_playingStreams;
180 SoundStateList m_playing_sounds;
182 bool m_streamsPlaying;
184 /* this will contain either float, or uint8_t depending on if we are in raw mode or not */
188 IAEEncoder *m_encoder;
189 CAEBuffer m_encodedBuffer;
191 /* the output conversion buffer */
192 uint8_t *m_converted;
193 size_t m_convertedSize;
195 /* thread run stages */
196 void MixSounds (float *buffer, unsigned int samples);
197 void FinalizeSamples (float *buffer, unsigned int samples);
199 CSoftAEStream *m_masterStream;
201 void (CSoftAE::*m_outputStageFn)();
202 void RunOutputStage ();
203 void RunRawOutputStage();
204 void RunTranscodeStage();
206 unsigned int (CSoftAE::*m_streamStageFn)(unsigned int channelCount, void *out, bool &restart);
207 unsigned int RunRawStreamStage (unsigned int channelCount, void *out, bool &restart);
208 unsigned int RunStreamStage (unsigned int channelCount, void *out, bool &restart);
210 void ResumeSlaveStreams(const StreamList &streams);
211 void RunNormalizeStage (unsigned int channelCount, void *out, unsigned int mixed);
213 void RemoveStream(StreamList &streams, CSoftAEStream *stream);