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