1/*
2 * OpenSound media addon for BeOS and Haiku
3 *
4 * Copyright (c) 2007, Fran��ois Revol (revol@free.fr)
5 * Copyright (c) 2002, 2003 Jerome Duval (jerome.duval@free.fr)
6 * Distributed under the terms of the MIT License.
7 *
8 */
9#ifndef _OPENSOUNDNODE_H
10#define _OPENSOUNDNODE_H
11
12#include <BufferConsumer.h>
13#include <BufferProducer.h>
14#include <Controllable.h>
15#include <MediaEventLooper.h>
16#include <MediaNode.h>
17#include <Message.h>
18#include <ParameterWeb.h>
19#include <TimeSource.h>
20
21class OpenSoundDevice;
22class OpenSoundDeviceEngine;
23class OpenSoundDeviceMixer;
24
25struct audio_buf_info;
26struct flavor_info;
27
28class OpenSoundNode : public BBufferConsumer, public BBufferProducer,
29	public BTimeSource, public BMediaEventLooper, public BControllable {
30
31private:
32	class NodeInput;
33	class NodeOutput;
34
35protected:
36	virtual						~OpenSoundNode();
37
38public:
39	explicit					OpenSoundNode(BMediaAddOn* addon,
40									const char* name,
41									OpenSoundDevice* device,
42									int32 internalID, BMessage* config);
43
44	virtual	status_t			InitCheck() const;
45
46	// BMediaNode interface
47public:
48	virtual	BMediaAddOn*		AddOn(int32* internalID) const;
49		// Who instantiated you -- or NULL for app class
50
51protected:
52	virtual	void				Preroll();
53		// These don't return errors; instead, they use the global error
54		// condition reporter. A node is required to have a queue of at
55		// least one pending command (plus TimeWarp) and is recommended to
56		// allow for at least one pending command of each type. Allowing an
57		// arbitrary number of outstanding commands might be nice, but apps
58		// cannot depend on that happening.
59
60public:
61	virtual	status_t			HandleMessage(int32 message,
62									const void* data, size_t size);
63
64protected:
65	virtual	void				NodeRegistered();
66	virtual	status_t			RequestCompleted(
67									const media_request_info& info);
68	virtual	void				SetTimeSource(BTimeSource* timeSource);
69
70	// BBufferConsumer interface
71protected:
72	virtual	status_t			AcceptFormat(
73									const media_destination& dest,
74									media_format* format);
75	virtual	status_t			GetNextInput(int32* cookie,
76									media_input* out_input);
77	virtual	void				DisposeInputCookie(int32 cookie);
78	virtual	void				BufferReceived(BBuffer* buffer);
79	virtual	void				ProducerDataStatus(
80									const media_destination& for_whom,
81									int32 status,
82									bigtime_t at_performance_time);
83	virtual	status_t			GetLatencyFor(
84									const media_destination& for_whom,
85									bigtime_t* out_latency,
86									media_node_id* out_timesource);
87	virtual	status_t			Connected(const media_source& producer,
88									const media_destination& where,
89									const media_format& with_format,
90									media_input* out_input);
91			// here's a good place to request buffer group usage
92
93	virtual	void				Disconnected(const media_source& producer,
94									const media_destination& where);
95
96	virtual	status_t			FormatChanged(const media_source& producer,
97									const media_destination& consumer,
98								int32 change_tag,
99								const media_format& format);
100
101	virtual	status_t			SeekTagRequested(
102									const media_destination& destination,
103									bigtime_t in_target_time,
104									uint32 in_flags,
105									media_seek_tag* out_seek_tag,
106									bigtime_t* out_tagged_time,
107									uint32* out_flags);
108
109	// BBufferProducer interface
110protected:
111	virtual	status_t			FormatSuggestionRequested(media_type type,
112									int32 quality, media_format* format);
113
114	virtual	status_t			FormatProposal(const media_source& output,
115									media_format* format);
116
117	virtual	status_t			FormatChangeRequested(
118									const media_source& source,
119									const media_destination& destination,
120									media_format* io_format,
121									int32* _deprecated_);
122	virtual	status_t			GetNextOutput(int32* cookie,
123									media_output* out_output);
124	virtual	status_t			DisposeOutputCookie(int32 cookie);
125
126	virtual	status_t			SetBufferGroup(
127									const media_source& for_source,
128									BBufferGroup* group);
129
130	virtual	status_t			PrepareToConnect(const media_source& what,
131									const media_destination& where,
132									media_format* format,
133									media_source* out_source,
134									char* out_name);
135
136	virtual	void				Connect(status_t error,
137									const media_source& source,
138									const media_destination& destination,
139									const media_format& format,
140									char* io_name);
141
142	virtual	void				Disconnect(const media_source& what,
143									const media_destination& where);
144
145	virtual	void				LateNoticeReceived(
146									const media_source& what,
147									bigtime_t how_much,
148									bigtime_t performance_time);
149
150	virtual	void				EnableOutput(const media_source& what,
151									bool enabled, int32* _deprecated_);
152	virtual	void				AdditionalBufferRequested(
153									const media_source& source,
154									media_buffer_id prev_buffer,
155									bigtime_t prev_time,
156									const media_seek_tag* prev_tag);
157
158	// BMediaEventLooper interface
159protected:
160		/* you must override to handle your events! */
161		/* you should not call HandleEvent directly */
162	virtual	void				HandleEvent(const media_timed_event* event,
163									bigtime_t lateness,
164									bool realTimeEvent = false);
165
166	// BTimeSource interface
167protected:
168	virtual	void				SetRunMode(run_mode mode);
169	virtual	status_t			TimeSourceOp(const time_source_op_info& op,
170									void* _reserved);
171
172	//  BControllable interface
173protected:
174	virtual	status_t			GetParameterValue(int32 id,
175									bigtime_t* last_change,
176									void* value, size_t* ioSize);
177	virtual	void				SetParameterValue(int32 id,
178									bigtime_t when, const void* value,
179									size_t size);
180	virtual	BParameterWeb*		MakeParameterWeb();
181
182private:
183			void 				_ProcessGroup(BParameterGroup* group,
184									int32 index, int32& _parameters);
185			void 				_ProcessMux(BDiscreteParameter* parameter,
186									int32 index);
187			status_t			_PropagateParameterChanges(int from,
188									int type, const char* id);
189
190protected:
191	virtual	status_t			HandleStart(const media_timed_event* event,
192									bigtime_t lateness,
193									bool realTimeEvent = false);
194	virtual	status_t			HandleSeek(const media_timed_event* event,
195									bigtime_t lateness,
196									bool realTimeEvent = false);
197	virtual	status_t			HandleWarp(const media_timed_event* event,
198									bigtime_t lateness,
199									bool realTimeEvent = false);
200	virtual	status_t			HandleStop(const media_timed_event* event,
201									bigtime_t lateness,
202									bool realTimeEvent = false);
203	virtual	status_t			HandleBuffer(
204									const media_timed_event* event,
205									bigtime_t lateness,
206									bool realTimeEvent = false);
207	virtual	status_t			HandleDataStatus(
208									const media_timed_event* event,
209									bigtime_t lateness,
210									bool realTimeEvent = false);
211	virtual	status_t			HandleParameter(
212									const media_timed_event* event,
213									bigtime_t lateness,
214									bool realTimeEvent = false);
215
216public:
217	static	void				GetFlavor(flavor_info* outInfo, int32 id);
218	static	void				GetFormat(media_format* outFormat);
219
220			status_t			GetConfigurationFor(BMessage* intoMessage);
221
222
223private:
224								OpenSoundNode(const OpenSoundNode& clone);
225									// private unimplemented
226			OpenSoundNode&		operator=(const OpenSoundNode& clone);
227
228private:
229	static	void				_SignalHandler(int sig);
230
231	static	int32				_PlayThreadEntry(void* data);
232	static	int32				_RecThreadEntry(void* data);
233			int32				_PlayThread(NodeInput* input);
234			int32				_RecThread(NodeOutput* output);
235
236			status_t			_StartPlayThread(NodeInput* input);
237			status_t			_StopPlayThread(NodeInput* input);
238			status_t			_StartRecThread(NodeOutput* output);
239			status_t			_StopRecThread(NodeOutput* output);
240
241			BBuffer* 			_FillNextBuffer(audio_buf_info* abinfo,
242									NodeOutput& channel);
243			void				_UpdateTimeSource(bigtime_t performanceTime,
244									bigtime_t realTime, float drift);
245
246
247			NodeOutput* 		_FindOutput(
248									const media_source& source) const;
249			NodeInput* 			_FindInput(
250									const media_destination& dest) const;
251			NodeInput* 			_FindInput(int32 destinationId);
252
253private:
254			status_t			fInitCheckStatus;
255
256			BMediaAddOn*		fAddOn;
257			int32				fId;
258
259			BList				fInputs;
260			BList				fOutputs;
261
262#if 1
263			// TODO: remove and use use a preferred format
264			// per NodeInput/NodeOutput channel
265			media_format 		fPreferredFormat;
266#endif
267			bigtime_t 			fLatency;
268			bigtime_t			fInternalLatency;
269				// this is computed from the real (negotiated) chunk size
270				// and bit rate, not the defaults that are in the
271				// parameters
272			OpenSoundDevice*	fDevice;
273
274			bool 				fTimeSourceStarted;
275			bigtime_t			fTimeSourceStartTime;
276
277			BParameterWeb*		fWeb;
278			BMessage			fConfig;
279};
280
281#endif // _OPENSOUNDNODE_H
282