xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerCore.h (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
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