1/*
2 * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr)
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef MULTI_AUDIO_NODE_H
6#define MULTI_AUDIO_NODE_H
7
8
9#include <BufferConsumer.h>
10#include <BufferProducer.h>
11#include <Controllable.h>
12#include <Locker.h>
13#include <MediaAddOn.h>
14#include <MediaDefs.h>
15#include <MediaEventLooper.h>
16#include <MediaNode.h>
17#include <Message.h>
18#include <TimeSource.h>
19
20#include "hmulti_audio.h"
21#include "MultiAudioDevice.h"
22#include "TimeComputer.h"
23
24
25class BDiscreteParameter;
26class BParameterGroup;
27
28class node_input;
29class node_output;
30
31
32class MultiAudioNode : public BBufferConsumer, public BBufferProducer,
33		public BTimeSource,	public BMediaEventLooper, public BControllable {
34protected:
35	virtual						~MultiAudioNode();
36
37public:
38								MultiAudioNode(BMediaAddOn* addon,
39									const char* name, MultiAudioDevice* device,
40									int32 internalID, BMessage* config);
41
42	virtual status_t			InitCheck() const;
43
44	static	void				GetFlavor(flavor_info* info, int32 id);
45	static	void				GetFormat(media_format* outFormat);
46
47			status_t			GetConfigurationFor(BMessage* message);
48
49	// BMediaNode methods
50	virtual	BMediaAddOn*		AddOn(int32* internalID) const;
51	virtual	status_t			HandleMessage(int32 message, const void* data,
52									size_t size);
53
54protected:
55	virtual	void				Preroll();
56	virtual	void				NodeRegistered();
57	virtual	status_t			RequestCompleted(
58									const media_request_info& info);
59	virtual	void				SetTimeSource(BTimeSource* timeSource);
60
61	// BBufferConsumer methods
62
63	virtual	status_t			AcceptFormat(const media_destination& dest,
64									media_format* format);
65	virtual	status_t			GetNextInput(int32* cookie, media_input* input);
66	virtual	void				DisposeInputCookie(int32 cookie);
67	virtual	void				BufferReceived(BBuffer* buffer);
68	virtual	void				ProducerDataStatus(
69									const media_destination& forWhom,
70									int32 status, bigtime_t atPerformanceTime);
71	virtual	status_t			GetLatencyFor(const media_destination& forWhom,
72									bigtime_t* latency,
73									media_node_id* timeSource);
74	virtual	status_t	 		Connected(const media_source& producer,
75									const media_destination& where,
76									const media_format& withFormat,
77									media_input* input);
78	virtual	void				Disconnected(const media_source& producer,
79									const media_destination& where);
80	virtual	status_t			FormatChanged(const media_source& producer,
81									const media_destination& consumer,
82									int32 changeTag,
83									const media_format& format);
84
85	virtual	status_t			SeekTagRequested(
86									const media_destination& destination,
87									bigtime_t targetTime, uint32 flags,
88									media_seek_tag* _seekTag,
89									bigtime_t* _taggedTime, uint32* _flags);
90
91	// BBufferProducer methods
92
93	virtual status_t			FormatSuggestionRequested(media_type type,
94									int32 quality, media_format* format);
95
96	virtual status_t			FormatProposal(const media_source& output,
97									media_format* format);
98
99	virtual status_t			FormatChangeRequested(
100									const media_source& source,
101									const media_destination& destination,
102									media_format* ioFormat,
103									int32* _deprecated);
104	virtual status_t			GetNextOutput(int32* cookie,
105									media_output* _output);
106	virtual status_t			DisposeOutputCookie(int32 cookie);
107
108	virtual	status_t			SetBufferGroup(const media_source& forSource,
109									BBufferGroup* group);
110
111	virtual status_t			PrepareToConnect(const media_source& what,
112									const media_destination& where,
113									media_format* format, media_source* source,
114									char* name);
115
116	virtual void				Connect(status_t error,
117									const media_source& source,
118									const media_destination& destination,
119									const media_format& format, char* name);
120	virtual void				Disconnect(const media_source& what,
121									const media_destination& where);
122
123	virtual void				LateNoticeReceived(const media_source& what,
124									bigtime_t howMuch,
125									bigtime_t performanceTime);
126
127	virtual void				EnableOutput(const media_source& what,
128									bool enabled, int32* _deprecated);
129	virtual void				AdditionalBufferRequested(
130									const media_source& source,
131									media_buffer_id previousBuffer,
132									bigtime_t previousTime,
133									const media_seek_tag* previousTag);
134
135	// BMediaEventLooper methods
136	virtual void				HandleEvent(const media_timed_event* event,
137									bigtime_t lateness,
138									bool realTimeEvent = false);
139
140	// BTimeSource methods
141	virtual void				SetRunMode(run_mode mode);
142	virtual status_t			TimeSourceOp(const time_source_op_info& op,
143									void *_reserved);
144
145	// BControllable methods
146	virtual status_t			GetParameterValue(int32 id,
147									bigtime_t* lastChange, void* value,
148									size_t* size);
149	virtual void				SetParameterValue(int32 id, bigtime_t when,
150									const void* value, size_t size);
151	virtual BParameterWeb*		MakeParameterWeb();
152
153private:
154	// private unimplemented
155								MultiAudioNode(const MultiAudioNode& clone);
156	MultiAudioNode& 			operator=(const MultiAudioNode& clone);
157
158			status_t			_HandleStart(const media_timed_event* event,
159									bigtime_t lateness,
160									bool realTimeEvent = false);
161			status_t			_HandleSeek(const media_timed_event* event,
162									bigtime_t lateness,
163									bool realTimeEvent = false);
164			status_t			_HandleWarp(const media_timed_event* event,
165									bigtime_t lateness,
166									bool realTimeEvent = false);
167			status_t			_HandleStop(const media_timed_event* event,
168									bigtime_t lateness,
169									bool realTimeEvent = false);
170			status_t			_HandleBuffer(const media_timed_event* event,
171									bigtime_t lateness,
172									bool realTimeEvent = false);
173			status_t			_HandleDataStatus(
174									const media_timed_event* event,
175									bigtime_t lateness,
176									bool realTimeEvent = false);
177			status_t			_HandleParameter(const media_timed_event* event,
178									bigtime_t lateness,
179									bool realTimeEvent = false);
180
181			char*				_PlaybackBuffer(int32 cycle, int32 channel)
182									{ return fDevice->BufferList()
183										.playback_buffers
184											[cycle][channel].base; }
185			uint32				_PlaybackStride(int32 cycle, int32 channel)
186									{ return fDevice->BufferList()
187										.playback_buffers
188											[cycle][channel].stride; }
189
190			char*				_RecordBuffer(int32 cycle, int32 channel)
191									{ return fDevice->BufferList()
192										.record_buffers
193											[cycle][channel].base; }
194			uint32				_RecordStride(int32 cycle, int32 channel)
195									{ return fDevice->BufferList()
196										.record_buffers
197											[cycle][channel].stride; }
198
199			void				_WriteZeros(node_input& input,
200									uint32 bufferCycle);
201			void				_FillWithZeros(node_input& input);
202			void				_FillNextBuffer(node_input& channel,
203									BBuffer* buffer);
204
205	static	int32				_OutputThreadEntry(void* data);
206			int32				_OutputThread();
207			status_t			_StartOutputThreadIfNeeded();
208			status_t			_StopOutputThread();
209
210			void	 			_AllocateBuffers(node_output& channel);
211			BBuffer*	 		_FillNextBuffer(multi_buffer_info& info,
212									node_output& output);
213			void				_UpdateTimeSource(multi_buffer_info& info,
214									node_input& input);
215
216			node_output*	 	_FindOutput(media_source source);
217			node_input* 		_FindInput(media_destination destination);
218			node_input* 		_FindInput(int32 destinationId);
219
220			const char*			_GetControlName(multi_mix_control& control);
221			void 				_ProcessGroup(BParameterGroup* group,
222									int32 index, int32& numParameters);
223			void 				_ProcessMux(BDiscreteParameter* parameter,
224									int32 index);
225			void				_CreateFrequencyParameterGroup(
226									BParameterGroup* parentGroup,
227									const char* name, int32 parameterID,
228									uint32 rateMask);
229
230			status_t			_SetNodeInputFrameRate(float frameRate);
231			status_t			_SetNodeOutputFrameRate(float frameRate);
232			void				_UpdateInternalLatency(
233									const media_format& format);
234
235private:
236			status_t			fInitStatus;
237
238			BMediaAddOn*		fAddOn;
239			int32				fId;
240
241			BLocker				fBufferLock;
242
243			BList				fInputs;
244			TimeComputer		fTimeComputer;
245
246			bigtime_t 			fLatency;
247			BList				fOutputs;
248			media_format 		fOutputPreferredFormat;
249			media_format 		fInputPreferredFormat;
250
251			bigtime_t			fInternalLatency;
252				// this is computed from the real (negotiated) chunk size and bit rate,
253				// not the defaults that are in the parameters
254			bigtime_t			fBufferPeriod;
255
256			int32				fQuitThread;
257			thread_id			fThread;
258			MultiAudioDevice*	fDevice;
259			bool 				fTimeSourceStarted;
260			BParameterWeb*		fWeb;
261			BMessage			fConfig;
262};
263
264
265#endif	// MULTI_AUDIO_NODE_H
266