xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerCore.h (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
1 /*
2  * Copyright 2003-2009 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 
19 class AudioMixer;
20 class BBufferGroup;
21 class MixerInput;
22 class MixerOutput;
23 class 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 
33 class MixerCore {
34 public:
35 								MixerCore(AudioMixer *node);
36 	virtual						~MixerCore();
37 
38 			MixerSettings*		Settings();
39 
40 	// To avoid calling Settings()->AttenuateOutput() for every outgoing
41 	// buffer, this setting is cached in fOutputGain and must be set by
42 	// the audio mixer node using SetOutputAttenuation()
43 			void				SetOutputAttenuation(float gain);
44 			MixerInput*			AddInput(const media_input& input);
45 			MixerOutput*		AddOutput(const media_output& output);
46 
47 			bool				RemoveInput(int32 inputID);
48 			bool				RemoveOutput();
49 			int32				CreateInputID();
50 
51 	// index = 0 to count-1, NOT inputID
52 			MixerInput*			Input(int index);
53 			MixerOutput*		Output();
54 
55 			void				Lock();
56 			bool				LockWithTimeout(bigtime_t timeout);
57 			bool				LockFromMixThread();
58 			void				Unlock();
59 
60 			void				BufferReceived(BBuffer* buffer,
61 									bigtime_t lateness);
62 
63 			void				InputFormatChanged(int32 inputID,
64 									const media_multi_audio_format& format);
65 			void				OutputFormatChanged(
66 									const media_multi_audio_format& format);
67 
68 			void				SetOutputBufferGroup(BBufferGroup* group);
69 			void				SetTimingInfo(BTimeSource* timeSource,
70 									bigtime_t downstream_latency);
71 			void				EnableOutput(bool enabled);
72 			bool				Start();
73 			bool				Stop();
74 
75 			void				StartMixThread();
76 			void				StopMixThread();
77 			uint32				OutputChannelCount();
78 
79 private:
80 			void				ApplyOutputFormat();
81 	static	int32				_mix_thread_(void* arg);
82 			void				MixThread();
83 
84 private:
85 			BLocker*			fLocker;
86 			BList*				fInputs;
87 			MixerOutput*		fOutput;
88 			int32				fNextInputID;
89 			bool				fRunning;
90 									// true = the mix thread is running
91 
92 			bool				fStarted;
93 									// true = mix thread should be
94 									// started of it is not running
95 
96 			bool				fOutputEnabled;
97 									// true = mix thread should be
98 									// started of it is not running
99 
100 			Resampler**			fResampler; // array
101 			float*				fMixBuffer;
102 			int32				fMixBufferFrameRate;
103 			int32				fMixBufferFrameCount;
104 			int32				fMixBufferChannelCount;
105 			int32*				fMixBufferChannelTypes; //array
106 			bool				fDoubleRateMixing;
107 			bigtime_t			fDownstreamLatency;
108 			MixerSettings*		fSettings;
109 			AudioMixer*			fNode;
110 			BBufferGroup*		fBufferGroup;
111 			BTimeSource*		fTimeSource;
112 			thread_id			fMixThread;
113 			sem_id				fMixThreadWaitSem;
114 			float				fOutputGain;
115 
116 	friend class MixerInput;
117 		// NOTE: debug only
118 };
119 
120 
121 inline void
122 MixerCore::Lock()
123 {
124 	fLocker->Lock();
125 }
126 
127 
128 inline bool
129 MixerCore::LockWithTimeout(bigtime_t timeout)
130 {
131 	return fLocker->LockWithTimeout(timeout) == B_OK;
132 }
133 
134 
135 inline void
136 MixerCore::Unlock()
137 {
138 	fLocker->Unlock();
139 }
140 
141 
142 inline bool
143 MixerCore::LockFromMixThread()
144 {
145 	for (;;) {
146 		if (LockWithTimeout(10000))
147 			return true;
148 		// XXX accessing fMixThreadWaitSem is still a race condition :(
149 		if (acquire_sem_etc(fMixThreadWaitSem, 1, B_RELATIVE_TIMEOUT, 0)
150 				!= B_WOULD_BLOCK) {
151 			return false;
152 		}
153 	}
154 }
155 
156 
157 #endif // _MIXER_CORE_H
158