1d5525d8cSshatty// MediaDemultiplexerNode.cpp
2d5525d8cSshatty//
3d5525d8cSshatty// Andrew Bachmann, 2002
4d5525d8cSshatty//
5d5525d8cSshatty// The MediaDemultiplexerNode class
6d5525d8cSshatty// takes a multistream input and supplies
7d5525d8cSshatty// the individual constituent streams as
8d5525d8cSshatty// the output.
9d5525d8cSshatty
10d5525d8cSshatty#include <MediaDefs.h>
11d5525d8cSshatty#include <MediaNode.h>
12d5525d8cSshatty#include <MediaAddOn.h>
13d5525d8cSshatty#include <BufferConsumer.h>
14d5525d8cSshatty#include <BufferProducer.h>
15d5525d8cSshatty#include <MediaEventLooper.h>
16d5525d8cSshatty#include <Errors.h>
17d5525d8cSshatty#include <BufferGroup.h>
18d5525d8cSshatty#include <TimeSource.h>
19d5525d8cSshatty#include <Buffer.h>
20d5525d8cSshatty#include <limits.h>
21d5525d8cSshatty
22d5525d8cSshatty#include "MediaDemultiplexerNode.h"
23d5525d8cSshatty#include "misc.h"
24d5525d8cSshatty
25d5525d8cSshatty#include <stdio.h>
26d5525d8cSshatty#include <string.h>
27d5525d8cSshatty
28d5525d8cSshatty// -------------------------------------------------------- //
29d5525d8cSshatty// ctor/dtor
30d5525d8cSshatty// -------------------------------------------------------- //
31d5525d8cSshatty
32d5525d8cSshattyMediaDemultiplexerNode::~MediaDemultiplexerNode(void)
33d5525d8cSshatty{
34d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::~MediaDemultiplexerNode\n");
35d5525d8cSshatty	// Stop the BMediaEventLooper thread
36d5525d8cSshatty	Quit();
37d5525d8cSshatty}
38d5525d8cSshatty
39d5525d8cSshattyMediaDemultiplexerNode::MediaDemultiplexerNode(
40d5525d8cSshatty				const flavor_info * info = 0,
41d5525d8cSshatty				BMessage * config = 0,
42d5525d8cSshatty				BMediaAddOn * addOn = 0)
43d5525d8cSshatty	: BMediaNode("MediaDemultiplexerNode"),
44d5525d8cSshatty	  BMediaEventLooper(),
45d5525d8cSshatty  	  BBufferConsumer(B_MEDIA_MULTISTREAM),
46728a8c74Sshatty  	  BBufferProducer(B_MEDIA_UNKNOWN_TYPE) // no B_MEDIA_ANY
47d5525d8cSshatty{
48d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::MediaDemultiplexerNode\n");
49d5525d8cSshatty	// keep our creator around for AddOn calls later
50d5525d8cSshatty	fAddOn = addOn;
51d5525d8cSshatty	// null out our latency estimates
52d5525d8cSshatty	fDownstreamLatency = 0;
53d5525d8cSshatty	fInternalLatency = 0;
54d5525d8cSshatty	// don't overwrite available space, and be sure to terminate
55d5525d8cSshatty	strncpy(input.name,"Demultiplexer Input",B_MEDIA_NAME_LENGTH-1);
56d5525d8cSshatty	input.name[B_MEDIA_NAME_LENGTH-1] = '\0';
57d5525d8cSshatty	// initialize the input
58d5525d8cSshatty	input.node = media_node::null;               // until registration
59d5525d8cSshatty	input.source = media_source::null;
60d5525d8cSshatty	input.destination = media_destination::null; // until registration
61d5525d8cSshatty	GetInputFormat(&input.format);
62d5525d8cSshatty
63d5525d8cSshatty	outputs.empty();
64d5525d8cSshatty	// outputs initialized after we connect,
65d5525d8cSshatty	// find a suitable extractor,
66d5525d8cSshatty	// and it tells us the ouputs
67d5525d8cSshatty
68d5525d8cSshatty	fInitCheckStatus = B_OK;
69d5525d8cSshatty}
70d5525d8cSshatty
71d5525d8cSshattystatus_t MediaDemultiplexerNode::InitCheck(void) const
72d5525d8cSshatty{
73d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::InitCheck\n");
74d5525d8cSshatty	return fInitCheckStatus;
75d5525d8cSshatty}
76d5525d8cSshatty
77d5525d8cSshattystatus_t MediaDemultiplexerNode::GetConfigurationFor(
78d5525d8cSshatty				BMessage * into_message)
79d5525d8cSshatty{
80d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetConfigurationFor\n");
81d5525d8cSshatty	return B_OK;
82d5525d8cSshatty}
83d5525d8cSshatty
84d5525d8cSshatty// -------------------------------------------------------- //
85d5525d8cSshatty// implementation of BMediaNode
86d5525d8cSshatty// -------------------------------------------------------- //
87d5525d8cSshatty
88d5525d8cSshattyBMediaAddOn * MediaDemultiplexerNode::AddOn(
89d5525d8cSshatty				int32 * internal_id) const
90d5525d8cSshatty{
91d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::AddOn\n");
92d5525d8cSshatty	// BeBook says this only gets called if we were in an add-on.
93d5525d8cSshatty	if (fAddOn != 0) {
94d5525d8cSshatty		// If we get a null pointer then we just won't write.
95d5525d8cSshatty		if (internal_id != 0) {
96d5525d8cSshatty			internal_id = 0;
97d5525d8cSshatty		}
98d5525d8cSshatty	}
99d5525d8cSshatty	return fAddOn;
100d5525d8cSshatty}
101d5525d8cSshatty
102d5525d8cSshattyvoid MediaDemultiplexerNode::Start(
103d5525d8cSshatty				bigtime_t performance_time)
104d5525d8cSshatty{
105d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::Start(pt=%lld)\n",performance_time);
106d5525d8cSshatty	BMediaEventLooper::Start(performance_time);
107d5525d8cSshatty}
108d5525d8cSshatty
109d5525d8cSshattyvoid MediaDemultiplexerNode::Stop(
110d5525d8cSshatty				bigtime_t performance_time,
111d5525d8cSshatty				bool immediate)
112d5525d8cSshatty{
113d5525d8cSshatty	if (immediate) {
114d5525d8cSshatty		fprintf(stderr,"MediaDemultiplexerNode::Stop(pt=%lld,<immediate>)\n",performance_time);
115d5525d8cSshatty	} else {
116d5525d8cSshatty		fprintf(stderr,"MediaDemultiplexerNode::Stop(pt=%lld,<scheduled>)\n",performance_time);
117d5525d8cSshatty	}
118d5525d8cSshatty	BMediaEventLooper::Stop(performance_time,immediate);
119d5525d8cSshatty}
120d5525d8cSshatty
121d5525d8cSshattyvoid MediaDemultiplexerNode::Seek(
122d5525d8cSshatty				bigtime_t media_time,
123d5525d8cSshatty				bigtime_t performance_time)
124d5525d8cSshatty{
125d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::Seek(mt=%lld,pt=%lld)\n",media_time,performance_time);
126d5525d8cSshatty	BMediaEventLooper::Seek(media_time,performance_time);
127d5525d8cSshatty}
128d5525d8cSshatty
129d5525d8cSshattyvoid MediaDemultiplexerNode::SetRunMode(
130d5525d8cSshatty				run_mode mode)
131d5525d8cSshatty{
132d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::SetRunMode(%i)\n",mode);
133d5525d8cSshatty	BMediaEventLooper::SetRunMode(mode);
134d5525d8cSshatty}
135d5525d8cSshatty
136d5525d8cSshattyvoid MediaDemultiplexerNode::TimeWarp(
137d5525d8cSshatty				bigtime_t at_real_time,
138d5525d8cSshatty				bigtime_t to_performance_time)
139d5525d8cSshatty{
140d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::TimeWarp(rt=%lld,pt=%lld)\n",at_real_time,to_performance_time);
141d5525d8cSshatty	BMediaEventLooper::TimeWarp(at_real_time,to_performance_time);
142d5525d8cSshatty}
143d5525d8cSshatty
144d5525d8cSshattyvoid MediaDemultiplexerNode::Preroll(void)
145d5525d8cSshatty{
146d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::Preroll\n");
147d5525d8cSshatty	// XXX:Performance opportunity
148d5525d8cSshatty	BMediaNode::Preroll();
149d5525d8cSshatty}
150d5525d8cSshatty
151d5525d8cSshattyvoid MediaDemultiplexerNode::SetTimeSource(
152d5525d8cSshatty				BTimeSource * time_source)
153d5525d8cSshatty{
154d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::SetTimeSource\n");
155d5525d8cSshatty	BMediaNode::SetTimeSource(time_source);
156d5525d8cSshatty}
157d5525d8cSshatty
158d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleMessage(
159d5525d8cSshatty				int32 message,
160d5525d8cSshatty				const void * data,
161d5525d8cSshatty				size_t size)
162d5525d8cSshatty{
163d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleMessage\n");
164d5525d8cSshatty	status_t status = B_OK;
165d5525d8cSshatty	switch (message) {
166d5525d8cSshatty		// no special messages for now
167d5525d8cSshatty		default:
168d5525d8cSshatty			status = BBufferConsumer::HandleMessage(message,data,size);
169d5525d8cSshatty			if (status == B_OK) {
170d5525d8cSshatty				break;
171d5525d8cSshatty			}
172d5525d8cSshatty			status = BBufferProducer::HandleMessage(message,data,size);
173d5525d8cSshatty			if (status == B_OK) {
174d5525d8cSshatty				break;
175d5525d8cSshatty			}
176d5525d8cSshatty			status = BMediaNode::HandleMessage(message,data,size);
177d5525d8cSshatty			if (status == B_OK) {
178d5525d8cSshatty				break;
179d5525d8cSshatty			}
180d5525d8cSshatty			BMediaNode::HandleBadMessage(message,data,size);
181d5525d8cSshatty			status = B_ERROR;
182d5525d8cSshatty			break;
183d5525d8cSshatty	}
184d5525d8cSshatty	return status;
185d5525d8cSshatty}
186d5525d8cSshatty
187d5525d8cSshattystatus_t MediaDemultiplexerNode::RequestCompleted(
188d5525d8cSshatty				const media_request_info & info)
189d5525d8cSshatty{
190d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::RequestCompleted\n");
191d5525d8cSshatty	return BMediaNode::RequestCompleted(info);
192d5525d8cSshatty}
193d5525d8cSshatty
194d5525d8cSshattystatus_t MediaDemultiplexerNode::DeleteHook(
195d5525d8cSshatty				BMediaNode * node)
196d5525d8cSshatty{
197d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::DeleteHook\n");
198d5525d8cSshatty	return BMediaEventLooper::DeleteHook(node);
199d5525d8cSshatty}
200d5525d8cSshatty
201d5525d8cSshattyvoid MediaDemultiplexerNode::NodeRegistered(void)
202d5525d8cSshatty{
203d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::NodeRegistered\n");
204d5525d8cSshatty
205d5525d8cSshatty	// now we can do this
206d5525d8cSshatty	input.node = Node();
207d5525d8cSshatty	input.destination.id = 0;
208d5525d8cSshatty	input.destination.port = input.node.port; // same as ControlPort()
209d5525d8cSshatty
210d5525d8cSshatty	// outputs initialized after we connect,
211d5525d8cSshatty	// find a suitable extractor,
212d5525d8cSshatty	// and it tells us the ouputs
213d5525d8cSshatty
214d5525d8cSshatty	// start the BMediaEventLooper thread
215d5525d8cSshatty	SetPriority(B_REAL_TIME_PRIORITY);
216d5525d8cSshatty	Run();
217d5525d8cSshatty}
218d5525d8cSshatty
219d5525d8cSshattystatus_t MediaDemultiplexerNode::GetNodeAttributes(
220d5525d8cSshatty				media_node_attribute * outAttributes,
221d5525d8cSshatty				size_t inMaxCount)
222d5525d8cSshatty{
223d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetNodeAttributes\n");
224d5525d8cSshatty	return BMediaNode::GetNodeAttributes(outAttributes,inMaxCount);
225d5525d8cSshatty}
226d5525d8cSshatty
227d5525d8cSshattystatus_t MediaDemultiplexerNode::AddTimer(
228d5525d8cSshatty					bigtime_t at_performance_time,
229d5525d8cSshatty					int32 cookie)
230d5525d8cSshatty{
231d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::AddTimer\n");
232d5525d8cSshatty	return BMediaEventLooper::AddTimer(at_performance_time,cookie);
233d5525d8cSshatty}
234d5525d8cSshatty
235d5525d8cSshatty// -------------------------------------------------------- //
236d5525d8cSshatty// implemention of BBufferConsumer
237d5525d8cSshatty// -------------------------------------------------------- //
238d5525d8cSshatty
239d5525d8cSshatty// Check to make sure the format is okay, then remove
240d5525d8cSshatty// any wildcards corresponding to our requirements.
241d5525d8cSshattystatus_t MediaDemultiplexerNode::AcceptFormat(
242d5525d8cSshatty				const media_destination & dest,
243d5525d8cSshatty				media_format * format)
244d5525d8cSshatty{
245d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::AcceptFormat\n");
246d5525d8cSshatty	if (input.destination != dest) {
247d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION");
248d5525d8cSshatty		return B_MEDIA_BAD_DESTINATION; // we only have one input so that better be it
249d5525d8cSshatty	}
250d5525d8cSshatty	media_format myFormat;
251d5525d8cSshatty	GetInputFormat(&myFormat);
252d5525d8cSshatty	// Be's format_is_compatible doesn't work,
253d5525d8cSshatty	// so use our format_is_acceptible instead
254d5525d8cSshatty	if (!format_is_acceptible(*format,myFormat)) {
255d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n");
256d5525d8cSshatty		return B_MEDIA_BAD_FORMAT;
257d5525d8cSshatty	}
258d5525d8cSshatty	AddRequirements(format);
259d5525d8cSshatty	return B_OK;
260d5525d8cSshatty}
261d5525d8cSshatty
262d5525d8cSshattystatus_t MediaDemultiplexerNode::GetNextInput(
263d5525d8cSshatty				int32 * cookie,
264d5525d8cSshatty				media_input * out_input)
265d5525d8cSshatty{
266d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetNextInput\n");
267bcf291edSMarcus Overhagen	if (*cookie != 0) {
268bcf291edSMarcus Overhagen		fprintf(stderr,"<- B_ERROR (no more inputs)\n");
269bcf291edSMarcus Overhagen		return B_ERROR;
270d5525d8cSshatty	}
271bcf291edSMarcus Overhagen
272bcf291edSMarcus Overhagen	// so next time they won't get the same input again
273bcf291edSMarcus Overhagen	*cookie = 1;
274d5525d8cSshatty	*out_input = input;
275d5525d8cSshatty	return B_OK;
276d5525d8cSshatty}
277d5525d8cSshatty
278d5525d8cSshattyvoid MediaDemultiplexerNode::DisposeInputCookie(
279d5525d8cSshatty				int32 cookie)
280d5525d8cSshatty{
281d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::DisposeInputCookie\n");
282d5525d8cSshatty	// nothing to do since our cookies are just integers
283d5525d8cSshatty	return; // B_OK;
284d5525d8cSshatty}
285d5525d8cSshatty
286d5525d8cSshattyvoid MediaDemultiplexerNode::BufferReceived(
287d5525d8cSshatty				BBuffer * buffer)
288d5525d8cSshatty{
289d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::BufferReceived\n");
290d5525d8cSshatty	switch (buffer->Header()->type) {
291d5525d8cSshatty//		case B_MEDIA_PARAMETERS:
292d5525d8cSshatty//			{
293d5525d8cSshatty//			status_t status = ApplyParameterData(buffer->Data(),buffer->SizeUsed());
294d5525d8cSshatty//			if (status != B_OK) {
295d5525d8cSshatty//				fprintf(stderr,"ApplyParameterData in MediaDemultiplexerNode::BufferReceived failed\n");
296d5525d8cSshatty//			}
297d5525d8cSshatty//			buffer->Recycle();
298d5525d8cSshatty//			}
299d5525d8cSshatty//			break;
300d5525d8cSshatty		case B_MEDIA_MULTISTREAM:
301d5525d8cSshatty			if (buffer->Flags() & BBuffer::B_SMALL_BUFFER) {
302d5525d8cSshatty				fprintf(stderr,"NOT IMPLEMENTED: B_SMALL_BUFFER in MediaDemultiplexerNode::BufferReceived\n");
303d5525d8cSshatty				// XXX: implement this part
304d5525d8cSshatty				buffer->Recycle();
305d5525d8cSshatty			} else {
306d5525d8cSshatty				media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
307d5525d8cSshatty										buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
308d5525d8cSshatty				status_t status = EventQueue()->AddEvent(event);
309d5525d8cSshatty				if (status != B_OK) {
310d5525d8cSshatty					fprintf(stderr,"EventQueue()->AddEvent(event) in MediaDemultiplexerNode::BufferReceived failed\n");
311d5525d8cSshatty					buffer->Recycle();
312d5525d8cSshatty				}
313d5525d8cSshatty			}
314d5525d8cSshatty			break;
315d5525d8cSshatty		default:
316d5525d8cSshatty			fprintf(stderr,"unexpected buffer type in MediaDemultiplexerNode::BufferReceived\n");
317d5525d8cSshatty			buffer->Recycle();
318d5525d8cSshatty			break;
319d5525d8cSshatty	}
320d5525d8cSshatty}
321d5525d8cSshatty
322d5525d8cSshattyvoid MediaDemultiplexerNode::ProducerDataStatus(
323d5525d8cSshatty				const media_destination & for_whom,
324d5525d8cSshatty				int32 status,
325d5525d8cSshatty				bigtime_t at_performance_time)
326d5525d8cSshatty{
327d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::ProducerDataStatus\n");
328d5525d8cSshatty	if (input.destination != for_whom) {
329d5525d8cSshatty		fprintf(stderr,"invalid destination received in MediaDemultiplexerNode::ProducerDataStatus\n");
330d5525d8cSshatty		return;
331d5525d8cSshatty	}
332d5525d8cSshatty	media_timed_event event(at_performance_time, BTimedEventQueue::B_DATA_STATUS,
333d5525d8cSshatty			&input, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
334d5525d8cSshatty	EventQueue()->AddEvent(event);
335d5525d8cSshatty}
336d5525d8cSshatty
337d5525d8cSshattystatus_t MediaDemultiplexerNode::GetLatencyFor(
338d5525d8cSshatty				const media_destination & for_whom,
339d5525d8cSshatty				bigtime_t * out_latency,
340d5525d8cSshatty				media_node_id * out_timesource)
341d5525d8cSshatty{
342d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetLatencyFor\n");
343d5525d8cSshatty	if ((out_latency == 0) || (out_timesource == 0)) {
344d5525d8cSshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
345d5525d8cSshatty		return B_BAD_VALUE;
346d5525d8cSshatty	}
347d5525d8cSshatty	if (input.destination != for_whom) {
348d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
349d5525d8cSshatty		return B_MEDIA_BAD_DESTINATION;
350d5525d8cSshatty	}
351d5525d8cSshatty	*out_latency = EventLatency();
352d5525d8cSshatty	*out_timesource = TimeSource()->ID();
353d5525d8cSshatty	return B_OK;
354d5525d8cSshatty}
355d5525d8cSshatty
356d5525d8cSshattystatus_t MediaDemultiplexerNode::Connected(
357d5525d8cSshatty				const media_source & producer,	/* here's a good place to request buffer group usage */
358d5525d8cSshatty				const media_destination & where,
359d5525d8cSshatty				const media_format & with_format,
360d5525d8cSshatty				media_input * out_input)
361d5525d8cSshatty{
362d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::Connected\n");
363d5525d8cSshatty	if (input.destination != where) {
364d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
365d5525d8cSshatty		return B_MEDIA_BAD_DESTINATION;
366d5525d8cSshatty	}
367d5525d8cSshatty
368d5525d8cSshatty	// find an appropriate extractor to handle this type
369d5525d8cSshatty	fprintf(stderr,"  XXX: no extractors yet\n");
370d5525d8cSshatty
371d5525d8cSshatty	// initialize the outputs here
372d5525d8cSshatty	// provide all the types that the extractor claims
373d5525d8cSshatty	outputs.empty();
374d5525d8cSshatty
375d5525d8cSshatty	// compute the latency or just guess
376d5525d8cSshatty	fInternalLatency = 500; // just guess
377d5525d8cSshatty	fprintf(stderr,"  internal latency guessed = %lld\n",fInternalLatency);
378d5525d8cSshatty
379d5525d8cSshatty	SetEventLatency(fInternalLatency);
380d5525d8cSshatty
381d5525d8cSshatty	// record the agreed upon values
382d5525d8cSshatty	input.source = producer;
383d5525d8cSshatty	input.format = with_format;
384d5525d8cSshatty	*out_input = input;
385d5525d8cSshatty	return B_OK;
386d5525d8cSshatty}
387d5525d8cSshatty
388d5525d8cSshattyvoid MediaDemultiplexerNode::Disconnected(
389d5525d8cSshatty				const media_source & producer,
390d5525d8cSshatty				const media_destination & where)
391d5525d8cSshatty{
392d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::Disconnected\n");
393d5525d8cSshatty	if (input.destination != where) {
394d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
395d5525d8cSshatty		return;
396d5525d8cSshatty	}
397d5525d8cSshatty	if (input.source != producer) {
398d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
399d5525d8cSshatty		return;
400d5525d8cSshatty	}
401d5525d8cSshatty	input.source = media_source::null;
402d5525d8cSshatty	GetInputFormat(&input.format);
403d5525d8cSshatty
404d5525d8cSshatty	outputs.empty();
405d5525d8cSshatty}
406d5525d8cSshatty
407d5525d8cSshatty	/* The notification comes from the upstream producer, so he's already cool with */
408d5525d8cSshatty	/* the format; you should not ask him about it in here. */
409d5525d8cSshattystatus_t MediaDemultiplexerNode::FormatChanged(
410d5525d8cSshatty				const media_source & producer,
411d5525d8cSshatty				const media_destination & consumer,
412d5525d8cSshatty				int32 change_tag,
413d5525d8cSshatty				const media_format & format)
414d5525d8cSshatty{
415d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::FormatChanged\n");
416d5525d8cSshatty	if (input.source != producer) {
417d5525d8cSshatty		return B_MEDIA_BAD_SOURCE;
418d5525d8cSshatty	}
419d5525d8cSshatty	if (input.destination != consumer) {
420d5525d8cSshatty		return B_MEDIA_BAD_DESTINATION;
421d5525d8cSshatty	}
422d5525d8cSshatty	// XXX: implement
423d5525d8cSshatty	fprintf(stderr,"  This is because we asked to have the format changed.\n"
424d5525d8cSshatty	               "  Therefore we must switch to the other extractor that\n"
425d5525d8cSshatty	               "  we presumably have ready.");
426d5525d8cSshatty	input.format = format;
427d5525d8cSshatty	return B_OK;
428d5525d8cSshatty}
429d5525d8cSshatty
430d5525d8cSshatty	/* Given a performance time of some previous buffer, retrieve the remembered tag */
431d5525d8cSshatty	/* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
432d5525d8cSshatty	/* idea being that flags can be added later, and the understood flags returned in */
433d5525d8cSshatty	/* *out_flags. */
434d5525d8cSshattystatus_t MediaDemultiplexerNode::SeekTagRequested(
435d5525d8cSshatty				const media_destination & destination,
436d5525d8cSshatty				bigtime_t in_target_time,
437d5525d8cSshatty				uint32 in_flags,
438d5525d8cSshatty				media_seek_tag * out_seek_tag,
439d5525d8cSshatty				bigtime_t * out_tagged_time,
440d5525d8cSshatty				uint32 * out_flags)
441d5525d8cSshatty{
442d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::SeekTagRequested\n");
443d5525d8cSshatty	// XXX: implement this
444d5525d8cSshatty	return BBufferConsumer::SeekTagRequested(destination,in_target_time,in_flags,
445d5525d8cSshatty											out_seek_tag,out_tagged_time,out_flags);
446d5525d8cSshatty}
447d5525d8cSshatty
448d5525d8cSshatty// -------------------------------------------------------- //
449d5525d8cSshatty// implemention of BBufferProducer
450d5525d8cSshatty// -------------------------------------------------------- //
451d5525d8cSshatty
452d5525d8cSshatty// They are asking us to make the first offering.
453d5525d8cSshatty// So, we get a fresh format and then add requirements
454d5525d8cSshattystatus_t MediaDemultiplexerNode::FormatSuggestionRequested(
455d5525d8cSshatty				media_type type,
456d5525d8cSshatty				int32 quality,
457d5525d8cSshatty				media_format * format)
458d5525d8cSshatty{
459d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::FormatSuggestionRequested\n");
460d5525d8cSshatty	// XXX: how do I pick which stream to supply here?....
461d5525d8cSshatty	//      answer?: get the first compatible stream that is available
462d5525d8cSshatty	fprintf(stderr,"  format suggestion requested not implemented\n");
463d5525d8cSshatty//	if ((type != B_MEDIA_MULTISTREAM) && (type != B_MEDIA_UNKNOWN_TYPE)) {
464d5525d8cSshatty//		fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n");
465d5525d8cSshatty//		return B_MEDIA_BAD_FORMAT;
466d5525d8cSshatty//	}
467d5525d8cSshatty	GetOutputFormat(format);
468d5525d8cSshatty//	AddRequirements(format);
469d5525d8cSshatty
470d5525d8cSshatty	return B_OK;
471d5525d8cSshatty}
472d5525d8cSshatty
473d5525d8cSshatty// They made an offer to us.  We should make sure that the offer is
474d5525d8cSshatty// acceptable, and then we can add any requirements we have on top of
475d5525d8cSshatty// that.  We leave wildcards for anything that we don't care about.
476d5525d8cSshattystatus_t MediaDemultiplexerNode::FormatProposal(
477d5525d8cSshatty				const media_source & output_source,
478d5525d8cSshatty				media_format * format)
479d5525d8cSshatty{
480d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::FormatProposal\n");
481d5525d8cSshatty	// find the information for this output
482d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
483d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
484d5525d8cSshatty		if (itr->output.source == output_source) {
485d5525d8cSshatty			break;
486d5525d8cSshatty		}
487d5525d8cSshatty	}
488d5525d8cSshatty	if (itr == outputs.end()) {
489d5525d8cSshatty		// we don't have that output
490d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
491d5525d8cSshatty		return B_MEDIA_BAD_SOURCE;
492d5525d8cSshatty	}
493d5525d8cSshatty	return itr->FormatProposal(format);
494d5525d8cSshatty}
495d5525d8cSshatty
496d5525d8cSshatty// Presumably we have already agreed with them that this format is
497d5525d8cSshatty// okay.  But just in case, we check the offer. (and complain if it
498d5525d8cSshatty// is invalid)  Then as the last thing we do, we get rid of any
499d5525d8cSshatty// remaining wilcards.
500d5525d8cSshattystatus_t MediaDemultiplexerNode::FormatChangeRequested(
501d5525d8cSshatty				const media_source & source,
502d5525d8cSshatty				const media_destination & destination,
503d5525d8cSshatty				media_format * io_format,
504d5525d8cSshatty				int32 * _deprecated_)
505d5525d8cSshatty{
506d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::FormatChangeRequested\n");
507d5525d8cSshatty	// find the information for this output
508d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
509d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
510d5525d8cSshatty		if (itr->output.source == source) {
511d5525d8cSshatty			break;
512d5525d8cSshatty		}
513d5525d8cSshatty	}
514d5525d8cSshatty	if (itr == outputs.end()) {
515d5525d8cSshatty		// we don't have that output
516d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
517d5525d8cSshatty		return B_MEDIA_BAD_SOURCE;
518d5525d8cSshatty	}
519d5525d8cSshatty	return itr->FormatChangeRequested(destination,io_format);
520d5525d8cSshatty}
521d5525d8cSshatty
522d5525d8cSshattystatus_t MediaDemultiplexerNode::GetNextOutput(	/* cookie starts as 0 */
523d5525d8cSshatty				int32 * cookie,
524d5525d8cSshatty				media_output * out_output)
525d5525d8cSshatty{
526d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetNextOutput\n");
527d5525d8cSshatty	// they want a clean start
528d5525d8cSshatty	if (*cookie == 0) {
529d5525d8cSshatty		*cookie = (int32)outputs.begin();
530d5525d8cSshatty	}
531d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr
532d5525d8cSshatty		= (vector<MediaOutputInfo>::iterator)(*cookie);
533d5525d8cSshatty	// XXX: check here if the vector has been modified.
534d5525d8cSshatty	//      if the iterator is invalid, return an error code??
535d5525d8cSshatty
536d5525d8cSshatty	// they already got our 1 output
537d5525d8cSshatty	if (itr == outputs.end()) {
538d5525d8cSshatty		fprintf(stderr,"<- B_ERROR (no more outputs)\n");
539d5525d8cSshatty		return B_ERROR;
540d5525d8cSshatty	}
541d5525d8cSshatty	// return this output
542d5525d8cSshatty	*out_output = itr->output;
543d5525d8cSshatty	// so next time they won't get the same output again
544728a8c74Sshatty	*cookie = (int32)++itr;
545d5525d8cSshatty	return B_OK;
546d5525d8cSshatty}
547d5525d8cSshatty
548d5525d8cSshattystatus_t MediaDemultiplexerNode::DisposeOutputCookie(
549d5525d8cSshatty				int32 cookie)
550d5525d8cSshatty{
551d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::DisposeOutputCookie\n");
552d5525d8cSshatty	// nothing to do since our cookies are part of the vector iterator
553d5525d8cSshatty	return B_OK;
554d5525d8cSshatty}
555d5525d8cSshatty
556d5525d8cSshattystatus_t MediaDemultiplexerNode::SetBufferGroup(
557d5525d8cSshatty				const media_source & for_source,
558d5525d8cSshatty				BBufferGroup * group)
559d5525d8cSshatty{
560d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::SetBufferGroup\n");
561d5525d8cSshatty	// find the information for this output
562d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
563d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
564728a8c74Sshatty		if (itr->output.source == for_source) {
565d5525d8cSshatty			break;
566d5525d8cSshatty		}
567d5525d8cSshatty	}
568d5525d8cSshatty	if (itr == outputs.end()) {
569d5525d8cSshatty		// we don't have that output
570d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
571d5525d8cSshatty		return B_MEDIA_BAD_SOURCE;
572d5525d8cSshatty	}
573d5525d8cSshatty	return itr->SetBufferGroup(group);
574d5525d8cSshatty}
575d5525d8cSshatty
576d5525d8cSshatty	/* Format of clipping is (as int16-s): <from line> <npairs> <startclip> <endclip>. */
577d5525d8cSshatty	/* Repeat for each line where the clipping is different from the previous line. */
578d5525d8cSshatty	/* If <npairs> is negative, use the data from line -<npairs> (there are 0 pairs after */
579d5525d8cSshatty	/* a negative <npairs>. Yes, we only support 32k*32k frame buffers for clipping. */
580d5525d8cSshatty	/* Any non-0 field of 'display' means that that field changed, and if you don't support */
581d5525d8cSshatty	/* that change, you should return an error and ignore the request. Note that the buffer */
582d5525d8cSshatty	/* offset values do not have wildcards; 0 (or -1, or whatever) are real values and must */
583d5525d8cSshatty	/* be adhered to. */
584d5525d8cSshattystatus_t MediaDemultiplexerNode::VideoClippingChanged(
585d5525d8cSshatty				const media_source & for_source,
586d5525d8cSshatty				int16 num_shorts,
587d5525d8cSshatty				int16 * clip_data,
588d5525d8cSshatty				const media_video_display_info & display,
589d5525d8cSshatty				int32 * _deprecated_)
590d5525d8cSshatty{
591d5525d8cSshatty	return BBufferProducer::VideoClippingChanged(for_source,num_shorts,clip_data,display,_deprecated_);
592d5525d8cSshatty}
593d5525d8cSshatty
594d5525d8cSshattystatus_t MediaDemultiplexerNode::GetLatency(
595d5525d8cSshatty				bigtime_t * out_latency)
596d5525d8cSshatty{
597d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetLatency\n");
598d5525d8cSshatty	if (out_latency == 0) {
599d5525d8cSshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
600d5525d8cSshatty		return B_BAD_VALUE;
601d5525d8cSshatty	}
602d5525d8cSshatty	*out_latency = EventLatency() + SchedulingLatency();
603d5525d8cSshatty	return B_OK;
604d5525d8cSshatty}
605d5525d8cSshatty
606d5525d8cSshattystatus_t MediaDemultiplexerNode::PrepareToConnect(
607d5525d8cSshatty				const media_source & what,
608d5525d8cSshatty				const media_destination & where,
609d5525d8cSshatty				media_format * format,
610d5525d8cSshatty				media_source * out_source,
611d5525d8cSshatty				char * out_name)
612d5525d8cSshatty{
613d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::PrepareToConnect\n");
614d5525d8cSshatty	// find the information for this output
615d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
616d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
617728a8c74Sshatty		if (itr->output.source == what) {
618d5525d8cSshatty			break;
619d5525d8cSshatty		}
620d5525d8cSshatty	}
621d5525d8cSshatty	if (itr == outputs.end()) {
622d5525d8cSshatty		// we don't have that output
623d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
624d5525d8cSshatty		return B_MEDIA_BAD_SOURCE;
625d5525d8cSshatty	}
626728a8c74Sshatty	return itr->PrepareToConnect(where,format,out_source,out_name);
627d5525d8cSshatty}
628d5525d8cSshatty
629d5525d8cSshattyvoid MediaDemultiplexerNode::Connect(
630d5525d8cSshatty				status_t error,
631d5525d8cSshatty				const media_source & source,
632d5525d8cSshatty				const media_destination & destination,
633d5525d8cSshatty				const media_format & format,
634d5525d8cSshatty				char * io_name)
635d5525d8cSshatty{
636d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::Connect\n");
637d5525d8cSshatty	// find the information for this output
638d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
639d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
640d5525d8cSshatty		if (itr->output.source == source) {
641d5525d8cSshatty			break;
642d5525d8cSshatty		}
643d5525d8cSshatty	}
644d5525d8cSshatty	if (itr == outputs.end()) {
645d5525d8cSshatty		// we don't have that output
646d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
647d5525d8cSshatty		return;
648d5525d8cSshatty	}
649728a8c74Sshatty	if (error != B_OK) {
650728a8c74Sshatty		fprintf(stderr,"<- error already\n");
651728a8c74Sshatty		itr->output.destination = media_destination::null;
652728a8c74Sshatty		itr->output.format = itr->generalFormat;
653728a8c74Sshatty		return;
654728a8c74Sshatty	}
655728a8c74Sshatty
656728a8c74Sshatty	// calculate the downstream latency
657728a8c74Sshatty	// must happen before itr->Connect
658728a8c74Sshatty	bigtime_t downstreamLatency;
659728a8c74Sshatty	media_node_id id;
660728a8c74Sshatty	FindLatencyFor(itr->output.destination, &downstreamLatency, &id);
661728a8c74Sshatty
662d5525d8cSshatty	// record the agreed upon values
663d5525d8cSshatty	status_t status;
664728a8c74Sshatty	status = itr->Connect(destination,format,io_name,downstreamLatency);
665d5525d8cSshatty	if (status != B_OK) {
666d5525d8cSshatty		fprintf(stderr,"  itr->Connect returned an error\n");
667d5525d8cSshatty		return;
668d5525d8cSshatty	}
669d5525d8cSshatty
670728a8c74Sshatty	// compute the internal latency
671728a8c74Sshatty	// must happen after itr->Connect
672728a8c74Sshatty	if (fInternalLatency == 0) {
673728a8c74Sshatty		fInternalLatency = 100; // temporary until we finish computing it
674728a8c74Sshatty		ComputeInternalLatency();
675d5525d8cSshatty	}
676d5525d8cSshatty
677d5525d8cSshatty	// If the downstream latency for this output is larger
678d5525d8cSshatty	// than our current downstream latency, we have to increase
679d5525d8cSshatty	// our current downstream latency to be the larger value.
680728a8c74Sshatty	if (downstreamLatency > fDownstreamLatency) {
681d5525d8cSshatty		SetEventLatency(fDownstreamLatency + fInternalLatency);
682d5525d8cSshatty	}
683728a8c74Sshatty
684728a8c74Sshatty	// XXX: what do I set the buffer duration to?
685728a8c74Sshatty	//      it depends on which output is sending!!
686728a8c74Sshatty	// SetBufferDuration(bufferPeriod);
687d5525d8cSshatty
688d5525d8cSshatty	// XXX: do anything else?
689728a8c74Sshatty	return;
690728a8c74Sshatty}
691728a8c74Sshatty
692728a8c74Sshattyvoid MediaDemultiplexerNode::ComputeInternalLatency() {
693728a8c74Sshatty	fprintf(stderr,"MediaDemultiplexerNode::ComputeInternalLatency\n");
694728a8c74Sshatty//	if (GetCurrentFile() != 0) {
695728a8c74Sshatty//		bigtime_t start, end;
696728a8c74Sshatty//		uint8 * data = new uint8[output.format.u.multistream.max_chunk_size]; // <- buffer group buffer size
697728a8c74Sshatty//		BBuffer * buffer = 0;
698728a8c74Sshatty//		ssize_t bytesRead = 0;
699728a8c74Sshatty//		{ // timed section
700728a8c74Sshatty//			start = TimeSource()->RealTime();
701728a8c74Sshatty//			// first we try to use a real BBuffer
702728a8c74Sshatty//			buffer = fBufferGroup->RequestBuffer(output.format.u.multistream.max_chunk_size,fBufferPeriod);
703728a8c74Sshatty//			if (buffer != 0) {
704728a8c74Sshatty//				FillFileBuffer(buffer);
705728a8c74Sshatty//			} else {
706728a8c74Sshatty//				// didn't get a real BBuffer, try simulation by just a read from the disk
707728a8c74Sshatty//				bytesRead = GetCurrentFile()->Read(data,output.format.u.multistream.max_chunk_size);
708728a8c74Sshatty//			}
709728a8c74Sshatty//			end = TimeSource()->RealTime();
710728a8c74Sshatty//		}
711728a8c74Sshatty//		bytesRead = buffer->SizeUsed();
712728a8c74Sshatty//		delete data;
713728a8c74Sshatty//		if (buffer != 0) {
714728a8c74Sshatty//			buffer->Recycle();
715728a8c74Sshatty//		}
716728a8c74Sshatty//		GetCurrentFile()->Seek(-bytesRead,SEEK_CUR); // put it back where we found it
717728a8c74Sshatty//
718728a8c74Sshatty//		fInternalLatency = end - start;
719728a8c74Sshatty//
720728a8c74Sshatty//		fprintf(stderr,"  internal latency from disk read = %lld\n",fInternalLatency);
721728a8c74Sshatty//	} else {
722728a8c74Sshatty		fInternalLatency = 100; // just guess
723728a8c74Sshatty		fprintf(stderr,"  internal latency guessed = %lld\n",fInternalLatency);
724728a8c74Sshatty//	}
725d5525d8cSshatty}
726d5525d8cSshatty
727d5525d8cSshattyvoid MediaDemultiplexerNode::Disconnect(
728d5525d8cSshatty				const media_source & what,
729d5525d8cSshatty				const media_destination & where)
730d5525d8cSshatty{
731d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::Disconnect\n");
732d5525d8cSshatty	// find the information for this output
733d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
734d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
735d5525d8cSshatty		if (itr->output.source == what) {
736d5525d8cSshatty			break;
737d5525d8cSshatty		}
738d5525d8cSshatty	}
739d5525d8cSshatty	if (itr == outputs.end()) {
740d5525d8cSshatty		// we don't have that output
741d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
742d5525d8cSshatty		return;
743d5525d8cSshatty	}
744728a8c74Sshatty	if (itr->output.destination != where) {
745728a8c74Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
746728a8c74Sshatty		return;
747728a8c74Sshatty	}
748d5525d8cSshatty	// if this output has an equal (or higher!) latency than
749d5525d8cSshatty	// our current believed downstream latency, we may have to
750d5525d8cSshatty	// update our downstream latency.
751d5525d8cSshatty	bool updateDownstreamLatency = (itr->downstreamLatency >= fDownstreamLatency);
752d5525d8cSshatty	// disconnect this output
753d5525d8cSshatty	itr->Disconnect();
754d5525d8cSshatty	// update the downstream latency if necessary
755d5525d8cSshatty	if (updateDownstreamLatency) {
756d5525d8cSshatty		bigtime_t newDownstreamLatency = 0;
757d5525d8cSshatty		for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
758d5525d8cSshatty			if (itr->downstreamLatency > newDownstreamLatency) {
759d5525d8cSshatty				newDownstreamLatency = itr->downstreamLatency;
760d5525d8cSshatty			}
761d5525d8cSshatty		}
762d5525d8cSshatty		fDownstreamLatency = newDownstreamLatency;
763d5525d8cSshatty	}
764d5525d8cSshatty}
765d5525d8cSshatty
766d5525d8cSshattyvoid MediaDemultiplexerNode::LateNoticeReceived(
767d5525d8cSshatty				const media_source & what,
768d5525d8cSshatty				bigtime_t how_much,
769d5525d8cSshatty				bigtime_t performance_time)
770d5525d8cSshatty{
771d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::LateNoticeReceived\n");
772728a8c74Sshatty	vector<MediaOutputInfo>::iterator itr;
773728a8c74Sshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
774728a8c74Sshatty		if (itr->output.source == what) {
775728a8c74Sshatty			break;
776d5525d8cSshatty		}
777d5525d8cSshatty	}
778728a8c74Sshatty	if (itr == outputs.end()) {
779728a8c74Sshatty		// we don't have that output
780728a8c74Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
781728a8c74Sshatty		return;
782728a8c74Sshatty	}
783728a8c74Sshatty	switch (RunMode()) {
784728a8c74Sshatty		case B_OFFLINE:
785728a8c74Sshatty		    // nothing to do
786728a8c74Sshatty			break;
787728a8c74Sshatty		case B_RECORDING:
788728a8c74Sshatty		    // nothing to do
789728a8c74Sshatty			break;
790728a8c74Sshatty		case B_INCREASE_LATENCY:
791728a8c74Sshatty			fInternalLatency += how_much;
792728a8c74Sshatty			SetEventLatency(fDownstreamLatency + fInternalLatency);
793728a8c74Sshatty			break;
794728a8c74Sshatty		case B_DECREASE_PRECISION:
795728a8c74Sshatty			// XXX: try to catch up by producing buffers faster
796728a8c74Sshatty			break;
797728a8c74Sshatty		case B_DROP_DATA:
798728a8c74Sshatty			// XXX: should we really drop buffers?  just for that output?
799728a8c74Sshatty			break;
800728a8c74Sshatty		default:
801728a8c74Sshatty			// huh?? there aren't any more run modes.
802728a8c74Sshatty			fprintf(stderr,"MediaDemultiplexerNode::LateNoticeReceived with unexpected run mode.\n");
803728a8c74Sshatty			break;
804728a8c74Sshatty	}
805d5525d8cSshatty}
806d5525d8cSshatty
807d5525d8cSshattyvoid MediaDemultiplexerNode::EnableOutput(
808d5525d8cSshatty				const media_source & what,
809d5525d8cSshatty				bool enabled,
810d5525d8cSshatty				int32 * _deprecated_)
811d5525d8cSshatty{
812d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::EnableOutput\n");
813d5525d8cSshatty	// find the information for this output
814d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
815d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
816d5525d8cSshatty		if (itr->output.source == what) {
817d5525d8cSshatty			break;
818d5525d8cSshatty		}
819d5525d8cSshatty	}
820d5525d8cSshatty	if (itr == outputs.end()) {
821d5525d8cSshatty		// we don't have that output
822d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
823d5525d8cSshatty		return;
824d5525d8cSshatty	}
825d5525d8cSshatty	status_t status = itr->EnableOutput(enabled);
826d5525d8cSshatty	if (status != B_OK) {
827d5525d8cSshatty		fprintf(stderr,"  error in itr->EnableOutput\n");
828d5525d8cSshatty		return;
829d5525d8cSshatty	}
830d5525d8cSshatty	return;
831d5525d8cSshatty}
832d5525d8cSshatty
833d5525d8cSshattystatus_t MediaDemultiplexerNode::SetPlayRate(
834d5525d8cSshatty				int32 numer,
835d5525d8cSshatty				int32 denom)
836d5525d8cSshatty{
837d5525d8cSshatty	BBufferProducer::SetPlayRate(numer,denom); // XXX: do something intelligent later
838d5525d8cSshatty}
839d5525d8cSshatty
840d5525d8cSshattyvoid MediaDemultiplexerNode::AdditionalBufferRequested(			//	used to be Reserved 0
841d5525d8cSshatty				const media_source & source,
842d5525d8cSshatty				media_buffer_id prev_buffer,
843d5525d8cSshatty				bigtime_t prev_time,
844d5525d8cSshatty				const media_seek_tag * prev_tag)
845d5525d8cSshatty{
846d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::AdditionalBufferRequested\n");
847d5525d8cSshatty	// find the information for this output
848d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
849d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
850728a8c74Sshatty		if (itr->output.source == source) {
851d5525d8cSshatty			break;
852d5525d8cSshatty		}
853d5525d8cSshatty	}
854d5525d8cSshatty	if (itr == outputs.end()) {
855d5525d8cSshatty		// we don't have that output
856d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
857d5525d8cSshatty		return;
858d5525d8cSshatty	}
859d5525d8cSshatty	BBuffer * buffer;
860728a8c74Sshatty	status_t status = itr->AdditionalBufferRequested(prev_buffer,prev_time,prev_tag);
861d5525d8cSshatty	if (status != B_OK) {
862728a8c74Sshatty		fprintf(stderr,"  itr->AdditionalBufferRequested returned an error.\n");
863728a8c74Sshatty		return;
864d5525d8cSshatty	}
865d5525d8cSshatty	return;
866d5525d8cSshatty}
867d5525d8cSshatty
868d5525d8cSshattyvoid MediaDemultiplexerNode::LatencyChanged(
869d5525d8cSshatty				const media_source & source,
870d5525d8cSshatty				const media_destination & destination,
871d5525d8cSshatty				bigtime_t new_latency,
872d5525d8cSshatty				uint32 flags)
873d5525d8cSshatty{
874d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::LatencyChanged\n");
875d5525d8cSshatty	// find the information for this output
876d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
877d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
878d5525d8cSshatty		if (itr->output.source == source) {
879d5525d8cSshatty			break;
880d5525d8cSshatty		}
881d5525d8cSshatty	}
882d5525d8cSshatty	if (itr == outputs.end()) {
883d5525d8cSshatty		// we don't have that output
884d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
885d5525d8cSshatty		return;
886d5525d8cSshatty	}
887d5525d8cSshatty	if (itr->output.destination != destination) {
888d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
889d5525d8cSshatty		return;
890d5525d8cSshatty	}
891d5525d8cSshatty	fDownstreamLatency = new_latency;
892d5525d8cSshatty	SetEventLatency(fDownstreamLatency + fInternalLatency);
893d5525d8cSshatty	// XXX: we may have to recompute the number of buffers that we are using
894d5525d8cSshatty	// see SetBufferGroup
895d5525d8cSshatty}
896d5525d8cSshatty
897d5525d8cSshatty// -------------------------------------------------------- //
898d5525d8cSshatty// implementation for BMediaEventLooper
899d5525d8cSshatty// -------------------------------------------------------- //
900d5525d8cSshatty
901d5525d8cSshattyvoid MediaDemultiplexerNode::HandleEvent(
902d5525d8cSshatty				const media_timed_event *event,
903d5525d8cSshatty				bigtime_t lateness,
904d5525d8cSshatty				bool realTimeEvent = false)
905d5525d8cSshatty{
906d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleEvent\n");
907d5525d8cSshatty	switch (event->type) {
908d5525d8cSshatty		case BTimedEventQueue::B_START:
909d5525d8cSshatty			HandleStart(event,lateness,realTimeEvent);
910d5525d8cSshatty			break;
911d5525d8cSshatty		case BTimedEventQueue::B_SEEK:
912d5525d8cSshatty			HandleSeek(event,lateness,realTimeEvent);
913d5525d8cSshatty			break;
914d5525d8cSshatty		case BTimedEventQueue::B_WARP:
915d5525d8cSshatty			HandleWarp(event,lateness,realTimeEvent);
916d5525d8cSshatty			break;
917d5525d8cSshatty		case BTimedEventQueue::B_STOP:
918d5525d8cSshatty			HandleStop(event,lateness,realTimeEvent);
919d5525d8cSshatty			break;
920d5525d8cSshatty		case BTimedEventQueue::B_HANDLE_BUFFER:
921d5525d8cSshatty			if (RunState() == BMediaEventLooper::B_STARTED) {
922d5525d8cSshatty				HandleBuffer(event,lateness,realTimeEvent);
923d5525d8cSshatty			}
924d5525d8cSshatty			break;
925d5525d8cSshatty		case BTimedEventQueue::B_DATA_STATUS:
926d5525d8cSshatty			HandleDataStatus(event,lateness,realTimeEvent);
927d5525d8cSshatty			break;
928d5525d8cSshatty		case BTimedEventQueue::B_PARAMETER:
929d5525d8cSshatty			HandleParameter(event,lateness,realTimeEvent);
930d5525d8cSshatty			break;
931d5525d8cSshatty		default:
932d5525d8cSshatty			fprintf(stderr,"  unknown event type: %i\n",event->type);
933d5525d8cSshatty			break;
934d5525d8cSshatty	}
935d5525d8cSshatty}
936d5525d8cSshatty
937d5525d8cSshatty/* override to clean up custom events you have added to your queue */
938d5525d8cSshattyvoid MediaDemultiplexerNode::CleanUpEvent(
939d5525d8cSshatty				const media_timed_event *event)
940d5525d8cSshatty{
941d5525d8cSshatty	BMediaEventLooper::CleanUpEvent(event);
942d5525d8cSshatty}
943d5525d8cSshatty
944d5525d8cSshatty/* called from Offline mode to determine the current time of the node */
945d5525d8cSshatty/* update your internal information whenever it changes */
946d5525d8cSshattybigtime_t MediaDemultiplexerNode::OfflineTime()
947d5525d8cSshatty{
948d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::OfflineTime\n");
949d5525d8cSshatty	return BMediaEventLooper::OfflineTime();
950d5525d8cSshatty// XXX: do something else?
951d5525d8cSshatty}
952d5525d8cSshatty
953d5525d8cSshatty/* override only if you know what you are doing! */
954d5525d8cSshatty/* otherwise much badness could occur */
955d5525d8cSshatty/* the actual control loop function: */
956d5525d8cSshatty/* 	waits for messages, Pops events off the queue and calls DispatchEvent */
957d5525d8cSshattyvoid MediaDemultiplexerNode::ControlLoop() {
958d5525d8cSshatty	BMediaEventLooper::ControlLoop();
959d5525d8cSshatty}
960d5525d8cSshatty
961d5525d8cSshatty// protected:
962d5525d8cSshatty
963d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleStart(
964d5525d8cSshatty						const media_timed_event *event,
965d5525d8cSshatty						bigtime_t lateness,
966d5525d8cSshatty						bool realTimeEvent = false)
967d5525d8cSshatty{
968d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleStart()\n");
969d5525d8cSshatty	if (RunState() != B_STARTED) {
970d5525d8cSshatty// XXX: Either use the following line or the lines that are not commented.
971d5525d8cSshatty// There doesn't seem to be a practical difference that i can tell.
972d5525d8cSshatty//		HandleBuffer(event,lateness,realTimeEvent);
973d5525d8cSshatty		media_timed_event firstBufferEvent(event->event_time, BTimedEventQueue::B_HANDLE_BUFFER);
974d5525d8cSshatty		HandleEvent(&firstBufferEvent, 0, false);
975d5525d8cSshatty		EventQueue()->AddEvent(firstBufferEvent);
976d5525d8cSshatty	}
977d5525d8cSshatty	return B_OK;
978d5525d8cSshatty}
979d5525d8cSshatty
980d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleSeek(
981d5525d8cSshatty						const media_timed_event *event,
982d5525d8cSshatty						bigtime_t lateness,
983d5525d8cSshatty						bool realTimeEvent = false)
984d5525d8cSshatty{
985d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleSeek(t=%lld,d=%i,bd=%lld)\n",event->event_time,event->data,event->bigdata);
986d5525d8cSshatty	return B_OK;
987d5525d8cSshatty}
988d5525d8cSshatty
989d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleWarp(
990d5525d8cSshatty						const media_timed_event *event,
991d5525d8cSshatty						bigtime_t lateness,
992d5525d8cSshatty						bool realTimeEvent = false)
993d5525d8cSshatty{
994d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleWarp\n");
995d5525d8cSshatty	return B_OK;
996d5525d8cSshatty}
997d5525d8cSshatty
998d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleStop(
999d5525d8cSshatty						const media_timed_event *event,
1000d5525d8cSshatty						bigtime_t lateness,
1001d5525d8cSshatty						bool realTimeEvent = false)
1002d5525d8cSshatty{
1003d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleStop\n");
1004d5525d8cSshatty	// flush the queue so downstreamers don't get any more
1005d5525d8cSshatty	EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
1006d5525d8cSshatty	return B_OK;
1007d5525d8cSshatty}
1008d5525d8cSshatty
1009d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleBuffer(
1010d5525d8cSshatty				const media_timed_event *event,
1011d5525d8cSshatty				bigtime_t lateness,
1012d5525d8cSshatty				bool realTimeEvent = false)
1013d5525d8cSshatty{
1014d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleBuffer\n");
1015d5525d8cSshatty	BBuffer * buffer = const_cast<BBuffer*>((BBuffer*)event->pointer);
1016d5525d8cSshatty	if (buffer == 0) {
1017d5525d8cSshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
1018d5525d8cSshatty		return B_BAD_VALUE;
1019d5525d8cSshatty	}
1020d5525d8cSshatty	if (buffer->Header()->destination != input.destination.id) {
1021d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
1022d5525d8cSshatty		return B_MEDIA_BAD_DESTINATION;
1023d5525d8cSshatty	}
1024d5525d8cSshatty	if (outputs.begin() == outputs.end()) {
1025d5525d8cSshatty		fprintf(stderr,"<- B_MEDIA_NOT_CONNECTED\n");
1026d5525d8cSshatty		return B_MEDIA_NOT_CONNECTED;
1027d5525d8cSshatty	}
1028d5525d8cSshatty	status_t status = B_OK;
1029d5525d8cSshatty	fprintf(stderr,"  XXX: HandleBuffer not yet implemented.\n");
1030d5525d8cSshatty	// we have to hand the buffer to the extractor
1031d5525d8cSshatty	// and then whenever we get a buffer for an output send it
1032d5525d8cSshatty	// to that particular output (assuming it exists and is enabled)
1033d5525d8cSshatty//	BBuffer * buffer = fBufferGroup->RequestBuffer(output.format.u.multistream.max_chunk_size,fBufferPeriod);
1034d5525d8cSshatty//	if (buffer != 0) {
1035d5525d8cSshatty//	    status = FillFileBuffer(buffer);
1036d5525d8cSshatty//	    if (status != B_OK) {
1037d5525d8cSshatty//			fprintf(stderr,"MediaDemultiplexerNode::HandleEvent got an error from FillFileBuffer.\n");
1038d5525d8cSshatty//			buffer->Recycle();
1039d5525d8cSshatty//		} else {
1040d5525d8cSshatty//			if (fOutputEnabled) {
1041d5525d8cSshatty//				status = SendBuffer(buffer,output.destination);
1042d5525d8cSshatty//				if (status != B_OK) {
1043d5525d8cSshatty//					fprintf(stderr,"MediaDemultiplexerNode::HandleEvent got an error from SendBuffer.\n");
1044d5525d8cSshatty//					buffer->Recycle();
1045d5525d8cSshatty//				}
1046d5525d8cSshatty//			} else {
1047d5525d8cSshatty				buffer->Recycle();
1048d5525d8cSshatty//			}
1049d5525d8cSshatty//		}
1050d5525d8cSshatty//	}
1051728a8c74Sshatty	bigtime_t nextEventTime = event->event_time+10000; // fBufferPeriod; // XXX : should multiply
1052d5525d8cSshatty	media_timed_event nextBufferEvent(nextEventTime, BTimedEventQueue::B_HANDLE_BUFFER);
1053d5525d8cSshatty	EventQueue()->AddEvent(nextBufferEvent);
1054d5525d8cSshatty	return status;
1055d5525d8cSshatty}
1056d5525d8cSshatty
1057d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleDataStatus(
1058d5525d8cSshatty						const media_timed_event *event,
1059d5525d8cSshatty						bigtime_t lateness,
1060d5525d8cSshatty						bool realTimeEvent = false)
1061d5525d8cSshatty{
1062d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleDataStatus");
1063d5525d8cSshatty	// find the information for this output
1064d5525d8cSshatty	vector<MediaOutputInfo>::iterator itr;
1065d5525d8cSshatty	for(itr = outputs.begin() ; (itr != outputs.end()) ; itr++) {
1066d5525d8cSshatty		SendDataStatus(event->data,itr->output.destination,event->event_time);
1067d5525d8cSshatty	}
1068d5525d8cSshatty	return B_OK;
1069d5525d8cSshatty}
1070d5525d8cSshatty
1071d5525d8cSshattystatus_t MediaDemultiplexerNode::HandleParameter(
1072d5525d8cSshatty				const media_timed_event *event,
1073d5525d8cSshatty				bigtime_t lateness,
1074d5525d8cSshatty				bool realTimeEvent = false)
1075d5525d8cSshatty{
1076d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::HandleParameter");
1077d5525d8cSshatty	return B_OK;
1078d5525d8cSshatty}
1079d5525d8cSshatty
1080d5525d8cSshatty// -------------------------------------------------------- //
1081d5525d8cSshatty// MediaDemultiplexerNode specific functions
1082d5525d8cSshatty// -------------------------------------------------------- //
1083d5525d8cSshatty
1084d5525d8cSshatty// public:
1085d5525d8cSshatty
1086d5525d8cSshattyvoid MediaDemultiplexerNode::GetFlavor(flavor_info * outInfo, int32 id)
1087d5525d8cSshatty{
1088d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetFlavor\n");
1089d5525d8cSshatty	if (outInfo == 0) {
1090d5525d8cSshatty		return;
1091d5525d8cSshatty	}
1092d5525d8cSshatty	outInfo->name = "OpenBeOS Demultiplexer";
1093d5525d8cSshatty	outInfo->info = "A MediaDemultiplexerNode node demultiplexes a multistream into its constituent streams.";
1094d5525d8cSshatty	outInfo->kinds = B_BUFFER_CONSUMER | B_BUFFER_PRODUCER;
1095d5525d8cSshatty	outInfo->flavor_flags = B_FLAVOR_IS_LOCAL;
1096d5525d8cSshatty	outInfo->possible_count = INT_MAX;
1097d5525d8cSshatty	outInfo->in_format_count = 1; // 1 input
1098d5525d8cSshatty	media_format * inFormats = new media_format[outInfo->in_format_count];
1099d5525d8cSshatty	GetInputFormat(&inFormats[0]);
1100d5525d8cSshatty	outInfo->in_formats = inFormats;
1101d5525d8cSshatty	outInfo->out_format_count = 1; // 1 output
1102d5525d8cSshatty	media_format * outFormats = new media_format[outInfo->out_format_count];
1103d5525d8cSshatty	GetOutputFormat(&outFormats[0]);
1104d5525d8cSshatty	outInfo->out_formats = outFormats;
1105d5525d8cSshatty	outInfo->internal_id = id;
1106d5525d8cSshatty	return;
1107d5525d8cSshatty}
1108d5525d8cSshatty
1109d5525d8cSshattyvoid MediaDemultiplexerNode::GetInputFormat(media_format * outFormat)
1110d5525d8cSshatty{
1111d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetInputFormat\n");
1112d5525d8cSshatty	if (outFormat == 0) {
1113d5525d8cSshatty		return;
1114d5525d8cSshatty	}
1115d5525d8cSshatty	outFormat->type = B_MEDIA_MULTISTREAM;
1116d5525d8cSshatty	outFormat->require_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
1117d5525d8cSshatty	outFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
1118d5525d8cSshatty	outFormat->u.multistream = media_multistream_format::wildcard;
1119d5525d8cSshatty}
1120d5525d8cSshatty
1121d5525d8cSshattyvoid MediaDemultiplexerNode::GetOutputFormat(media_format * outFormat)
1122d5525d8cSshatty{
1123d5525d8cSshatty	fprintf(stderr,"MediaDemultiplexerNode::GetOutputFormat\n");
1124d5525d8cSshatty	if (outFormat == 0) {
1125d5525d8cSshatty		return;
1126d5525d8cSshatty	}
1127