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