1/*
2 * Copyright 2007 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _MIXER_OUTPUT_H
6#define _MIXER_OUTPUT_H
7
8#include <Buffer.h>
9#include "MixerDebug.h"
10#include "ByteSwap.h"
11#include "MixerCore.h"
12
13/* The data storage for channel sources is optimized
14 * for fast data retrieval by the MixerCore, which
15 * will call GetOutputChannelSourceInfoAt() and
16 * iterate through the first source_count array entries
17 * for source_gain[] and source_type[] arrays, they are
18 * index by 0 to GetOutputChannelSourceCount() - 1.
19 * To allow gain change for not active sources,
20 * we use the source_gain_cache[] array that is indexed
21 * by source_type.
22 */
23
24class MixerOutput
25{
26	public:
27										MixerOutput(MixerCore *core,
28													const media_output &output);
29										~MixerOutput();
30
31		media_output&					MediaOutput();
32		void							ChangeFormat(
33											const media_multi_audio_format &format);
34
35		// The physical output channels
36		int								GetOutputChannelCount();
37		int								GetOutputChannelType(int channel);
38		void							SetOutputChannelGain(int channel,
39															float gain);
40		float							GetOutputChannelGain(int channel);
41
42		// The sources for each channel
43		void							AddOutputChannelSource(int channel,
44															int source_type);
45		void							RemoveOutputChannelSource(int channel,
46															int source_type);
47		void							SetOutputChannelSourceGain(int channel,
48															int source_type,
49															float source_gain);
50		float							GetOutputChannelSourceGain(int channel,
51															int source_type);
52		bool							HasOutputChannelSource(int channel,
53															int source_type);
54
55		// The output can be muted
56		void							SetMuted(bool yesno);
57		bool							IsMuted();
58
59		// Only for use by MixerCore:
60		// For iteration of a channel's sources
61		int								GetOutputChannelSourceCount(int channel);
62		void							GetOutputChannelSourceInfoAt(int channel,
63															int source_index,
64															int *source_type,
65															float *source_gain);
66
67		// To swap byteorder in a buffer is that is needed
68		void							AdjustByteOrder(BBuffer *buffer);
69
70	private:
71		void							UpdateByteOrderSwap();
72		void							UpdateOutputChannels();
73		void							AssignDefaultSources();
74
75	private:
76
77		// An entry in the source array is not the same as the
78	 	// channel type, but the count should be the same
79		enum {
80			MAX_SOURCE_ENTRIES = MAX_CHANNEL_TYPES
81		};
82
83		struct output_chan_info {
84				int		channel_type;
85				float	channel_gain;
86				int		source_count;
87				float	source_gain[MAX_SOURCE_ENTRIES];
88				int		source_type[MAX_SOURCE_ENTRIES];
89				float	source_gain_cache[MAX_CHANNEL_TYPES];
90		};
91
92		MixerCore						*fCore;
93		media_output					fOutput;
94		int								fOutputChannelCount;
95		output_chan_info				*fOutputChannelInfo; //array
96		ByteSwap						*fOutputByteSwap;
97		bool							fMuted;
98};
99
100
101inline int
102MixerOutput::GetOutputChannelCount()
103{
104	return fOutputChannelCount;
105}
106
107
108inline float
109MixerOutput::GetOutputChannelGain(int channel)
110{
111	if (channel < 0 || channel >= fOutputChannelCount)
112		return 1.0;
113	return fOutputChannelInfo[channel].channel_gain;
114}
115
116
117inline int
118MixerOutput::GetOutputChannelSourceCount(int channel)
119{
120	ASSERT(channel >= 0 && channel < fOutputChannelCount);
121	return fOutputChannelInfo[channel].source_count;
122}
123
124
125inline void MixerOutput::GetOutputChannelSourceInfoAt(int channel,
126													int source_index,
127													int *source_type,
128													float *source_gain)
129{
130	ASSERT(channel >= 0 && channel < fOutputChannelCount);
131	ASSERT(source_index >= 0 && source_index < fOutputChannelInfo[channel].source_count);
132	*source_type = fOutputChannelInfo[channel].source_type[source_index];
133	*source_gain = fOutputChannelInfo[channel].source_gain[source_index];
134}
135
136
137inline void
138MixerOutput::AdjustByteOrder(BBuffer *buffer)
139{
140	if (fOutputByteSwap)
141		fOutputByteSwap->Swap(buffer->Data(), buffer->SizeUsed());
142}
143
144inline bool
145MixerOutput::IsMuted()
146{
147	return fMuted;
148}
149
150#endif
151