xref: /haiku/src/add-ons/media/media-add-ons/opensound/OpenSoundNode.h (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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 
21 class OpenSoundDevice;
22 class OpenSoundDeviceEngine;
23 class OpenSoundDeviceMixer;
24 
25 struct audio_buf_info;
26 struct flavor_info;
27 
28 class OpenSoundNode : public BBufferConsumer, public BBufferProducer,
29 	public BTimeSource, public BMediaEventLooper, public BControllable {
30 
31 private:
32 	class NodeInput;
33 	class NodeOutput;
34 	friend class NodeInput;
35 	friend class NodeOutput;
36 
37 protected:
38 	virtual						~OpenSoundNode();
39 
40 public:
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
49 public:
50 	virtual	BMediaAddOn*		AddOn(int32* internalID) const;
51 		// Who instantiated you -- or NULL for app class
52 
53 protected:
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 
62 public:
63 	virtual	status_t			HandleMessage(int32 message,
64 									const void* data, size_t size);
65 
66 protected:
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
73 protected:
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
112 protected:
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
161 protected:
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
169 protected:
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
175 protected:
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 
184 private:
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 
192 protected:
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 
218 public:
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 
225 private:
226 								OpenSoundNode(const OpenSoundNode& clone);
227 									// private unimplemented
228 			OpenSoundNode&		operator=(const OpenSoundNode& clone);
229 
230 private:
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 
255 private:
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