138920778Sshatty// MediaWriter.cpp
238920778Sshatty//
338920778Sshatty// Andrew Bachmann, 2002
438920778Sshatty//
538920778Sshatty// A MediaWriter is a node that
638920778Sshatty// implements FileInterface and BBufferConsumer.
738920778Sshatty// It consumes on input, which is a multistream,
838920778Sshatty// and writes the stream to a file.
938920778Sshatty//
1038920778Sshatty// see also MediaWriterAddOn.cpp
1138920778Sshatty
1238920778Sshatty#include <MediaDefs.h>
1338920778Sshatty#include <MediaNode.h>
1438920778Sshatty#include <MediaAddOn.h>
1538920778Sshatty#include <BufferConsumer.h>
1638920778Sshatty#include <FileInterface.h>
1738920778Sshatty#include <Controllable.h>
1838920778Sshatty#include <MediaEventLooper.h>
1938920778Sshatty#include <File.h>
2038920778Sshatty#include <Errors.h>
2138920778Sshatty#include <Entry.h>
2238920778Sshatty#include <BufferGroup.h>
2338920778Sshatty#include <TimeSource.h>
2438920778Sshatty#include <Buffer.h>
2538920778Sshatty#include <ParameterWeb.h>
26d25a7b31Sshatty#include <MediaRoster.h>
2738920778Sshatty#include <limits.h>
2838920778Sshatty
298811eeb6Sshatty#include "../AbstractFileInterfaceNode.h"
3038920778Sshatty#include "MediaWriter.h"
3144200efdSDario Casalinuovo#include "../misc.h"
3238920778Sshatty
3338920778Sshatty#include <stdio.h>
3438920778Sshatty#include <string.h>
3538920778Sshatty
36d25a7b31Sshatty// -------------------------------------------------------- //
37d25a7b31Sshatty// ctor/dtor
38d25a7b31Sshatty// -------------------------------------------------------- //
39d25a7b31Sshatty
40d25a7b31SshattyMediaWriter::~MediaWriter(void)
41d25a7b31Sshatty{
42d25a7b31Sshatty	fprintf(stderr,"MediaWriter::~MediaWriter\n");
43d25a7b31Sshatty	if (fBufferGroup != 0) {
44d25a7b31Sshatty		BBufferGroup * group = fBufferGroup;
45d25a7b31Sshatty		fBufferGroup = 0;
46d25a7b31Sshatty		delete group;
47d25a7b31Sshatty	}
48d25a7b31Sshatty}
49d25a7b31Sshatty
50d25a7b31SshattyMediaWriter::MediaWriter(
5144200efdSDario Casalinuovo				size_t defaultChunkSize,
5244200efdSDario Casalinuovo				float defaultBitRate,
5344200efdSDario Casalinuovo				const flavor_info * info,
5444200efdSDario Casalinuovo				BMessage * config,
5544200efdSDario Casalinuovo				BMediaAddOn * addOn)
56d25a7b31Sshatty	: BMediaNode("MediaWriter"),
5744200efdSDario Casalinuovo	  BBufferConsumer(B_MEDIA_MULTISTREAM),
5844200efdSDario Casalinuovo	  AbstractFileInterfaceNode(defaultChunkSize,defaultBitRate,info,config,addOn)
59d25a7b31Sshatty{
60d25a7b31Sshatty	fprintf(stderr,"MediaWriter::MediaWriter\n");
61d25a7b31Sshatty	// null some fields
62d25a7b31Sshatty	fBufferGroup = 0;
63d25a7b31Sshatty	// don't overwrite available space, and be sure to terminate
64d25a7b31Sshatty	strncpy(input.name,"MediaWriter Input",B_MEDIA_NAME_LENGTH-1);
65d25a7b31Sshatty	input.name[B_MEDIA_NAME_LENGTH-1] = '\0';
66d25a7b31Sshatty	// initialize the input
67d25a7b31Sshatty	input.node = media_node::null;               // until registration
68d25a7b31Sshatty	input.source = media_source::null;
69d25a7b31Sshatty	input.destination = media_destination::null; // until registration
70d25a7b31Sshatty	GetFormat(&input.format);
71d25a7b31Sshatty}
72d25a7b31Sshatty
73d25a7b31Sshatty// -------------------------------------------------------- //
74d25a7b31Sshatty// implementation of BMediaNode
75d25a7b31Sshatty// -------------------------------------------------------- //
76d25a7b31Sshatty
77d25a7b31Sshattyvoid MediaWriter::Preroll(void)
78d25a7b31Sshatty{
79d25a7b31Sshatty	fprintf(stderr,"MediaWriter::Preroll\n");
80d25a7b31Sshatty	// XXX:Performance opportunity
81d25a7b31Sshatty	BMediaNode::Preroll();
82d25a7b31Sshatty}
83d25a7b31Sshatty
84d25a7b31Sshattystatus_t MediaWriter::HandleMessage(
85d25a7b31Sshatty				int32 message,
86d25a7b31Sshatty				const void * data,
87d25a7b31Sshatty				size_t size)
88d25a7b31Sshatty{
89d25a7b31Sshatty	fprintf(stderr,"MediaWriter::HandleMessage\n");
90d25a7b31Sshatty	status_t status = B_OK;
91d25a7b31Sshatty	switch (message) {
92d25a7b31Sshatty		// no special messages for now
93d25a7b31Sshatty		default:
94d25a7b31Sshatty			status = BBufferConsumer::HandleMessage(message,data,size);
95d25a7b31Sshatty			if (status == B_OK) {
96d25a7b31Sshatty				break;
97d25a7b31Sshatty			}
98d25a7b31Sshatty			status = AbstractFileInterfaceNode::HandleMessage(message,data,size);
99d25a7b31Sshatty			break;
100d25a7b31Sshatty	}
101d25a7b31Sshatty	return status;
102d25a7b31Sshatty}
103d25a7b31Sshatty
104d25a7b31Sshattyvoid MediaWriter::NodeRegistered(void)
105d25a7b31Sshatty{
106d25a7b31Sshatty	fprintf(stderr,"MediaWriter::NodeRegistered\n");
107d25a7b31Sshatty
108d25a7b31Sshatty	// now we can do this
109d25a7b31Sshatty	input.node = Node();
110d25a7b31Sshatty	input.destination.id = 0;
111d25a7b31Sshatty	input.destination.port = input.node.port; // same as ControlPort()
112d25a7b31Sshatty
113d25a7b31Sshatty	// creates the parameter web and starts the looper thread
114d25a7b31Sshatty	AbstractFileInterfaceNode::NodeRegistered();
115d25a7b31Sshatty}
116d25a7b31Sshatty
117d25a7b31Sshatty// -------------------------------------------------------- //
118d25a7b31Sshatty// implementation of BFileInterface
119d25a7b31Sshatty// -------------------------------------------------------- //
120d25a7b31Sshatty
121d25a7b31Sshattystatus_t MediaWriter::SetRef(
122d25a7b31Sshatty				const entry_ref & file,
123d25a7b31Sshatty				bool create,
124d25a7b31Sshatty				bigtime_t * out_time)
125d25a7b31Sshatty{
126d25a7b31Sshatty	fprintf(stderr,"MediaWriter::SetRef\n");
127d25a7b31Sshatty	status_t status;
128d25a7b31Sshatty	status = AbstractFileInterfaceNode::SetRef(file,B_WRITE_ONLY,create,out_time);
129d25a7b31Sshatty	if (status != B_OK) {
130d25a7b31Sshatty		fprintf(stderr,"AbstractFileInterfaceNode::SetRef returned an error\n");
131d25a7b31Sshatty		return status;
132d25a7b31Sshatty	}
133d25a7b31Sshatty	if (input.source == media_source::null) {
134d25a7b31Sshatty		// reset the format, and set the requirements imposed by this file
135d25a7b31Sshatty		GetFormat(&input.format);
136d25a7b31Sshatty		AddRequirements(&input.format);
137d25a7b31Sshatty		return B_OK;
138d25a7b31Sshatty	}
139d25a7b31Sshatty	// if we are connected we may have to re-negotiate the connection
140d25a7b31Sshatty	media_format format;
141d25a7b31Sshatty	GetFormat(&format);
142d25a7b31Sshatty	AddRequirements(&format);
143d25a7b31Sshatty	if (format_is_acceptible(input.format,format)) {
144d25a7b31Sshatty		fprintf(stderr,"  compatible format = no re-negotiation necessary\n");
145d25a7b31Sshatty		return B_OK;
146d25a7b31Sshatty	}
147d25a7b31Sshatty	// first try the easy way : SORRY DEPRECATED into private :-(
148d25a7b31Sshatty//	int32 change_tag = NewChangeTag();
149d25a7b31Sshatty//	status = this->BBufferConsumer::RequestFormatChange(input.source,input.destination,&format,&change_tag);
150d25a7b31Sshatty//	if (status == B_OK) {
151d25a7b31Sshatty//		fprintf(stderr,"  format change successful\n");
152d25a7b31Sshatty//		return B_OK;
153d25a7b31Sshatty//	}
154d25a7b31Sshatty	// okay, the hard way requires we get the MediaRoster
155d25a7b31Sshatty	BMediaRoster * roster = BMediaRoster::Roster(&status);
156d25a7b31Sshatty	if (roster == 0) {
157d25a7b31Sshatty		return B_MEDIA_SYSTEM_FAILURE;
158d25a7b31Sshatty	}
159d25a7b31Sshatty	if (status != B_OK) {
160d25a7b31Sshatty		return status;
161d25a7b31Sshatty	}
162d25a7b31Sshatty	// before disconnect one should always stop the nodes (bebook says)
163d25a7b31Sshatty	// requires run_state cast since the return type on RunState() is
164d25a7b31Sshatty	// wrong [int32]
165d25a7b31Sshatty	run_state destinationRunState = run_state(RunState());
166d25a7b31Sshatty	if (destinationRunState == BMediaEventLooper::B_STARTED) {
167d25a7b31Sshatty		Stop(0,true); // stop us right now
168d25a7b31Sshatty	}
169d25a7b31Sshatty	// should also stop the source if it is running, but how?
170d25a7b31Sshatty/*	BMediaNode sourceNode = ??
171d25a7b31Sshatty	run_state sourceRunState = sourceNode->??;
172d25a7b31Sshatty	status = sourceNode->StopNode(??,0,true);
173d25a7b31Sshatty	if (status != B_OK) {
174d25a7b31Sshatty		return status;
175d25a7b31Sshatty	}  */
176d25a7b31Sshatty	// we should disconnect right now
177d25a7b31Sshatty	media_source inputSource = input.source;
178d25a7b31Sshatty	status = roster->Disconnect(input.source.id,input.source,
179d25a7b31Sshatty							    input.destination.id,input.destination);
180d25a7b31Sshatty	if (status != B_OK) {
181d25a7b31Sshatty		return status;
182d25a7b31Sshatty	}
183d25a7b31Sshatty	// if that went okay, we'll try reconnecting
184d25a7b31Sshatty	media_output connectOutput;
185d25a7b31Sshatty	media_input connectInput;
186d25a7b31Sshatty	status = roster->Connect(inputSource,input.destination,
187d25a7b31Sshatty							 &format,&connectOutput,&connectInput);
188d25a7b31Sshatty	if (status != B_OK) {
189d25a7b31Sshatty		return status;
190d25a7b31Sshatty	}
191d25a7b31Sshatty	// now restart if necessary
192d25a7b31Sshatty	if (destinationRunState == BMediaEventLooper::B_STARTED) {
193d25a7b31Sshatty		Start(0);
194d25a7b31Sshatty	}
195d25a7b31Sshatty	return status;
196d25a7b31Sshatty}
197d25a7b31Sshatty
198d25a7b31Sshatty// -------------------------------------------------------- //
199d25a7b31Sshatty// implemention of BBufferConsumer
200d25a7b31Sshatty// -------------------------------------------------------- //
201d25a7b31Sshatty
2028811eeb6Sshatty// Check to make sure the format is okay, then remove
2038811eeb6Sshatty// any wildcards corresponding to our requirements.
20438920778Sshattystatus_t MediaWriter::AcceptFormat(
20538920778Sshatty				const media_destination & dest,
20638920778Sshatty				media_format * format)
20738920778Sshatty{
20838920778Sshatty	fprintf(stderr,"MediaWriter::AcceptFormat\n");
20938920778Sshatty	if (format == 0) {
21038920778Sshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
21138920778Sshatty		return B_BAD_VALUE; // no crashing
21238920778Sshatty	}
21338920778Sshatty	if (input.destination != dest) {
21438920778Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION");
21538920778Sshatty		return B_MEDIA_BAD_DESTINATION; // we only have one input so that better be it
21638920778Sshatty	}
2178811eeb6Sshatty/*	media_format * myFormat = GetFormat();
2188811eeb6Sshatty	fprintf(stderr,"proposed format: ");
2198811eeb6Sshatty	print_media_format(format);
2208811eeb6Sshatty	fprintf(stderr,"\n");
2218811eeb6Sshatty	fprintf(stderr,"my format: ");
2228811eeb6Sshatty	print_media_format(myFormat);
2238811eeb6Sshatty	fprintf(stderr,"\n");*/
2248811eeb6Sshatty	// Be's format_is_compatible doesn't work.
2258811eeb6Sshatty//	if (!format_is_compatible(*format,*myFormat)) {
22645ed7b19Sshatty	media_format myFormat;
22745ed7b19Sshatty	GetFormat(&myFormat);
22845ed7b19Sshatty	if (!format_is_acceptible(*format,myFormat)) {
2298811eeb6Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_FORMAT\n");
2308811eeb6Sshatty		return B_MEDIA_BAD_FORMAT;
2318811eeb6Sshatty	}
2328811eeb6Sshatty	AddRequirements(format);
23338920778Sshatty	return B_OK;
23438920778Sshatty}
23538920778Sshatty
23638920778Sshattystatus_t MediaWriter::GetNextInput(
23738920778Sshatty				int32 * cookie,
23838920778Sshatty				media_input * out_input)
23938920778Sshatty{
24038920778Sshatty	fprintf(stderr,"MediaWriter::GetNextInput\n");
24138920778Sshatty	// let's not crash even if they are stupid
24238920778Sshatty	if (out_input == 0) {
24338920778Sshatty		// no place to write!
24438920778Sshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
24538920778Sshatty		return B_BAD_VALUE;
24638920778Sshatty	}
24738920778Sshatty	if (cookie != 0) {
24838920778Sshatty		// it's valid but they already got our 1 input
24938920778Sshatty		if (*cookie != 0) {
250d25a7b31Sshatty			fprintf(stderr,"<- B_ERROR (no more inputs)\n");
25138920778Sshatty			return B_ERROR;
25238920778Sshatty		}
25338920778Sshatty		// so next time they won't get the same input again
25438920778Sshatty		*cookie = 1;
25538920778Sshatty	}
25638920778Sshatty	*out_input = input;
25738920778Sshatty	return B_OK;
25838920778Sshatty}
25938920778Sshatty
26038920778Sshattyvoid MediaWriter::DisposeInputCookie(
26138920778Sshatty				int32 cookie)
26238920778Sshatty{
26338920778Sshatty	fprintf(stderr,"MediaWriter::DisposeInputCookie\n");
26438920778Sshatty	// nothing to do since our cookies are just integers
2658811eeb6Sshatty	return; // B_OK;
26638920778Sshatty}
26738920778Sshatty
26838920778Sshattyvoid MediaWriter::BufferReceived(
26938920778Sshatty				BBuffer * buffer)
27038920778Sshatty{
27138920778Sshatty	fprintf(stderr,"MediaWriter::BufferReceived\n");
27238920778Sshatty	switch (buffer->Header()->type) {
27338920778Sshatty		case B_MEDIA_PARAMETERS:
27438920778Sshatty			{
27538920778Sshatty			status_t status = ApplyParameterData(buffer->Data(),buffer->SizeUsed());
27638920778Sshatty			if (status != B_OK) {
27738920778Sshatty				fprintf(stderr,"ApplyParameterData in MediaWriter::BufferReceived failed\n");
27838920778Sshatty			}
27938920778Sshatty			buffer->Recycle();
28038920778Sshatty			}
28138920778Sshatty			break;
28238920778Sshatty		case B_MEDIA_MULTISTREAM:
28338920778Sshatty			if (buffer->Flags() & BBuffer::B_SMALL_BUFFER) {
28438920778Sshatty				fprintf(stderr,"NOT IMPLEMENTED: B_SMALL_BUFFER in MediaWriter::BufferReceived\n");
28538920778Sshatty				// XXX: implement this part
28638920778Sshatty				buffer->Recycle();
28738920778Sshatty			} else {
28838920778Sshatty				media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
28938920778Sshatty										buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
29038920778Sshatty				status_t status = EventQueue()->AddEvent(event);
29138920778Sshatty				if (status != B_OK) {
29238920778Sshatty					fprintf(stderr,"EventQueue()->AddEvent(event) in MediaWriter::BufferReceived failed\n");
29338920778Sshatty					buffer->Recycle();
29438920778Sshatty				}
29538920778Sshatty			}
29638920778Sshatty			break;
29738920778Sshatty		default:
29838920778Sshatty			fprintf(stderr,"unexpected buffer type in MediaWriter::BufferReceived\n");
29938920778Sshatty			buffer->Recycle();
30038920778Sshatty			break;
30138920778Sshatty	}
30238920778Sshatty}
30338920778Sshatty
30438920778Sshattyvoid MediaWriter::ProducerDataStatus(
30538920778Sshatty				const media_destination & for_whom,
30638920778Sshatty				int32 status,
30738920778Sshatty				bigtime_t at_performance_time)
30838920778Sshatty{
30938920778Sshatty	fprintf(stderr,"MediaWriter::ProducerDataStatus\n");
31038920778Sshatty	if (input.destination != for_whom) {
31138920778Sshatty		fprintf(stderr,"invalid destination received in MediaWriter::ProducerDataStatus\n");
31238920778Sshatty		return;
31338920778Sshatty	}
31438920778Sshatty	media_timed_event event(at_performance_time, BTimedEventQueue::B_DATA_STATUS,
31538920778Sshatty			&input, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
31638920778Sshatty	EventQueue()->AddEvent(event);
31738920778Sshatty}
31838920778Sshatty
31938920778Sshattystatus_t MediaWriter::GetLatencyFor(
32038920778Sshatty				const media_destination & for_whom,
32138920778Sshatty				bigtime_t * out_latency,
32238920778Sshatty				media_node_id * out_timesource)
32338920778Sshatty{
32438920778Sshatty	fprintf(stderr,"MediaWriter::GetLatencyFor\n");
32538920778Sshatty	if ((out_latency == 0) || (out_timesource == 0)) {
32638920778Sshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
32738920778Sshatty		return B_BAD_VALUE;
32838920778Sshatty	}
32938920778Sshatty	if (input.destination != for_whom) {
33038920778Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
33138920778Sshatty		return B_MEDIA_BAD_DESTINATION;
33238920778Sshatty	}
33338920778Sshatty	*out_latency = EventLatency();
33438920778Sshatty	*out_timesource = TimeSource()->ID();
33538920778Sshatty	return B_OK;
33638920778Sshatty}
33738920778Sshatty
33838920778Sshattystatus_t MediaWriter::Connected(
33938920778Sshatty				const media_source & producer,	/* here's a good place to request buffer group usage */
34038920778Sshatty				const media_destination & where,
34138920778Sshatty				const media_format & with_format,
34238920778Sshatty				media_input * out_input)
34338920778Sshatty{
34438920778Sshatty	fprintf(stderr,"MediaWriter::Connected\n");
34538920778Sshatty	if (out_input == 0) {
34638920778Sshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
34738920778Sshatty		return B_BAD_VALUE; // no crashing
34838920778Sshatty	}
34938920778Sshatty	if (input.destination != where) {
35038920778Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
35138920778Sshatty		return B_MEDIA_BAD_DESTINATION;
35238920778Sshatty	}
35338920778Sshatty
35438920778Sshatty	// clear any stale buffer groups
3558811eeb6Sshatty	if (fBufferGroup != 0) {
3568811eeb6Sshatty		BBufferGroup * group = fBufferGroup;
3578811eeb6Sshatty		fBufferGroup = 0;
35838920778Sshatty		delete group;
35938920778Sshatty	}
36038920778Sshatty
361378762daSshatty	// compute the latency or just guess
362378762daSshatty	if (GetCurrentFile() != 0) {
363378762daSshatty		bigtime_t start, end;
364378762daSshatty		uint8 * data = new uint8[input.format.u.multistream.max_chunk_size]; // <- buffer group buffer size
365378762daSshatty		ssize_t bytesWritten = 0;
366378762daSshatty		{ // timed section
367378762daSshatty			start = TimeSource()->RealTime();
368378762daSshatty			bytesWritten = GetCurrentFile()->Write(data,input.format.u.multistream.max_chunk_size);
369378762daSshatty			end = TimeSource()->RealTime();
370378762daSshatty		}
371040e39c5SLioncash		delete[] data;
372378762daSshatty		GetCurrentFile()->Seek(-bytesWritten,SEEK_CUR); // put it back where we found it
373378762daSshatty
374378762daSshatty		fInternalLatency = end - start;
375378762daSshatty
376d25a7b31Sshatty		fprintf(stderr,"  internal latency from disk write = %lld\n",fInternalLatency);
377378762daSshatty	} else {
378378762daSshatty		fInternalLatency = 500; // just guess
379d25a7b31Sshatty		fprintf(stderr,"  internal latency guessed = %lld\n",fInternalLatency);
380378762daSshatty	}
381378762daSshatty
382378762daSshatty	SetEventLatency(fInternalLatency);
38338920778Sshatty
38438920778Sshatty	// record the agreed upon values
38538920778Sshatty	input.source = producer;
38638920778Sshatty	input.format = with_format;
38738920778Sshatty	*out_input = input;
38838920778Sshatty	return B_OK;
38938920778Sshatty}
39038920778Sshatty
39138920778Sshattyvoid MediaWriter::Disconnected(
39238920778Sshatty				const media_source & producer,
39338920778Sshatty				const media_destination & where)
39438920778Sshatty{
39538920778Sshatty	fprintf(stderr,"MediaWriter::Disconnected\n");
3968811eeb6Sshatty	if (input.destination != where) {
3978811eeb6Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
3988811eeb6Sshatty		return;
3998811eeb6Sshatty	}
4008811eeb6Sshatty	if (input.source != producer) {
4018811eeb6Sshatty		fprintf(stderr,"<- B_MEDIA_BAD_SOURCE\n");
4028811eeb6Sshatty		return;
4038811eeb6Sshatty	}
4048811eeb6Sshatty	input.source = media_source::null;
40545ed7b19Sshatty	GetFormat(&input.format);
4068811eeb6Sshatty	if (fBufferGroup != 0) {
4078811eeb6Sshatty		BBufferGroup * group = fBufferGroup;
4088811eeb6Sshatty		fBufferGroup = 0;
4098811eeb6Sshatty		delete group;
41038920778Sshatty	}
41138920778Sshatty}
41238920778Sshatty
41338920778Sshatty	/* The notification comes from the upstream producer, so he's already cool with */
41438920778Sshatty	/* the format; you should not ask him about it in here. */
41538920778Sshattystatus_t MediaWriter::FormatChanged(
41638920778Sshatty				const media_source & producer,
41738920778Sshatty				const media_destination & consumer,
41838920778Sshatty				int32 change_tag,
41938920778Sshatty				const media_format & format)
42038920778Sshatty{
42138920778Sshatty	fprintf(stderr,"MediaWriter::FormatChanged\n");
4228811eeb6Sshatty	if (input.source != producer) {
4238811eeb6Sshatty		return B_MEDIA_BAD_SOURCE;
4248811eeb6Sshatty	}
4258811eeb6Sshatty	if (input.destination != consumer) {
4268811eeb6Sshatty		return B_MEDIA_BAD_DESTINATION;
4278811eeb6Sshatty	}
4288811eeb6Sshatty	// Since we don't really care about the format of the data
4298811eeb6Sshatty	// we can just continue to treat things the same way.
4308811eeb6Sshatty	input.format = format;
4318811eeb6Sshatty	return B_OK;
43238920778Sshatty}
43338920778Sshatty
43438920778Sshatty	/* Given a performance time of some previous buffer, retrieve the remembered tag */
43538920778Sshatty	/* of the closest (previous or exact) performance time. Set *out_flags to 0; the */
43638920778Sshatty	/* idea being that flags can be added later, and the understood flags returned in */
43738920778Sshatty	/* *out_flags. */
43838920778Sshattystatus_t MediaWriter::SeekTagRequested(
43938920778Sshatty				const media_destination & destination,
44038920778Sshatty				bigtime_t in_target_time,
44138920778Sshatty				uint32 in_flags,
44238920778Sshatty				media_seek_tag * out_seek_tag,
44338920778Sshatty				bigtime_t * out_tagged_time,
44438920778Sshatty				uint32 * out_flags)
44538920778Sshatty{
44638920778Sshatty	fprintf(stderr,"MediaWriter::SeekTagRequested\n");
447378762daSshatty	return BBufferConsumer::SeekTagRequested(destination,in_target_time,in_flags,
448378762daSshatty											out_seek_tag,out_tagged_time,out_flags);
44938920778Sshatty}
45038920778Sshatty
45138920778Sshatty// -------------------------------------------------------- //
45238920778Sshatty// implementation for BMediaEventLooper
45338920778Sshatty// -------------------------------------------------------- //
45438920778Sshatty
45538920778Sshatty// protected:
45638920778Sshatty
4578811eeb6Sshatty// how should we handle late buffers?  drop them?
4588811eeb6Sshatty// notify the producer?
45938920778Sshattystatus_t MediaWriter::HandleBuffer(
46038920778Sshatty				const media_timed_event *event,
46138920778Sshatty				bigtime_t lateness,
46244200efdSDario Casalinuovo				bool realTimeEvent)
46338920778Sshatty{
46438920778Sshatty	fprintf(stderr,"MediaWriter::HandleBuffer\n");
4658811eeb6Sshatty	BBuffer * buffer = const_cast<BBuffer*>((BBuffer*)event->pointer);
466378762daSshatty	if (buffer == 0) {
467378762daSshatty		fprintf(stderr,"<- B_BAD_VALUE\n");
468378762daSshatty		return B_BAD_VALUE;
469378762daSshatty	}
470378762daSshatty	if (buffer->Header()->destination != input.destination.id) {
471378762daSshatty		fprintf(stderr,"<- B_MEDIA_BAD_DESTINATION\n");
472378762daSshatty		return B_MEDIA_BAD_DESTINATION;
473378762daSshatty	}
4748811eeb6Sshatty	WriteFileBuffer(buffer);
4758811eeb6Sshatty	buffer->Recycle();
4767229ad13Sshatty	return B_OK;
47738920778Sshatty}
47838920778Sshatty
4798811eeb6Sshattystatus_t MediaWriter::HandleDataStatus(
4808811eeb6Sshatty						const media_timed_event *event,
4818811eeb6Sshatty						bigtime_t lateness,
48244200efdSDario Casalinuovo						bool realTimeEvents)
48338920778Sshatty{
4848811eeb6Sshatty	fprintf(stderr,"MediaWriter::HandleDataStatus");
4858811eeb6Sshatty	// we have no where to send a data status to.
4868811eeb6Sshatty	return B_OK;
48738920778Sshatty}
48838920778Sshatty
4898811eeb6Sshatty
49038920778Sshatty// -------------------------------------------------------- //
49138920778Sshatty// MediaWriter specific functions
49238920778Sshatty// -------------------------------------------------------- //
49338920778Sshatty
4948811eeb6Sshatty// static:
4958811eeb6Sshatty
49645ed7b19Sshattyvoid MediaWriter::GetFlavor(flavor_info * outInfo, int32 id)
49738920778Sshatty{
49838920778Sshatty	fprintf(stderr,"MediaWriter::GetFlavor\n");
49945ed7b19Sshatty	if (outInfo == 0) {
50045ed7b19Sshatty		return;
50145ed7b19Sshatty	}
50245ed7b19Sshatty	AbstractFileInterfaceNode::GetFlavor(outInfo,id);
50330456a32SDario Casalinuovo	strcpy(outInfo->name, "Media Writer");
50430456a32SDario Casalinuovo	strcpy(outInfo->info,
50530456a32SDario Casalinuovo		"The Haiku Media Writer consumes a multistream and writes a file.");
50645ed7b19Sshatty	outInfo->kinds |= B_BUFFER_CONSUMER;
50745ed7b19Sshatty	outInfo->in_format_count = 1; // 1 input
50845ed7b19Sshatty	media_format * formats = new media_format[outInfo->in_format_count];
50945ed7b19Sshatty	GetFormat(&formats[0]);
51045ed7b19Sshatty	outInfo->in_formats = formats;
5118811eeb6Sshatty	return;
51238920778Sshatty}
51338920778Sshatty
51445ed7b19Sshattyvoid MediaWriter::GetFormat(media_format * outFormat)
51538920778Sshatty{
51638920778Sshatty	fprintf(stderr,"MediaWriter::GetFormat\n");
51745ed7b19Sshatty	if (outFormat == 0) {
51845ed7b19Sshatty		return;
51945ed7b19Sshatty	}
52045ed7b19Sshatty	AbstractFileInterfaceNode::GetFormat(outFormat);
52145ed7b19Sshatty	return;
52238920778Sshatty}
52338920778Sshatty
52445ed7b19Sshattyvoid MediaWriter::GetFileFormat(media_file_format * outFileFormat)
52538920778Sshatty{
52638920778Sshatty	fprintf(stderr,"MediaWriter::GetFileFormat\n");
52745ed7b19Sshatty	if (outFileFormat == 0) {
52845ed7b19Sshatty		return;
52945ed7b19Sshatty	}
53045ed7b19Sshatty	AbstractFileInterfaceNode::GetFileFormat(outFileFormat);
53145ed7b19Sshatty	outFileFormat->capabilities |= media_file_format::B_WRITABLE;
53245ed7b19Sshatty	return;
53338920778Sshatty}
53438920778Sshatty
5358811eeb6Sshatty// protected:
53638920778Sshatty
5378811eeb6Sshattystatus_t MediaWriter::WriteFileBuffer(
53838920778Sshatty				BBuffer * buffer)
53938920778Sshatty{
5408811eeb6Sshatty	fprintf(stderr,"MediaWriter::WriteFileBuffer\n");
5418811eeb6Sshatty	if (GetCurrentFile() == 0) {
54238920778Sshatty		fprintf(stderr,"<- B_NO_INIT\n");
54338920778Sshatty		return B_NO_INIT;
5448811eeb6Sshatty	}
54544200efdSDario Casalinuovo	fprintf(stderr,"  writing %" B_PRId32 " bytes at %lld\n",
546378762daSshatty			buffer->SizeUsed(),GetCurrentFile()->Position());
5478811eeb6Sshatty	ssize_t bytesWriten = GetCurrentFile()->Write(buffer->Data(),buffer->SizeUsed());
5488811eeb6Sshatty	if (bytesWriten < 0) {
54938920778Sshatty		fprintf(stderr,"<- B_FILE_ERROR\n");
55038920778Sshatty		return B_FILE_ERROR; // some sort of file related error
55138920778Sshatty	}
55238920778Sshatty	// nothing more to say?
55338920778Sshatty	return B_OK;
55438920778Sshatty}
55538920778Sshatty
55638920778Sshatty// -------------------------------------------------------- //
55738920778Sshatty// stuffing
55838920778Sshatty// -------------------------------------------------------- //
55938920778Sshatty
56044200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_0(void *) { return B_ERROR; }
56144200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_1(void *) { return B_ERROR; }
56244200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_2(void *) { return B_ERROR; }
56344200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_3(void *) { return B_ERROR; }
56444200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_4(void *) { return B_ERROR; }
56544200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_5(void *) { return B_ERROR; }
56644200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_6(void *) { return B_ERROR; }
56744200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_7(void *) { return B_ERROR; }
56844200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_8(void *) { return B_ERROR; }
56944200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_9(void *) { return B_ERROR; }
57044200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_10(void *) { return B_ERROR; }
57144200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_11(void *) { return B_ERROR; }
57244200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_12(void *) { return B_ERROR; }
57344200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_13(void *) { return B_ERROR; }
57444200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_14(void *) { return B_ERROR; }
57544200efdSDario Casalinuovostatus_t MediaWriter::_Reserved_MediaWriter_15(void *) { return B_ERROR; }
576