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