xref: /haiku/src/add-ons/media/media-add-ons/mixer/MixerCore.h (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
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 
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 			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 
80 private:
81 			void				_UpdateResamplers(
82 									const media_multi_audio_format& format);
83 			void				_ApplyOutputFormat();
84 	static	int32				_MixThreadEntry(void* arg);
85 			void				_MixThread();
86 
87 private:
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 
124 inline void
125 MixerCore::Lock()
126 {
127 	fLocker->Lock();
128 }
129 
130 
131 inline bool
132 MixerCore::LockWithTimeout(bigtime_t timeout)
133 {
134 	return fLocker->LockWithTimeout(timeout) == B_OK;
135 }
136 
137 
138 inline void
139 MixerCore::Unlock()
140 {
141 	fLocker->Unlock();
142 }
143 
144 
145 inline bool
146 MixerCore::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