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