xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioNode.h (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 /*
2  * multiaudio replacement media addon for BeOS
3  *
4  * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr)
5  *
6  * All rights reserved.
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  *   this list of conditions and the following disclaimer in the documentation
14  *   and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 #ifndef _MULTIAUDIONODE_H
29 #define _MULTIAUDIONODE_H
30 
31 #include <MediaDefs.h>
32 #include <MediaNode.h>
33 #include <FileInterface.h>
34 #include <BufferConsumer.h>
35 #include <BufferProducer.h>
36 #include <Controllable.h>
37 #include <MediaEventLooper.h>
38 #include <TimeSource.h>
39 #include <Controllable.h>
40 #include <File.h>
41 #include <Entry.h>
42 #include "multi_audio.h"
43 #include "MultiAudioDevice.h"
44 
45 /*bool format_is_acceptible(
46 						const media_format & producer_format,
47 						const media_format & consumer_format);*/
48 
49 
50 class node_input
51 {
52 	public:
53 						node_input(media_input &input, media_format format);
54 						~node_input();
55 
56 	int32				fChannelId;
57 	media_input			fInput;
58 	media_format 		fPreferredFormat;
59 	media_format		fFormat;
60 	uint32 				fBufferCycle;
61 	multi_buffer_info	fOldMBI;
62 	BBuffer				*fBuffer;
63 };
64 
65 class node_output
66 {
67 	public:
68 						node_output(media_output &output, media_format format);
69 						~node_output();
70 
71 	int32				fChannelId;
72 	media_output		fOutput;
73 	media_format 		fPreferredFormat;
74 	media_format		fFormat;
75 
76 	BBufferGroup		*fBufferGroup;
77 	bool 				fOutputEnabled;
78 	uint64 				fSamplesSent;
79 	volatile uint32 	fBufferCycle;
80 	multi_buffer_info	fOldMBI;
81 };
82 
83 class MultiAudioNode :
84     public BBufferConsumer,
85     public BBufferProducer,
86     public BTimeSource,
87     public BMediaEventLooper,
88     public BControllable
89 {
90 protected:
91 virtual ~MultiAudioNode(void);
92 
93 public:
94 
95 explicit MultiAudioNode(BMediaAddOn *addon, char* name, MultiAudioDevice *device,
96 		int32 internal_id, BMessage * config);
97 
98 virtual status_t InitCheck(void) const;
99 
100 /*************************/
101 /* begin from BMediaNode */
102 public:
103 virtual	BMediaAddOn* AddOn(
104 				int32 * internal_id) const;	/* Who instantiated you -- or NULL for app class */
105 
106 protected:
107 		/* These don't return errors; instead, they use the global error condition reporter. */
108 		/* A node is required to have a queue of at least one pending command (plus TimeWarp) */
109 		/* and is recommended to allow for at least one pending command of each type. */
110 		/* Allowing an arbitrary number of outstanding commands might be nice, but apps */
111 		/* cannot depend on that happening. */
112 virtual	void Preroll(void);
113 
114 public:
115 virtual	status_t HandleMessage(
116 				int32 message,
117 				const void * data,
118 				size_t size);
119 
120 protected:
121 virtual		void NodeRegistered(void);	/* reserved 2 */
122 virtual		status_t RequestCompleted(const media_request_info &info);
123 virtual		void SetTimeSource(BTimeSource *timeSource);
124 
125 /* end from BMediaNode */
126 /***********************/
127 
128 /******************************/
129 /* begin from BBufferConsumer */
130 
131 //included from BMediaAddOn
132 //virtual	status_t HandleMessage(
133 //				int32 message,
134 //				const void * data,
135 //				size_t size);
136 
137 	/* Someone, probably the producer, is asking you about this format. Give */
138 	/* your honest opinion, possibly modifying *format. Do not ask upstream */
139 	/* producer about the format, since he's synchronously waiting for your */
140 	/* reply. */
141 virtual	status_t AcceptFormat(
142 				const media_destination & dest,
143 				media_format * format);
144 virtual	status_t GetNextInput(
145 				int32 * cookie,
146 				media_input * out_input);
147 virtual	void DisposeInputCookie(
148 				int32 cookie);
149 virtual	void BufferReceived(
150 				BBuffer * buffer);
151 virtual	void ProducerDataStatus(
152 				const media_destination & for_whom,
153 				int32 status,
154 				bigtime_t at_performance_time);
155 virtual	status_t GetLatencyFor(
156 				const media_destination & for_whom,
157 				bigtime_t * out_latency,
158 				media_node_id * out_timesource);
159 virtual	status_t Connected(
160 				const media_source & producer,	/* here's a good place to request buffer group usage */
161 				const media_destination & where,
162 				const media_format & with_format,
163 				media_input * out_input);
164 virtual	void Disconnected(
165 				const media_source & producer,
166 				const media_destination & where);
167 	/* The notification comes from the upstream producer, so he's already cool with */
168 	/* the format; you should not ask him about it in here. */
169 virtual	status_t FormatChanged(
170 				const media_source & producer,
171 				const media_destination & consumer,
172 				int32 change_tag,
173 				const media_format & format);
174 
175 	/* Given a performance time of some previous buffer, retrieve the remembered tag */
176 	/* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
177 	/* idea being that flags can be added later, and the understood flags returned in */
178 	/* *out_flags. */
179 virtual	status_t SeekTagRequested(
180 				const media_destination & destination,
181 				bigtime_t in_target_time,
182 				uint32 in_flags,
183 				media_seek_tag * out_seek_tag,
184 				bigtime_t * out_tagged_time,
185 				uint32 * out_flags);
186 
187 /* end from BBufferConsumer */
188 /****************************/
189 
190 /******************************/
191 /* begin from BBufferProducer */
192 
193 		virtual status_t 	FormatSuggestionRequested(	media_type type,
194 														int32 quality,
195 														media_format* format);
196 
197 		virtual status_t 	FormatProposal(				const media_source& output,
198 														media_format* format);
199 
200 		virtual status_t 	FormatChangeRequested(		const media_source& source,
201 														const media_destination& destination,
202 														media_format* io_format,
203 														int32* _deprecated_);
204 		virtual status_t 	GetNextOutput(				int32* cookie,
205 														media_output* out_output);
206 		virtual status_t 	DisposeOutputCookie(		int32 cookie);
207 
208 		virtual	status_t 	SetBufferGroup(				const media_source& for_source,
209 														BBufferGroup* group);
210 
211 		virtual status_t 	PrepareToConnect(			const media_source& what,
212 														const media_destination& where,
213 														media_format* format,
214 														media_source* out_source,
215 														char* out_name);
216 
217 		virtual void 		Connect(					status_t error,
218 														const media_source& source,
219 														const media_destination& destination,
220 														const media_format& format,
221 														char* io_name);
222 
223 		virtual void 		Disconnect(					const media_source& what,
224 														const media_destination& where);
225 
226 		virtual void 		LateNoticeReceived(			const media_source& what,
227 														bigtime_t how_much,
228 														bigtime_t performance_time);
229 
230 		virtual void 		EnableOutput(				const media_source & what,
231 														bool enabled,
232 														int32* _deprecated_);
233 		virtual void 		AdditionalBufferRequested(	const media_source& source,
234 														media_buffer_id prev_buffer,
235 														bigtime_t prev_time,
236 														const media_seek_tag* prev_tag);
237 
238 /* end from BBufferProducer */
239 /****************************/
240 
241 /*****************/
242 /* BControllable */
243 /*****************/
244 
245 /********************************/
246 /* start from BMediaEventLooper */
247 
248 	protected:
249 		/* you must override to handle your events! */
250 		/* you should not call HandleEvent directly */
251 		virtual void		HandleEvent(	const media_timed_event *event,
252 											bigtime_t lateness,
253 											bool realTimeEvent = false);
254 
255 /* end from BMediaEventLooper */
256 /******************************/
257 
258 /********************************/
259 /* start from BTimeSource */
260 	protected:
261 		virtual void		SetRunMode(		run_mode mode);
262 		virtual status_t 	TimeSourceOp(	const time_source_op_info &op,
263 											void *_reserved);
264 
265 /* end from BTimeSource */
266 /******************************/
267 
268 /********************************/
269 /* start from BControllable */
270 	protected:
271 		virtual status_t 	GetParameterValue(	int32 id,
272 												bigtime_t* last_change,
273 												void* value,
274 												size_t* ioSize);
275 		virtual void 		SetParameterValue(	int32 id,
276 												bigtime_t when,
277 												const void* value,
278 												size_t size);
279 		virtual BParameterWeb* MakeParameterWeb();
280 
281 /* end from BControllable */
282 /******************************/
283 
284 protected:
285 
286 virtual status_t HandleStart(
287 						const media_timed_event *event,
288 						bigtime_t lateness,
289 						bool realTimeEvent = false);
290 virtual status_t HandleSeek(
291 						const media_timed_event *event,
292 						bigtime_t lateness,
293 						bool realTimeEvent = false);
294 virtual status_t HandleWarp(
295 						const media_timed_event *event,
296 						bigtime_t lateness,
297 						bool realTimeEvent = false);
298 virtual status_t HandleStop(
299 						const media_timed_event *event,
300 						bigtime_t lateness,
301 						bool realTimeEvent = false);
302 virtual status_t HandleBuffer(
303 						const media_timed_event *event,
304 						bigtime_t lateness,
305 						bool realTimeEvent = false);
306 virtual status_t HandleDataStatus(
307 						const media_timed_event *event,
308 						bigtime_t lateness,
309 						bool realTimeEvent = false);
310 virtual status_t HandleParameter(
311 						const media_timed_event *event,
312 						bigtime_t lateness,
313 						bool realTimeEvent = false);
314 
315 public:
316 
317 static void GetFlavor(flavor_info * outInfo, int32 id);
318 static void GetFormat(media_format * outFormat);
319 
320 status_t GetConfigurationFor(BMessage * into_message);
321 
322 
323 private:
324 
325 		MultiAudioNode(	/* private unimplemented */
326 				const MultiAudioNode & clone);
327 		MultiAudioNode & operator=(
328 				const MultiAudioNode & clone);
329 
330 		//void	WriteBuffer( BBuffer *buffer, node_input &input );
331 		void	WriteZeros(node_input &input, uint32 bufferCycle);
332 		void	FillWithZeros(node_input &input);
333 		void	FillNextBuffer(node_input &channel, BBuffer* buffer);
334 
335 		static int32		_run_thread_( void *data );
336 		int32				RunThread();
337 		status_t			StartThread();
338 		status_t			StopThread();
339 
340 
341 		void 				AllocateBuffers(node_output &channel);
342 		BBuffer* 			FillNextBuffer(	multi_buffer_info &MBI,
343 										node_output &channel);
344 		void				UpdateTimeSource(multi_buffer_info &MBI,
345 										multi_buffer_info &oldMBI,
346 										node_input &input);
347 
348 		node_output* 		FindOutput(media_source source);
349 		node_input* 		FindInput(media_destination dest);
350 		node_input* 		FindInput(int32 destinationId);
351 
352 		void 				ProcessGroup(BParameterGroup *group, int32 index, int32 &nbParameters);
353 		void 				ProcessMux(BDiscreteParameter *parameter, int32 index);
354 
355 		status_t fInitCheckStatus;
356 
357 		BMediaAddOn 		*fAddOn;
358 		int32				fId;
359 
360 		BList				fInputs;
361 
362 		bigtime_t 			fLatency;
363 		BList				fOutputs;
364 		media_format 		fPreferredFormat;
365 
366 		bigtime_t fInternalLatency;
367 		// this is computed from the real (negotiated) chunk size and bit rate,
368 		// not the defaults that are in the parameters
369 		bigtime_t fBufferPeriod;
370 
371 
372 		//volatile uint32 	fBufferCycle;
373 		sem_id				fBuffer_free;
374 
375 
376 		thread_id			fThread;
377 
378 		MultiAudioDevice 	*fDevice;
379 
380 		//multi_description	MD;
381 		//multi_format_info 	MFI;
382 		//multi_buffer_list 	MBL;
383 
384 		//multi_mix_control_info MMCI;
385 		//multi_mix_control	MMC[MAX_CONTROLS];
386 
387 		bool 				fTimeSourceStarted;
388 
389 		BParameterWeb		*fWeb;
390 
391 		BMessage			fConfig;
392 };
393 
394 #endif /* _MULTIAUDIONODE_H */
395