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, const char* name,
39								MultiAudioDevice* device, int32 internalID,
40								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(const media_request_info& info);
58	virtual	void			SetTimeSource(BTimeSource* timeSource);
59
60	// BBufferConsumer methods
61
62	virtual	status_t		AcceptFormat(const media_destination& dest,
63								media_format* format);
64	virtual	status_t		GetNextInput(int32* cookie, media_input* input);
65	virtual	void			DisposeInputCookie(int32 cookie);
66	virtual	void			BufferReceived(BBuffer* buffer);
67	virtual	void			ProducerDataStatus(const media_destination& forWhom,
68								int32 status, bigtime_t atPerformanceTime);
69	virtual	status_t		GetLatencyFor(const media_destination& forWhom,
70								bigtime_t* latency, media_node_id* timeSource);
71	virtual	status_t 		Connected(const media_source& producer,
72								const media_destination& where,
73								const media_format& withFormat,
74								media_input* input);
75	virtual	void			Disconnected(const media_source& producer,
76								const media_destination& where);
77	virtual	status_t		FormatChanged(const media_source& producer,
78								const media_destination& consumer,
79								int32 changeTag, const media_format& format);
80
81	virtual	status_t		SeekTagRequested(
82								const media_destination& destination,
83								bigtime_t targetTime, uint32 flags,
84								media_seek_tag* _seekTag, bigtime_t* _taggedTime,
85								uint32* _flags);
86
87	// BBufferProducer methods
88
89	virtual status_t		FormatSuggestionRequested(media_type type,
90								int32 quality, media_format* format);
91
92	virtual status_t		FormatProposal(const media_source& output,
93								media_format* format);
94
95	virtual status_t		FormatChangeRequested(const media_source& source,
96								const media_destination& destination,
97								media_format* io_format, int32* _deprecated);
98	virtual status_t		GetNextOutput(int32* cookie,
99								media_output* out_output);
100	virtual status_t		DisposeOutputCookie(int32 cookie);
101
102	virtual	status_t		SetBufferGroup(const media_source& for_source,
103								BBufferGroup* group);
104
105	virtual status_t		PrepareToConnect(const media_source& what,
106								const media_destination& where,
107								media_format* format, media_source* source,
108								char* name);
109
110	virtual void			Connect(status_t error, const media_source& source,
111								const media_destination& destination,
112								const media_format& format, char* name);
113	virtual void			Disconnect(const media_source& what,
114								const media_destination& where);
115
116	virtual void			LateNoticeReceived(const media_source& what,
117								bigtime_t howMuch, bigtime_t performanceTime);
118
119	virtual void			EnableOutput(const media_source& what, bool enabled,
120								int32* _deprecated);
121	virtual void			AdditionalBufferRequested(const media_source& source,
122								media_buffer_id previousBuffer,
123								bigtime_t previousTime,
124								const media_seek_tag* previousTag);
125
126	// BMediaEventLooper methods
127	virtual void			HandleEvent(const media_timed_event* event,
128								bigtime_t lateness, bool realTimeEvent = false);
129
130	// BTimeSource methods
131	virtual void			SetRunMode(run_mode mode);
132	virtual status_t		TimeSourceOp(const time_source_op_info& op,
133								void *_reserved);
134
135	// BControllable methods
136	virtual status_t		GetParameterValue(int32 id, bigtime_t* lastChange,
137								void* value, size_t* size);
138	virtual void			SetParameterValue(int32 id, bigtime_t when,
139								const void* value, size_t size);
140	virtual BParameterWeb*	MakeParameterWeb();
141
142private:
143	// private unimplemented
144							MultiAudioNode(const MultiAudioNode& clone);
145	MultiAudioNode& 		operator=(const MultiAudioNode& clone);
146
147			status_t		_HandleStart(const media_timed_event* event,
148								bigtime_t lateness, bool realTimeEvent = false);
149			status_t		_HandleSeek(const media_timed_event* event,
150								bigtime_t lateness, bool realTimeEvent = false);
151			status_t		_HandleWarp(const media_timed_event* event,
152								bigtime_t lateness, bool realTimeEvent = false);
153			status_t		_HandleStop(const media_timed_event* event,
154								bigtime_t lateness, bool realTimeEvent = false);
155			status_t		_HandleBuffer(const media_timed_event* event,
156								bigtime_t lateness, bool realTimeEvent = false);
157			status_t		_HandleDataStatus(const media_timed_event* event,
158								bigtime_t lateness, bool realTimeEvent = false);
159			status_t		_HandleParameter(const media_timed_event* event,
160								bigtime_t lateness, bool realTimeEvent = false);
161
162			char*			_PlaybackBuffer(int32 cycle, int32 channel)
163								{ return fDevice->BufferList().playback_buffers
164									[cycle][channel].base; }
165			uint32			_PlaybackStride(int32 cycle, int32 channel)
166								{ return fDevice->BufferList().playback_buffers
167									[cycle][channel].stride; }
168
169			char*			_RecordBuffer(int32 cycle, int32 channel)
170								{ return fDevice->BufferList().record_buffers
171									[cycle][channel].base; }
172			uint32			_RecordStride(int32 cycle, int32 channel)
173								{ return fDevice->BufferList().record_buffers
174									[cycle][channel].stride; }
175
176			void			_WriteZeros(node_input& input, uint32 bufferCycle);
177			void			_FillWithZeros(node_input& input);
178			void			_FillNextBuffer(node_input& channel,
179								BBuffer* buffer);
180
181	static	int32			_OutputThreadEntry(void* data);
182			int32			_OutputThread();
183			status_t		_StartOutputThreadIfNeeded();
184			status_t		_StopOutputThread();
185
186			void 			_AllocateBuffers(node_output& channel);
187			BBuffer* 		_FillNextBuffer(multi_buffer_info& info,
188								node_output& output);
189			void			_UpdateTimeSource(multi_buffer_info& info,
190								multi_buffer_info& oldInfo, node_input& input);
191
192			node_output* 	_FindOutput(media_source source);
193			node_input* 	_FindInput(media_destination destination);
194			node_input* 	_FindInput(int32 destinationId);
195
196			const char*		_GetControlName(multi_mix_control& control);
197			void 			_ProcessGroup(BParameterGroup* group, int32 index,
198								int32& numParameters);
199			void 			_ProcessMux(BDiscreteParameter* parameter,
200								int32 index);
201			void			_CreateFrequencyParameterGroup(
202								BParameterGroup* parentGroup, const char* name,
203								int32 parameterID, uint32 rateMask);
204
205			status_t		_SetNodeInputFrameRate(float frameRate);
206			status_t		_SetNodeOutputFrameRate(float frameRate);
207			void			_UpdateInternalLatency(const media_format& format);
208
209private:
210	status_t			fInitStatus;
211
212	BMediaAddOn*		fAddOn;
213	int32				fId;
214
215	BLocker				fBufferLock;
216
217	BList				fInputs;
218	TimeComputer		fTimeComputer;
219
220	bigtime_t 			fLatency;
221	BList				fOutputs;
222	media_format 		fOutputPreferredFormat;
223	media_format 		fInputPreferredFormat;
224
225	bigtime_t			fInternalLatency;
226		// this is computed from the real (negotiated) chunk size and bit rate,
227		// not the defaults that are in the parameters
228	bigtime_t			fBufferPeriod;
229
230	sem_id				fBufferFreeSem;
231	thread_id			fThread;
232	MultiAudioDevice*	fDevice;
233	bool 				fTimeSourceStarted;
234	BParameterWeb*		fWeb;
235	BMessage			fConfig;
236};
237
238#endif	// MULTI_AUDIO_NODE_H
239