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