1 #ifndef _MIXER_CORE_H 2 #define _MIXER_CORE_H 3 4 #include <Buffer.h> 5 #include <Locker.h> 6 #include <TimeSource.h> 7 #include "MixerSettings.h" 8 9 class AudioMixer; 10 class MixerInput; 11 class MixerOutput; 12 class Resampler; 13 14 // The number of "enum media_multi_channels" types from MediaDefs.h 15 // XXX should be 18, but limited to 12 here 16 #define MAX_CHANNEL_TYPES 12 17 // XXX using a dedicated mono channel, this should be channel type 31 18 // but for now we redefine type 12 19 #define B_CHANNEL_MONO B_CHANNEL_TOP_CENTER 20 21 class MixerCore 22 { 23 public: 24 MixerCore(AudioMixer *node); 25 ~MixerCore(); 26 27 MixerSettings *Settings(); 28 29 // To avoid calling Settings()->AttenuateOutput() for every outgoing 30 // buffer, this setting is cached in fOutputGain and must be set by 31 // the audio mixer node using SetOutputAttenuation() 32 void SetOutputAttenuation(float gain); 33 34 MixerInput * AddInput(const media_input &input); 35 MixerOutput * AddOutput(const media_output &output); 36 37 bool RemoveInput(int32 inputID); 38 bool RemoveOutput(); 39 40 int32 CreateInputID(); 41 42 MixerInput *Input(int index); // index = 0 to count-1, NOT inputID 43 MixerOutput *Output(); 44 45 void Lock(); 46 bool LockWithTimeout(bigtime_t timeout); 47 bool LockFromMixThread(); 48 void Unlock(); 49 50 void BufferReceived(BBuffer *buffer, bigtime_t lateness); 51 52 void InputFormatChanged(int32 inputID, const media_multi_audio_format &format); 53 void OutputFormatChanged(const media_multi_audio_format &format); 54 55 void SetOutputBufferGroup(BBufferGroup *group); 56 void SetTimingInfo(BTimeSource *ts, bigtime_t downstream_latency); 57 void EnableOutput(bool enabled); 58 bool Start(); 59 bool Stop(); 60 61 void StartMixThread(); 62 void StopMixThread(); 63 64 uint32 OutputChannelCount(); 65 66 private: 67 void ApplyOutputFormat(); 68 static int32 _mix_thread_(void *arg); 69 void MixThread(); 70 71 private: 72 BLocker *fLocker; 73 74 BList *fInputs; 75 MixerOutput *fOutput; 76 int32 fNextInputID; 77 bool fRunning; // true = the mix thread is running 78 bool fStarted; // true = mix thread should be started of it is not running 79 bool fOutputEnabled; // true = mix thread should be started of it is not running 80 81 Resampler **fResampler; // array 82 83 float *fMixBuffer; 84 int32 fMixBufferFrameRate; 85 int32 fMixBufferFrameCount; 86 int32 fMixBufferChannelCount; 87 int32 *fMixBufferChannelTypes; //array 88 bool fDoubleRateMixing; 89 bigtime_t fDownstreamLatency; 90 91 friend class MixerInput; // XXX debug only 92 93 MixerSettings *fSettings; 94 AudioMixer *fNode; 95 BBufferGroup *fBufferGroup; 96 BTimeSource *fTimeSource; 97 thread_id fMixThread; 98 sem_id fMixThreadWaitSem; 99 100 float fOutputGain; 101 }; 102 103 104 inline void MixerCore::Lock() 105 { 106 fLocker->Lock(); 107 } 108 109 inline bool MixerCore::LockWithTimeout(bigtime_t timeout) 110 { 111 return B_OK == fLocker->LockWithTimeout(timeout); 112 } 113 114 inline void MixerCore::Unlock() 115 { 116 fLocker->Unlock(); 117 } 118 119 inline bool MixerCore::LockFromMixThread() 120 { 121 for (;;) { 122 if (LockWithTimeout(10000)) 123 return true; 124 // XXX accessing fMixThreadWaitSem is still a race condition :( 125 if (B_WOULD_BLOCK != acquire_sem_etc(fMixThreadWaitSem, 1, B_RELATIVE_TIMEOUT, 0)) 126 return false; 127 } 128 } 129 130 #endif 131