1820c41b9Sshatty// MediaReader.cpp
2820c41b9Sshatty//
3820c41b9Sshatty// Andrew Bachmann, 2002
4820c41b9Sshatty//
5820c41b9Sshatty// A MediaReader is a node that
6820c41b9Sshatty// implements FileInterface and BBufferProducer.
7820c41b9Sshatty// It reads any file and produces one output,
8820c41b9Sshatty// which is a multistream.
9820c41b9Sshatty//
10820c41b9Sshatty// see also MediaReaderAddOn.cpp
11fb16552fSMaurice Kalinowski#include "../AbstractFileInterfaceNode.h"
12fb16552fSMaurice Kalinowski#include "MediaReader.h"
1330456a32SDario Casalinuovo#include "../misc.h"
14fb16552fSMaurice Kalinowski#include "debug.h"
15820c41b9Sshatty
16fb16552fSMaurice Kalinowski#include <Buffer.h>
17fb16552fSMaurice Kalinowski#include <BufferGroup.h>
18820c41b9Sshatty#include <BufferProducer.h>
19820c41b9Sshatty#include <Controllable.h>
20820c41b9Sshatty#include <Entry.h>
21fb16552fSMaurice Kalinowski#include <Errors.h>
22fb16552fSMaurice Kalinowski#include <File.h>
23fb16552fSMaurice Kalinowski#include <FileInterface.h>
24fb16552fSMaurice Kalinowski#include <MediaAddOn.h>
25fb16552fSMaurice Kalinowski#include <MediaDefs.h>
26fb16552fSMaurice Kalinowski#include <MediaEventLooper.h>
27fb16552fSMaurice Kalinowski#include <MediaNode.h>
284895a3a9Sshatty#include <MediaRoster.h>
29fb16552fSMaurice Kalinowski#include <ParameterWeb.h>
30fb16552fSMaurice Kalinowski#include <TimeSource.h>
31820c41b9Sshatty
32820c41b9Sshatty
33fb16552fSMaurice Kalinowski#include <limits.h>
34820c41b9Sshatty#include <stdio.h>
35820c41b9Sshatty#include <string.h>
36820c41b9Sshatty
37820c41b9Sshatty
38820c41b9SshattyMediaReader::~MediaReader(void)
39820c41b9Sshatty{
40820c41b9Sshatty	fprintf(stderr,"MediaReader::~MediaReader\n");
41794887f8Sshatty	if (fBufferGroup != 0) {
42794887f8Sshatty		BBufferGroup * group = fBufferGroup;
43794887f8Sshatty		fBufferGroup = 0;
44912d7a22Sshatty		delete group;
45912d7a22Sshatty	}
46820c41b9Sshatty}
47820c41b9Sshatty
48fb16552fSMaurice Kalinowski
49820c41b9SshattyMediaReader::MediaReader(
50fb16552fSMaurice Kalinowski				size_t defaultChunkSize,
51fb16552fSMaurice Kalinowski				float defaultBitRate,
52fb16552fSMaurice Kalinowski				const flavor_info * info,
53fb16552fSMaurice Kalinowski				BMessage * config,
54fb16552fSMaurice Kalinowski				BMediaAddOn * addOn)
55820c41b9Sshatty	: BMediaNode("MediaReader"),
56fb16552fSMaurice Kalinowski	  BBufferProducer(B_MEDIA_MULTISTREAM),
57fb16552fSMaurice Kalinowski	  AbstractFileInterfaceNode(defaultChunkSize, defaultBitRate, info, config, addOn)
58820c41b9Sshatty{
59fb16552fSMaurice Kalinowski	CALLED();
60fb16552fSMaurice Kalinowski
61820c41b9Sshatty	// null some fields
62794887f8Sshatty	fBufferGroup = 0;
63820c41b9Sshatty	// start enabled
64794887f8Sshatty	fOutputEnabled = true;
65820c41b9Sshatty	// don't overwrite available space, and be sure to terminate
66820c41b9Sshatty	strncpy(output.name,"MediaReader Output",B_MEDIA_NAME_LENGTH-1);
67820c41b9Sshatty	output.name[B_MEDIA_NAME_LENGTH-1] = '\0';
68820c41b9Sshatty	// initialize the output
69820c41b9Sshatty	output.node = media_node::null;     // until registration
70820c41b9Sshatty	output.source = media_source::null; // until registration
71820c41b9Sshatty	output.destination = media_destination::null;
7245ed7b19Sshatty	GetFormat(&output.format);
73820c41b9Sshatty}
74820c41b9Sshatty
75fb16552fSMaurice Kalinowski
76820c41b9Sshatty// -------------------------------------------------------- //
77820c41b9Sshatty// implementation of BMediaNode
78820c41b9Sshatty// -------------------------------------------------------- //
79820c41b9Sshattyvoid MediaReader::Preroll(void)
80820c41b9Sshatty{
81fb16552fSMaurice Kalinowski	CALLED();
82820c41b9Sshatty	// XXX:Performance opportunity
83820c41b9Sshatty	BMediaNode::Preroll();
84820c41b9Sshatty}
85820c41b9Sshatty
86fb16552fSMaurice Kalinowski
87820c41b9Sshattystatus_t MediaReader::HandleMessage(
88820c41b9Sshatty				int32 message,
89820c41b9Sshatty				const void * data,
90820c41b9Sshatty				size_t size)
91820c41b9Sshatty{
92fb16552fSMaurice Kalinowski	CALLED();
93fb16552fSMaurice Kalinowski
94820c41b9Sshatty	status_t status = B_OK;
95fb16552fSMaurice Kalinowski
96820c41b9Sshatty	switch (message) {
97794887f8Sshatty		// no special messages for now
98820c41b9Sshatty		default:
99820c41b9Sshatty			status = BBufferProducer::HandleMessage(message,data,size);
100820c41b9Sshatty			if (status == B_OK) {
101820c41b9Sshatty				break;
102820c41b9Sshatty			}
103794887f8Sshatty			status = AbstractFileInterfaceNode::HandleMessage(message,data,size);
104820c41b9Sshatty			break;
105820c41b9Sshatty	}
106fb16552fSMaurice Kalinowski
107820c41b9Sshatty	return status;
108820c41b9Sshatty}
109820c41b9Sshatty
110fb16552fSMaurice Kalinowski
111820c41b9Sshattyvoid MediaReader::NodeRegistered(void)
112820c41b9Sshatty{
113fb16552fSMaurice Kalinowski	CALLED();
114820c41b9Sshatty
115820c41b9Sshatty	// now we can do this
116820c41b9Sshatty	output.node = Node();
117820c41b9Sshatty	output.source.id = 0;
11839a0622eSshatty	output.source.port = output.node.port; // same as ControlPort();
119820c41b9Sshatty
120794887f8Sshatty	// creates the parameter web and starts the looper thread
121794887f8Sshatty	AbstractFileInterfaceNode::NodeRegistered();
122820c41b9Sshatty}
123820c41b9Sshatty
124fb16552fSMaurice Kalinowski
125820c41b9Sshatty// -------------------------------------------------------- //
126820c41b9Sshatty// implementation of BFileInterface
127820c41b9Sshatty// -------------------------------------------------------- //
128820c41b9Sshattystatus_t MediaReader::SetRef(
129820c41b9Sshatty				const entry_ref & file,
130820c41b9Sshatty				bool create,
131820c41b9Sshatty				bigtime_t * out_time)
132820c41b9Sshatty{
133fb16552fSMaurice Kalinowski	CALLED();
134fb16552fSMaurice Kalinowski
135794887f8Sshatty	status_t status = AbstractFileInterfaceNode::SetRef(file,B_READ_ONLY,create,out_time);
136820c41b9Sshatty	if (status != B_OK) {
137fb16552fSMaurice Kalinowski		PRINT("AbstractFileInterfaceNode::SetRef returned an error\n");
138820c41b9Sshatty		return status;
139820c41b9Sshatty	}
140fb16552fSMaurice Kalinowski
1414895a3a9Sshatty	if (output.destination == media_destination::null) {
1424895a3a9Sshatty		// reset the format, and set the requirements imposed by this file
1434895a3a9Sshatty		GetFormat(&output.format);
1444895a3a9Sshatty		AddRequirements(&output.format);
1454895a3a9Sshatty		return B_OK;
1464895a3a9Sshatty	}
147fb16552fSMaurice Kalinowski
1484895a3a9Sshatty	// if we are connected we may have to re-negotiate the connection
1494895a3a9Sshatty	media_format format;
1504895a3a9Sshatty	GetFormat(&format);
1514895a3a9Sshatty	AddRequirements(&format);
1524895a3a9Sshatty	if (format_is_acceptible(format,output.format)) {
1534895a3a9Sshatty		fprintf(stderr,"  compatible format = no re-negotiation necessary\n");
1544895a3a9Sshatty		return B_OK;
1554895a3a9Sshatty	}
1564895a3a9Sshatty	// first try the easy way : SORRY DEPRECATED into private :-(
1574895a3a9Sshatty	// this code from MediaWriter would be different for MediaReader even if it worked...
158fb16552fSMaurice Kalinowski	//	int32 change_tag = NewChangeTag();
159fb16552fSMaurice Kalinowski	//	status = this->BBufferConsumer::RequestFormatChange(output.source,output.destination,&format,&change_tag);
160fb16552fSMaurice Kalinowski	//	if (status == B_OK) {
161fb16552fSMaurice Kalinowski	//		fprintf(stderr,"  format change successful\n");
162fb16552fSMaurice Kalinowski	//		return B_OK;
163fb16552fSMaurice Kalinowski	//	}
164fb16552fSMaurice Kalinowski
1654895a3a9Sshatty	// okay, the hard way requires we get the MediaRoster
1664895a3a9Sshatty	BMediaRoster * roster = BMediaRoster::Roster(&status);
167fb16552fSMaurice Kalinowski	if (roster == 0)
1684895a3a9Sshatty		return B_MEDIA_SYSTEM_FAILURE;
169fb16552fSMaurice Kalinowski
170fb16552fSMaurice Kalinowski	if (status != B_OK)
1714895a3a9Sshatty		return status;
172fb16552fSMaurice Kalinowski
1734895a3a9Sshatty	// before disconnect one should always stop the nodes (bebook says)
1744895a3a9Sshatty	// requires run_state cast since the return type on RunState() is
1754895a3a9Sshatty	// wrong [int32]
1764895a3a9Sshatty	run_state destinationRunState = run_state(RunState());
177fb16552fSMaurice Kalinowski	if (destinationRunState == BMediaEventLooper::B_STARTED)
1784895a3a9Sshatty		Stop(0,true); // stop us right now
179fb16552fSMaurice Kalinowski
1804895a3a9Sshatty	// should also stop the destination if it is running, but how?
181fb16552fSMaurice Kalinowski	/*	BMediaNode destinationNode = ??
1824895a3a9Sshatty	run_state destinationRunState = destinationNode->??;
1834895a3a9Sshatty	status = destinationNode->StopNode(??,0,true);
1844895a3a9Sshatty	if (status != B_OK) {
1854895a3a9Sshatty		return status;
1864895a3a9Sshatty	}  */
1874895a3a9Sshatty	// we should disconnect right now
1884895a3a9Sshatty	media_destination outputDestination = output.destination;
1894895a3a9Sshatty	status = roster->Disconnect(output.source.id,output.source,
1904895a3a9Sshatty							    output.destination.id,output.destination);
191fb16552fSMaurice Kalinowski	if (status != B_OK)
1924895a3a9Sshatty		return status;
193fb16552fSMaurice Kalinowski
1944895a3a9Sshatty	// if that went okay, we'll try reconnecting
1954895a3a9Sshatty	media_output connectOutput;
1964895a3a9Sshatty	media_input connectInput;
1974895a3a9Sshatty	status = roster->Connect(output.source,outputDestination,
1984895a3a9Sshatty							 &format,&connectOutput,&connectInput);
199fb16552fSMaurice Kalinowski	if (status != B_OK)
2004895a3a9Sshatty		return status;
201fb16552fSMaurice Kalinowski
2024895a3a9Sshatty	// now restart if necessary
2034895a3a9Sshatty	if (destinationRunState == BMediaEventLooper::B_STARTED) {
2044895a3a9Sshatty		Start(0);
2054895a3a9Sshatty	}
2064895a3a9Sshatty	return status;
207820c41b9Sshatty}
208820c41b9Sshatty
209fb16552fSMaurice Kalinowski
210820c41b9Sshatty// -------------------------------------------------------- //
211820c41b9Sshatty// implemention of BBufferProducer
212820c41b9Sshatty// -------------------------------------------------------- //
213820c41b9Sshatty
214794887f8Sshatty// They are asking us to make the first offering.
215794887f8Sshatty// So, we get a fresh format and then add requirements based
216794887f8Sshatty// on the current file. (if any)
217820c41b9Sshattystatus_t MediaReader::FormatSuggestionRequested(
218820c41b9Sshatty				media_type type,
219820c41b9Sshatty				int32 quality,
220820c41b9Sshatty				media_format * format)
221820c41b9Sshatty{
222fb16552fSMaurice Kalinowski	CALLED();
223fb16552fSMaurice Kalinowski
224820c41b9Sshatty	if ((type != B_MEDIA_MULTISTREAM) && (type != B_MEDIA_UNKNOWN_TYPE)) {
225fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_FORMAT\n");
226820c41b9Sshatty		return B_MEDIA_BAD_FORMAT;
227820c41b9Sshatty	}
228fb16552fSMaurice Kalinowski
22945ed7b19Sshatty	GetFormat(format);
230794887f8Sshatty	AddRequirements(format);
231794887f8Sshatty	return B_OK;
232820c41b9Sshatty}
233820c41b9Sshatty
234fb16552fSMaurice Kalinowski
235794887f8Sshatty// They made an offer to us.  We should make sure that the offer is
236794887f8Sshatty// acceptable, and then we can add any requirements we have on top of
237794887f8Sshatty// that.  We leave wildcards for anything that we don't care about.
238820c41b9Sshattystatus_t MediaReader::FormatProposal(
239820c41b9Sshatty				const media_source & output_source,
240820c41b9Sshatty				media_format * format)
241820c41b9Sshatty{
242fb16552fSMaurice Kalinowski	CALLED();
243fb16552fSMaurice Kalinowski
244820c41b9Sshatty	if (output.source != output_source) {
245fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
246820c41b9Sshatty		return B_MEDIA_BAD_SOURCE; // we only have one output so that better be it
247820c41b9Sshatty	}
248fb16552fSMaurice Kalinowski	/*	media_format * myFormat = GetFormat();
249794887f8Sshatty	fprintf(stderr,"proposed format: ");
250794887f8Sshatty	print_media_format(format);
251794887f8Sshatty	fprintf(stderr,"\n");
252794887f8Sshatty	fprintf(stderr,"my format: ");
253794887f8Sshatty	print_media_format(myFormat);
254794887f8Sshatty	fprintf(stderr,"\n"); */
255794887f8Sshatty	// Be's format_is_compatible doesn't work.
256fb16552fSMaurice Kalinowski	//	if (!format_is_compatible(*format,*myFormat)) {
25745ed7b19Sshatty	media_format myFormat;
25845ed7b19Sshatty	GetFormat(&myFormat);
25945ed7b19Sshatty	if (!format_is_acceptible(*format,myFormat)) {
260fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_FORMAT\n");
261820c41b9Sshatty		return B_MEDIA_BAD_FORMAT;
262820c41b9Sshatty	}
263794887f8Sshatty	AddRequirements(format);
264820c41b9Sshatty	return B_OK;
265820c41b9Sshatty}
266820c41b9Sshatty
267fb16552fSMaurice Kalinowski
268794887f8Sshatty// Presumably we have already agreed with them that this format is
269794887f8Sshatty// okay.  But just in case, we check the offer. (and complain if it
270794887f8Sshatty// is invalid)  Then as the last thing we do, we get rid of any
271794887f8Sshatty// remaining wilcards.
272820c41b9Sshattystatus_t MediaReader::FormatChangeRequested(
273820c41b9Sshatty				const media_source & source,
274820c41b9Sshatty				const media_destination & destination,
275820c41b9Sshatty				media_format * io_format,
276820c41b9Sshatty				int32 * _deprecated_)
277820c41b9Sshatty{
278fb16552fSMaurice Kalinowski	CALLED();
279fb16552fSMaurice Kalinowski
280794887f8Sshatty	if (output.source != source) {
281fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
282794887f8Sshatty		return B_MEDIA_BAD_SOURCE;
283794887f8Sshatty	}
284820c41b9Sshatty	status_t status = FormatProposal(source,io_format);
285794887f8Sshatty	if (status != B_OK) {
286fb16552fSMaurice Kalinowski		PRINT("\terror returned by FormatProposal\n");
28745ed7b19Sshatty		GetFormat(io_format);
288794887f8Sshatty		return status;
289820c41b9Sshatty	}
290fb16552fSMaurice Kalinowski
291794887f8Sshatty	return ResolveWildcards(io_format);
292820c41b9Sshatty}
293820c41b9Sshatty
294fb16552fSMaurice Kalinowski
295820c41b9Sshattystatus_t MediaReader::GetNextOutput(	/* cookie starts as 0 */
296820c41b9Sshatty				int32 * cookie,
297820c41b9Sshatty				media_output * out_output)
298820c41b9Sshatty{
299fb16552fSMaurice Kalinowski	CALLED();
300fb16552fSMaurice Kalinowski
301bcf291edSMarcus Overhagen	if (*cookie != 0) {
302bcf291edSMarcus Overhagen		PRINT("\t<- B_ERROR (no more outputs)\n");
303bcf291edSMarcus Overhagen		return B_ERROR;
304820c41b9Sshatty	}
305bcf291edSMarcus Overhagen
306bcf291edSMarcus Overhagen	// so next time they won't get the same output again
307bcf291edSMarcus Overhagen	*cookie = 1;
308820c41b9Sshatty	*out_output = output;
309820c41b9Sshatty	return B_OK;
310820c41b9Sshatty}
311820c41b9Sshatty
312fb16552fSMaurice Kalinowski
313820c41b9Sshattystatus_t MediaReader::DisposeOutputCookie(
314820c41b9Sshatty				int32 cookie)
315820c41b9Sshatty{
316fb16552fSMaurice Kalinowski	CALLED();
317820c41b9Sshatty	// nothing to do since our cookies are just integers
318820c41b9Sshatty	return B_OK;
319820c41b9Sshatty}
320820c41b9Sshatty
321fb16552fSMaurice Kalinowski
322820c41b9Sshattystatus_t MediaReader::SetBufferGroup(
323820c41b9Sshatty				const media_source & for_source,
324820c41b9Sshatty				BBufferGroup * group)
325820c41b9Sshatty{
326fb16552fSMaurice Kalinowski	CALLED();
327fb16552fSMaurice Kalinowski
328820c41b9Sshatty	if (output.source != for_source) {
329fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
330820c41b9Sshatty		return B_MEDIA_BAD_SOURCE; // we only have one output so that better be it
331820c41b9Sshatty	}
332794887f8Sshatty	if (fBufferGroup != 0) {
333fb16552fSMaurice Kalinowski		if (fBufferGroup == group)
334820c41b9Sshatty			return B_OK; // time saver
335794887f8Sshatty		delete fBufferGroup;
336820c41b9Sshatty	}
337820c41b9Sshatty	if (group != 0) {
338794887f8Sshatty		fBufferGroup = group;
339820c41b9Sshatty	} else {
340820c41b9Sshatty		// let's take advantage of this opportunity to recalculate
341820c41b9Sshatty		// our downstream latency and ensure that it is up to date
342820c41b9Sshatty		media_node_id id;
343794887f8Sshatty		FindLatencyFor(output.destination, &fDownstreamLatency, &id);
344820c41b9Sshatty		// buffer period gets initialized in Connect() because
345820c41b9Sshatty		// that is the first time we get the real values for
346820c41b9Sshatty		// chunk size and bit rate, which are used to compute buffer period
347820c41b9Sshatty		// note: you can still make a buffer group before connecting (why?)
348820c41b9Sshatty		//       but we don't make it, you make it yourself and pass it here.
349820c41b9Sshatty		//       not sure why anybody would want to do that since they need
350820c41b9Sshatty		//       a connection anyway...
351794887f8Sshatty		if (fBufferPeriod <= 0) {
352820c41b9Sshatty			fprintf(stderr,"<- B_NO_INIT");
353820c41b9Sshatty			return B_NO_INIT;
354820c41b9Sshatty		}
355794887f8Sshatty		int32 count = int32(fDownstreamLatency/fBufferPeriod)+2;
356fb16552fSMaurice Kalinowski		PRINT("\tdownstream latency = %lld, buffer period = %lld, buffer count = %ld\n",
357fb16552fSMaurice Kalinowski				fDownstreamLatency, fBufferPeriod, count);
35839a0622eSshatty
359820c41b9Sshatty		// allocate the buffers
360794887f8Sshatty		fBufferGroup = new BBufferGroup(output.format.u.multistream.max_chunk_size,count);
361794887f8Sshatty		if (fBufferGroup == 0) {
362fb16552fSMaurice Kalinowski			PRINT("\t<- B_NO_MEMORY\n");
363820c41b9Sshatty			return B_NO_MEMORY;
364820c41b9Sshatty		}
365794887f8Sshatty		status_t status = fBufferGroup->InitCheck();
366820c41b9Sshatty		if (status != B_OK) {
367fb16552fSMaurice Kalinowski			PRINT("\t<- fBufferGroup initialization failed\n");
368820c41b9Sshatty			return status;
369820c41b9Sshatty		}
370820c41b9Sshatty	}
371820c41b9Sshatty	return B_OK;
372820c41b9Sshatty}
373820c41b9Sshatty
374fb16552fSMaurice Kalinowski
375fb16552fSMaurice Kalinowski/* Format of clipping is (as int16-s): <from line> <npairs> <startclip> <endclip>. */
376fb16552fSMaurice Kalinowski/* Repeat for each line where the clipping is different from the previous line. */
377fb16552fSMaurice Kalinowski/* If <npairs> is negative, use the data from line -<npairs> (there are 0 pairs after */
378fb16552fSMaurice Kalinowski/* a negative <npairs>. Yes, we only support 32k*32k frame buffers for clipping. */
379fb16552fSMaurice Kalinowski/* Any non-0 field of 'display' means that that field changed, and if you don't support */
380fb16552fSMaurice Kalinowski/* that change, you should return an error and ignore the request. Note that the buffer */
381fb16552fSMaurice Kalinowski/* offset values do not have wildcards; 0 (or -1, or whatever) are real values and must */
382fb16552fSMaurice Kalinowski/* be adhered to. */
383820c41b9Sshattystatus_t MediaReader::VideoClippingChanged(
384820c41b9Sshatty				const media_source & for_source,
385820c41b9Sshatty				int16 num_shorts,
386820c41b9Sshatty				int16 * clip_data,
387820c41b9Sshatty				const media_video_display_info & display,
388820c41b9Sshatty				int32 * _deprecated_)
389820c41b9Sshatty{
390820c41b9Sshatty	return BBufferProducer::VideoClippingChanged(for_source,num_shorts,clip_data,display,_deprecated_);
391820c41b9Sshatty}
392820c41b9Sshatty
393fb16552fSMaurice Kalinowski
394820c41b9Sshattystatus_t MediaReader::GetLatency(
395820c41b9Sshatty				bigtime_t * out_latency)
396820c41b9Sshatty{
397fb16552fSMaurice Kalinowski	CALLED();
398fb16552fSMaurice Kalinowski
399820c41b9Sshatty	*out_latency = EventLatency() + SchedulingLatency();
400820c41b9Sshatty	return B_OK;
401820c41b9Sshatty}
402820c41b9Sshatty
403fb16552fSMaurice Kalinowski
404820c41b9Sshattystatus_t MediaReader::PrepareToConnect(
405820c41b9Sshatty				const media_source & what,
406820c41b9Sshatty				const media_destination & where,
407820c41b9Sshatty				media_format * format,
408820c41b9Sshatty				media_source * out_source,
409820c41b9Sshatty				char * out_name)
410820c41b9Sshatty{
411fb16552fSMaurice Kalinowski	CALLED();
412fb16552fSMaurice Kalinowski
413794887f8Sshatty	if (output.source != what) {
414fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
415794887f8Sshatty		return B_MEDIA_BAD_SOURCE;
416794887f8Sshatty	}
417820c41b9Sshatty	if (output.destination != media_destination::null) {
418fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_ALREADY_CONNECTED\n");
419820c41b9Sshatty		return B_MEDIA_ALREADY_CONNECTED;
420fb16552fSMaurice Kalinowski	}
421fb16552fSMaurice Kalinowski
422820c41b9Sshatty	status_t status = FormatChangeRequested(output.source,where,format,0);
423820c41b9Sshatty	if (status != B_OK) {
424fb16552fSMaurice Kalinowski		PRINT("\t<- MediaReader::FormatChangeRequested failed\n");
425820c41b9Sshatty		return status;
426820c41b9Sshatty	}
427fb16552fSMaurice Kalinowski
428820c41b9Sshatty	// last check for wildcards and general validity
429820c41b9Sshatty	if (format->type != B_MEDIA_MULTISTREAM) {
430fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_FORMAT\n");
431820c41b9Sshatty		return B_MEDIA_BAD_FORMAT;
432820c41b9Sshatty	}
433fb16552fSMaurice Kalinowski
434820c41b9Sshatty	*out_source = output.source;
435820c41b9Sshatty	output.destination = where;
436820c41b9Sshatty	strncpy(out_name,output.name,B_MEDIA_NAME_LENGTH-1);
437820c41b9Sshatty	out_name[B_MEDIA_NAME_LENGTH] = '\0';
438794887f8Sshatty	return ResolveWildcards(format);
439820c41b9Sshatty}
440820c41b9Sshatty
441fb16552fSMaurice Kalinowski
442820c41b9Sshattyvoid MediaReader::Connect(
443820c41b9Sshatty				status_t error,
444820c41b9Sshatty				const media_source & source,
445820c41b9Sshatty				const media_destination & destination,
446820c41b9Sshatty				const media_format & format,
447820c41b9Sshatty				char * io_name)
448820c41b9Sshatty{
449fb16552fSMaurice Kalinowski	CALLED();
450fb16552fSMaurice Kalinowski
451820c41b9Sshatty	if (error != B_OK) {
452fb16552fSMaurice Kalinowski		PRINT("\t<- error already\n");
453820c41b9Sshatty		output.destination = media_destination::null;
45445ed7b19Sshatty		GetFormat(&output.format);
455820c41b9Sshatty		return;
456820c41b9Sshatty	}
457794887f8Sshatty	if (output.source != source) {
458fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
459794887f8Sshatty		output.destination = media_destination::null;
46045ed7b19Sshatty		GetFormat(&output.format);
461794887f8Sshatty		return;
462794887f8Sshatty	}
463820c41b9Sshatty
464820c41b9Sshatty	// record the agreed upon values
465820c41b9Sshatty	output.destination = destination;
466820c41b9Sshatty	output.format = format;
467820c41b9Sshatty	strncpy(io_name,output.name,B_MEDIA_NAME_LENGTH-1);
46839a0622eSshatty	io_name[B_MEDIA_NAME_LENGTH-1] = '\0';
469820c41b9Sshatty
470820c41b9Sshatty	// determine our downstream latency
471820c41b9Sshatty	media_node_id id;
472794887f8Sshatty	FindLatencyFor(output.destination, &fDownstreamLatency, &id);
473820c41b9Sshatty
474820c41b9Sshatty	// compute the buffer period (must be done before setbuffergroup)
47544200efdSDario Casalinuovo	fBufferPeriod = bigtime_t(1000u * 8000000u / 1024u
476820c41b9Sshatty	                     * output.format.u.multistream.max_chunk_size
477820c41b9Sshatty			             / output.format.u.multistream.max_bit_rate);
478820c41b9Sshatty
479fb16552fSMaurice Kalinowski	PRINT("\tmax chunk size = %ld, max bit rate = %f, buffer period = %lld\n",
48039a0622eSshatty			output.format.u.multistream.max_chunk_size,
48139a0622eSshatty			output.format.u.multistream.max_bit_rate,fBufferPeriod);
48239a0622eSshatty
483820c41b9Sshatty	// setup the buffers if they aren't setup yet
484794887f8Sshatty	if (fBufferGroup == 0) {
485820c41b9Sshatty		status_t status = SetBufferGroup(output.source,0);
486820c41b9Sshatty		if (status != B_OK) {
487fb16552fSMaurice Kalinowski			PRINT("\t<- SetBufferGroup failed\n");
488794887f8Sshatty			output.destination = media_destination::null;
48945ed7b19Sshatty			GetFormat(&output.format);
490820c41b9Sshatty			return;
491820c41b9Sshatty		}
492820c41b9Sshatty	}
493fb16552fSMaurice Kalinowski
494794887f8Sshatty	SetBufferDuration(fBufferPeriod);
495fb16552fSMaurice Kalinowski
496794887f8Sshatty	if (GetCurrentFile() != 0) {
497820c41b9Sshatty		bigtime_t start, end;
498fb16552fSMaurice Kalinowski		// buffer group buffer size
499fb16552fSMaurice Kalinowski		uint8 * data = new uint8[output.format.u.multistream.max_chunk_size];
500820c41b9Sshatty		BBuffer * buffer = 0;
501820c41b9Sshatty		ssize_t bytesRead = 0;
502820c41b9Sshatty		{ // timed section
503820c41b9Sshatty			start = TimeSource()->RealTime();
504820c41b9Sshatty			// first we try to use a real BBuffer
505fb16552fSMaurice Kalinowski			buffer = fBufferGroup->RequestBuffer(
506fb16552fSMaurice Kalinowski					output.format.u.multistream.max_chunk_size,fBufferPeriod);
507820c41b9Sshatty			if (buffer != 0) {
508820c41b9Sshatty				FillFileBuffer(buffer);
509820c41b9Sshatty			} else {
510820c41b9Sshatty				// didn't get a real BBuffer, try simulation by just a read from the disk
511fb16552fSMaurice Kalinowski				bytesRead = GetCurrentFile()->Read(
512fb16552fSMaurice Kalinowski						data, output.format.u.multistream.max_chunk_size);
513820c41b9Sshatty			}
514820c41b9Sshatty			end = TimeSource()->RealTime();
515820c41b9Sshatty		}
516820c41b9Sshatty		bytesRead = buffer->SizeUsed();
51702402d00SMurai Takashi		delete[] data;
518820c41b9Sshatty		if (buffer != 0) {
519820c41b9Sshatty			buffer->Recycle();
520820c41b9Sshatty		}
521794887f8Sshatty		GetCurrentFile()->Seek(-bytesRead,SEEK_CUR); // put it back where we found it
522820c41b9Sshatty
523794887f8Sshatty		fInternalLatency = end - start;
524820c41b9Sshatty
525fb16552fSMaurice Kalinowski		PRINT("\tinternal latency from disk read = %lld\n", fInternalLatency);
526820c41b9Sshatty	} else {
527794887f8Sshatty		fInternalLatency = 100; // just guess
528fb16552fSMaurice Kalinowski		PRINT("\tinternal latency guessed = %lld\n", fInternalLatency);
529820c41b9Sshatty	}
530820c41b9Sshatty
531794887f8Sshatty	SetEventLatency(fDownstreamLatency + fInternalLatency);
532820c41b9Sshatty
533820c41b9Sshatty	// XXX: do anything else?
534820c41b9Sshatty}
535820c41b9Sshatty
536fb16552fSMaurice Kalinowski
537820c41b9Sshattyvoid MediaReader::Disconnect(
538820c41b9Sshatty				const media_source & what,
539820c41b9Sshatty				const media_destination & where)
540820c41b9Sshatty{
541fb16552fSMaurice Kalinowski	CALLED();
542fb16552fSMaurice Kalinowski
543794887f8Sshatty	if (output.destination != where) {
544fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_DESTINATION\n");
545794887f8Sshatty		return;
546820c41b9Sshatty	}
547794887f8Sshatty	if (output.source != what) {
548fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
549794887f8Sshatty		return;
550794887f8Sshatty	}
551fb16552fSMaurice Kalinowski
552794887f8Sshatty	output.destination = media_destination::null;
55345ed7b19Sshatty	GetFormat(&output.format);
554794887f8Sshatty	if (fBufferGroup != 0) {
555794887f8Sshatty		BBufferGroup * group = fBufferGroup;
556794887f8Sshatty		fBufferGroup = 0;
557794887f8Sshatty		delete group;
558794887f8Sshatty	}
559820c41b9Sshatty}
560820c41b9Sshatty
561fb16552fSMaurice Kalinowski
562820c41b9Sshattyvoid MediaReader::LateNoticeReceived(
563820c41b9Sshatty				const media_source & what,
564820c41b9Sshatty				bigtime_t how_much,
565820c41b9Sshatty				bigtime_t performance_time)
566820c41b9Sshatty{
567fb16552fSMaurice Kalinowski	CALLED();
568fb16552fSMaurice Kalinowski
569820c41b9Sshatty	if (what == output.source) {
570820c41b9Sshatty		switch (RunMode()) {
571820c41b9Sshatty			case B_OFFLINE:
572820c41b9Sshatty			    // nothing to do
573820c41b9Sshatty				break;
574820c41b9Sshatty			case B_RECORDING:
575820c41b9Sshatty			    // nothing to do
576820c41b9Sshatty				break;
577820c41b9Sshatty			case B_INCREASE_LATENCY:
578794887f8Sshatty				fInternalLatency += how_much;
579794887f8Sshatty				SetEventLatency(fDownstreamLatency + fInternalLatency);
580820c41b9Sshatty				break;
581820c41b9Sshatty			case B_DECREASE_PRECISION:
582a1eca89cSshatty				// XXX : shorten our buffer period
583a1eca89cSshatty				//       We could opt to just not wait but we should
584a1eca89cSshatty				//       probably gradually shorten the period so we
585a1eca89cSshatty				//       don't starve others.  Also, we need to make
586a1eca89cSshatty				//       sure we are catching up!  We may have some sort
587a1eca89cSshatty				//       of time goal for how long it takes us to
588a1eca89cSshatty				//       catch up, as well.
589820c41b9Sshatty				break;
590820c41b9Sshatty			case B_DROP_DATA:
591820c41b9Sshatty				// Okay you asked for it, we'll skip ahead in the file!
592820c41b9Sshatty				// We'll drop 1 buffer's worth
593794887f8Sshatty				if (GetCurrentFile() == 0) {
594fb16552fSMaurice Kalinowski					PRINT("MediaReader::LateNoticeReceived called without"
595fb16552fSMaurice Kalinowski						  "an GetCurrentFile() (!)\n");
596820c41b9Sshatty				} else {
597794887f8Sshatty					GetCurrentFile()->Seek(output.format.u.multistream.max_chunk_size,SEEK_CUR);
598820c41b9Sshatty				}
599820c41b9Sshatty				break;
600820c41b9Sshatty			default:
601820c41b9Sshatty				// huh?? there aren't any more run modes.
602fb16552fSMaurice Kalinowski				PRINT("MediaReader::LateNoticeReceived with unexpected run mode.\n");
603820c41b9Sshatty				break;
604820c41b9Sshatty		}
605820c41b9Sshatty	}
606820c41b9Sshatty}
607820c41b9Sshatty
608fb16552fSMaurice Kalinowski
609820c41b9Sshattyvoid MediaReader::EnableOutput(
610820c41b9Sshatty				const media_source & what,
611820c41b9Sshatty				bool enabled,
612820c41b9Sshatty				int32 * _deprecated_)
613820c41b9Sshatty{
614fb16552fSMaurice Kalinowski	CALLED();
615fb16552fSMaurice Kalinowski
616794887f8Sshatty	if (output.source != what) {
617fb16552fSMaurice Kalinowski		PRINT("\t<- B_MEDIA_BAD_SOURCE\n");
618794887f8Sshatty		return;
619820c41b9Sshatty	}
620fb16552fSMaurice Kalinowski
621794887f8Sshatty	fOutputEnabled = enabled;
622820c41b9Sshatty}
623820c41b9Sshatty
624fb16552fSMaurice Kalinowski
625820c41b9Sshattystatus_t MediaReader::SetPlayRate(
626820c41b9Sshatty				int32 numer,
627820c41b9Sshatty				int32 denom)
628820c41b9Sshatty{
629fb16552fSMaurice Kalinowski	return BBufferProducer::SetPlayRate(numer,denom); // XXX: do something intelligent later
630820c41b9Sshatty}
631820c41b9Sshatty
632fb16552fSMaurice Kalinowski
633820c41b9Sshattyvoid MediaReader::AdditionalBufferRequested(			//	used to be Reserved 0
634820c41b9Sshatty				const media_source & source,
635820c41b9Sshatty				media_buffer_id prev_buffer,
636820c41b9Sshatty				bigtime_t prev_time,
637820c41b9Sshatty				const media_seek_tag * prev_tag)
638820c41b9Sshatty{
639fb16552fSMaurice Kalinowski	CALLED();
640fb16552fSMaurice Kalinowski
641820c41b9Sshatty	if (output.source == source) {
642820c41b9Sshatty		BBuffer * buffer;
643820c41b9Sshatty		status_t status = GetFilledBuffer(&buffer);
644820c41b9Sshatty		if (status != B_OK) {
645fb16552fSMaurice Kalinowski			PRINT("MediaReader::AdditionalBufferRequested got an error from GetFilledBuffer.\n");
646820c41b9Sshatty			return; // don't send the buffer
647820c41b9Sshatty		}
64844200efdSDario Casalinuovo		SendBuffer(buffer, output.source, output.destination);
649820c41b9Sshatty	}
650820c41b9Sshatty}
651820c41b9Sshatty
652fb16552fSMaurice Kalinowski
653820c41b9Sshattyvoid MediaReader::LatencyChanged(
654820c41b9Sshatty				const media_source & source,
655820c41b9Sshatty				const media_destination & destination,
656820c41b9Sshatty				bigtime_t new_latency,
657820c41b9Sshatty				uint32 flags)
658820c41b9Sshatty{
659fb16552fSMaurice Kalinowski	CALLED();
660820c41b9Sshatty	if ((output.source == source) && (output.destination == destination)) {
661794887f8Sshatty		fDownstreamLatency = new_latency;
662794887f8Sshatty		SetEventLatency(fDownstreamLatency + fInternalLatency);
663820c41b9Sshatty	}
66439a0622eSshatty	// we may have to recompute the number of buffers that we are using
66539a0622eSshatty	// see SetBufferGroup
666820c41b9Sshatty}
667820c41b9Sshatty
668fb16552fSMaurice Kalinowski
669820c41b9Sshatty// -------------------------------------------------------- //
670820c41b9Sshatty// implementation for BMediaEventLooper
671820c41b9Sshatty// -------------------------------------------------------- //
672820c41b9Sshatty// protected:
673820c41b9Sshattystatus_t MediaReader::HandleBuffer(
674820c41b9Sshatty				const media_timed_event *event,
675820c41b9Sshatty				bigtime_t lateness,
676fb16552fSMaurice Kalinowski				bool realTimeEvent)
677820c41b9Sshatty{
678fb16552fSMaurice Kalinowski	CALLED();
679fb16552fSMaurice Kalinowski
680fb16552fSMaurice Kalinowski	if (output.destination == media_destination::null)
681794887f8Sshatty		return B_MEDIA_NOT_CONNECTED;
682fb16552fSMaurice Kalinowski
683820c41b9Sshatty	status_t status = B_OK;
684794887f8Sshatty	BBuffer * buffer = fBufferGroup->RequestBuffer(output.format.u.multistream.max_chunk_size,fBufferPeriod);
685820c41b9Sshatty	if (buffer != 0) {
686820c41b9Sshatty	    status = FillFileBuffer(buffer);
687820c41b9Sshatty	    if (status != B_OK) {
688fb16552fSMaurice Kalinowski			PRINT("MediaReader::HandleEvent got an error from FillFileBuffer.\n");
689820c41b9Sshatty			buffer->Recycle();
690820c41b9Sshatty		} else {
691794887f8Sshatty			if (fOutputEnabled) {
69244200efdSDario Casalinuovo				status = SendBuffer(buffer, output.source, output.destination);
693794887f8Sshatty				if (status != B_OK) {
694fb16552fSMaurice Kalinowski					PRINT("MediaReader::HandleEvent got an error from SendBuffer.\n");
695794887f8Sshatty					buffer->Recycle();
696794887f8Sshatty				}
697794887f8Sshatty			} else {
698820c41b9Sshatty				buffer->Recycle();
699820c41b9Sshatty			}
700820c41b9Sshatty		}
701820c41b9Sshatty	}
702794887f8Sshatty	bigtime_t nextEventTime = event->event_time+fBufferPeriod;
703820c41b9Sshatty	media_timed_event nextBufferEvent(nextEventTime, BTimedEventQueue::B_HANDLE_BUFFER);
704820c41b9Sshatty	EventQueue()->AddEvent(nextBufferEvent);
705820c41b9Sshatty	return status;
706820c41b9Sshatty}
707820c41b9Sshatty
708fb16552fSMaurice Kalinowski
709794887f8Sshattystatus_t MediaReader::HandleDataStatus(
710794887f8Sshatty						const media_timed_event *event,
711794887f8Sshatty						bigtime_t lateness,
712fb16552fSMaurice Kalinowski						bool realTimeEvent)
713820c41b9Sshatty{
714fb16552fSMaurice Kalinowski	CALLED();
715794887f8Sshatty	return SendDataStatus(event->data,output.destination,event->event_time);
716820c41b9Sshatty}
717820c41b9Sshatty
718fb16552fSMaurice Kalinowski
719820c41b9Sshatty// -------------------------------------------------------- //
720820c41b9Sshatty// MediaReader specific functions
721820c41b9Sshatty// -------------------------------------------------------- //
722794887f8Sshatty// static:
72345ed7b19Sshattyvoid MediaReader::GetFlavor(flavor_info * outInfo, int32 id)
724820c41b9Sshatty{
725fb16552fSMaurice Kalinowski	CALLED();
726fb16552fSMaurice Kalinowski
727fb16552fSMaurice Kalinowski	if (outInfo == 0)
72845ed7b19Sshatty		return;
729fb16552fSMaurice Kalinowski
73045ed7b19Sshatty	AbstractFileInterfaceNode::GetFlavor(outInfo,id);
73130456a32SDario Casalinuovo	outInfo->name = strdup("Media Reader");
73230456a32SDario Casalinuovo	outInfo->info = strdup(
73330456a32SDario Casalinuovo		"The Haiku Media Reader reads a file and produces a multistream.");
73445ed7b19Sshatty	outInfo->kinds |= B_BUFFER_PRODUCER;
73545ed7b19Sshatty	outInfo->out_format_count = 1; // 1 output
73645ed7b19Sshatty	media_format * formats = new media_format[outInfo->out_format_count];
73745ed7b19Sshatty	GetFormat(&formats[0]);
73845ed7b19Sshatty	outInfo->out_formats = formats;
739ca6f35b1Sshatty	return;
740820c41b9Sshatty}
741820c41b9Sshatty
742fb16552fSMaurice Kalinowski
74345ed7b19Sshattyvoid MediaReader::GetFormat(media_format * outFormat)
744820c41b9Sshatty{
745fb16552fSMaurice Kalinowski	CALLED();
746fb16552fSMaurice Kalinowski
74745ed7b19Sshatty	AbstractFileInterfaceNode::GetFormat(outFormat);
74845ed7b19Sshatty	return;
749820c41b9Sshatty}
750820c41b9Sshatty
751fb16552fSMaurice Kalinowski
75245ed7b19Sshattyvoid MediaReader::GetFileFormat(media_file_format * outFileFormat)
753820c41b9Sshatty{
754fb16552fSMaurice Kalinowski	CALLED();
755fb16552fSMaurice Kalinowski
75645ed7b19Sshatty	AbstractFileInterfaceNode::GetFileFormat(outFileFormat);
75745ed7b19Sshatty	outFileFormat->capabilities |= media_file_format::B_READABLE;
75845ed7b19Sshatty	return;
759820c41b9Sshatty}
760820c41b9Sshatty
761820c41b9Sshatty
762fb16552fSMaurice Kalinowski// protected:
763820c41b9Sshattystatus_t MediaReader::GetFilledBuffer(
764820c41b9Sshatty				BBuffer ** outBuffer)
765820c41b9Sshatty{
766fb16552fSMaurice Kalinowski	CALLED();
767fb16552fSMaurice Kalinowski
768794887f8Sshatty	BBuffer * buffer = fBufferGroup->RequestBuffer(output.format.u.multistream.max_chunk_size,-1);
769820c41b9Sshatty	if (buffer == 0) {
770820c41b9Sshatty		// XXX: add a new buffer and get it
771fb16552fSMaurice Kalinowski		PRINT("MediaReader::GetFilledBuffer needs a new buffer.\n");
772820c41b9Sshatty		return B_ERROR; // don't send the buffer
773820c41b9Sshatty	}
774fb16552fSMaurice Kalinowski
775820c41b9Sshatty	status_t status = FillFileBuffer(buffer);
776820c41b9Sshatty	*outBuffer = buffer;
777820c41b9Sshatty	return status;
778820c41b9Sshatty}
779820c41b9Sshatty
780fb16552fSMaurice Kalinowski
781820c41b9Sshattystatus_t MediaReader::FillFileBuffer(
782820c41b9Sshatty				BBuffer * buffer)
783820c41b9Sshatty{
784fb16552fSMaurice Kalinowski	CALLED();
785fb16552fSMaurice Kalinowski
786794887f8Sshatty	if (GetCurrentFile() == 0) {
787fb16552fSMaurice Kalinowski		PRINT("\t<- B_NO_INIT\n");
788820c41b9Sshatty		return B_NO_INIT;
78939a0622eSshatty	}
790fb16552fSMaurice Kalinowski	PRINT("\t%ld buffer bytes used, %ld buffer bytes available\n",
791fb16552fSMaurice Kalinowski			buffer->SizeUsed(), buffer->SizeAvailable());
792794887f8Sshatty	off_t position = GetCurrentFile()->Position();
793794887f8Sshatty	ssize_t bytesRead = GetCurrentFile()->Read(buffer->Data(),buffer->SizeAvailable());
794820c41b9Sshatty	if (bytesRead < 0) {
795fb16552fSMaurice Kalinowski		PRINT("\t<- B_FILE_ERROR\n");
796820c41b9Sshatty		return B_FILE_ERROR; // some sort of file related error
797820c41b9Sshatty	}
798fb16552fSMaurice Kalinowski	PRINT("\t%ld file bytes read at position %ld.\n",
799fb16552fSMaurice Kalinowski			bytesRead, position);
800fb16552fSMaurice Kalinowski
801820c41b9Sshatty	buffer->SetSizeUsed(bytesRead);
802820c41b9Sshatty	media_header * header = buffer->Header();
803820c41b9Sshatty	header->type = B_MEDIA_MULTISTREAM;
804820c41b9Sshatty	header->size_used = bytesRead;
805820c41b9Sshatty	header->file_pos = position;
806820c41b9Sshatty	header->orig_size = bytesRead;
807820c41b9Sshatty	header->time_source = TimeSource()->ID();
80839a0622eSshatty	header->start_time = TimeSource()->Now();
809820c41b9Sshatty	// nothing more to say?
810820c41b9Sshatty	return B_OK;
811820c41b9Sshatty}
812820c41b9Sshatty
813fb16552fSMaurice Kalinowski
814820c41b9Sshatty// -------------------------------------------------------- //
815820c41b9Sshatty// stuffing
816820c41b9Sshatty// -------------------------------------------------------- //
817fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_0(void *) { return B_ERROR; }
818fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_1(void *) { return B_ERROR; }
819fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_2(void *) { return B_ERROR; }
820fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_3(void *) { return B_ERROR; }
821fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_4(void *) { return B_ERROR; }
822fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_5(void *) { return B_ERROR; }
823fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_6(void *) { return B_ERROR; }
824fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_7(void *) { return B_ERROR; }
825fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_8(void *) { return B_ERROR; }
826fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_9(void *) { return B_ERROR; }
827fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_10(void *) { return B_ERROR; }
828fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_11(void *) { return B_ERROR; }
829fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_12(void *) { return B_ERROR; }
830fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_13(void *) { return B_ERROR; }
831fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_14(void *) { return B_ERROR; }
832fb16552fSMaurice Kalinowskistatus_t MediaReader::_Reserved_MediaReader_15(void *) { return B_ERROR; }
833