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