xref: /haiku/src/tests/kits/media/nodetest/ConsumerNode.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 #include <TimeSource.h>
2 #include <Buffer.h>
3 #include <stdlib.h>
4 #include "ConsumerNode.h"
5 #include "misc.h"
6 
7 ConsumerNode::ConsumerNode() :
8 	BBufferConsumer(B_MEDIA_RAW_AUDIO),
9 	BMediaEventLooper(),
10 	BMediaNode("ConsumerNode")
11 {
12 	out("ConsumerNode::ConsumerNode\n");
13 }
14 
15 ConsumerNode::~ConsumerNode()
16 {
17 	out("ConsumerNode::~ConsumerNode\n");
18 	Quit();
19 }
20 
21 void
22 ConsumerNode::NodeRegistered()
23 {
24 	out("ConsumerNode::NodeRegistered\n");
25 	InitializeInput();
26 	SetPriority(108);
27 	Run();
28 }
29 
30 status_t
31 ConsumerNode::AcceptFormat(
32 				const media_destination & dest,
33 				media_format * format)
34 {
35 	out("ConsumerNode::AcceptFormat\n");
36 
37 	if (dest != mInput.destination)
38 		return B_MEDIA_BAD_DESTINATION;
39 
40 	if (format == NULL)
41 		return B_BAD_VALUE;
42 
43 	if (format->type != B_MEDIA_RAW_AUDIO)
44 		return B_MEDIA_BAD_FORMAT;
45 
46 	return B_OK;
47 }
48 
49 status_t
50 ConsumerNode::GetNextInput(
51 				int32 * cookie,
52 				media_input * out_input)
53 {
54 	out("ConsumerNode::GetNextInput\n");
55 
56 	if (out_input == NULL)
57 		return B_BAD_VALUE;
58 
59 	if (++(*cookie) > 1)
60 		return B_BAD_INDEX;
61 
62 	*out_input = mInput;
63 	return B_OK;
64 }
65 
66 void
67 ConsumerNode::DisposeInputCookie(
68 				int32 cookie)
69 {
70 	out("ConsumerNode::DisposeInputCookie\n");
71 	return;
72 }
73 
74 void
75 ConsumerNode::BufferReceived(
76 				BBuffer * buffer)
77 {
78 	out("ConsumerNode::BufferReceived, sheduled time = %5.4f\n",buffer->Header()->start_time / 1E6);
79 	media_timed_event event(buffer->Header()->start_time,BTimedEventQueue::B_HANDLE_BUFFER,
80 							buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
81 	EventQueue()->AddEvent(event);
82 	return;
83 }
84 
85 void
86 ConsumerNode::ProducerDataStatus(
87 				const media_destination & for_whom,
88 				int32 status,
89 				bigtime_t at_performance_time)
90 {
91 	out("ConsumerNode::ProducerDataStatus\n");
92 	if (for_whom == mInput.destination) {
93 		media_timed_event event(at_performance_time,BTimedEventQueue::B_DATA_STATUS,
94 								&mInput, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
95 		EventQueue()->AddEvent(event);
96 	}
97 }
98 
99 status_t
100 ConsumerNode::GetLatencyFor(
101 				const media_destination & for_whom,
102 				bigtime_t * out_latency,
103 				media_node_id * out_timesource)
104 {
105 	out("ConsumerNode::GetLatencyFor\n");
106 	// make sure this is one of my valid inputs
107 	if (for_whom != mInput.destination)
108 		return B_MEDIA_BAD_DESTINATION;
109 
110 	*out_latency = 23000;
111 	*out_timesource = TimeSource()->ID();
112 	return B_OK;
113 }
114 
115 status_t
116 ConsumerNode::Connected(
117 				const media_source & producer,
118 				const media_destination & where,
119 				const media_format & with_format,
120 				media_input * out_input)
121 {
122 	out("ConsumerNode::Connected\n");
123 	if (where != mInput.destination)
124 		return B_MEDIA_BAD_DESTINATION;
125 
126 	// calculate my latency here, because it may depend on buffer sizes/durations, then
127 	// tell the BMediaEventLooper how early we need to get the buffers
128 	SetEventLatency(10 * 1000); //fixme
129 
130 	/* reserve the connection */
131 	mInput.source = producer;
132 	mInput.format = with_format;
133 
134 	/* and publish it's name and connection info */
135 	*out_input = mInput;
136 
137 #if 0
138 	/* create the buffer group */
139 	if (mBufferGroup == NULL) {
140 		create_own_buffer_group();
141 		mBufferGroup = mOwnBufferGroup;
142 	}
143 
144 	/* set the duration of the node's buffers */
145 	int32 numBuffers;
146 	mBufferGroup->CountBuffers(&numBuffers);
147 	SetBufferDuration((1000000LL * numBuffers) / mOutput.format.u.raw_video.field_rate);
148 #endif
149 
150 	return B_OK;
151 }
152 
153 void
154 ConsumerNode::Disconnected(
155 				const media_source & producer,
156 				const media_destination & where)
157 {
158 	out("ConsumerNode::Disconnected\n");
159 
160 	/* unreserve the connection */
161 	InitializeInput();
162 
163 #if 0
164 	/* release buffer group */
165 	mBufferGroup = NULL;
166 	if (mOwnBufferGroup != NULL) {
167 		delete_own_buffer_group();
168 	}
169 #endif
170 
171 	return;
172 }
173 
174 status_t
175 ConsumerNode::FormatChanged(
176 				const media_source & producer,
177 				const media_destination & consumer,
178 				int32 change_tag,
179 				const media_format & format)
180 {
181 	out("ConsumerNode::FormatChanged\n");
182 	return B_OK;
183 }
184 
185 status_t
186 ConsumerNode::SeekTagRequested(
187 				const media_destination& destination,
188 				bigtime_t in_target_time,
189 				uint32 in_flags,
190 				media_seek_tag* out_seek_tag,
191 				bigtime_t* out_tagged_time,
192 				uint32* out_flags)
193 {
194 	out("ConsumerNode::SeekTagRequested\n");
195 	return B_OK;
196 }
197 
198 BMediaAddOn*
199 ConsumerNode::AddOn(int32 * internal_id) const
200 {
201 	out("ConsumerNode::AddOn\n");
202 	return NULL;
203 }
204 
205 void
206 ConsumerNode::HandleEvent(const media_timed_event *event,
207 						 bigtime_t lateness,
208 						 bool realTimeEvent)
209 {
210 	switch (event->type)
211 	{
212 	case BTimedEventQueue::B_HANDLE_BUFFER:
213 		{
214 			out("ConsumerNode::HandleEvent B_HANDLE_BUFFER\n");
215 			BBuffer* buffer = const_cast<BBuffer*>((BBuffer*) event->pointer);
216 
217 			out("### sheduled time = %5.4f, current time = %5.4f, lateness = %5.4f\n",buffer->Header()->start_time / 1E6,TimeSource()->Now() / 1E6,lateness / 1E6);
218 
219 			snooze((rand()*100) % 200000);
220 
221 			if (buffer)
222 				buffer->Recycle();
223 		}
224 		break;
225 
226 	case BTimedEventQueue::B_PARAMETER:
227 		{
228 			out("ConsumerNode::HandleEvent B_PARAMETER\n");
229 		}
230 		break;
231 
232 	case BTimedEventQueue::B_START:
233 		{
234 			out("ConsumerNode::HandleEvent B_START\n");
235 		}
236 		break;
237 
238 	case BTimedEventQueue::B_STOP:
239 		{
240 			out("ConsumerNode::HandleEvent B_STOP\n");
241 		}
242 		// stopping implies not handling any more buffers.  So, we flush all pending
243 		// buffers out of the event queue before returning to the event loop.
244 		EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
245 		break;
246 
247 	case BTimedEventQueue::B_SEEK:
248 		{
249 			out("ConsumerNode::HandleEvent B_SEEK\n");
250 		}
251 		break;
252 
253 	case BTimedEventQueue::B_WARP:
254 		{
255 			out("ConsumerNode::HandleEvent B_WARP\n");
256 		}
257 		// similarly, time warps aren't meaningful to the logger, so just record it and return
258 		//mLogger->Log(LOG_WARP_HANDLED, logMsg);
259 		break;
260 
261 	case BTimedEventQueue::B_DATA_STATUS:
262 		{
263 			out("ConsumerNode::HandleEvent B_DATA_STATUS\n");
264 		}
265 		break;
266 
267 	default:
268 		{
269 			out("ConsumerNode::HandleEvent default\n");
270 		}
271 		break;
272 	}
273 }
274 
275 status_t
276 ConsumerNode::HandleMessage(int32 message,const void *data, size_t size)
277 {
278 	out("ConsumerNode::HandleMessage %lx\n",message);
279 	if (B_OK == BBufferConsumer::HandleMessage(message,data,size))
280 		return B_OK;
281 	if (B_OK == BMediaEventLooper::HandleMessage(message,data,size))
282 		return B_OK;
283 	return BMediaNode::HandleMessage(message,data,size);
284 }
285 
286 void
287 ConsumerNode::InitializeInput()
288 {
289 	out("ConsumerNode::InitializeInput()\n");
290 	mInput.source = media_source::null;
291 	mInput.destination.port = ControlPort();
292 	mInput.destination.id = 0;
293 	mInput.node = Node();
294 	mInput.format.type = B_MEDIA_RAW_AUDIO;
295 	mInput.format.u.raw_audio = media_raw_audio_format::wildcard;
296 	mInput.format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
297 	mInput.format.u.raw_audio.channel_count = 1;
298 	mInput.format.u.raw_audio.frame_rate = 44100;
299 	mInput.format.u.raw_audio.byte_order = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
300 	strcpy(mInput.name, "this way in");
301 }
302