1255a01c7Sbeveloper/*
275486484SDario Casalinuovo * Copyright (c) 2015, Dario Casalinuovo
3255a01c7Sbeveloper * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
4255a01c7Sbeveloper *
5255a01c7Sbeveloper * Permission is hereby granted, free of charge, to any person obtaining
6255a01c7Sbeveloper * a copy of this software and associated documentation files or portions
7255a01c7Sbeveloper * thereof (the "Software"), to deal in the Software without restriction,
8255a01c7Sbeveloper * including without limitation the rights to use, copy, modify, merge,
9255a01c7Sbeveloper * publish, distribute, sublicense, and/or sell copies of the Software,
10255a01c7Sbeveloper * and to permit persons to whom the Software is furnished to do so, subject
11255a01c7Sbeveloper * to the following conditions:
12255a01c7Sbeveloper *
13255a01c7Sbeveloper *  * Redistributions of source code must retain the above copyright notice,
14255a01c7Sbeveloper *    this list of conditions and the following disclaimer.
15255a01c7Sbeveloper *
16255a01c7Sbeveloper *  * Redistributions in binary form must reproduce the above copyright notice
17255a01c7Sbeveloper *    in the  binary, as well as this list of conditions and the following
18255a01c7Sbeveloper *    disclaimer in the documentation and/or other materials provided with
19255a01c7Sbeveloper *    the distribution.
20255a01c7Sbeveloper *
21255a01c7Sbeveloper * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22255a01c7Sbeveloper * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23255a01c7Sbeveloper * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24255a01c7Sbeveloper * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25255a01c7Sbeveloper * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26255a01c7Sbeveloper * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27255a01c7Sbeveloper * THE SOFTWARE.
28255a01c7Sbeveloper *
29255a01c7Sbeveloper */
302e60efdaSDario Casalinuovo
312e60efdaSDario Casalinuovo
3252a38012Sejakowatz#include <BufferConsumer.h>
3352a38012Sejakowatz#include <BufferProducer.h>
3452a38012Sejakowatz#include <Controllable.h>
3552a38012Sejakowatz#include <FileInterface.h>
362e60efdaSDario Casalinuovo#include <MediaRoster.h>
372e60efdaSDario Casalinuovo#include <MediaNode.h>
38c079d8d6SDario Casalinuovo#include <SupportDefs.h>
392e60efdaSDario Casalinuovo#include <TimeSource.h>
402e60efdaSDario Casalinuovo
4152a38012Sejakowatz#include <string.h>
422e60efdaSDario Casalinuovo
432e60efdaSDario Casalinuovo#include "DataExchange.h"
44b84955d4SBarrett#include "MediaDebug.h"
455917dd5bSbeveloper#include "MediaMisc.h"
4654187cc6Sbeveloper#include "MediaRosterEx.h"
47f4925104Sbeveloper#include "Notifications.h"
482e60efdaSDario Casalinuovo#include "ServerInterface.h"
49d6379053Sbeveloper#include "TimeSourceObject.h"
505917dd5bSbeveloper#include "TimeSourceObjectManager.h"
5152a38012Sejakowatz
52758b1d0eSIngo Weinholdusing std::nothrow;
53758b1d0eSIngo Weinholdusing std::nothrow_t;
54758b1d0eSIngo Weinhold
5531cf24c1SMarcus Overhagen#undef TRACE
5631cf24c1SMarcus Overhagen//#define TRACE_MEDIA_NODE
5731cf24c1SMarcus Overhagen#ifdef TRACE_MEDIA_NODE
5831cf24c1SMarcus Overhagen  #define TRACE printf
5931cf24c1SMarcus Overhagen#else
6031cf24c1SMarcus Overhagen  #define TRACE(x...)
6131cf24c1SMarcus Overhagen#endif
6231cf24c1SMarcus Overhagen
632e60efdaSDario Casalinuovo// Don't rename this one, it's used and exported for binary compatibility
6452a38012Sejakowatzint32 BMediaNode::_m_changeTag = 0;
6552a38012Sejakowatz
662e60efdaSDario Casalinuovo// media_node
672e60efdaSDario Casalinuovo
682e60efdaSDario Casalinuovomedia_node media_node::null;
6952a38012Sejakowatz
7052a38012Sejakowatzmedia_node::media_node()
712e60efdaSDario Casalinuovo	:
722e60efdaSDario Casalinuovo	node(-1),
7352a38012Sejakowatz	port(-1),
7452a38012Sejakowatz	kind(0)
7552a38012Sejakowatz{
7652a38012Sejakowatz}
7752a38012Sejakowatz
782e60efdaSDario Casalinuovo
7952a38012Sejakowatzmedia_node::~media_node()
8052a38012Sejakowatz{
8152a38012Sejakowatz}
8252a38012Sejakowatz
832e60efdaSDario Casalinuovo// media_input
8452a38012Sejakowatz
8552a38012Sejakowatzmedia_input::media_input()
8652a38012Sejakowatz{
8752a38012Sejakowatz	name[0] = '\0';
8852a38012Sejakowatz}
8952a38012Sejakowatz
902e60efdaSDario Casalinuovo
9152a38012Sejakowatzmedia_input::~media_input()
9252a38012Sejakowatz{
9352a38012Sejakowatz}
9452a38012Sejakowatz
952e60efdaSDario Casalinuovo// media_output
9652a38012Sejakowatz
9752a38012Sejakowatzmedia_output::media_output()
9852a38012Sejakowatz{
9952a38012Sejakowatz	name[0] = '\0';
10052a38012Sejakowatz}
10152a38012Sejakowatz
1022e60efdaSDario Casalinuovo
10352a38012Sejakowatzmedia_output::~media_output()
10452a38012Sejakowatz{
10552a38012Sejakowatz}
10652a38012Sejakowatz
1072e60efdaSDario Casalinuovo// live_node_info
10852a38012Sejakowatz
10952a38012Sejakowatzlive_node_info::live_node_info()
1102e60efdaSDario Casalinuovo	:
1112e60efdaSDario Casalinuovo	hint_point(0.0f, 0.0f)
11252a38012Sejakowatz{
11352a38012Sejakowatz	name[0] = '\0';
11452a38012Sejakowatz}
11552a38012Sejakowatz
1162e60efdaSDario Casalinuovo
11752a38012Sejakowatzlive_node_info::~live_node_info()
11852a38012Sejakowatz{
11952a38012Sejakowatz}
12052a38012Sejakowatz
1212e60efdaSDario Casalinuovo// BMediaNode
12252a38012Sejakowatz
12352a38012SejakowatzBMediaNode::~BMediaNode()
12452a38012Sejakowatz{
12552a38012Sejakowatz	CALLED();
1262e60efdaSDario Casalinuovo	// BeBook: UnregisterNode() unregisters a node from the Media Server.
1272e60efdaSDario Casalinuovo	// It's called automatically by the BMediaNode destructor, but it might
1282e60efdaSDario Casalinuovo	// be convenient to call it sometime before you delete your node instance,
1292e60efdaSDario Casalinuovo	// depending on your implementation and circumstances.
130d6379053Sbeveloper
1312e60efdaSDario Casalinuovo	// First we remove the time source
1327fd43270Sbeveloper	if (fTimeSource) {
1337fd43270Sbeveloper		fTimeSource->RemoveMe(this);
1347fd43270Sbeveloper		fTimeSource->Release();
13554187cc6Sbeveloper		fTimeSource = NULL;
1367fd43270Sbeveloper	}
1377fd43270Sbeveloper
138c74afb57SJérôme Duval	// Attention! We do not delete their control ports, since they are only a
139d6379053Sbeveloper	// shadow object, and the real one still exists
1402e60efdaSDario Casalinuovo	if ((fKinds & NODE_KIND_SHADOW_TIMESOURCE) == 0) {
141d6379053Sbeveloper		if (fControlPort > 0)
142d6379053Sbeveloper			delete_port(fControlPort);
1438abf9450SDario Casalinuovo	} else {
1448abf9450SDario Casalinuovo		TRACE("BMediaNode::~BMediaNode: shadow timesource,"
1458abf9450SDario Casalinuovo			" not unregistering\n");
1468abf9450SDario Casalinuovo	}
14752a38012Sejakowatz}
14852a38012Sejakowatz
14952a38012Sejakowatz
1502e60efdaSDario CasalinuovoBMediaNode*
15152a38012SejakowatzBMediaNode::Acquire()
15252a38012Sejakowatz{
15352a38012Sejakowatz	CALLED();
1546423f87fSDario Casalinuovo	if (atomic_add(&fRefCount,1) == 0) {
1556423f87fSDario Casalinuovo		status_t status = B_ERROR;
1566423f87fSDario Casalinuovo		BMediaRoster* roster = BMediaRoster::Roster(&status);
1576423f87fSDario Casalinuovo		if (roster != NULL && status == B_OK)
1586423f87fSDario Casalinuovo			MediaRosterEx(roster)->RegisterLocalNode(this);
1596423f87fSDario Casalinuovo	}
16052a38012Sejakowatz	return this;
16152a38012Sejakowatz}
16252a38012Sejakowatz
16352a38012Sejakowatz
1642e60efdaSDario CasalinuovoBMediaNode*
16552a38012SejakowatzBMediaNode::Release()
16652a38012Sejakowatz{
16752a38012Sejakowatz	CALLED();
16854187cc6Sbeveloper	if (atomic_add(&fRefCount, -1) == 1) {
1696423f87fSDario Casalinuovo		status_t status = B_ERROR;
1706423f87fSDario Casalinuovo		BMediaRoster* roster = BMediaRoster::Roster(&status);
1716423f87fSDario Casalinuovo		if (roster != NULL && status == B_OK) {
1726423f87fSDario Casalinuovo			MediaRosterEx(roster)->UnregisterLocalNode(this);
1736423f87fSDario Casalinuovo
1746423f87fSDario Casalinuovo			// Only addons needs the configuration to be saved.
1756423f87fSDario Casalinuovo			int32 id;
1766423f87fSDario Casalinuovo			if (AddOn(&id) != NULL) {
1776423f87fSDario Casalinuovo				TRACE("BMediaNode::Release() saving node %ld"
1786423f87fSDario Casalinuovo					" configuration\n", fNodeID);
1796423f87fSDario Casalinuovo				MediaRosterEx(roster)->SaveNodeConfiguration(this);
1806423f87fSDario Casalinuovo			}
1816423f87fSDario Casalinuovo
1826423f87fSDario Casalinuovo			if (DeleteHook(this) != B_OK) {
1836423f87fSDario Casalinuovo				ERROR("BMediaNode::Release(): DeleteHook failed\n");
1846423f87fSDario Casalinuovo				return Acquire();
1856423f87fSDario Casalinuovo			}
1866423f87fSDario Casalinuovo			return NULL;
18752a38012Sejakowatz		}
1886423f87fSDario Casalinuovo		TRACE("BMediaRoster::Release() the media roster is NULL!");
18952a38012Sejakowatz	}
19052a38012Sejakowatz	return this;
19152a38012Sejakowatz}
19252a38012Sejakowatz
19352a38012Sejakowatz
1942e60efdaSDario Casalinuovoconst char*
19552a38012SejakowatzBMediaNode::Name() const
19652a38012Sejakowatz{
19752a38012Sejakowatz	CALLED();
19852a38012Sejakowatz	return fName;
19952a38012Sejakowatz}
20052a38012Sejakowatz
20152a38012Sejakowatz
20252a38012Sejakowatzmedia_node_id
20352a38012SejakowatzBMediaNode::ID() const
20452a38012Sejakowatz{
20552a38012Sejakowatz	CALLED();
20652a38012Sejakowatz	return fNodeID;
20752a38012Sejakowatz}
20852a38012Sejakowatz
20952a38012Sejakowatz
21052a38012Sejakowatzuint64
21152a38012SejakowatzBMediaNode::Kinds() const
21252a38012Sejakowatz{
21352a38012Sejakowatz	CALLED();
214d6379053Sbeveloper	return fKinds & NODE_KIND_USER_MASK;
21552a38012Sejakowatz}
21652a38012Sejakowatz
21752a38012Sejakowatz
21852a38012Sejakowatzmedia_node
21952a38012SejakowatzBMediaNode::Node() const
22052a38012Sejakowatz{
22152a38012Sejakowatz	CALLED();
22252a38012Sejakowatz	media_node temp;
2234295907bSbeveloper	temp.node = ID();
2242e60efdaSDario Casalinuovo	// We *must* call ControlPort(), some derived nodes
2252e60efdaSDario Casalinuovo	// use it to start the port read thread!
2262e60efdaSDario Casalinuovo	temp.port = ControlPort();
22752a38012Sejakowatz	temp.kind = Kinds();
22852a38012Sejakowatz	return temp;
22952a38012Sejakowatz}
23052a38012Sejakowatz
23152a38012Sejakowatz
23252a38012SejakowatzBMediaNode::run_mode
23352a38012SejakowatzBMediaNode::RunMode() const
23452a38012Sejakowatz{
23552a38012Sejakowatz	CALLED();
23652a38012Sejakowatz	return fRunMode;
23752a38012Sejakowatz}
23852a38012Sejakowatz
23952a38012Sejakowatz
2402e60efdaSDario CasalinuovoBTimeSource*
24152a38012SejakowatzBMediaNode::TimeSource() const
24252a38012Sejakowatz{
2435ac4fbd7Sbeveloper	PRINT(7, "CALLED BMediaNode::TimeSource()\n");
24417a5db77SStephan Aßmus
2452e60efdaSDario Casalinuovo	// Return the currently assigned time source
246287f7492Sbeveloper	if (fTimeSource != 0)
247287f7492Sbeveloper		return fTimeSource;
24817a5db77SStephan Aßmus
2494295907bSbeveloper	TRACE("BMediaNode::TimeSource node %ld enter\n", ID());
25017a5db77SStephan Aßmus
2515917dd5bSbeveloper	// If the node doesn't have a time source object, we need to create one.
2525917dd5bSbeveloper	// If the node is still unregistered, we can't call MakeTimeSourceFor(),
2535917dd5bSbeveloper	// but since the node does still have the default system time source, we
2545917dd5bSbeveloper	// can use GetSystemTimeSource
25586bce45bSbeveloper
2562e60efdaSDario Casalinuovo	BMediaNode* self = const_cast<BMediaNode*>(this);
2572e60efdaSDario Casalinuovo	self->fTimeSource = MediaRosterEx(
2582e60efdaSDario Casalinuovo		BMediaRoster::Roster())->MakeTimeSourceObject(fTimeSourceID);
2592e60efdaSDario Casalinuovo
260d6379053Sbeveloper	ASSERT(fTimeSource == self->fTimeSource);
2615917dd5bSbeveloper
262287f7492Sbeveloper	if (fTimeSource == 0) {
2635ac4fbd7Sbeveloper		ERROR("BMediaNode::TimeSource: MakeTimeSourceFor failed\n");
2640e21b167Sbeveloper	} else {
2655917dd5bSbeveloper		ASSERT(fTimeSourceID == fTimeSource->ID());
2660e21b167Sbeveloper		fTimeSource->AddMe(self);
267287f7492Sbeveloper	}
26886bce45bSbeveloper
2694295907bSbeveloper	TRACE("BMediaNode::TimeSource node %ld leave\n", ID());
270287f7492Sbeveloper
27152a38012Sejakowatz	return fTimeSource;
27252a38012Sejakowatz}
27352a38012Sejakowatz
27452a38012Sejakowatz
2752e60efdaSDario Casalinuovoport_id
27652a38012SejakowatzBMediaNode::ControlPort() const
27752a38012Sejakowatz{
2785ac4fbd7Sbeveloper	PRINT(7, "CALLED BMediaNode::ControlPort()\n");
27952a38012Sejakowatz	return fControlPort;
28052a38012Sejakowatz}
28152a38012Sejakowatz
28252a38012Sejakowatz
28352a38012Sejakowatzstatus_t
2842e60efdaSDario CasalinuovoBMediaNode::ReportError(node_error what, const BMessage* info)
28552a38012Sejakowatz{
286eae26d3dSbeveloper	CALLED();
287f4925104Sbeveloper
2882e60efdaSDario Casalinuovo	// Sanity check the what value
289f4925104Sbeveloper	switch (what) {
290f4925104Sbeveloper		case BMediaNode::B_NODE_FAILED_START:
291f4925104Sbeveloper		case BMediaNode::B_NODE_FAILED_STOP:
292f4925104Sbeveloper		case BMediaNode::B_NODE_FAILED_SEEK:
293f4925104Sbeveloper		case BMediaNode::B_NODE_FAILED_SET_RUN_MODE:
294f4925104Sbeveloper		case BMediaNode::B_NODE_FAILED_TIME_WARP:
295f4925104Sbeveloper		case BMediaNode::B_NODE_FAILED_PREROLL:
296f4925104Sbeveloper		case BMediaNode::B_NODE_FAILED_SET_TIME_SOURCE_FOR:
297f4925104Sbeveloper		case BMediaNode::B_NODE_IN_DISTRESS:
298f4925104Sbeveloper			break;
299f4925104Sbeveloper		default:
3005ac4fbd7Sbeveloper			ERROR("BMediaNode::ReportError: invalid what!\n");
301f4925104Sbeveloper			return B_BAD_VALUE;
302f4925104Sbeveloper	}
30317a5db77SStephan Aßmus
304eae26d3dSbeveloper	// Transmits the error code specified by what to anyone
305eae26d3dSbeveloper	// that's receiving notifications from this node
306f4925104Sbeveloper	return BPrivate::media::notifications::ReportError(Node(), what, info);
30752a38012Sejakowatz}
30852a38012Sejakowatz
30952a38012Sejakowatz
31052a38012Sejakowatzstatus_t
31152a38012SejakowatzBMediaNode::NodeStopped(bigtime_t whenPerformance)
31252a38012Sejakowatz{
31352a38012Sejakowatz	UNIMPLEMENTED();
3142e60efdaSDario Casalinuovo	// Called by derived classes when they have
31552a38012Sejakowatz	// finished handling a stop request.
31617a5db77SStephan Aßmus
3172e60efdaSDario Casalinuovo	// Notify anyone who is listening for stop notifications!
318f4925104Sbeveloper	BPrivate::media::notifications::NodeStopped(Node(), whenPerformance);
31917a5db77SStephan Aßmus
3202e60efdaSDario Casalinuovo	// NOTE: If your node is a BBufferProducer, downstream consumers
3212e60efdaSDario Casalinuovo	// will be notified that your node stopped (automatically, no less) through
3222e60efdaSDario Casalinuovo	// the BBufferConsumer::ProducerDataStatus(B_PRODUCER_STOPPED) call.
32317a5db77SStephan Aßmus
32452a38012Sejakowatz	return B_OK;
32552a38012Sejakowatz}
32652a38012Sejakowatz
32752a38012Sejakowatz
32875486484SDario Casalinuovo/*
32975486484SDario Casalinuovo * Used in couple with AddTimer, this will cause the BMediaRoster::SyncToNode()
33075486484SDario Casalinuovo * call that requested the timer to return to the caller with an appropriate
33175486484SDario Casalinuovo * value.
33275486484SDario Casalinuovo */
33352a38012Sejakowatzvoid
3342e60efdaSDario CasalinuovoBMediaNode::TimerExpired(bigtime_t notifyPoint, int32 cookie, status_t error)
33552a38012Sejakowatz{
33675486484SDario Casalinuovo	CALLED();
33775486484SDario Casalinuovo	if (write_port((port_id)cookie, 0, &error, sizeof(error)) < 0) {
33875486484SDario Casalinuovo		TRACE("BMediaNode::TimerExpired: error writing port" B_PRId32
33975486484SDario Casalinuovo			", at notifyPoint" B_PRId64 "\n", cookie, notifyPoint);
34075486484SDario Casalinuovo	}
34152a38012Sejakowatz}
34252a38012Sejakowatz
34352a38012Sejakowatz
3442e60efdaSDario CasalinuovoBMediaNode::BMediaNode(const char* name)
34552a38012Sejakowatz{
346570f7d04Sbeveloper	TRACE("BMediaNode::BMediaNode: name '%s'\n", name);
3475917dd5bSbeveloper	_InitObject(name, NODE_JUST_CREATED_ID, 0);
34852a38012Sejakowatz}
34952a38012Sejakowatz
35052a38012Sejakowatz
35152a38012Sejakowatzstatus_t
3522e60efdaSDario CasalinuovoBMediaNode::WaitForMessage(bigtime_t waitUntil, uint32 flags,
3532e60efdaSDario Casalinuovo	void* _reserved_)
35452a38012Sejakowatz{
35531cf24c1SMarcus Overhagen	TRACE("entering: BMediaNode::WaitForMessage()\n");
3565ac4fbd7Sbeveloper
35717a5db77SStephan Aßmus	// This function waits until either real time specified by
35852a38012Sejakowatz	// waitUntil or a message is received on the control port.
35917a5db77SStephan Aßmus	// The flags are currently unused and should be 0.
3602e60efdaSDario Casalinuovo	// Note: about 16 KByte stack used
3612e60efdaSDario Casalinuovo	char data[B_MEDIA_MESSAGE_SIZE];
36252a38012Sejakowatz	int32 message;
363ec4d0e42SMichael Lotz	ssize_t size;
36490cdf5e4SDario Casalinuovo
365ec4d0e42SMichael Lotz	while (true) {
366ec4d0e42SMichael Lotz		size = read_port_etc(ControlPort(), &message, data,
367ec4d0e42SMichael Lotz			sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil);
368ec4d0e42SMichael Lotz
369ec4d0e42SMichael Lotz		if (size >= 0)
370ec4d0e42SMichael Lotz			break;
371ec4d0e42SMichael Lotz
372e339f816SStephan Aßmus		status_t error = (status_t)size;
373ec4d0e42SMichael Lotz		if (error == B_INTERRUPTED)
374ec4d0e42SMichael Lotz			continue;
375ec4d0e42SMichael Lotz
376ec4d0e42SMichael Lotz		if (error != B_TIMED_OUT && error != B_BAD_PORT_ID) {
3776b8545a4SStephan Aßmus			ERROR("BMediaNode::WaitForMessage: read_port_etc error: %s\n",
378e339f816SStephan Aßmus				strerror(error));
379ec4d0e42SMichael Lotz		}
380ec4d0e42SMichael Lotz
381e339f816SStephan Aßmus		return error;
38252a38012Sejakowatz	}
38352a38012Sejakowatz
3846b8545a4SStephan Aßmus	TRACE("BMediaNode::WaitForMessage request is: %#lx, node %ld, this %p\n",
3856b8545a4SStephan Aßmus		message, fNodeID, this);
386570f7d04Sbeveloper
3872e60efdaSDario Casalinuovo	if (message == GENERAL_PURPOSE_WAKEUP)
3882e60efdaSDario Casalinuovo		return B_OK;
389ba5e652dSAdrien Destugues
390570f7d04Sbeveloper	if (message > NODE_MESSAGE_START && message < NODE_MESSAGE_END) {
39131cf24c1SMarcus Overhagen		TRACE("BMediaNode::WaitForMessage calling BMediaNode\n");
3922e60efdaSDario Casalinuovo
393570f7d04Sbeveloper		if (B_OK == BMediaNode::HandleMessage(message, data, size))
394570f7d04Sbeveloper			return B_OK;
395570f7d04Sbeveloper	}
39617a5db77SStephan Aßmus
397570f7d04Sbeveloper	if (message > PRODUCER_MESSAGE_START && message < PRODUCER_MESSAGE_END) {
398570f7d04Sbeveloper		if (!fProducerThis)
3992e60efdaSDario Casalinuovo			fProducerThis = dynamic_cast<BBufferProducer*>(this);
4002e60efdaSDario Casalinuovo
4016b8545a4SStephan Aßmus		TRACE("BMediaNode::WaitForMessage calling BBufferProducer %p\n",
4026b8545a4SStephan Aßmus			fProducerThis);
4032e60efdaSDario Casalinuovo
4046b8545a4SStephan Aßmus		if (fProducerThis && fProducerThis->BBufferProducer::HandleMessage(
4056b8545a4SStephan Aßmus				message, data, size) == B_OK) {
406570f7d04Sbeveloper			return B_OK;
4076b8545a4SStephan Aßmus		}
408570f7d04Sbeveloper	}
409570f7d04Sbeveloper
410570f7d04Sbeveloper	if (message > CONSUMER_MESSAGE_START && message < CONSUMER_MESSAGE_END) {
411570f7d04Sbeveloper		if (!fConsumerThis)
4122e60efdaSDario Casalinuovo			fConsumerThis = dynamic_cast<BBufferConsumer*>(this);
4132e60efdaSDario Casalinuovo
4146b8545a4SStephan Aßmus		TRACE("BMediaNode::WaitForMessage calling BBufferConsumer %p\n",
4156b8545a4SStephan Aßmus			fConsumerThis);
4162e60efdaSDario Casalinuovo
4176b8545a4SStephan Aßmus		if (fConsumerThis && fConsumerThis->BBufferConsumer::HandleMessage(
4186b8545a4SStephan Aßmus			message, data, size) == B_OK) {
419570f7d04Sbeveloper			return B_OK;
4206b8545a4SStephan Aßmus		}
421570f7d04Sbeveloper	}
422570f7d04Sbeveloper
4236b8545a4SStephan Aßmus	if (message > FILEINTERFACE_MESSAGE_START
4246b8545a4SStephan Aßmus		&& message < FILEINTERFACE_MESSAGE_END) {
425570f7d04Sbeveloper		if (!fFileInterfaceThis)
4262e60efdaSDario Casalinuovo			fFileInterfaceThis = dynamic_cast<BFileInterface*>(this);
4272e60efdaSDario Casalinuovo
4286b8545a4SStephan Aßmus		TRACE("BMediaNode::WaitForMessage calling BFileInterface %p\n",
4296b8545a4SStephan Aßmus			fFileInterfaceThis);
4302e60efdaSDario Casalinuovo
4316b8545a4SStephan Aßmus		if (fFileInterfaceThis
4326b8545a4SStephan Aßmus			&& fFileInterfaceThis->BFileInterface::HandleMessage(
4336b8545a4SStephan Aßmus				message, data, size) == B_OK) {
434570f7d04Sbeveloper			return B_OK;
4356b8545a4SStephan Aßmus		}
436570f7d04Sbeveloper	}
437570f7d04Sbeveloper
4386b8545a4SStephan Aßmus	if (message > CONTROLLABLE_MESSAGE_START
4396b8545a4SStephan Aßmus		&& message < CONTROLLABLE_MESSAGE_END) {
440570f7d04Sbeveloper		if (!fControllableThis)
4412e60efdaSDario Casalinuovo			fControllableThis = dynamic_cast<BControllable*>(this);
4422e60efdaSDario Casalinuovo
4436b8545a4SStephan Aßmus		TRACE("BMediaNode::WaitForMessage calling BControllable %p\n",
4446b8545a4SStephan Aßmus			fControllableThis);
4452e60efdaSDario Casalinuovo
4466b8545a4SStephan Aßmus		if (fControllableThis
4476b8545a4SStephan Aßmus			&& fControllableThis->BControllable::HandleMessage(
4486b8545a4SStephan Aßmus				message, data, size) == B_OK) {
449570f7d04Sbeveloper			return B_OK;
4506b8545a4SStephan Aßmus		}
451570f7d04Sbeveloper	}
452570f7d04Sbeveloper
4536b8545a4SStephan Aßmus	if (message > TIMESOURCE_MESSAGE_START
4546b8545a4SStephan Aßmus		&& message < TIMESOURCE_MESSAGE_END) {
455570f7d04Sbeveloper		if (!fTimeSourceThis)
4562e60efdaSDario Casalinuovo			fTimeSourceThis = dynamic_cast<BTimeSource*>(this);
4572e60efdaSDario Casalinuovo
4586b8545a4SStephan Aßmus		TRACE("BMediaNode::WaitForMessage calling BTimeSource %p\n",
4596b8545a4SStephan Aßmus			fTimeSourceThis);
4602e60efdaSDario Casalinuovo
4616b8545a4SStephan Aßmus		if (fTimeSourceThis && fTimeSourceThis->BTimeSource::HandleMessage(
4626b8545a4SStephan Aßmus				message, data, size) == B_OK) {
463570f7d04Sbeveloper			return B_OK;
4646b8545a4SStephan Aßmus		}
465570f7d04Sbeveloper	}
466570f7d04Sbeveloper
46731cf24c1SMarcus Overhagen	TRACE("BMediaNode::WaitForMessage calling default HandleMessage\n");
4682e60efdaSDario Casalinuovo	if (HandleMessage(message, data, size) == B_OK)
46952a38012Sejakowatz		return B_OK;
47052a38012Sejakowatz
47152a38012Sejakowatz	HandleBadMessage(message, data, size);
47217a5db77SStephan Aßmus
47352a38012Sejakowatz	return B_ERROR;
47452a38012Sejakowatz}
47552a38012Sejakowatz
47652a38012Sejakowatz
4772e60efdaSDario Casalinuovovoid
47852a38012SejakowatzBMediaNode::Start(bigtime_t performance_time)
47952a38012Sejakowatz{
48052a38012Sejakowatz	CALLED();
48152a38012Sejakowatz	// This hook function is called when a node is started
48217a5db77SStephan Aßmus	// by a call to the BMediaRoster. The specified
48317a5db77SStephan Aßmus	// performanceTime, the time at which the node
48452a38012Sejakowatz	// should start running, may be in the future.
48552a38012Sejakowatz	// It may be overriden by derived classes.
48652a38012Sejakowatz	// The BMediaEventLooper class handles this event!
48752a38012Sejakowatz	// The BMediaNode class does nothing here.
48852a38012Sejakowatz}
48952a38012Sejakowatz
49052a38012Sejakowatz
4912e60efdaSDario Casalinuovovoid
4922e60efdaSDario CasalinuovoBMediaNode::Stop(bigtime_t performance_time, bool immediate)
49352a38012Sejakowatz{
49452a38012Sejakowatz	CALLED();
49552a38012Sejakowatz	// This hook function is called when a node is stopped
49617a5db77SStephan Aßmus	// by a call to the BMediaRoster. The specified
49717a5db77SStephan Aßmus	// performanceTime, the time at which the node
49852a38012Sejakowatz	// should stop running, may be in the future.
49952a38012Sejakowatz	// It may be overriden by derived classes.
50052a38012Sejakowatz	// The BMediaEventLooper class handles this event!
50152a38012Sejakowatz	// The BMediaNode class does nothing here.
50252a38012Sejakowatz}
50352a38012Sejakowatz
50452a38012Sejakowatz
5052e60efdaSDario Casalinuovovoid
5062e60efdaSDario CasalinuovoBMediaNode::Seek(bigtime_t media_time, bigtime_t performance_time)
50752a38012Sejakowatz{
50852a38012Sejakowatz	CALLED();
50952a38012Sejakowatz	// This hook function is called when a node is asked
51017a5db77SStephan Aßmus	// to seek to the specified mediaTime by a call to
51117a5db77SStephan Aßmus	// the BMediaRoster. The specified performanceTime,
51252a38012Sejakowatz	// the time at which the node should begin the seek
51352a38012Sejakowatz	// operation, may be in the future.
51452a38012Sejakowatz	// It may be overriden by derived classes.
51552a38012Sejakowatz	// The BMediaEventLooper class handles this event!
51652a38012Sejakowatz	// The BMediaNode class does nothing here.
51752a38012Sejakowatz}
51852a38012Sejakowatz
51952a38012Sejakowatz
5202e60efdaSDario Casalinuovovoid
52152a38012SejakowatzBMediaNode::SetRunMode(run_mode mode)
52252a38012Sejakowatz{
52352a38012Sejakowatz	CALLED();
52452a38012Sejakowatz
5252e60efdaSDario Casalinuovo	// This is a hook function, and
52652a38012Sejakowatz	// may be overriden by derived classes.
52717a5db77SStephan Aßmus
5282e60efdaSDario Casalinuovo	// The functionality here is only to
52952a38012Sejakowatz	// support those people that don't
53052a38012Sejakowatz	// use the roster to set the run mode
53152a38012Sejakowatz	fRunMode = mode;
53252a38012Sejakowatz}
53352a38012Sejakowatz
53452a38012Sejakowatz
5352e60efdaSDario Casalinuovovoid
5362e60efdaSDario CasalinuovoBMediaNode::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time)
53752a38012Sejakowatz{
53852a38012Sejakowatz	CALLED();
53952a38012Sejakowatz	// May be overriden by derived classes.
54052a38012Sejakowatz}
54152a38012Sejakowatz
54252a38012Sejakowatz
5432e60efdaSDario Casalinuovovoid
54452a38012SejakowatzBMediaNode::Preroll()
54552a38012Sejakowatz{
54652a38012Sejakowatz	CALLED();
54752a38012Sejakowatz	// May be overriden by derived classes.
54852a38012Sejakowatz}
54952a38012Sejakowatz
55052a38012Sejakowatz
5512e60efdaSDario Casalinuovovoid
5522e60efdaSDario CasalinuovoBMediaNode::SetTimeSource(BTimeSource* time_source)
55352a38012Sejakowatz{
55452a38012Sejakowatz	CALLED();
5552e60efdaSDario Casalinuovo	// This is a hook function, and
55652a38012Sejakowatz	// may be overriden by derived classes.
557287f7492Sbeveloper
55886bce45bSbeveloper	if (time_source == NULL || time_source == fTimeSource)
55986bce45bSbeveloper		return;
56017a5db77SStephan Aßmus
5612e60efdaSDario Casalinuovo	// We just trip into debugger, code that tries to do this is broken.
5622e60efdaSDario Casalinuovo	debugger("BMediaNode::SetTimeSource() can't be used to set a timesource, "
5632e60efdaSDario Casalinuovo		"use BMediaRoster::SetTimeSourceFor()!\n");
56452a38012Sejakowatz}
56552a38012Sejakowatz
56652a38012Sejakowatz
5672e60efdaSDario Casalinuovostatus_t
5682e60efdaSDario CasalinuovoBMediaNode::HandleMessage(int32 message, const void* data, size_t size)
56952a38012Sejakowatz{
57031cf24c1SMarcus Overhagen	TRACE("BMediaNode::HandleMessage %#lx, node %ld\n", message, fNodeID);
57152a38012Sejakowatz	switch (message) {
572cf4e2277Sbeveloper		case NODE_FINAL_RELEASE:
573cf4e2277Sbeveloper		{
5742e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_FINAL_RELEASE, this %p\n",
5752e60efdaSDario Casalinuovo				this);
5762e60efdaSDario Casalinuovo
577cf4e2277Sbeveloper			// This is called by the media server to delete the object
578cf4e2277Sbeveloper			// after is has been released by all nodes that are using it.
579cf4e2277Sbeveloper			// We forward the function to the BMediaRoster, since the
580cf4e2277Sbeveloper			// deletion must be done from a different thread, or the
581cf4e2277Sbeveloper			// outermost destructor that will exit the thread that is
582cf4e2277Sbeveloper			// reading messages from the port (this thread contex) will
583cf4e2277Sbeveloper			// quit, and ~BMediaNode destructor won't be called ever.
584cf4e2277Sbeveloper			BMessage msg(NODE_FINAL_RELEASE);
585cf4e2277Sbeveloper			msg.AddPointer("node", this);
586cf4e2277Sbeveloper			BMediaRoster::Roster()->PostMessage(&msg);
587cf4e2277Sbeveloper			return B_OK;
588cf4e2277Sbeveloper		}
58917a5db77SStephan Aßmus
59052a38012Sejakowatz		case NODE_START:
59152a38012Sejakowatz		{
5922e60efdaSDario Casalinuovo			const node_start_command* command
5932e60efdaSDario Casalinuovo				= static_cast<const node_start_command*>(data);
59431cf24c1SMarcus Overhagen			TRACE("BMediaNode::HandleMessage NODE_START, node %ld\n", fNodeID);
595dfb2ad61Sbeveloper			Start(command->performance_time);
59652a38012Sejakowatz			return B_OK;
59752a38012Sejakowatz		}
59852a38012Sejakowatz
59952a38012Sejakowatz		case NODE_STOP:
60052a38012Sejakowatz		{
6012e60efdaSDario Casalinuovo			const node_stop_command* command
6022e60efdaSDario Casalinuovo				= static_cast<const node_stop_command*>(data);
60331cf24c1SMarcus Overhagen			TRACE("BMediaNode::HandleMessage NODE_STOP, node %ld\n", fNodeID);
604dfb2ad61Sbeveloper			Stop(command->performance_time, command->immediate);
60552a38012Sejakowatz			return B_OK;
60652a38012Sejakowatz		}
60752a38012Sejakowatz
60852a38012Sejakowatz		case NODE_SEEK:
60952a38012Sejakowatz		{
6102e60efdaSDario Casalinuovo			const node_seek_command* command
6112e60efdaSDario Casalinuovo				= static_cast<const node_seek_command*>(data);
61231cf24c1SMarcus Overhagen			TRACE("BMediaNode::HandleMessage NODE_SEEK, node %ld\n", fNodeID);
613dfb2ad61Sbeveloper			Seek(command->media_time, command->performance_time);
61452a38012Sejakowatz			return B_OK;
61552a38012Sejakowatz		}
61652a38012Sejakowatz
61752a38012Sejakowatz		case NODE_SET_RUN_MODE:
61852a38012Sejakowatz		{
6192e60efdaSDario Casalinuovo			const node_set_run_mode_command* command
6202e60efdaSDario Casalinuovo				= static_cast<const node_set_run_mode_command*>(data);
6212e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_SET_RUN_MODE,"
6222e60efdaSDario Casalinuovo				" node %ld\n", fNodeID);
6232e60efdaSDario Casalinuovo			// Need to change PRODUCER_SET_RUN_MODE_DELAY
624dfb2ad61Sbeveloper			fRunMode = command->mode;
62552a38012Sejakowatz			SetRunMode(fRunMode);
62652a38012Sejakowatz			return B_OK;
62752a38012Sejakowatz		}
62852a38012Sejakowatz
62952a38012Sejakowatz		case NODE_TIME_WARP:
63052a38012Sejakowatz		{
6312e60efdaSDario Casalinuovo			const node_time_warp_command* command
6322e60efdaSDario Casalinuovo				= static_cast<const node_time_warp_command*>(data);
6332e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_TIME_WARP,"
6342e60efdaSDario Casalinuovo				" node %ld\n", fNodeID);
635dfb2ad61Sbeveloper			TimeWarp(command->at_real_time, command->to_performance_time);
63652a38012Sejakowatz			return B_OK;
63752a38012Sejakowatz		}
63852a38012Sejakowatz
63952a38012Sejakowatz		case NODE_PREROLL:
64052a38012Sejakowatz		{
6412e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_PREROLL, "
6422e60efdaSDario Casalinuovo				" node %ld\n", fNodeID);
64352a38012Sejakowatz			Preroll();
64452a38012Sejakowatz			return B_OK;
64552a38012Sejakowatz		}
64617a5db77SStephan Aßmus
64714896b93SDario Casalinuovo		case NODE_ROLL:
64814896b93SDario Casalinuovo		{
6492e60efdaSDario Casalinuovo			const node_roll_command* command
6502e60efdaSDario Casalinuovo				= static_cast<const node_roll_command*>(data);
65114896b93SDario Casalinuovo
65214896b93SDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_ROLL, node %ld\n",
65314896b93SDario Casalinuovo				fNodeID);
65414896b93SDario Casalinuovo
65514896b93SDario Casalinuovo			if (command->seek_media_time != B_INFINITE_TIMEOUT)
65614896b93SDario Casalinuovo				Seek(command->seek_media_time,
65714896b93SDario Casalinuovo					command->start_performance_time);
65814896b93SDario Casalinuovo
65914896b93SDario Casalinuovo			Start(command->start_performance_time);
66014896b93SDario Casalinuovo			Stop(command->stop_performance_time, false);
66114896b93SDario Casalinuovo			return B_OK;
66214896b93SDario Casalinuovo		}
66314896b93SDario Casalinuovo
66475486484SDario Casalinuovo		case NODE_SYNC_TO:
66575486484SDario Casalinuovo		{
6662e60efdaSDario Casalinuovo			const node_sync_to_request* request
6672e60efdaSDario Casalinuovo				= static_cast<const node_sync_to_request*>(data);
66875486484SDario Casalinuovo			node_sync_to_reply reply;
66975486484SDario Casalinuovo
67075486484SDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_SYNC_TO, node %ld\n",
67175486484SDario Casalinuovo				fNodeID);
67275486484SDario Casalinuovo
67375486484SDario Casalinuovo			// If AddTimer return an error the caller will know that the node
67475486484SDario Casalinuovo			// doesn't support this feature or there was a problem when adding
67575486484SDario Casalinuovo			// it, this will result in SyncToNode returning immediately
67675486484SDario Casalinuovo			// to the caller with an error.
67775486484SDario Casalinuovo			status_t status = AddTimer(request->performance_time,
67875486484SDario Casalinuovo				request->port);
67975486484SDario Casalinuovo
68075486484SDario Casalinuovo			request->SendReply(status, &reply, sizeof(reply));
68175486484SDario Casalinuovo			return B_OK;
68275486484SDario Casalinuovo		}
68375486484SDario Casalinuovo
68452a38012Sejakowatz		case NODE_SET_TIMESOURCE:
68552a38012Sejakowatz		{
6862e60efdaSDario Casalinuovo			const node_set_timesource_command* command
6872e60efdaSDario Casalinuovo				= static_cast<const node_set_timesource_command*>(data);
6885917dd5bSbeveloper
6892e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE,"
6902e60efdaSDario Casalinuovo				" node %ld, timesource %ld enter\n",
6912e60efdaSDario Casalinuovo				fNodeID, command->timesource_id);
69217a5db77SStephan Aßmus
6935917dd5bSbeveloper			fTimeSourceID = command->timesource_id;
69417a5db77SStephan Aßmus
695287f7492Sbeveloper			if (fTimeSource) {
6962e60efdaSDario Casalinuovo				// As this node already had a timesource, to remove this node
6972e60efdaSDario Casalinuovo				// from time source control
6980e21b167Sbeveloper				fTimeSource->RemoveMe(this);
6992e60efdaSDario Casalinuovo				// Release the time source
70052a38012Sejakowatz				fTimeSource->Release();
7012e60efdaSDario Casalinuovo				// Force next call to TimeSource() to create a new object
7025917dd5bSbeveloper				fTimeSource = 0;
703287f7492Sbeveloper			}
7045917dd5bSbeveloper
7052e60efdaSDario Casalinuovo			// Create new time source object and call the SetTimeSource
7062e60efdaSDario Casalinuovo			// hook function to notify any derived class
7075917dd5bSbeveloper			fTimeSource = TimeSource();
7085917dd5bSbeveloper			SetTimeSource(fTimeSource);
7095917dd5bSbeveloper
7102e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE, node %ld,"
7112e60efdaSDario Casalinuovo				"timesource %ld leave\n", fNodeID, command->timesource_id);
7125917dd5bSbeveloper
7135917dd5bSbeveloper			return B_OK;
7145917dd5bSbeveloper		}
71517a5db77SStephan Aßmus
7165917dd5bSbeveloper		case NODE_GET_TIMESOURCE:
7175917dd5bSbeveloper		{
7182e60efdaSDario Casalinuovo			const node_get_timesource_request* request
7192e60efdaSDario Casalinuovo				= static_cast<const node_get_timesource_request*>(data);
7202e60efdaSDario Casalinuovo
7212e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_GET_TIMESOURCE,"
7222e60efdaSDario Casalinuovo				" node %ld\n", fNodeID);
7232e60efdaSDario Casalinuovo
7245917dd5bSbeveloper			node_get_timesource_reply reply;
7255917dd5bSbeveloper			reply.timesource_id = fTimeSourceID;
7265917dd5bSbeveloper			request->SendReply(B_OK, &reply, sizeof(reply));
72752a38012Sejakowatz			return B_OK;
72852a38012Sejakowatz		}
72952a38012Sejakowatz
730c079d8d6SDario Casalinuovo		case NODE_GET_ATTRIBUTES_FOR:
731c079d8d6SDario Casalinuovo		{
732c079d8d6SDario Casalinuovo			const node_get_attributes_for_request *request =
733c079d8d6SDario Casalinuovo				(const node_get_attributes_for_request*) data;
734c079d8d6SDario Casalinuovo
735c079d8d6SDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_GET_ATTRIBUTES_FOR,"
736c079d8d6SDario Casalinuovo				"node %ld\n", fNodeID);
737c079d8d6SDario Casalinuovo
738c079d8d6SDario Casalinuovo			node_get_attributes_for_reply reply;
739c079d8d6SDario Casalinuovo
740c079d8d6SDario Casalinuovo			media_node_attribute* addr;
741c079d8d6SDario Casalinuovo			area_id dataArea = clone_area("client attributes area",
742c079d8d6SDario Casalinuovo				(void**)&addr, B_ANY_ADDRESS, B_WRITE_AREA,
743c079d8d6SDario Casalinuovo				request->area);
744c079d8d6SDario Casalinuovo
745c079d8d6SDario Casalinuovo			if (dataArea < 0) {
746c079d8d6SDario Casalinuovo				ERROR("NODE_GET_ATTRIBUTES_FOR can't clone area\n");
747c079d8d6SDario Casalinuovo				return B_NO_MEMORY;
748c079d8d6SDario Casalinuovo			}
749c079d8d6SDario Casalinuovo
750c079d8d6SDario Casalinuovo			status_t status = GetNodeAttributes(addr, request->count);
751c079d8d6SDario Casalinuovo			if (status == B_OK) {
752c079d8d6SDario Casalinuovo				// NOTE: we do it because there's not an easy way
753c079d8d6SDario Casalinuovo				// to guess the number of attributes filled.
754c079d8d6SDario Casalinuovo				size_t i;
755c079d8d6SDario Casalinuovo				for (i = 0; i < request->count; i++) {
756c079d8d6SDario Casalinuovo					if (addr[i].what <= 0)
757c079d8d6SDario Casalinuovo						break;
758c079d8d6SDario Casalinuovo				}
759c079d8d6SDario Casalinuovo				reply.filled_count = i;
760c079d8d6SDario Casalinuovo			}
761c079d8d6SDario Casalinuovo			request->SendReply(status, &reply, sizeof(reply));
762c079d8d6SDario Casalinuovo			delete_area(dataArea);
763c079d8d6SDario Casalinuovo			return B_OK;
764c079d8d6SDario Casalinuovo		}
765c079d8d6SDario Casalinuovo
76652a38012Sejakowatz		case NODE_REQUEST_COMPLETED:
76752a38012Sejakowatz		{
7682e60efdaSDario Casalinuovo			const node_request_completed_command* command
7692e60efdaSDario Casalinuovo				= static_cast<const node_request_completed_command*>(data);
7702e60efdaSDario Casalinuovo			TRACE("BMediaNode::HandleMessage NODE_REQUEST_COMPLETED,"
7712e60efdaSDario Casalinuovo				" node %ld\n", fNodeID);
772dfb2ad61Sbeveloper			RequestCompleted(command->info);
77352a38012Sejakowatz			return B_OK;
77452a38012Sejakowatz		}
77517a5db77SStephan Aßmus
7762e60efdaSDario Casalinuovo		default:
7772e60efdaSDario Casalinuovo			return B_ERROR;
7782e60efdaSDario Casalinuovo
7792e60efdaSDario Casalinuovo	}
78052a38012Sejakowatz	return B_ERROR;
78152a38012Sejakowatz}
78252a38012Sejakowatz
78352a38012Sejakowatz
78452a38012Sejakowatzvoid
7852e60efdaSDario CasalinuovoBMediaNode::HandleBadMessage(int32 code, const void* buffer, size_t size)
78652a38012Sejakowatz{
78752a38012Sejakowatz	CALLED();
7883620737cSbeveloper
7892e60efdaSDario Casalinuovo	TRACE("BMediaNode::HandleBadMessage: code %#08lx, buffer %p, size %ld\n",
7902e60efdaSDario Casalinuovo		code, buffer, size);
7917fd43270Sbeveloper	if (code < NODE_MESSAGE_START || code > TIMESOURCE_MESSAGE_END) {
7925ac4fbd7Sbeveloper		ERROR("BMediaNode::HandleBadMessage: unknown code!\n");
7931299bfb2Sbeveloper	} else {
7942e60efdaSDario Casalinuovo		 // All messages targeted to nodes should be handled here,
7952e60efdaSDario Casalinuovo		 // messages targetted to the wrong node should be handled
7962e60efdaSDario Casalinuovo		 // by returning an error, not by stalling the sender.
7972e60efdaSDario Casalinuovo		const request_data* request = static_cast<const request_data* >(buffer);
7981299bfb2Sbeveloper		reply_data reply;
7991299bfb2Sbeveloper		request->SendReply(B_ERROR, &reply, sizeof(reply));
8003620737cSbeveloper	}
80152a38012Sejakowatz}
80252a38012Sejakowatz
80352a38012Sejakowatz
80452a38012Sejakowatzvoid
80552a38012SejakowatzBMediaNode::AddNodeKind(uint64 kind)
80652a38012Sejakowatz{
807570f7d04Sbeveloper	TRACE("BMediaNode::AddNodeKind: node %ld, this %p\n", fNodeID, this);
80852a38012Sejakowatz	fKinds |= kind;
80952a38012Sejakowatz}
81052a38012Sejakowatz
81152a38012Sejakowatz
8122e60efdaSDario Casalinuovovoid*
81352a38012SejakowatzBMediaNode::operator new(size_t size)
81452a38012Sejakowatz{
81552a38012Sejakowatz	CALLED();
81652a38012Sejakowatz	return ::operator new(size);
81752a38012Sejakowatz}
81852a38012Sejakowatz
8192e60efdaSDario Casalinuovo
8202e60efdaSDario Casalinuovovoid*
8212e60efdaSDario CasalinuovoBMediaNode::operator new(size_t size, const nothrow_t&) throw()
82252a38012Sejakowatz{
82352a38012Sejakowatz	CALLED();
824d54e84e0Sbeveloper	return ::operator new(size, nothrow);
82552a38012Sejakowatz}
82652a38012Sejakowatz
8272e60efdaSDario Casalinuovo
82852a38012Sejakowatzvoid
8292e60efdaSDario CasalinuovoBMediaNode::operator delete(void* ptr)
83052a38012Sejakowatz{
83152a38012Sejakowatz	CALLED();
83252a38012Sejakowatz	::operator delete(ptr);
83352a38012Sejakowatz}
83452a38012Sejakowatz
8352e60efdaSDario Casalinuovo
83617a5db77SStephan Aßmusvoid
8372e60efdaSDario CasalinuovoBMediaNode::operator delete(void* ptr, const nothrow_t&) throw()
83852a38012Sejakowatz{
83952a38012Sejakowatz	CALLED();
840d54e84e0Sbeveloper	::operator delete(ptr, nothrow);
84152a38012Sejakowatz}
84252a38012Sejakowatz
84352a38012Sejakowatz
8442e60efdaSDario Casalinuovostatus_t
8452e60efdaSDario CasalinuovoBMediaNode::RequestCompleted(const media_request_info& info)
84652a38012Sejakowatz{
84752a38012Sejakowatz	CALLED();
8488abf9450SDario Casalinuovo	// This function is called whenever
8498abf9450SDario Casalinuovo	// a request issued by the node is completed.
85052a38012Sejakowatz	// May be overriden by derived classes.
85117a5db77SStephan Aßmus	// info.change_tag can be used to match up requests against
85252a38012Sejakowatz	// the accompaning calles from
85352a38012Sejakowatz	// BBufferConsumer::RequestFormatChange()
85452a38012Sejakowatz	// BBufferConsumer::SetOutputBuffersFor()
85552a38012Sejakowatz	// BBufferConsumer::SetOutputEnabled()
85652a38012Sejakowatz	// BBufferConsumer::SetVideoClippingFor()
85752a38012Sejakowatz	return B_OK;
85852a38012Sejakowatz}
85952a38012Sejakowatz
86052a38012Sejakowatz
86152a38012Sejakowatzstatus_t
8622e60efdaSDario CasalinuovoBMediaNode::DeleteHook(BMediaNode* node)
86352a38012Sejakowatz{
86452a38012Sejakowatz	CALLED();
865c74afb57SJérôme Duval	// Attention! We do not unregister TimeSourceObject nodes,
866c74afb57SJérôme Duval	// since they are only a shadow object, and the real one still exists
867c74afb57SJérôme Duval	if ((fKinds & NODE_KIND_SHADOW_TIMESOURCE) == 0)
868c74afb57SJérôme Duval		BMediaRoster::Roster()->UnregisterNode(this);
869cf4e2277Sbeveloper	delete this; // delete "this" or "node", both are the same
87052a38012Sejakowatz	return B_OK;
87152a38012Sejakowatz}
87252a38012Sejakowatz
87352a38012Sejakowatz
8742e60efdaSDario Casalinuovovoid
87552a38012SejakowatzBMediaNode::NodeRegistered()
87652a38012Sejakowatz{
87752a38012Sejakowatz	CALLED();
8788abf9450SDario Casalinuovo	// The Media Server calls this hook function
8798abf9450SDario Casalinuovo	// after the node has been registered.
88052a38012Sejakowatz	// May be overriden by derived classes.
88152a38012Sejakowatz}
88252a38012Sejakowatz
88352a38012Sejakowatz
8842e60efdaSDario Casalinuovostatus_t
8852e60efdaSDario CasalinuovoBMediaNode::GetNodeAttributes(media_node_attribute* outAttributes,
8862e60efdaSDario Casalinuovo	size_t inMaxCount)
88752a38012Sejakowatz{
8888abf9450SDario Casalinuovo	CALLED();
8898abf9450SDario Casalinuovo	// This is implemented by derived classes that fills
890c079d8d6SDario Casalinuovo	// it's own attributes to a max of inMaxCount elements.
89152a38012Sejakowatz	return B_ERROR;
89252a38012Sejakowatz}
89352a38012Sejakowatz
89452a38012Sejakowatz
8952e60efdaSDario Casalinuovostatus_t
8962e60efdaSDario CasalinuovoBMediaNode::AddTimer(bigtime_t at_performance_time, int32 cookie)
89752a38012Sejakowatz{
89875486484SDario Casalinuovo	CALLED();
89952a38012Sejakowatz	return B_ERROR;
90052a38012Sejakowatz}
90152a38012Sejakowatz
90252a38012Sejakowatz
9032e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_0(void*) { return B_ERROR; }
9042e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_1(void*) { return B_ERROR; }
9052e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_2(void*) { return B_ERROR; }
9062e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_3(void*) { return B_ERROR; }
9072e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_4(void*) { return B_ERROR; }
9082e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_5(void*) { return B_ERROR; }
9092e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_6(void*) { return B_ERROR; }
9102e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_7(void*) { return B_ERROR; }
9112e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_8(void*) { return B_ERROR; }
9122e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_9(void*) { return B_ERROR; }
9132e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_10(void*) { return B_ERROR; }
9142e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_11(void*) { return B_ERROR; }
9152e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_12(void*) { return B_ERROR; }
9162e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_13(void*) { return B_ERROR; }
9172e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_14(void*) { return B_ERROR; }
9182e60efdaSDario Casalinuovostatus_t BMediaNode::_Reserved_MediaNode_15(void*) { return B_ERROR; }
91952a38012Sejakowatz
92052a38012Sejakowatz/*
92152a38012Sejakowatzprivate unimplemented
92252a38012SejakowatzBMediaNode::BMediaNode()
92352a38012SejakowatzBMediaNode::BMediaNode(const BMediaNode &clone)
92452a38012SejakowatzBMediaNode &BMediaNode::operator=(const BMediaNode &clone)
92552a38012Sejakowatz*/
92652a38012Sejakowatz
927570f7d04Sbevelopervoid
9282e60efdaSDario CasalinuovoBMediaNode::_InitObject(const char* name, media_node_id id, uint64 kinds)
92952a38012Sejakowatz{
930570f7d04Sbeveloper	TRACE("BMediaNode::_InitObject: nodeid %ld, this %p\n", id, this);
931570f7d04Sbeveloper
932570f7d04Sbeveloper	fNodeID = id;
933570f7d04Sbeveloper	fRefCount = 1;
93452a38012Sejakowatz	fName[0] = 0;
935a49fe9b8SJonas Sundström	if (name)
936a49fe9b8SJonas Sundström		strlcpy(fName, name, B_MEDIA_NAME_LENGTH);
937570f7d04Sbeveloper	fRunMode = B_INCREASE_LATENCY;
938570f7d04Sbeveloper	fKinds = kinds;
939570f7d04Sbeveloper	fProducerThis = 0;
940570f7d04Sbeveloper	fConsumerThis = 0;
941570f7d04Sbeveloper	fFileInterfaceThis = 0;
942570f7d04Sbeveloper	fControllableThis = 0;
943570f7d04Sbeveloper	fTimeSourceThis = 0;
94452a38012Sejakowatz
9452e60efdaSDario Casalinuovo	// Create control port
94686bce45bSbeveloper	fControlPort = create_port(64, fName);
94717a5db77SStephan Aßmus
9482e60efdaSDario Casalinuovo	// Nodes are assigned the system time source by default
9495917dd5bSbeveloper	fTimeSourceID = NODE_SYSTEM_TIMESOURCE_ID;
9505917dd5bSbeveloper
9515917dd5bSbeveloper	// We can't create the timesource object here, because
9525917dd5bSbeveloper	// every timesource is a BMediaNode, which would result
9535917dd5bSbeveloper	// in infinite recursions
9545917dd5bSbeveloper	fTimeSource = NULL;
95552a38012Sejakowatz}
95652a38012Sejakowatz
95752a38012Sejakowatz
9582e60efdaSDario CasalinuovoBMediaNode::BMediaNode(const char* name, media_node_id id, uint32 kinds)
959570f7d04Sbeveloper{
9602e60efdaSDario Casalinuovo	TRACE("BMediaNode::BMediaNode: name '%s', nodeid %ld, kinds %#lx\n",
9612e60efdaSDario Casalinuovo		name, id, kinds);
962570f7d04Sbeveloper	_InitObject(name, id, kinds);
963570f7d04Sbeveloper}
964570f7d04Sbeveloper
965570f7d04Sbeveloper
9662e60efdaSDario Casalinuovoint32
96752a38012SejakowatzBMediaNode::NewChangeTag()
96852a38012Sejakowatz{
96952a38012Sejakowatz	CALLED();
9702e60efdaSDario Casalinuovo	// Change tags have been used in BeOS R4 to match up
97152a38012Sejakowatz	// format change requests between producer and consumer,
97252a38012Sejakowatz	// This has changed starting with R4.5
9732e60efdaSDario Casalinuovo	// now "change tags" are used with the following functions:
97452a38012Sejakowatz	// BMediaNode::RequestCompleted()
97552a38012Sejakowatz	// BBufferConsumer::RequestFormatChange()
97652a38012Sejakowatz	// BBufferConsumer::SetOutputBuffersFor()
97752a38012Sejakowatz	// BBufferConsumer::SetOutputEnabled()
97852a38012Sejakowatz	// BBufferConsumer::SetVideoClippingFor()
97952a38012Sejakowatz	return atomic_add(&BMediaNode::_m_changeTag,1);
98052a38012Sejakowatz}
9812e60efdaSDario Casalinuovo
9822e60efdaSDario Casalinuovo// BeOS R4 deprecated API
9832e60efdaSDario Casalinuovo
9842e60efdaSDario Casalinuovoint32
9852e60efdaSDario CasalinuovoBMediaNode::IncrementChangeTag()
9862e60efdaSDario Casalinuovo{
9872e60efdaSDario Casalinuovo	CALLED();
9882e60efdaSDario Casalinuovo	// Only present in BeOS R4
9892e60efdaSDario Casalinuovo	// Obsoleted in BeOS R4.5 and later
9908abf9450SDario Casalinuovo	// "updates the change tag, so that downstream consumers
9918abf9450SDario Casalinuovo	// know that the node is in a new state."
9922e60efdaSDario Casalinuovo	// not supported, only for binary compatibility
9932e60efdaSDario Casalinuovo	return 0;
9942e60efdaSDario Casalinuovo}
9952e60efdaSDario Casalinuovo
9962e60efdaSDario Casalinuovo
9972e60efdaSDario Casalinuovoint32
9982e60efdaSDario CasalinuovoBMediaNode::ChangeTag()
9992e60efdaSDario Casalinuovo{
10002e60efdaSDario Casalinuovo	UNIMPLEMENTED();
10012e60efdaSDario Casalinuovo	// Only present in BeOS R4
10022e60efdaSDario Casalinuovo	// Obsoleted in BeOS R4.5 and later
10032e60efdaSDario Casalinuovo	// "returns the node's current change tag value."
10042e60efdaSDario Casalinuovo	// not supported, only for binary compatibility
10052e60efdaSDario Casalinuovo	return 0;
10062e60efdaSDario Casalinuovo}
10072e60efdaSDario Casalinuovo
10082e60efdaSDario Casalinuovo
10092e60efdaSDario Casalinuovoint32
10102e60efdaSDario CasalinuovoBMediaNode::MintChangeTag()
10112e60efdaSDario Casalinuovo{
10122e60efdaSDario Casalinuovo	UNIMPLEMENTED();
10132e60efdaSDario Casalinuovo	// Only present in BeOS R4
10142e60efdaSDario Casalinuovo	// Obsoleted in BeOS R4.5 and later
10152e60efdaSDario Casalinuovo	// "mints a new, reserved, change tag."
10162e60efdaSDario Casalinuovo	// "Call ApplyChangeTag() to apply it to the node"
10172e60efdaSDario Casalinuovo	// not supported, only for binary compatibility
10182e60efdaSDario Casalinuovo	return 0;
10192e60efdaSDario Casalinuovo}
10202e60efdaSDario Casalinuovo
10212e60efdaSDario Casalinuovo
10222e60efdaSDario Casalinuovostatus_t
10232e60efdaSDario CasalinuovoBMediaNode::ApplyChangeTag(int32 previously_reserved)
10242e60efdaSDario Casalinuovo{
10252e60efdaSDario Casalinuovo	UNIMPLEMENTED();
10262e60efdaSDario Casalinuovo	// Only present in BeOS R4
10272e60efdaSDario Casalinuovo	// Obsoleted in BeOS R4.5 and later
10282e60efdaSDario Casalinuovo	// "this returns B_OK if the new change tag is"
10292e60efdaSDario Casalinuovo	// "successfully applied, or B_MEDIA_STALE_CHANGE_TAG if the new change"
10302e60efdaSDario Casalinuovo	// "count you tried to apply is already obsolete."
10312e60efdaSDario Casalinuovo	// not supported, only for binary compatibility
10322e60efdaSDario Casalinuovo	return B_OK;
10332e60efdaSDario Casalinuovo}
1034