MixerOutput.cpp revision 9c3be6a5
1678c2017Sbeveloper#include <MediaNode.h>
2678c2017Sbeveloper#include "MixerOutput.h"
3678c2017Sbeveloper#include "MixerCore.h"
4e6c7c99fSbeveloper#include "MixerUtils.h"
5e6c7c99fSbeveloper#include "debug.h"
6678c2017Sbeveloper
7e6c7c99fSbeveloperMixerOutput::MixerOutput(MixerCore *core, const media_output &output)
8e6c7c99fSbeveloper :	fCore(core),
9fae6ce82Sbeveloper	fOutput(output),
10fae6ce82Sbeveloper	fOutputChannelCount(0),
111081d7ceSbeveloper	fOutputChannelInfo(0),
12b326a30eSbeveloper	fOutputByteSwap(0),
13b326a30eSbeveloper	fMuted(false)
14678c2017Sbeveloper{
15e6c7c99fSbeveloper	fix_multiaudio_format(&fOutput.format.u.raw_audio);
16e6c7c99fSbeveloper	PRINT_OUTPUT("MixerOutput::MixerOutput", fOutput);
17e6c7c99fSbeveloper	PRINT_CHANNEL_MASK(fOutput.format);
18fae6ce82Sbeveloper
19fae6ce82Sbeveloper	UpdateOutputChannels();
201081d7ceSbeveloper	UpdateByteOrderSwap();
21678c2017Sbeveloper}
22678c2017Sbeveloper
23678c2017SbeveloperMixerOutput::~MixerOutput()
24678c2017Sbeveloper{
25fae6ce82Sbeveloper	delete fOutputChannelInfo;
261081d7ceSbeveloper	delete fOutputByteSwap;
27678c2017Sbeveloper}
28678c2017Sbeveloper
297ee2c804Sbevelopermedia_output &
307ee2c804SbeveloperMixerOutput::MediaOutput()
317ee2c804Sbeveloper{
327ee2c804Sbeveloper	return fOutput;
337ee2c804Sbeveloper}
34c47e5a5aSbeveloper
35c47e5a5aSbevelopervoid
36c47e5a5aSbeveloperMixerOutput::ChangeFormat(const media_multi_audio_format &format)
37c47e5a5aSbeveloper{
38c47e5a5aSbeveloper	fOutput.format.u.raw_audio = format;
39c47e5a5aSbeveloper	fix_multiaudio_format(&fOutput.format.u.raw_audio);
40c47e5a5aSbeveloper
41c47e5a5aSbeveloper	PRINT_OUTPUT("MixerOutput::ChangeFormat", fOutput);
42c47e5a5aSbeveloper	PRINT_CHANNEL_MASK(fOutput.format);
43fae6ce82Sbeveloper
44fae6ce82Sbeveloper	UpdateOutputChannels();
451081d7ceSbeveloper	UpdateByteOrderSwap();
461081d7ceSbeveloper}
471081d7ceSbeveloper
481081d7ceSbevelopervoid
491081d7ceSbeveloperMixerOutput::UpdateByteOrderSwap()
501081d7ceSbeveloper{
511081d7ceSbeveloper	delete fOutputByteSwap;
521081d7ceSbeveloper	fOutputByteSwap = 0;
531081d7ceSbeveloper
541081d7ceSbeveloper	// perhaps we need byte swapping
551081d7ceSbeveloper	if (fOutput.format.u.raw_audio.byte_order != B_MEDIA_HOST_ENDIAN) {
561081d7ceSbeveloper		if (	fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_FLOAT
571081d7ceSbeveloper			 ||	fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_INT
581081d7ceSbeveloper			 ||	fOutput.format.u.raw_audio.format == media_raw_audio_format::B_AUDIO_SHORT) {
591081d7ceSbeveloper			fOutputByteSwap = new ByteSwap(fOutput.format.u.raw_audio.format);
601081d7ceSbeveloper		}
611081d7ceSbeveloper	}
62fae6ce82Sbeveloper}
63fae6ce82Sbeveloper
64fae6ce82Sbevelopervoid
65fae6ce82SbeveloperMixerOutput::UpdateOutputChannels()
66fae6ce82Sbeveloper{
67fae6ce82Sbeveloper	output_chan_info *oldInfo = fOutputChannelInfo;
68fae6ce82Sbeveloper	uint32 oldCount = fOutputChannelCount;
69fae6ce82Sbeveloper
70fae6ce82Sbeveloper	fOutputChannelCount = fOutput.format.u.raw_audio.channel_count;
71fae6ce82Sbeveloper	fOutputChannelInfo = new output_chan_info[fOutputChannelCount];
72fae6ce82Sbeveloper	for (int i = 0; i < fOutputChannelCount; i++) {
73b6270d60Sbeveloper		fOutputChannelInfo[i].channel_type = GetChannelType(i, fOutput.format.u.raw_audio.channel_mask);
74b6270d60Sbeveloper		fOutputChannelInfo[i].channel_gain = 1.0;
75fae6ce82Sbeveloper		fOutputChannelInfo[i].source_count = 1;
76fae6ce82Sbeveloper		fOutputChannelInfo[i].source_gain[0] = 1.0;
77b6270d60Sbeveloper		fOutputChannelInfo[i].source_type[0] = fOutputChannelInfo[i].channel_type;
78e0dc5b6dSbeveloper		// all the cached values are 0.0 for a new channel
79e0dc5b6dSbeveloper		for (int j = 0; j < MAX_CHANNEL_TYPES; j++)
80e0dc5b6dSbeveloper			fOutputChannelInfo[i].source_gain_cache[j] = 0.0;
81fae6ce82Sbeveloper	}
82e0dc5b6dSbeveloper
83fae6ce82Sbeveloper	AssignDefaultSources();
84fae6ce82Sbeveloper
85fae6ce82Sbeveloper	// apply old gains and sources, overriding the 1.0 gain defaults for the old channels
86fae6ce82Sbeveloper	if (oldInfo != 0 && oldCount != 0) {
87fae6ce82Sbeveloper		for (int i = 0; i < fOutputChannelCount; i++) {
88fae6ce82Sbeveloper			for (int j = 0; j < oldCount; j++) {
89b6270d60Sbeveloper				if (fOutputChannelInfo[i].channel_type == oldInfo[j].channel_type) {
90b6270d60Sbeveloper					fOutputChannelInfo[i].channel_gain == oldInfo[j].channel_gain;
91fae6ce82Sbeveloper					fOutputChannelInfo[i].source_count == oldInfo[j].source_count;
92fae6ce82Sbeveloper					for (int k = 0; k < fOutputChannelInfo[i].source_count; k++) {
93fae6ce82Sbeveloper						fOutputChannelInfo[i].source_gain[k] == oldInfo[j].source_gain[k];
94fae6ce82Sbeveloper						fOutputChannelInfo[i].source_type[k] == oldInfo[j].source_type[k];
95fae6ce82Sbeveloper					}
96e0dc5b6dSbeveloper					// also copy the old gain cache
97e0dc5b6dSbeveloper					for (int k = 0; k < MAX_CHANNEL_TYPES; k++)
98e0dc5b6dSbeveloper						fOutputChannelInfo[i].source_gain_cache[k] = oldInfo[j].source_gain_cache[k];
99fae6ce82Sbeveloper					break;
100fae6ce82Sbeveloper				}
101fae6ce82Sbeveloper			}
102fae6ce82Sbeveloper		}
103fae6ce82Sbeveloper		// also delete the old info array
104fae6ce82Sbeveloper		delete [] oldInfo;
105fae6ce82Sbeveloper	}
106fae6ce82Sbeveloper	for (int i = 0; i < fOutputChannelCount; i++)
1079c3be6a5Sbeveloper		TRACE("UpdateOutputChannels: output channel %d, type %2d, gain %.3f\n", i, fOutputChannelInfo[i].channel_type, fOutputChannelInfo[i].channel_gain);
108fae6ce82Sbeveloper}
109fae6ce82Sbeveloper
110fae6ce82Sbevelopervoid
111fae6ce82SbeveloperMixerOutput::AssignDefaultSources()
112fae6ce82Sbeveloper{
113806cf560Sbeveloper	uint32 mask = fOutput.format.u.raw_audio.channel_mask;
114806cf560Sbeveloper	uint32 count = fOutputChannelCount;
115806cf560Sbeveloper
116806cf560Sbeveloper	// assign default sources for a few known setups,
117806cf560Sbeveloper	// everything else is left unchanged (it already is 1:1)
118806cf560Sbeveloper
119806cf560Sbeveloper	if (count == 1 && mask & (B_CHANNEL_LEFT | B_CHANNEL_RIGHT)) {
120806cf560Sbeveloper		// we have only one phycial output channel, and use it as a mix of
121806cf560Sbeveloper		// left, right, rear-left, rear-right, center and sub
122a2ca4723Sbeveloper		TRACE("AssignDefaultSources: 1 channel setup\n");
123806cf560Sbeveloper		fOutputChannelInfo[0].source_count = 6;
124806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[0] = 1.0;
125806cf560Sbeveloper		fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
126806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[1] = 1.0;
127806cf560Sbeveloper		fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
128806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[2] = 0.8;
129806cf560Sbeveloper		fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
130806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[3] = 0.8;
131806cf560Sbeveloper		fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
132806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[4] = 0.7;
133806cf560Sbeveloper		fOutputChannelInfo[0].source_type[4] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
134806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[5] = 0.6;
135806cf560Sbeveloper		fOutputChannelInfo[0].source_type[5] = ChannelMaskToChannelType(B_CHANNEL_SUB);
136806cf560Sbeveloper	} else if (count == 2 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT)) {
137806cf560Sbeveloper		// we have have two phycial output channels
138a2ca4723Sbeveloper		TRACE("AssignDefaultSources: 2 channel setup\n");
139806cf560Sbeveloper		// left channel:
140806cf560Sbeveloper		fOutputChannelInfo[0].source_count = 4;
141806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[0] = 1.0;
142806cf560Sbeveloper		fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
143806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[1] = 0.8;
144806cf560Sbeveloper		fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
145806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[2] = 0.7;
146806cf560Sbeveloper		fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
147806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[3] = 0.6;
148806cf560Sbeveloper		fOutputChannelInfo[0].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SUB);
149806cf560Sbeveloper		// right channel:
150806cf560Sbeveloper		fOutputChannelInfo[1].source_count = 4;
151806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[0] = 1.0;
152806cf560Sbeveloper		fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
153806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[1] = 0.8;
154806cf560Sbeveloper		fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
155806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[2] = 0.7;
156806cf560Sbeveloper		fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
157806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[3] = 0.6;
158806cf560Sbeveloper		fOutputChannelInfo[1].source_type[3] = ChannelMaskToChannelType(B_CHANNEL_SUB);
159806cf560Sbeveloper	} else if (count == 4 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT)) {
160a2ca4723Sbeveloper		TRACE("AssignDefaultSources: 4 channel setup\n");
161806cf560Sbeveloper		// left channel:
162806cf560Sbeveloper		fOutputChannelInfo[0].source_count = 3;
163806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[0] = 1.0;
164806cf560Sbeveloper		fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
165806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[1] = 0.7;
166806cf560Sbeveloper		fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
167806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[2] = 0.6;
168806cf560Sbeveloper		fOutputChannelInfo[0].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_SUB);
169806cf560Sbeveloper		// right channel:
170806cf560Sbeveloper		fOutputChannelInfo[1].source_count = 3;
171806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[0] = 1.0;
172806cf560Sbeveloper		fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
173806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[1] = 0.7;
174806cf560Sbeveloper		fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
175806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[2] = 0.6;
176806cf560Sbeveloper		fOutputChannelInfo[1].source_type[2] = ChannelMaskToChannelType(B_CHANNEL_SUB);
177806cf560Sbeveloper		// rear-left channel:
178806cf560Sbeveloper		fOutputChannelInfo[2].source_count = 2;
179806cf560Sbeveloper		fOutputChannelInfo[2].source_gain[0] = 1.0;
180806cf560Sbeveloper		fOutputChannelInfo[2].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
181806cf560Sbeveloper		fOutputChannelInfo[2].source_gain[1] = 0.6;
182806cf560Sbeveloper		fOutputChannelInfo[2].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
183806cf560Sbeveloper		// rear-right channel:
184806cf560Sbeveloper		fOutputChannelInfo[3].source_count = 2;
185806cf560Sbeveloper		fOutputChannelInfo[3].source_gain[0] = 1.0;
186806cf560Sbeveloper		fOutputChannelInfo[3].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
187806cf560Sbeveloper		fOutputChannelInfo[3].source_gain[1] = 0.6;
188806cf560Sbeveloper		fOutputChannelInfo[3].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
189806cf560Sbeveloper	} else if (count == 5 && mask == (B_CHANNEL_LEFT | B_CHANNEL_RIGHT | B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT | B_CHANNEL_CENTER)) {
190a2ca4723Sbeveloper		TRACE("AssignDefaultSources: 5 channel setup\n");
191806cf560Sbeveloper		// left channel:
192806cf560Sbeveloper		fOutputChannelInfo[0].source_count = 2;
193806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[0] = 1.0;
194806cf560Sbeveloper		fOutputChannelInfo[0].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_LEFT);
195806cf560Sbeveloper		fOutputChannelInfo[0].source_gain[1] = 0.6;
196806cf560Sbeveloper		fOutputChannelInfo[0].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
197806cf560Sbeveloper		// right channel:
198806cf560Sbeveloper		fOutputChannelInfo[1].source_count = 2;
199806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[0] = 1.0;
200806cf560Sbeveloper		fOutputChannelInfo[1].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_RIGHT);
201806cf560Sbeveloper		fOutputChannelInfo[1].source_gain[1] = 0.6;
202806cf560Sbeveloper		fOutputChannelInfo[1].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
203806cf560Sbeveloper		// rear-left channel:
204806cf560Sbeveloper		fOutputChannelInfo[2].source_count = 2;
205806cf560Sbeveloper		fOutputChannelInfo[2].source_gain[0] = 1.0;
206806cf560Sbeveloper		fOutputChannelInfo[2].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARLEFT);
207806cf560Sbeveloper		fOutputChannelInfo[2].source_gain[1] = 0.6;
208806cf560Sbeveloper		fOutputChannelInfo[2].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
209806cf560Sbeveloper		// rear-right channel:
210806cf560Sbeveloper		fOutputChannelInfo[3].source_count = 2;
211806cf560Sbeveloper		fOutputChannelInfo[3].source_gain[0] = 1.0;
212806cf560Sbeveloper		fOutputChannelInfo[3].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_REARRIGHT);
213806cf560Sbeveloper		fOutputChannelInfo[3].source_gain[1] = 0.6;
214806cf560Sbeveloper		fOutputChannelInfo[3].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
215806cf560Sbeveloper		// center channel:
216806cf560Sbeveloper		fOutputChannelInfo[4].source_count = 2;
217806cf560Sbeveloper		fOutputChannelInfo[4].source_gain[0] = 1.0;
218806cf560Sbeveloper		fOutputChannelInfo[4].source_type[0] = ChannelMaskToChannelType(B_CHANNEL_CENTER);
219806cf560Sbeveloper		fOutputChannelInfo[4].source_gain[1] = 0.5;
220806cf560Sbeveloper		fOutputChannelInfo[4].source_type[1] = ChannelMaskToChannelType(B_CHANNEL_SUB);
221806cf560Sbeveloper	} else {
222a2ca4723Sbeveloper		TRACE("AssignDefaultSources: no default setup\n");
223806cf560Sbeveloper	}
224806cf560Sbeveloper
225fae6ce82Sbeveloper	for (int i = 0; i < fOutputChannelCount; i++) {
226fae6ce82Sbeveloper		for (int j = 0; j < fOutputChannelInfo[i].source_count; j++) {
227b6270d60Sbeveloper			TRACE("AssignDefaultSources: output channel %d, source index %d: source_type %2d, source_gain %.3f\n", i, j, fOutputChannelInfo[i].source_type[j], fOutputChannelInfo[i].source_gain[j]);
228fae6ce82Sbeveloper		}
229fae6ce82Sbeveloper	}
230fae6ce82Sbeveloper}
231fae6ce82Sbeveloper
2329c3be6a5Sbeveloperint
2330c63c7d0SbeveloperMixerOutput::GetOutputChannelType(int channel)
234fae6ce82Sbeveloper{
235fae6ce82Sbeveloper	if (channel < 0 || channel >= fOutputChannelCount)
236fae6ce82Sbeveloper		return 0;
237b6270d60Sbeveloper	return fOutputChannelInfo[channel].channel_type;
238fae6ce82Sbeveloper}
239fae6ce82Sbeveloper
240fae6ce82Sbevelopervoid
241fae6ce82SbeveloperMixerOutput::SetOutputChannelGain(int channel, float gain)
242fae6ce82Sbeveloper{
2439391f0a5Sbeveloper	TRACE("SetOutputChannelGain chan %d, gain %.5f\n", channel, gain);
244fae6ce82Sbeveloper	if (channel < 0 || channel >= fOutputChannelCount)
245fae6ce82Sbeveloper		return;
246b6270d60Sbeveloper	fOutputChannelInfo[channel].channel_gain = gain;
247fae6ce82Sbeveloper}
248fae6ce82Sbeveloper
249fae6ce82Sbevelopervoid
250e0dc5b6dSbeveloperMixerOutput::AddOutputChannelSource(int channel, int source_type)
251fae6ce82Sbeveloper{
252fae6ce82Sbeveloper	if (channel < 0 || channel >= fOutputChannelCount)
253fae6ce82Sbeveloper		return;
254e0dc5b6dSbeveloper	if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES)
255e0dc5b6dSbeveloper		return;
256b6270d60Sbeveloper	if (fOutputChannelInfo[channel].source_count == MAX_SOURCE_ENTRIES)
257fae6ce82Sbeveloper		return;
258fae6ce82Sbeveloper	for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
259fae6ce82Sbeveloper		if (fOutputChannelInfo[channel].source_type[i] == source_type)
260fae6ce82Sbeveloper			return;
261fae6ce82Sbeveloper	}
262e0dc5b6dSbeveloper	// when adding a new source, use the current gain value from cache
263e0dc5b6dSbeveloper	float source_gain = fOutputChannelInfo[channel].source_gain_cache[source_type];
264fae6ce82Sbeveloper	fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count] = source_type;
265fae6ce82Sbeveloper	fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count] = source_gain;
266fae6ce82Sbeveloper	fOutputChannelInfo[channel].source_count++;
267fae6ce82Sbeveloper}
268fae6ce82Sbeveloper
269fae6ce82Sbevelopervoid
270b6270d60SbeveloperMixerOutput::RemoveOutputChannelSource(int channel, int source_type)
271fae6ce82Sbeveloper{
272fae6ce82Sbeveloper	if (channel < 0 || channel >= fOutputChannelCount)
273fae6ce82Sbeveloper		return;
274fae6ce82Sbeveloper	for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
275fae6ce82Sbeveloper		if (fOutputChannelInfo[channel].source_type[i] == source_type) {
276e0dc5b6dSbeveloper			// when removing a source, save the current gain value into the cache
277e0dc5b6dSbeveloper			fOutputChannelInfo[channel].source_gain_cache[source_type] = fOutputChannelInfo[channel].source_gain[i];
278e0dc5b6dSbeveloper			// remove the entry
279fae6ce82Sbeveloper			fOutputChannelInfo[channel].source_type[i] = fOutputChannelInfo[channel].source_type[fOutputChannelInfo[channel].source_count - 1];
280fae6ce82Sbeveloper			fOutputChannelInfo[channel].source_gain[i] = fOutputChannelInfo[channel].source_gain[fOutputChannelInfo[channel].source_count - 1];
281fae6ce82Sbeveloper			fOutputChannelInfo[channel].source_count--;
282fae6ce82Sbeveloper			return;
283fae6ce82Sbeveloper		}
284fae6ce82Sbeveloper	}
285fae6ce82Sbeveloper}
286fae6ce82Sbeveloper
287e0dc5b6dSbevelopervoid
288b6270d60SbeveloperMixerOutput::SetOutputChannelSourceGain(int channel, int source_type, float source_gain)
289fae6ce82Sbeveloper{
290fae6ce82Sbeveloper	if (channel < 0 || channel >= fOutputChannelCount)
291e0dc5b6dSbeveloper		return;
292e0dc5b6dSbeveloper	// set gain for active source
293fae6ce82Sbeveloper	for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
294fae6ce82Sbeveloper		if (fOutputChannelInfo[channel].source_type[i] == source_type) {
295fae6ce82Sbeveloper			fOutputChannelInfo[channel].source_gain[i] = source_gain;
296e0dc5b6dSbeveloper			return;
297fae6ce82Sbeveloper		}
298fae6ce82Sbeveloper	}
299e0dc5b6dSbeveloper	// we don't have an active source of that type, save gain in cache
300e0dc5b6dSbeveloper	if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES)
301e0dc5b6dSbeveloper		return;
302e0dc5b6dSbeveloper	fOutputChannelInfo[channel].source_gain_cache[source_type] = source_gain;
303fae6ce82Sbeveloper}
304fae6ce82Sbeveloper
305fae6ce82Sbeveloperfloat
306b6270d60SbeveloperMixerOutput::GetOutputChannelSourceGain(int channel, int source_type)
307fae6ce82Sbeveloper{
308fae6ce82Sbeveloper	if (channel < 0 || channel >= fOutputChannelCount)
309b6270d60Sbeveloper		return 0.0;
310e0dc5b6dSbeveloper	// get gain for active source
311fae6ce82Sbeveloper	for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
312fae6ce82Sbeveloper		if (fOutputChannelInfo[channel].source_type[i] == source_type) {
313fae6ce82Sbeveloper			return fOutputChannelInfo[channel].source_gain[i];
314fae6ce82Sbeveloper		}
315fae6ce82Sbeveloper	}
316e0dc5b6dSbeveloper	// we don't have an active source of that type, get gain from cache
317e0dc5b6dSbeveloper	if (source_type < 0 || source_type >= MAX_CHANNEL_TYPES)
318e0dc5b6dSbeveloper		return 0.0;
319e0dc5b6dSbeveloper	return fOutputChannelInfo[channel].source_gain_cache[source_type];
320fae6ce82Sbeveloper}
321fae6ce82Sbeveloper
322b6270d60Sbeveloperbool
323b6270d60SbeveloperMixerOutput::HasOutputChannelSource(int channel, int source_type)
324fae6ce82Sbeveloper{
325fae6ce82Sbeveloper	if (channel < 0 || channel >= fOutputChannelCount)
326b6270d60Sbeveloper		return false;
327b6270d60Sbeveloper	for (int i = 0; i < fOutputChannelInfo[channel].source_count; i++) {
328b6270d60Sbeveloper		if (fOutputChannelInfo[channel].source_type[i] == source_type) {
329b6270d60Sbeveloper			return true;
330b6270d60Sbeveloper		}
331fae6ce82Sbeveloper	}
332b6270d60Sbeveloper	return false;
333c47e5a5aSbeveloper}
334b326a30eSbeveloper
335b326a30eSbevelopervoid
336b326a30eSbeveloperMixerOutput::SetMuted(bool yesno)
337b326a30eSbeveloper{
338b326a30eSbeveloper	fMuted = yesno;
33957b75f14Sbeveloper}
340