152a38012Sejakowatz#include "ConsumerNode.h"
29ae0991aSAxel Dörfler
39ae0991aSAxel Dörfler#include <stdlib.h>
49ae0991aSAxel Dörfler#include <string.h>
59ae0991aSAxel Dörfler
69ae0991aSAxel Dörfler#include <Buffer.h>
79ae0991aSAxel Dörfler#include <TimeSource.h>
89ae0991aSAxel Dörfler
952a38012Sejakowatz#include "misc.h"
1052a38012Sejakowatz
119ae0991aSAxel Dörfler
129ae0991aSAxel DörflerConsumerNode::ConsumerNode()
139ae0991aSAxel Dörfler	:
145720dfd4SDario Casalinuovo	BMediaNode("ConsumerNode"),
1552a38012Sejakowatz	BBufferConsumer(B_MEDIA_RAW_AUDIO),
165720dfd4SDario Casalinuovo	BMediaEventLooper()
1752a38012Sejakowatz{
1852a38012Sejakowatz	out("ConsumerNode::ConsumerNode\n");
1952a38012Sejakowatz}
2052a38012Sejakowatz
219ae0991aSAxel Dörfler
2252a38012SejakowatzConsumerNode::~ConsumerNode()
239ae0991aSAxel Dörfler{
2452a38012Sejakowatz	out("ConsumerNode::~ConsumerNode\n");
2552a38012Sejakowatz	Quit();
2652a38012Sejakowatz}
2752a38012Sejakowatz
289ae0991aSAxel Dörfler
2952a38012Sejakowatzvoid
3052a38012SejakowatzConsumerNode::NodeRegistered()
3152a38012Sejakowatz{
3252a38012Sejakowatz	out("ConsumerNode::NodeRegistered\n");
3352a38012Sejakowatz	InitializeInput();
349ae0991aSAxel Dörfler	SetPriority(108);
359ae0991aSAxel Dörfler	Run();
3652a38012Sejakowatz}
3752a38012Sejakowatz
389ae0991aSAxel Dörfler
3952a38012Sejakowatzstatus_t
409ae0991aSAxel DörflerConsumerNode::AcceptFormat(const media_destination& dest, media_format* format)
4152a38012Sejakowatz{
4252a38012Sejakowatz	out("ConsumerNode::AcceptFormat\n");
4352a38012Sejakowatz
449ae0991aSAxel Dörfler	if (dest != fInput.destination)
4552a38012Sejakowatz		return B_MEDIA_BAD_DESTINATION;
4652a38012Sejakowatz
4752a38012Sejakowatz	if (format == NULL)
4852a38012Sejakowatz		return B_BAD_VALUE;
499ae0991aSAxel Dörfler
5052a38012Sejakowatz	if (format->type != B_MEDIA_RAW_AUDIO)
5152a38012Sejakowatz		return B_MEDIA_BAD_FORMAT;
529ae0991aSAxel Dörfler
5352a38012Sejakowatz	return B_OK;
5452a38012Sejakowatz}
5552a38012Sejakowatz
569ae0991aSAxel Dörfler
5752a38012Sejakowatzstatus_t
589ae0991aSAxel DörflerConsumerNode::GetNextInput(int32* cookie, media_input* _input)
5952a38012Sejakowatz{
6052a38012Sejakowatz	out("ConsumerNode::GetNextInput\n");
6152a38012Sejakowatz
629ae0991aSAxel Dörfler	if (_input == NULL)
6352a38012Sejakowatz		return B_BAD_VALUE;
649ae0991aSAxel Dörfler
6552a38012Sejakowatz	if (++(*cookie) > 1)
6652a38012Sejakowatz		return B_BAD_INDEX;
679ae0991aSAxel Dörfler
689ae0991aSAxel Dörfler	*_input = fInput;
6952a38012Sejakowatz	return B_OK;
7052a38012Sejakowatz}
7152a38012Sejakowatz
729ae0991aSAxel Dörfler
7352a38012Sejakowatzvoid
749ae0991aSAxel DörflerConsumerNode::DisposeInputCookie(int32 cookie)
7552a38012Sejakowatz{
7652a38012Sejakowatz	out("ConsumerNode::DisposeInputCookie\n");
7752a38012Sejakowatz	return;
7852a38012Sejakowatz}
7952a38012Sejakowatz
809ae0991aSAxel Dörfler
8152a38012Sejakowatzvoid
829ae0991aSAxel DörflerConsumerNode::BufferReceived(BBuffer* buffer)
8352a38012Sejakowatz{
849ae0991aSAxel Dörfler	out("ConsumerNode::BufferReceived, sheduled time = %5.4f\n",
859ae0991aSAxel Dörfler		buffer->Header()->start_time / 1E6);
869ae0991aSAxel Dörfler
879ae0991aSAxel Dörfler	media_timed_event event(buffer->Header()->start_time,
889ae0991aSAxel Dörfler		BTimedEventQueue::B_HANDLE_BUFFER, buffer,
899ae0991aSAxel Dörfler		BTimedEventQueue::B_RECYCLE_BUFFER);
9052a38012Sejakowatz	EventQueue()->AddEvent(event);
9152a38012Sejakowatz	return;
9252a38012Sejakowatz}
9352a38012Sejakowatz
949ae0991aSAxel Dörfler
9552a38012Sejakowatzvoid
969ae0991aSAxel DörflerConsumerNode::ProducerDataStatus(const media_destination& forWhom, int32 status,
979ae0991aSAxel Dörfler	bigtime_t atPerformanceTime)
9852a38012Sejakowatz{
9952a38012Sejakowatz	out("ConsumerNode::ProducerDataStatus\n");
1009ae0991aSAxel Dörfler
1019ae0991aSAxel Dörfler	if (forWhom == fInput.destination) {
1029ae0991aSAxel Dörfler		media_timed_event event(atPerformanceTime,
1039ae0991aSAxel Dörfler			BTimedEventQueue::B_DATA_STATUS, &fInput,
1049ae0991aSAxel Dörfler			BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
10552a38012Sejakowatz		EventQueue()->AddEvent(event);
10652a38012Sejakowatz	}
10752a38012Sejakowatz}
10852a38012Sejakowatz
1099ae0991aSAxel Dörfler
11052a38012Sejakowatzstatus_t
1119ae0991aSAxel DörflerConsumerNode::GetLatencyFor(const media_destination& forWhom,
1129ae0991aSAxel Dörfler	bigtime_t* _latency, media_node_id* _timesource)
11352a38012Sejakowatz{
11452a38012Sejakowatz	out("ConsumerNode::GetLatencyFor\n");
11552a38012Sejakowatz	// make sure this is one of my valid inputs
1169ae0991aSAxel Dörfler	if (forWhom != fInput.destination)
11752a38012Sejakowatz		return B_MEDIA_BAD_DESTINATION;
11852a38012Sejakowatz
1199ae0991aSAxel Dörfler	*_latency = 23000;
1209ae0991aSAxel Dörfler	*_timesource = TimeSource()->ID();
12152a38012Sejakowatz	return B_OK;
12252a38012Sejakowatz}
12352a38012Sejakowatz
1249ae0991aSAxel Dörfler
12552a38012Sejakowatzstatus_t
1269ae0991aSAxel DörflerConsumerNode::Connected(const media_source& producer,
1279ae0991aSAxel Dörfler	const media_destination& where, const media_format& withFormat,
1289ae0991aSAxel Dörfler	media_input* _input)
12952a38012Sejakowatz{
13052a38012Sejakowatz	out("ConsumerNode::Connected\n");
1319ae0991aSAxel Dörfler	if (where != fInput.destination)
13252a38012Sejakowatz		return B_MEDIA_BAD_DESTINATION;
13352a38012Sejakowatz
1349ae0991aSAxel Dörfler	// calculate my latency here, because it may depend on buffer
1359ae0991aSAxel Dörfler	// sizes/durations, then tell the BMediaEventLooper how early
1369ae0991aSAxel Dörfler	// we need to get the buffers
1379ae0991aSAxel Dörfler	SetEventLatency(10 * 1000); // TODO: fix me
13852a38012Sejakowatz
13952a38012Sejakowatz	/* reserve the connection */
1409ae0991aSAxel Dörfler	fInput.source = producer;
1419ae0991aSAxel Dörfler	fInput.format = withFormat;
14252a38012Sejakowatz
14352a38012Sejakowatz	/* and publish it's name and connection info */
1449ae0991aSAxel Dörfler	*_input = fInput;
14552a38012Sejakowatz
14652a38012Sejakowatz#if 0
14752a38012Sejakowatz	/* create the buffer group */
14852a38012Sejakowatz	if (mBufferGroup == NULL) {
14952a38012Sejakowatz		create_own_buffer_group();
15052a38012Sejakowatz		mBufferGroup = mOwnBufferGroup;
15152a38012Sejakowatz	}
15252a38012Sejakowatz
15352a38012Sejakowatz	/* set the duration of the node's buffers */
15452a38012Sejakowatz	int32 numBuffers;
15552a38012Sejakowatz	mBufferGroup->CountBuffers(&numBuffers);
15652a38012Sejakowatz	SetBufferDuration((1000000LL * numBuffers) / mOutput.format.u.raw_video.field_rate);
15752a38012Sejakowatz#endif
15852a38012Sejakowatz
15952a38012Sejakowatz	return B_OK;
16052a38012Sejakowatz}
16152a38012Sejakowatz
1629ae0991aSAxel Dörfler
16352a38012Sejakowatzvoid
1649ae0991aSAxel DörflerConsumerNode::Disconnected(const media_source& producer,
1659ae0991aSAxel Dörfler	const media_destination& where)
16652a38012Sejakowatz{
16752a38012Sejakowatz	out("ConsumerNode::Disconnected\n");
16852a38012Sejakowatz
16952a38012Sejakowatz	/* unreserve the connection */
17052a38012Sejakowatz	InitializeInput();
17152a38012Sejakowatz
17252a38012Sejakowatz#if 0
17352a38012Sejakowatz	/* release buffer group */
17452a38012Sejakowatz	mBufferGroup = NULL;
17552a38012Sejakowatz	if (mOwnBufferGroup != NULL) {
17652a38012Sejakowatz		delete_own_buffer_group();
17752a38012Sejakowatz	}
1789ae0991aSAxel Dörfler#endif
17952a38012Sejakowatz
18052a38012Sejakowatz	return;
18152a38012Sejakowatz}
18252a38012Sejakowatz
1839ae0991aSAxel Dörfler
18452a38012Sejakowatzstatus_t
1859ae0991aSAxel DörflerConsumerNode::FormatChanged(const media_source& producer,
1869ae0991aSAxel Dörfler	const media_destination& consumer, int32 changeTag,
1879ae0991aSAxel Dörfler	const media_format& format)
18852a38012Sejakowatz{
18952a38012Sejakowatz	out("ConsumerNode::FormatChanged\n");
19052a38012Sejakowatz	return B_OK;
19152a38012Sejakowatz}
19252a38012Sejakowatz
1939ae0991aSAxel Dörfler
1949ae0991aSAxel Dörflerstatus_t
1959ae0991aSAxel DörflerConsumerNode::SeekTagRequested(const media_destination& destination,
1969ae0991aSAxel Dörfler	bigtime_t targetTime, uint32 flags, media_seek_tag* _seekTag,
1979ae0991aSAxel Dörfler	bigtime_t* _taggedTime, uint32* _flags)
19852a38012Sejakowatz{
19952a38012Sejakowatz	out("ConsumerNode::SeekTagRequested\n");
20052a38012Sejakowatz	return B_OK;
20152a38012Sejakowatz}
20252a38012Sejakowatz
2039ae0991aSAxel Dörfler
2049ae0991aSAxel DörflerBMediaAddOn*
2059ae0991aSAxel DörflerConsumerNode::AddOn(int32* internalID) const
20652a38012Sejakowatz{
20752a38012Sejakowatz	out("ConsumerNode::AddOn\n");
20852a38012Sejakowatz	return NULL;
20952a38012Sejakowatz}
21052a38012Sejakowatz
2119ae0991aSAxel Dörfler
2129ae0991aSAxel Dörflervoid
2139ae0991aSAxel DörflerConsumerNode::HandleEvent(const media_timed_event* event, bigtime_t lateness,
2149ae0991aSAxel Dörfler	bool realTimeEvent)
21552a38012Sejakowatz{
2169ae0991aSAxel Dörfler	switch (event->type) {
2179ae0991aSAxel Dörfler		case BTimedEventQueue::B_HANDLE_BUFFER:
21852a38012Sejakowatz		{
21952a38012Sejakowatz			out("ConsumerNode::HandleEvent B_HANDLE_BUFFER\n");
2209ae0991aSAxel Dörfler			BBuffer* buffer = const_cast<BBuffer*>((BBuffer*)event->pointer);
2219ae0991aSAxel Dörfler
2229ae0991aSAxel Dörfler			out("### sheduled time = %5.4f, current time = %5.4f, lateness = "
2239ae0991aSAxel Dörfler				"%5.4f\n", buffer->Header()->start_time / 1E6,
2249ae0991aSAxel Dörfler				TimeSource()->Now() / 1E6,lateness / 1E6);
2259ae0991aSAxel Dörfler
2269ae0991aSAxel Dörfler			snooze((rand() * 100) % 200000);
22752a38012Sejakowatz
22852a38012Sejakowatz			if (buffer)
22952a38012Sejakowatz				buffer->Recycle();
2309ae0991aSAxel Dörfler			break;
23152a38012Sejakowatz		}
23252a38012Sejakowatz
2339ae0991aSAxel Dörfler		case BTimedEventQueue::B_PARAMETER:
23452a38012Sejakowatz			out("ConsumerNode::HandleEvent B_PARAMETER\n");
2359ae0991aSAxel Dörfler			break;
23652a38012Sejakowatz
2379ae0991aSAxel Dörfler		case BTimedEventQueue::B_START:
23852a38012Sejakowatz			out("ConsumerNode::HandleEvent B_START\n");
2399ae0991aSAxel Dörfler			break;
24052a38012Sejakowatz
2419ae0991aSAxel Dörfler		case BTimedEventQueue::B_STOP:
24252a38012Sejakowatz			out("ConsumerNode::HandleEvent B_STOP\n");
2439ae0991aSAxel Dörfler			// stopping implies not handling any more buffers.  So, we flush
2449ae0991aSAxel Dörfler			// all pending buffers out of the event queue before returning to
2459ae0991aSAxel Dörfler			// the event loop.
2469ae0991aSAxel Dörfler			EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true,
2479ae0991aSAxel Dörfler				BTimedEventQueue::B_HANDLE_BUFFER);
2489ae0991aSAxel Dörfler			break;
2499ae0991aSAxel Dörfler
2509ae0991aSAxel Dörfler		case BTimedEventQueue::B_SEEK:
25152a38012Sejakowatz			out("ConsumerNode::HandleEvent B_SEEK\n");
2529ae0991aSAxel Dörfler			break;
25352a38012Sejakowatz
2549ae0991aSAxel Dörfler		case BTimedEventQueue::B_WARP:
25552a38012Sejakowatz			out("ConsumerNode::HandleEvent B_WARP\n");
2569ae0991aSAxel Dörfler			// similarly, time warps aren't meaningful to the logger, so just
2579ae0991aSAxel Dörfler			// record it and return
2589ae0991aSAxel Dörfler			//mLogger->Log(LOG_WARP_HANDLED, logMsg);
2599ae0991aSAxel Dörfler			break;
26052a38012Sejakowatz
2619ae0991aSAxel Dörfler		case BTimedEventQueue::B_DATA_STATUS:
26252a38012Sejakowatz			out("ConsumerNode::HandleEvent B_DATA_STATUS\n");
2639ae0991aSAxel Dörfler			break;
26452a38012Sejakowatz
2659ae0991aSAxel Dörfler		default:
26652a38012Sejakowatz			out("ConsumerNode::HandleEvent default\n");
2679ae0991aSAxel Dörfler			break;
26852a38012Sejakowatz	}
26952a38012Sejakowatz}
27052a38012Sejakowatz
2719ae0991aSAxel Dörfler
2729ae0991aSAxel Dörflerstatus_t
2739ae0991aSAxel DörflerConsumerNode::HandleMessage(int32 message, const void* data, size_t size)
27452a38012Sejakowatz{
2759ae0991aSAxel Dörfler	out("ConsumerNode::HandleMessage %lx\n", message);
2769ae0991aSAxel Dörfler
2779ae0991aSAxel Dörfler	if (BBufferConsumer::HandleMessage(message, data, size) == B_OK
2789ae0991aSAxel Dörfler		|| BMediaEventLooper::HandleMessage(message, data, size) == B_OK)
27952a38012Sejakowatz		return B_OK;
2809ae0991aSAxel Dörfler
2819ae0991aSAxel Dörfler	return BMediaNode::HandleMessage(message, data, size);
28252a38012Sejakowatz}
28352a38012Sejakowatz
2849ae0991aSAxel Dörfler
2859ae0991aSAxel Dörflervoid
28652a38012SejakowatzConsumerNode::InitializeInput()
28752a38012Sejakowatz{
28852a38012Sejakowatz	out("ConsumerNode::InitializeInput()\n");
2899ae0991aSAxel Dörfler	fInput.source = media_source::null;
2909ae0991aSAxel Dörfler	fInput.destination.port = ControlPort();
2919ae0991aSAxel Dörfler	fInput.destination.id = 0;
2929ae0991aSAxel Dörfler	fInput.node = Node();
2939ae0991aSAxel Dörfler	fInput.format.type = B_MEDIA_RAW_AUDIO;
2949ae0991aSAxel Dörfler	fInput.format.u.raw_audio = media_raw_audio_format::wildcard;
2959ae0991aSAxel Dörfler	fInput.format.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
2969ae0991aSAxel Dörfler	fInput.format.u.raw_audio.channel_count = 1;
2979ae0991aSAxel Dörfler	fInput.format.u.raw_audio.frame_rate = 44100;
2989ae0991aSAxel Dörfler	fInput.format.u.raw_audio.byte_order = B_HOST_IS_BENDIAN
2999ae0991aSAxel Dörfler		? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
3009ae0991aSAxel Dörfler	strcpy(fInput.name, "this way in");
30152a38012Sejakowatz}
302