1c284bb0fSMatt Madia/*
2a820304dSMatt Madia * Copyright 1991-1999, Be Incorporated.
3c284bb0fSMatt Madia * Copyright (c) 1999-2000, Eric Moon.
4c284bb0fSMatt Madia * All rights reserved.
5c284bb0fSMatt Madia *
6c284bb0fSMatt Madia * Redistribution and use in source and binary forms, with or without
7c284bb0fSMatt Madia * modification, are permitted provided that the following conditions
8c284bb0fSMatt Madia * are met:
9c284bb0fSMatt Madia *
10c284bb0fSMatt Madia * 1. Redistributions of source code must retain the above copyright
11c284bb0fSMatt Madia *    notice, this list of conditions, and the following disclaimer.
12c284bb0fSMatt Madia *
13c284bb0fSMatt Madia * 2. Redistributions in binary form must reproduce the above copyright
14c284bb0fSMatt Madia *    notice, this list of conditions, and the following disclaimer in the
15c284bb0fSMatt Madia *    documentation and/or other materials provided with the distribution.
16c284bb0fSMatt Madia *
17c284bb0fSMatt Madia * 3. The name of the author may not be used to endorse or promote products
18c284bb0fSMatt Madia *    derived from this software without specific prior written permission.
19c284bb0fSMatt Madia *
20c284bb0fSMatt Madia * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
21c284bb0fSMatt Madia * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22c284bb0fSMatt Madia * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23c284bb0fSMatt Madia * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24c284bb0fSMatt Madia * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25c284bb0fSMatt Madia * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26c284bb0fSMatt Madia * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27c284bb0fSMatt Madia * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
28c284bb0fSMatt Madia * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29c284bb0fSMatt Madia * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30c284bb0fSMatt Madia */
31c284bb0fSMatt Madia
32c284bb0fSMatt Madia
33a0795c6fSMarcus Overhagen// LoggingConsumer.cpp
34a0795c6fSMarcus Overhagen
35a0795c6fSMarcus Overhagen#include "LoggingConsumer.h"
36a0795c6fSMarcus Overhagen#include "LogWriter.h"
37a0795c6fSMarcus Overhagen#include <media/MediaRoster.h>
38a0795c6fSMarcus Overhagen#include <media/TimeSource.h>
39a0795c6fSMarcus Overhagen#include <media/ParameterWeb.h>
40a0795c6fSMarcus Overhagen#include <media/Buffer.h>
41a0795c6fSMarcus Overhagen#include <kernel/OS.h>
42a0795c6fSMarcus Overhagen#include <stdio.h>
43a0795c6fSMarcus Overhagen#include <string.h>
44a0795c6fSMarcus Overhagen
45a0795c6fSMarcus Overhagen// e.moon [11jun99]
46a0795c6fSMarcus Overhagen#include <Debug.h>
47a0795c6fSMarcus Overhagen
48a0795c6fSMarcus Overhagen// id's of the node's BParameters
49a0795c6fSMarcus Overhagenconst int32 INPUT_NULL_PARAM = 1;
50a0795c6fSMarcus Overhagenconst int32 LATENCY_PARAM = 2;
51a0795c6fSMarcus Overhagenconst int32 OUTPUT_NULL_PARAM = 3;
52a0795c6fSMarcus Overhagenconst int32 CPU_NULL_PARAM = 11;
53a0795c6fSMarcus Overhagenconst int32 CPU_SPIN_PARAM = 12;
54a0795c6fSMarcus Overhagenconst int32 PRIO_NULL_PARAM = 21;
55a0795c6fSMarcus Overhagenconst int32 PRIORITY_PARAM = 22;
56a0795c6fSMarcus Overhagen
57a0795c6fSMarcus Overhagen// build the LoggingConsumer's BParameterWeb
58a0795c6fSMarcus Overhagenstatic BParameterWeb* build_parameter_web()
59a0795c6fSMarcus Overhagen{
60a0795c6fSMarcus Overhagen	BParameterWeb* web = new BParameterWeb;
61a0795c6fSMarcus Overhagen
62a0795c6fSMarcus Overhagen	BParameterGroup* mainGroup = web->MakeGroup("LoggingConsumer Parameters");
637974d3dcSStephan Aßmus	BParameterGroup* group = mainGroup->MakeGroup("Latency control");
64a0795c6fSMarcus Overhagen	BParameter* nullParam = group->MakeNullParameter(INPUT_NULL_PARAM, B_MEDIA_NO_TYPE, "Latency", B_GENERIC);
65a0795c6fSMarcus Overhagen	BParameter* latencyParam = group->MakeContinuousParameter(LATENCY_PARAM, B_MEDIA_NO_TYPE, "",
667974d3dcSStephan Aßmus		B_GAIN, "ms", 5, 100, 5);
67a0795c6fSMarcus Overhagen	nullParam->AddOutput(latencyParam);
68a0795c6fSMarcus Overhagen	latencyParam->AddInput(nullParam);
69a0795c6fSMarcus Overhagen
707974d3dcSStephan Aßmus	group = mainGroup->MakeGroup("CPU percentage");
717974d3dcSStephan Aßmus	nullParam = group->MakeNullParameter(CPU_NULL_PARAM, B_MEDIA_NO_TYPE, "CPU spin percentage", B_GENERIC);
72a0795c6fSMarcus Overhagen	BContinuousParameter* cpuParam = group->MakeContinuousParameter(CPU_SPIN_PARAM, B_MEDIA_NO_TYPE, "",
73a0795c6fSMarcus Overhagen		B_GAIN, "percent", 5, 80, 5);
74a0795c6fSMarcus Overhagen	nullParam->AddOutput(cpuParam);
75a0795c6fSMarcus Overhagen	cpuParam->AddInput(nullParam);
76a0795c6fSMarcus Overhagen
77a0795c6fSMarcus Overhagen	group = mainGroup->MakeGroup("Priority");
787974d3dcSStephan Aßmus	nullParam = group->MakeNullParameter(PRIO_NULL_PARAM, B_MEDIA_NO_TYPE, "Thread priority", B_GENERIC);
79a0795c6fSMarcus Overhagen	BDiscreteParameter* prioParam = group->MakeDiscreteParameter(PRIORITY_PARAM, B_MEDIA_NO_TYPE, "", B_GENERIC);
80a0795c6fSMarcus Overhagen	prioParam->AddItem(5, "B_LOW_PRIORITY");
81a0795c6fSMarcus Overhagen	prioParam->AddItem(10, "B_NORMAL_PRIORITY");
82a0795c6fSMarcus Overhagen	prioParam->AddItem(15, "B_DISPLAY_PRIORITY");
83a0795c6fSMarcus Overhagen	prioParam->AddItem(20, "B_URGENT_DISPLAY_PRIORITY");
84a0795c6fSMarcus Overhagen	prioParam->AddItem(100, "B_REAL_TIME_DISPLAY_PRIORITY");
85a0795c6fSMarcus Overhagen	prioParam->AddItem(110, "B_URGENT_PRIORITY");
86a0795c6fSMarcus Overhagen	prioParam->AddItem(120, "B_REAL_TIME_PRIORITY");
87a0795c6fSMarcus Overhagen
88a0795c6fSMarcus Overhagen	return web;
89a0795c6fSMarcus Overhagen}
90a0795c6fSMarcus Overhagen
91a0795c6fSMarcus Overhagen// --------------------
92a0795c6fSMarcus Overhagen// LoggingConsumer class implementation
93a0795c6fSMarcus OverhagenLoggingConsumer::LoggingConsumer(
94a0795c6fSMarcus Overhagen	const entry_ref& logFile,
95a0795c6fSMarcus Overhagen	BMediaAddOn* pAddOn)
96a820304dSMatt Madia
97a0795c6fSMarcus Overhagen	:	BMediaNode("LoggingConsumer"),
98a0795c6fSMarcus Overhagen		BBufferConsumer(B_MEDIA_UNKNOWN_TYPE),
99a0795c6fSMarcus Overhagen		BControllable(),
100a0795c6fSMarcus Overhagen		BMediaEventLooper(),
101a0795c6fSMarcus Overhagen		mLogRef(logFile),
102a0795c6fSMarcus Overhagen		mWeb(NULL),
103a0795c6fSMarcus Overhagen		mLateBuffers(0),
104a0795c6fSMarcus Overhagen		mLatency(50 * 1000),		// default to 50 milliseconds
105a0795c6fSMarcus Overhagen		mSpinPercentage(0.10),		// default to spinning 10% of total latency
106a0795c6fSMarcus Overhagen		mPriority(B_URGENT_DISPLAY_PRIORITY),		// !!! testing; will be B_REAL_TIME_PRIORITY for release
107a0795c6fSMarcus Overhagen		mLastLatencyChange(0),
108a0795c6fSMarcus Overhagen		mLastSpinChange(0),
10981fa5e80SMaurice Kalinowski		mLastPrioChange(0),
11081fa5e80SMaurice Kalinowski		m_pAddOn(pAddOn)
111a0795c6fSMarcus Overhagen{
112a0795c6fSMarcus Overhagen	// spin off the logging thread
113a0795c6fSMarcus Overhagen	mLogger = new LogWriter(logFile);
114a0795c6fSMarcus Overhagen
115a0795c6fSMarcus Overhagen	// parameter-web init moved to NodeRegistered()
116a0795c6fSMarcus Overhagen	// e.moon [11jun99]
117a0795c6fSMarcus Overhagen}
118a0795c6fSMarcus Overhagen
119a0795c6fSMarcus OverhagenLoggingConsumer::~LoggingConsumer()
120a0795c6fSMarcus Overhagen{
121a0795c6fSMarcus Overhagen	PRINT(("~LoggingConsumer()\n"));
122a0795c6fSMarcus Overhagen	BMediaEventLooper::Quit();
123a0795c6fSMarcus Overhagen// ahem:
124a0795c6fSMarcus Overhagen// "Once you've called BControllable::SetParameterWeb(), the node takes
125a0795c6fSMarcus Overhagen//  responsibility for the parameter web object and you shouldn't delete it. "
126a0795c6fSMarcus Overhagen//	SetParameterWeb(NULL);
127a0795c6fSMarcus Overhagen//	delete mWeb;
128a0795c6fSMarcus Overhagen
129a0795c6fSMarcus Overhagen	// delete the logging thread only after the looper thread has quit, otherwise there's
130a0795c6fSMarcus Overhagen	// a potential race condition with the looper thread trying to write to the now-
131a0795c6fSMarcus Overhagen	// deleted log
132a0795c6fSMarcus Overhagen	delete mLogger;
133a0795c6fSMarcus Overhagen}
134a0795c6fSMarcus Overhagen
135a0795c6fSMarcus Overhagen//
136a0795c6fSMarcus Overhagen// Log message filtering control
137a0795c6fSMarcus Overhagen//
138a0795c6fSMarcus Overhagen
139a820304dSMatt Madiavoid
140a0795c6fSMarcus OverhagenLoggingConsumer::SetEnabled(log_what what, bool enable)
141a0795c6fSMarcus Overhagen{
142a0795c6fSMarcus Overhagen	mLogger->SetEnabled(what, enable);
143a0795c6fSMarcus Overhagen}
144a0795c6fSMarcus Overhagen
145a820304dSMatt Madiavoid
146a0795c6fSMarcus OverhagenLoggingConsumer::EnableAllMessages()
147a0795c6fSMarcus Overhagen{
148a0795c6fSMarcus Overhagen	mLogger->EnableAllMessages();
149a0795c6fSMarcus Overhagen}
150a0795c6fSMarcus Overhagen
151a820304dSMatt Madiavoid
152a0795c6fSMarcus OverhagenLoggingConsumer::DisableAllMessages()
153a0795c6fSMarcus Overhagen{
154a0795c6fSMarcus Overhagen	mLogger->DisableAllMessages();
155a0795c6fSMarcus Overhagen}
156a0795c6fSMarcus Overhagen
157a0795c6fSMarcus Overhagen//
158a0795c6fSMarcus Overhagen// BMediaNode methods
159a0795c6fSMarcus Overhagen//
160a0795c6fSMarcus Overhagen
161a0795c6fSMarcus Overhagen
162a0795c6fSMarcus OverhagenBMediaAddOn*
163a0795c6fSMarcus OverhagenLoggingConsumer::AddOn(int32 *internal_id) const
164a0795c6fSMarcus Overhagen{
165a0795c6fSMarcus Overhagen	PRINT(("~LoggingConsumer::AddOn()\n"));
166a0795c6fSMarcus Overhagen	// e.moon [11jun99]
167a0795c6fSMarcus Overhagen	if(m_pAddOn) {
168a0795c6fSMarcus Overhagen		*internal_id = 0;
169a0795c6fSMarcus Overhagen		return m_pAddOn;
170a0795c6fSMarcus Overhagen	} else
171a0795c6fSMarcus Overhagen		return NULL;
172a0795c6fSMarcus Overhagen}
173a0795c6fSMarcus Overhagen
174a820304dSMatt Madiavoid
175a0795c6fSMarcus OverhagenLoggingConsumer::SetRunMode(run_mode mode)
176a0795c6fSMarcus Overhagen{
177a0795c6fSMarcus Overhagen	// !!! Need to handle offline mode etc. properly!
178a0795c6fSMarcus Overhagen	log_message logMsg;
179a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
180a0795c6fSMarcus Overhagen	mLogger->Log(LOG_SET_RUN_MODE, logMsg);
181a0795c6fSMarcus Overhagen
182a0795c6fSMarcus Overhagen	BMediaEventLooper::SetRunMode(mode);
183a0795c6fSMarcus Overhagen}
184a0795c6fSMarcus Overhagen
185a820304dSMatt Madiavoid
186a0795c6fSMarcus OverhagenLoggingConsumer::Preroll()
187a0795c6fSMarcus Overhagen{
188a0795c6fSMarcus Overhagen	log_message logMsg;
189a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
190a0795c6fSMarcus Overhagen	mLogger->Log(LOG_PREROLL, logMsg);
191a0795c6fSMarcus Overhagen
192a0795c6fSMarcus Overhagen	BMediaEventLooper::Preroll();
193a0795c6fSMarcus Overhagen}
194a0795c6fSMarcus Overhagen
195a820304dSMatt Madiavoid
196a0795c6fSMarcus OverhagenLoggingConsumer::SetTimeSource(BTimeSource* time_source)
197a0795c6fSMarcus Overhagen{
198a0795c6fSMarcus Overhagen	log_message logMsg;
199a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
200a0795c6fSMarcus Overhagen	mLogger->Log(LOG_SET_TIME_SOURCE, logMsg);
201a0795c6fSMarcus Overhagen
202a0795c6fSMarcus Overhagen	BMediaNode::SetTimeSource(time_source);
203a0795c6fSMarcus Overhagen}
204a0795c6fSMarcus Overhagen
205a820304dSMatt Madiastatus_t
206a0795c6fSMarcus OverhagenLoggingConsumer::RequestCompleted(const media_request_info &info)
207a0795c6fSMarcus Overhagen{
208a0795c6fSMarcus Overhagen	log_message logMsg;
209a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
210a0795c6fSMarcus Overhagen	mLogger->Log(LOG_REQUEST_COMPLETED, logMsg);
211a0795c6fSMarcus Overhagen
212a0795c6fSMarcus Overhagen	return BMediaNode::RequestCompleted(info);
213a0795c6fSMarcus Overhagen}
214a0795c6fSMarcus Overhagen
215a820304dSMatt Madia// e.moon [11jun99; testing add-on]
216a0795c6fSMarcus Overhagenstatus_t
217a0795c6fSMarcus OverhagenLoggingConsumer::DeleteHook(BMediaNode* pNode) {
218a0795c6fSMarcus Overhagen	PRINT(("LoggingConsumer::DeleteHook(%p)\n", pNode));
219a0795c6fSMarcus Overhagen	return BBufferConsumer::DeleteHook(pNode);
220a0795c6fSMarcus Overhagen//	ASSERT(pNode == this);
221a0795c6fSMarcus Overhagen//	delete this;
222a0795c6fSMarcus Overhagen//	return B_OK;
223a0795c6fSMarcus Overhagen}
224a0795c6fSMarcus Overhagen
225a0795c6fSMarcus Overhagen//
226a0795c6fSMarcus Overhagen// BControllable methods
227a0795c6fSMarcus Overhagen//
228a0795c6fSMarcus Overhagen
229a820304dSMatt Madiastatus_t
230a0795c6fSMarcus OverhagenLoggingConsumer::GetParameterValue(int32 id, bigtime_t* last_change, void* value, size_t* ioSize)
231a0795c6fSMarcus Overhagen{
232a0795c6fSMarcus Overhagen	log_message logMsg;
233a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
234a0795c6fSMarcus Overhagen	logMsg.param.id = id;
235a0795c6fSMarcus Overhagen	mLogger->Log(LOG_GET_PARAM_VALUE, logMsg);
236a0795c6fSMarcus Overhagen
237a0795c6fSMarcus Overhagen	// return an error if the caller hasn't reserved enough space for the parameter data.
238a0795c6fSMarcus Overhagen	// we know that all of our parameters fit in a float or int32 (4 bytes), so we can just
239a0795c6fSMarcus Overhagen	// check for it once here, instead of on a per-parameter basis
240a0795c6fSMarcus Overhagen	if (*ioSize < sizeof(float)) return B_ERROR;
241a0795c6fSMarcus Overhagen
242a0795c6fSMarcus Overhagen	// write out the designated parameter data
243a0795c6fSMarcus Overhagen	switch (id)
244a0795c6fSMarcus Overhagen	{
245a0795c6fSMarcus Overhagen	case LATENCY_PARAM:
246a0795c6fSMarcus Overhagen		*last_change = mLastLatencyChange;
247a0795c6fSMarcus Overhagen		*((float*) value) = mLatency / 1000;		// the BParameter reads milliseconds, not microseconds
248a0795c6fSMarcus Overhagen		*ioSize = sizeof(float);
249a0795c6fSMarcus Overhagen		break;
250a0795c6fSMarcus Overhagen
251a0795c6fSMarcus Overhagen	case CPU_SPIN_PARAM:
252a0795c6fSMarcus Overhagen		*last_change = mLastSpinChange;
253a0795c6fSMarcus Overhagen		*((float*) value) = mSpinPercentage;
254a0795c6fSMarcus Overhagen		*ioSize = sizeof(float);
255a0795c6fSMarcus Overhagen		break;
256a0795c6fSMarcus Overhagen
257a0795c6fSMarcus Overhagen	case PRIORITY_PARAM:
258a0795c6fSMarcus Overhagen		*last_change = mLastPrioChange;
259a0795c6fSMarcus Overhagen		*((int32*) value) = mPriority;
260a0795c6fSMarcus Overhagen		*ioSize = sizeof(int32);
261a0795c6fSMarcus Overhagen		break;
262a0795c6fSMarcus Overhagen
263a0795c6fSMarcus Overhagen	default:
264a0795c6fSMarcus Overhagen		return B_ERROR;
265a0795c6fSMarcus Overhagen	}
266a0795c6fSMarcus Overhagen
267a0795c6fSMarcus Overhagen	return B_OK;
268a0795c6fSMarcus Overhagen}
269a0795c6fSMarcus Overhagen
270a820304dSMatt Madiavoid
271a0795c6fSMarcus OverhagenLoggingConsumer::SetParameterValue(int32 id, bigtime_t performance_time, const void* value, size_t size)
272a0795c6fSMarcus Overhagen{
273a0795c6fSMarcus Overhagen	log_message logMsg;
274a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
275a0795c6fSMarcus Overhagen	logMsg.param.id = id;
276a0795c6fSMarcus Overhagen	mLogger->Log(LOG_SET_PARAM_VALUE, logMsg);
277a0795c6fSMarcus Overhagen
278a0795c6fSMarcus Overhagen	// if it's one of our parameters, enqueue a "set parameter" event for handling at the appropriate time
279a0795c6fSMarcus Overhagen	switch (id)
280a0795c6fSMarcus Overhagen	{
281a0795c6fSMarcus Overhagen	case LATENCY_PARAM:
282a0795c6fSMarcus Overhagen	case CPU_SPIN_PARAM:
283a0795c6fSMarcus Overhagen	case PRIORITY_PARAM:
284a0795c6fSMarcus Overhagen		{
285a0795c6fSMarcus Overhagen			// !!! Change from B_USER_EVENT to B_SET_PARAMETER once it's defined
286a0795c6fSMarcus Overhagen			media_timed_event event(performance_time, BTimedEventQueue::B_USER_EVENT,
287a0795c6fSMarcus Overhagen				(void*) value, BTimedEventQueue::B_NO_CLEANUP, size, id, NULL);
288a0795c6fSMarcus Overhagen			EventQueue()->AddEvent(event);
289a0795c6fSMarcus Overhagen		}
290a0795c6fSMarcus Overhagen		break;
291a0795c6fSMarcus Overhagen
292a0795c6fSMarcus Overhagen	default:		// do nothing for other parameter IDs
293a0795c6fSMarcus Overhagen		break;
294a0795c6fSMarcus Overhagen	}
295a0795c6fSMarcus Overhagen	return;
296a0795c6fSMarcus Overhagen}
297a0795c6fSMarcus Overhagen
298a0795c6fSMarcus Overhagen//
299a0795c6fSMarcus Overhagen// BBufferConsumer methods
300a0795c6fSMarcus Overhagen//
301a0795c6fSMarcus Overhagen
302a820304dSMatt Madiastatus_t
303a0795c6fSMarcus OverhagenLoggingConsumer::HandleMessage(int32 message, const void *data, size_t size)
304a0795c6fSMarcus Overhagen{
305a0795c6fSMarcus Overhagen	log_message logMsg;
306a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
307a0795c6fSMarcus Overhagen	mLogger->Log(LOG_HANDLE_MESSAGE, logMsg);
308a0795c6fSMarcus Overhagen
309a0795c6fSMarcus Overhagen	// try each of our superclasses to handle the message
310a0795c6fSMarcus Overhagen	status_t err;
311a0795c6fSMarcus Overhagen	err = BControllable::HandleMessage(message, data, size);
312a0795c6fSMarcus Overhagen	if (err) err = BBufferConsumer::HandleMessage(message, data, size);
313a0795c6fSMarcus Overhagen	if (err) err = BMediaNode::HandleMessage(message, data, size);
314a0795c6fSMarcus Overhagen	return err;
315a0795c6fSMarcus Overhagen}
316a0795c6fSMarcus Overhagen
317a0795c6fSMarcus Overhagen// all of these next methods are pure virtual in BBufferConsumer
318a0795c6fSMarcus Overhagen
319a820304dSMatt Madiastatus_t
320a0795c6fSMarcus OverhagenLoggingConsumer::AcceptFormat(const media_destination& dest, media_format* format)
321a0795c6fSMarcus Overhagen{
322a0795c6fSMarcus Overhagen	char formatStr[256];
323a0795c6fSMarcus Overhagen	string_for_format(*format, formatStr, 255);
324a0795c6fSMarcus Overhagen	PRINT(("LoggingConsumer::AcceptFormat:\n\tformat %s\n", formatStr));
325a0795c6fSMarcus Overhagen
326a0795c6fSMarcus Overhagen	log_message logMsg;
327a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
328a0795c6fSMarcus Overhagen	mLogger->Log(LOG_ACCEPT_FORMAT, logMsg);
329a0795c6fSMarcus Overhagen
330a0795c6fSMarcus Overhagen	// return an error if this isn't really our one input's destination
331a0795c6fSMarcus Overhagen	if (dest != mInput.destination) return B_MEDIA_BAD_DESTINATION;
332a0795c6fSMarcus Overhagen
333a0795c6fSMarcus Overhagen	// the destination given really is our input, and we accept any kind of media data,
334a0795c6fSMarcus Overhagen	// so now we just confirm that we can handle whatever the producer asked for.
335a0795c6fSMarcus Overhagen	return B_OK;
336a0795c6fSMarcus Overhagen}
337a0795c6fSMarcus Overhagen
338a820304dSMatt Madiastatus_t
339a0795c6fSMarcus OverhagenLoggingConsumer::GetNextInput(int32* cookie, media_input* out_input)
340a0795c6fSMarcus Overhagen{
341a0795c6fSMarcus Overhagen	// we have a single hardcoded input that can accept any kind of media data
342a0795c6fSMarcus Overhagen	if (0 == *cookie)
343a0795c6fSMarcus Overhagen	{
344a0795c6fSMarcus Overhagen		mInput.format.type = B_MEDIA_UNKNOWN_TYPE;		// accept any format
345a820304dSMatt Madia
346a0795c6fSMarcus Overhagen		*out_input = mInput;
347a0795c6fSMarcus Overhagen		*cookie = 1;
348a0795c6fSMarcus Overhagen		return B_OK;
349a0795c6fSMarcus Overhagen	}
350a0795c6fSMarcus Overhagen	else return B_BAD_INDEX;
351a0795c6fSMarcus Overhagen}
352a0795c6fSMarcus Overhagen
353a820304dSMatt Madiavoid
354a0795c6fSMarcus OverhagenLoggingConsumer::DisposeInputCookie(int32 /*cookie*/ )
355a0795c6fSMarcus Overhagen{
356a0795c6fSMarcus Overhagen	// we don't use any kind of state or extra storage for iterating over our
357a0795c6fSMarcus Overhagen	// inputs, so we don't have to do any special disposal of input cookies.
358a0795c6fSMarcus Overhagen}
359a0795c6fSMarcus Overhagen
360a820304dSMatt Madiavoid
361a0795c6fSMarcus OverhagenLoggingConsumer::BufferReceived(BBuffer* buffer)
362a0795c6fSMarcus Overhagen{
363a0795c6fSMarcus Overhagen	bigtime_t bufferStart = buffer->Header()->start_time;
364a0795c6fSMarcus Overhagen	bigtime_t now = TimeSource()->Now();
365a0795c6fSMarcus Overhagen	bigtime_t how_early = bufferStart - EventLatency() - SchedulingLatency() - now;
366a0795c6fSMarcus Overhagen
367a0795c6fSMarcus Overhagen	log_message logMsg;
368a0795c6fSMarcus Overhagen	logMsg.now = now;
369a0795c6fSMarcus Overhagen	logMsg.buffer_data.start_time = bufferStart;
370a0795c6fSMarcus Overhagen	logMsg.buffer_data.offset = how_early;
371a0795c6fSMarcus Overhagen	mLogger->Log(LOG_BUFFER_RECEIVED, logMsg);
372a0795c6fSMarcus Overhagen
373a0795c6fSMarcus Overhagen	// There's a special case here with handling B_MEDIA_PARAMETERS buffers.
374a0795c6fSMarcus Overhagen	// These contain sets of parameter value changes, with their own performance
375a0795c6fSMarcus Overhagen	// times embedded in the buffers.  So, we want to dispatch those parameter
376a0795c6fSMarcus Overhagen	// changes as their own events rather than pushing this buffer on the queue to
377a0795c6fSMarcus Overhagen	// be handled later.
378a0795c6fSMarcus Overhagen	if (B_MEDIA_PARAMETERS == buffer->Header()->type)
379a0795c6fSMarcus Overhagen	{
380a0795c6fSMarcus Overhagen		ApplyParameterData(buffer->Data(), buffer->SizeUsed());
381a0795c6fSMarcus Overhagen		buffer->Recycle();
382a0795c6fSMarcus Overhagen	}
383a0795c6fSMarcus Overhagen	else		// ahh, it's a regular media buffer, so push it on the event queue
384a0795c6fSMarcus Overhagen	{
385a0795c6fSMarcus Overhagen		status_t err;
386a0795c6fSMarcus Overhagen		media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
387a0795c6fSMarcus Overhagen			buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
388a0795c6fSMarcus Overhagen		err = EventQueue()->AddEvent(event);
389a0795c6fSMarcus Overhagen
390a0795c6fSMarcus Overhagen		// HandleEvent() will recycle the buffer.  However, if we incurred an error trying to
391a0795c6fSMarcus Overhagen		// put the event into the queue, we have to recycle it ourselves, since HandleEvent()
392a0795c6fSMarcus Overhagen		// will never see the buffer in that case.
393a0795c6fSMarcus Overhagen		if (err) buffer->Recycle();
394a0795c6fSMarcus Overhagen	}
395a0795c6fSMarcus Overhagen}
396a0795c6fSMarcus Overhagen
397a820304dSMatt Madiavoid
398a0795c6fSMarcus OverhagenLoggingConsumer::ProducerDataStatus(const media_destination& for_whom, int32 status, bigtime_t at_performance_time)
399a0795c6fSMarcus Overhagen{
400a0795c6fSMarcus Overhagen	log_message logMsg;
401a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
402a0795c6fSMarcus Overhagen	logMsg.data_status.status = status;
403a0795c6fSMarcus Overhagen	mLogger->Log(LOG_PRODUCER_DATA_STATUS, logMsg);
404a0795c6fSMarcus Overhagen
405a0795c6fSMarcus Overhagen	if (for_whom == mInput.destination)
406a0795c6fSMarcus Overhagen	{
407a0795c6fSMarcus Overhagen		media_timed_event event(at_performance_time, BTimedEventQueue::B_DATA_STATUS,
408a0795c6fSMarcus Overhagen			&mInput, BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
409a0795c6fSMarcus Overhagen		EventQueue()->AddEvent(event);
410a0795c6fSMarcus Overhagen	}
411a0795c6fSMarcus Overhagen}
412a0795c6fSMarcus Overhagen
413a820304dSMatt Madiastatus_t
414a0795c6fSMarcus OverhagenLoggingConsumer::GetLatencyFor(const media_destination& for_whom, bigtime_t* out_latency, media_node_id* out_timesource)
415a0795c6fSMarcus Overhagen{
416a0795c6fSMarcus Overhagen	// make sure this is one of my valid inputs
417a0795c6fSMarcus Overhagen	if (for_whom != mInput.destination) return B_MEDIA_BAD_DESTINATION;
418a0795c6fSMarcus Overhagen
419a0795c6fSMarcus Overhagen	// report internal latency + downstream latency here, NOT including scheduling latency.
420a0795c6fSMarcus Overhagen	// we're a final consumer (no outputs), so we have no downstream latency.
421a0795c6fSMarcus Overhagen	*out_latency = mLatency;
422a0795c6fSMarcus Overhagen	*out_timesource = TimeSource()->ID();
423a0795c6fSMarcus Overhagen	return B_OK;
424a0795c6fSMarcus Overhagen}
425a0795c6fSMarcus Overhagen
426a820304dSMatt Madiastatus_t
427a0795c6fSMarcus OverhagenLoggingConsumer::Connected(
428a0795c6fSMarcus Overhagen	const media_source& producer,
429a0795c6fSMarcus Overhagen	const media_destination& where,
430a0795c6fSMarcus Overhagen	const media_format& with_format,
431a0795c6fSMarcus Overhagen	media_input* out_input)
432a0795c6fSMarcus Overhagen{
433a0795c6fSMarcus Overhagen
434a0795c6fSMarcus Overhagen	char formatStr[256];
435a0795c6fSMarcus Overhagen	string_for_format(with_format, formatStr, 255);
436a0795c6fSMarcus Overhagen	PRINT(("LoggingConsumer::Connected:\n\tformat %s\n", formatStr));
437a0795c6fSMarcus Overhagen	string_for_format(mInput.format, formatStr, 255);
438a0795c6fSMarcus Overhagen	PRINT(("\tinput format %s\n", formatStr));
439a0795c6fSMarcus Overhagen
440a0795c6fSMarcus Overhagen	log_message logMsg;
441a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
442a0795c6fSMarcus Overhagen	mLogger->Log(LOG_CONNECTED, logMsg);
443a0795c6fSMarcus Overhagen
444a0795c6fSMarcus Overhagen	if (where != mInput.destination) return B_MEDIA_BAD_DESTINATION;
445a0795c6fSMarcus Overhagen
446a0795c6fSMarcus Overhagen	// calculate my latency here, because it may depend on buffer sizes/durations, then
447a0795c6fSMarcus Overhagen	// tell the BMediaEventLooper how early we need to get the buffers
448a0795c6fSMarcus Overhagen	SetEventLatency(mLatency);
449a0795c6fSMarcus Overhagen
450a0795c6fSMarcus Overhagen	// record useful information about the connection, and return success
451a0795c6fSMarcus Overhagen	// * e.moon [14jun99]: stores format
452a0795c6fSMarcus Overhagen	mInput.format = with_format;
453a0795c6fSMarcus Overhagen	mInput.source = producer;
454a0795c6fSMarcus Overhagen	*out_input = mInput;
455a0795c6fSMarcus Overhagen	return B_OK;
456a0795c6fSMarcus Overhagen}
457a0795c6fSMarcus Overhagen
458a820304dSMatt Madiavoid
459a0795c6fSMarcus OverhagenLoggingConsumer::Disconnected(
460a0795c6fSMarcus Overhagen	const media_source& producer,
461a0795c6fSMarcus Overhagen	const media_destination& where)
462a0795c6fSMarcus Overhagen{
463a0795c6fSMarcus Overhagen	log_message logMsg;
464a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
465a0795c6fSMarcus Overhagen	mLogger->Log(LOG_DISCONNECTED, logMsg);
466a0795c6fSMarcus Overhagen
467a0795c6fSMarcus Overhagen	// wipe out our input record
46838b01557SAugustin Cavalier	mInput = media_input();
469a0795c6fSMarcus Overhagen}
470a0795c6fSMarcus Overhagen
471a820304dSMatt Madiastatus_t
472a0795c6fSMarcus OverhagenLoggingConsumer::FormatChanged(
473a0795c6fSMarcus Overhagen	const media_source& producer,
474a0795c6fSMarcus Overhagen	const media_destination& consumer,
475a0795c6fSMarcus Overhagen	int32 change_tag,
476a0795c6fSMarcus Overhagen	const media_format& format)
477a0795c6fSMarcus Overhagen{
478a0795c6fSMarcus Overhagen	log_message logMsg;
479a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
480a0795c6fSMarcus Overhagen	mLogger->Log(LOG_FORMAT_CHANGED, logMsg);
481a0795c6fSMarcus Overhagen
482a0795c6fSMarcus Overhagen	return B_OK;
483a0795c6fSMarcus Overhagen}
484a0795c6fSMarcus Overhagen
485a820304dSMatt Madiastatus_t
486a0795c6fSMarcus OverhagenLoggingConsumer::SeekTagRequested(
487a0795c6fSMarcus Overhagen	const media_destination& destination,
488a0795c6fSMarcus Overhagen	bigtime_t in_target_time,
489a0795c6fSMarcus Overhagen	uint32 in_flags,
490a0795c6fSMarcus Overhagen	media_seek_tag* out_seek_tag,
491a0795c6fSMarcus Overhagen	bigtime_t* out_tagged_time,
492a0795c6fSMarcus Overhagen	uint32* out_flags)
493a0795c6fSMarcus Overhagen{
494a0795c6fSMarcus Overhagen	log_message logMsg;
495a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
496a0795c6fSMarcus Overhagen	mLogger->Log(LOG_SEEK_TAG, logMsg);
497a0795c6fSMarcus Overhagen
498a0795c6fSMarcus Overhagen	return B_OK;
499a0795c6fSMarcus Overhagen}
500a0795c6fSMarcus Overhagen
501a0795c6fSMarcus Overhagen//
502a0795c6fSMarcus Overhagen// BMediaEventLooper virtual methods
503a0795c6fSMarcus Overhagen//
504a0795c6fSMarcus Overhagen
505a820304dSMatt Madiavoid
506a0795c6fSMarcus OverhagenLoggingConsumer::NodeRegistered()
507a0795c6fSMarcus Overhagen{
508a0795c6fSMarcus Overhagen	log_message logMsg;
509a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
510a0795c6fSMarcus Overhagen	mLogger->Log(LOG_REGISTERED, logMsg);
511a0795c6fSMarcus Overhagen
512a0795c6fSMarcus Overhagen	// publish our parameter web
513a0795c6fSMarcus Overhagen	mWeb = build_parameter_web();
514a0795c6fSMarcus Overhagen	SetParameterWeb(mWeb);
515a0795c6fSMarcus Overhagen
516a0795c6fSMarcus Overhagen	// Set our priority and start the BMediaEventLooper's thread
517a0795c6fSMarcus Overhagen	SetPriority(mPriority);
518a0795c6fSMarcus Overhagen	Run();
519a0795c6fSMarcus Overhagen
520a0795c6fSMarcus Overhagen	// Initialize as much of our input as we can, now that the Media Kit really "knows" about us
521a0795c6fSMarcus Overhagen	mInput.destination.port = ControlPort();
522a0795c6fSMarcus Overhagen	mInput.destination.id = 0;
523a0795c6fSMarcus Overhagen	mInput.node = Node();
524a0795c6fSMarcus Overhagen	strcpy(mInput.name, "Logged input");
525a0795c6fSMarcus Overhagen}
526a0795c6fSMarcus Overhagen
527a820304dSMatt Madiavoid
528a0795c6fSMarcus OverhagenLoggingConsumer::Start(bigtime_t performance_time)
529a0795c6fSMarcus Overhagen{
5307bd2f594SAugustin Cavalier	PRINT(("LoggingConsumer::Start(%" B_PRIdBIGTIME "): now %" B_PRIdBIGTIME "\n",
5317bd2f594SAugustin Cavalier		performance_time, TimeSource()->Now()));
532a0795c6fSMarcus Overhagen
533a0795c6fSMarcus Overhagen	log_message logMsg;
534a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
535a0795c6fSMarcus Overhagen	mLogger->Log(LOG_START, logMsg);
536a0795c6fSMarcus Overhagen
537a0795c6fSMarcus Overhagen	BMediaEventLooper::Start(performance_time);
538a0795c6fSMarcus Overhagen}
539a0795c6fSMarcus Overhagen
540a820304dSMatt Madiavoid
541a0795c6fSMarcus OverhagenLoggingConsumer::Stop(bigtime_t performance_time, bool immediate)
542a0795c6fSMarcus Overhagen{
543a0795c6fSMarcus Overhagen	log_message logMsg;
544a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
545a0795c6fSMarcus Overhagen	mLogger->Log(LOG_STOP, logMsg);
546a0795c6fSMarcus Overhagen
547a0795c6fSMarcus Overhagen	BMediaEventLooper::Stop(performance_time, immediate);
548a0795c6fSMarcus Overhagen}
549a0795c6fSMarcus Overhagen
550a820304dSMatt Madiavoid
551a0795c6fSMarcus OverhagenLoggingConsumer::Seek(bigtime_t media_time, bigtime_t performance_time)
552a0795c6fSMarcus Overhagen{
553a0795c6fSMarcus Overhagen	log_message logMsg;
554a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
555a0795c6fSMarcus Overhagen	mLogger->Log(LOG_SEEK, logMsg);
556a0795c6fSMarcus Overhagen
557a0795c6fSMarcus Overhagen	BMediaEventLooper::Seek(media_time, performance_time);
558a0795c6fSMarcus Overhagen}
559a0795c6fSMarcus Overhagen
560a820304dSMatt Madiavoid
561a0795c6fSMarcus OverhagenLoggingConsumer::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time)
562a0795c6fSMarcus Overhagen{
563a0795c6fSMarcus Overhagen	log_message logMsg;
564a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
565a0795c6fSMarcus Overhagen	mLogger->Log(LOG_TIMEWARP, logMsg);
566a0795c6fSMarcus Overhagen
567a0795c6fSMarcus Overhagen	BMediaEventLooper::TimeWarp(at_real_time, to_performance_time);
568a0795c6fSMarcus Overhagen}
569a0795c6fSMarcus Overhagen
570a820304dSMatt Madiavoid
571a0795c6fSMarcus OverhagenLoggingConsumer::HandleEvent(const media_timed_event *event, bigtime_t /* lateness */, bool /* realTimeEvent */)
572a0795c6fSMarcus Overhagen{
573a0795c6fSMarcus Overhagen	log_message logMsg;
574a0795c6fSMarcus Overhagen	logMsg.now = TimeSource()->Now();
575a0795c6fSMarcus Overhagen	mLogger->Log(LOG_HANDLE_EVENT, logMsg);
576a0795c6fSMarcus Overhagen
577a0795c6fSMarcus Overhagen	switch (event->type)
578a0795c6fSMarcus Overhagen	{
579a0795c6fSMarcus Overhagen	case BTimedEventQueue::B_HANDLE_BUFFER:
580a0795c6fSMarcus Overhagen		{
581a0795c6fSMarcus Overhagen			BBuffer* buffer = const_cast<BBuffer*>((BBuffer*) event->pointer);
582a0795c6fSMarcus Overhagen			if (buffer)
583a0795c6fSMarcus Overhagen			{
584a0795c6fSMarcus Overhagen				media_header* hdr = buffer->Header();
585a0795c6fSMarcus Overhagen				if (hdr->destination == mInput.destination.id)
586a0795c6fSMarcus Overhagen				{
587a0795c6fSMarcus Overhagen					bigtime_t now = TimeSource()->Now();
588a0795c6fSMarcus Overhagen					bigtime_t perf_time = hdr->start_time;
589a0795c6fSMarcus Overhagen
590a0795c6fSMarcus Overhagen					// the how_early calculated here doesn't include scheduling latency because
591a0795c6fSMarcus Overhagen					// we've already been scheduled to handle the buffer
592a0795c6fSMarcus Overhagen					bigtime_t how_early = perf_time - mLatency - now;
593a0795c6fSMarcus Overhagen
594a0795c6fSMarcus Overhagen					// logMsg.now is already set
595a0795c6fSMarcus Overhagen					logMsg.buffer_data.start_time = perf_time;
596a0795c6fSMarcus Overhagen					logMsg.buffer_data.offset = how_early;
597a0795c6fSMarcus Overhagen					mLogger->Log(LOG_BUFFER_HANDLED, logMsg);
598a0795c6fSMarcus Overhagen
599a0795c6fSMarcus Overhagen					// if the buffer is late, we ignore it and report the fact to the producer
600a0795c6fSMarcus Overhagen					// who sent it to us
601a0795c6fSMarcus Overhagen					if (how_early < 0)
602a0795c6fSMarcus Overhagen					{
603a0795c6fSMarcus Overhagen						mLateBuffers++;
604a0795c6fSMarcus Overhagen						NotifyLateProducer(mInput.source, -how_early, perf_time);
605a0795c6fSMarcus Overhagen					}
606a0795c6fSMarcus Overhagen					else
607a0795c6fSMarcus Overhagen					{
608a0795c6fSMarcus Overhagen						// burn some percentage of our stated latency in CPU time (controlled by
609a0795c6fSMarcus Overhagen						// a BParameter).  this simulates a user-configurable amount of CPU cost
610a0795c6fSMarcus Overhagen						// associated with the consumer.
611a0795c6fSMarcus Overhagen						bigtime_t spin_start = ::system_time();
612a0795c6fSMarcus Overhagen						bigtime_t spin_now = spin_start;
613a0795c6fSMarcus Overhagen						bigtime_t usecToSpin = bigtime_t(mSpinPercentage / 100.0 * mLatency);
614a0795c6fSMarcus Overhagen						while (spin_now - spin_start < usecToSpin)
615a0795c6fSMarcus Overhagen						{
616a0795c6fSMarcus Overhagen							for (long k = 0; k < 1000000; k++) { /* intentionally blank */ }
617a0795c6fSMarcus Overhagen							spin_now = ::system_time();
618a0795c6fSMarcus Overhagen						}
619a0795c6fSMarcus Overhagen					}
620a0795c6fSMarcus Overhagen
621a0795c6fSMarcus Overhagen					// we're done "processing the buffer;" now we recycle it and return to the loop
622a0795c6fSMarcus Overhagen					buffer->Recycle();
623a0795c6fSMarcus Overhagen				}
624a0795c6fSMarcus Overhagen				else
625a0795c6fSMarcus Overhagen				{
626a0795c6fSMarcus Overhagen					//fprintf(stderr, "* Woah!  Got a buffer for a different destination!\n");
627a0795c6fSMarcus Overhagen				}
628a0795c6fSMarcus Overhagen			}
629a0795c6fSMarcus Overhagen		}
630a0795c6fSMarcus Overhagen		break;
631a0795c6fSMarcus Overhagen
632a0795c6fSMarcus Overhagen	// !!! change to B_PARAMETER as soon as it's available
633a820304dSMatt Madia
634a0795c6fSMarcus Overhagen	// +++++ e.moon [16jun99]
635a0795c6fSMarcus Overhagen	// !!! this can't be right: the parameter value is accessed by the pointer
636a0795c6fSMarcus Overhagen	//     originally passed to SetParameterValue().  there's no guarantee that
637a0795c6fSMarcus Overhagen	//     value's still valid, is there?
638a820304dSMatt Madia
639a0795c6fSMarcus Overhagen	case BTimedEventQueue::B_USER_EVENT:
640a0795c6fSMarcus Overhagen		{
641a0795c6fSMarcus Overhagen			size_t dataSize = size_t(event->data);
642a0795c6fSMarcus Overhagen			int32 param = int32(event->bigdata);
643a0795c6fSMarcus Overhagen			logMsg.param.id = param;
644a0795c6fSMarcus Overhagen
645a0795c6fSMarcus Overhagen			// handle the message if there's sufficient data provided.  we only check against
646a0795c6fSMarcus Overhagen			// sizeof(float) because all of our parameters happen to be 4 bytes.  if various
647a0795c6fSMarcus Overhagen			// parameters took different amounts of data, we'd check the size on a per-parameter
648a0795c6fSMarcus Overhagen			// basis.
649a0795c6fSMarcus Overhagen			if (dataSize >= sizeof(float)) switch (param)
650a0795c6fSMarcus Overhagen			{
651a0795c6fSMarcus Overhagen			case LATENCY_PARAM:
652a0795c6fSMarcus Overhagen				{
653a0795c6fSMarcus Overhagen					float value = *((float*) event->pointer);
654a0795c6fSMarcus Overhagen					mLatency = bigtime_t(value* 1000);
655a0795c6fSMarcus Overhagen					mLastLatencyChange = logMsg.now;
656a0795c6fSMarcus Overhagen
657a0795c6fSMarcus Overhagen					// my latency just changed, so reconfigure the BMediaEventLooper
658a0795c6fSMarcus Overhagen					// to give me my events at the proper time
659a0795c6fSMarcus Overhagen					SetEventLatency(mLatency);
660a0795c6fSMarcus Overhagen
661a0795c6fSMarcus Overhagen					// tell the producer that my latency changed, and broadcast a message
662a0795c6fSMarcus Overhagen					// about the parameter change to any applications that may be looking
663a0795c6fSMarcus Overhagen					// for it through the BMediaRoster::StartWatching() mechanism.
664a0795c6fSMarcus Overhagen					//
665a0795c6fSMarcus Overhagen					// if we had more than one input, we'd need to tell *all* producers about
666a0795c6fSMarcus Overhagen					// the change in our latency.
667a0795c6fSMarcus Overhagen					SendLatencyChange(mInput.source, mInput.destination, EventLatency() + SchedulingLatency());
668a0795c6fSMarcus Overhagen					BroadcastNewParameterValue(logMsg.now, param, &value, sizeof(value));
669a0795c6fSMarcus Overhagen
670a0795c6fSMarcus Overhagen					// log the new latency value, for recordkeeping
671a0795c6fSMarcus Overhagen					logMsg.param.value = value;
672a0795c6fSMarcus Overhagen					mLogger->Log(LOG_SET_PARAM_HANDLED, logMsg);
673a0795c6fSMarcus Overhagen				}
674a0795c6fSMarcus Overhagen				break;
675a0795c6fSMarcus Overhagen
676a0795c6fSMarcus Overhagen			case CPU_SPIN_PARAM:
677a0795c6fSMarcus Overhagen				{
678a0795c6fSMarcus Overhagen					float value = *((float*) event->pointer);
679a0795c6fSMarcus Overhagen					mSpinPercentage = value;
680a0795c6fSMarcus Overhagen					mLastSpinChange = logMsg.now;
681a0795c6fSMarcus Overhagen					BroadcastNewParameterValue(logMsg.now, param, &value, sizeof(value));
682a0795c6fSMarcus Overhagen					logMsg.param.value = value;
683a0795c6fSMarcus Overhagen					mLogger->Log(LOG_SET_PARAM_HANDLED, logMsg);
684a0795c6fSMarcus Overhagen				}
685a0795c6fSMarcus Overhagen				break;
686a0795c6fSMarcus Overhagen
687a0795c6fSMarcus Overhagen			case PRIORITY_PARAM:
688a0795c6fSMarcus Overhagen				{
689a0795c6fSMarcus Overhagen					mPriority = *((int32*) event->pointer);
690a0795c6fSMarcus Overhagen					// DO NOT use ::set_thead_priority() to directly alter the node's control
691a0795c6fSMarcus Overhagen					// thread priority.  BMediaEventLooper tracks the priority itself and recalculates
692a0795c6fSMarcus Overhagen					// the node's scheduling latency whenever SetPriority() is called.  This is VERY
693a0795c6fSMarcus Overhagen					// important for correct functioning of a node chain.  You should *only* alter a
694a0795c6fSMarcus Overhagen					// BMediaEventLooper's priority by calling its SetPriority() method.
695a0795c6fSMarcus Overhagen					SetPriority(mPriority);
696a0795c6fSMarcus Overhagen
697a0795c6fSMarcus Overhagen					mLastPrioChange = logMsg.now;
698a0795c6fSMarcus Overhagen					BroadcastNewParameterValue(logMsg.now, param, &mPriority, sizeof(mPriority));
699a0795c6fSMarcus Overhagen					logMsg.param.value = (float) mPriority;
700a0795c6fSMarcus Overhagen					mLogger->Log(LOG_SET_PARAM_HANDLED, logMsg);
701a0795c6fSMarcus Overhagen				}
702a0795c6fSMarcus Overhagen				break;
703a0795c6fSMarcus Overhagen
704a0795c6fSMarcus Overhagen			// log the fact that we "handled" a "set parameter" event for a
705a0795c6fSMarcus Overhagen			// nonexistent parameter
706a0795c6fSMarcus Overhagen			default:
707a0795c6fSMarcus Overhagen				mLogger->Log(LOG_INVALID_PARAM_HANDLED, logMsg);
708a0795c6fSMarcus Overhagen				break;
709a0795c6fSMarcus Overhagen			}
710a0795c6fSMarcus Overhagen		}
711a0795c6fSMarcus Overhagen		break;
712a0795c6fSMarcus Overhagen
713a0795c6fSMarcus Overhagen	case BTimedEventQueue::B_START:
714a0795c6fSMarcus Overhagen		// okay, let's go!
715a0795c6fSMarcus Overhagen		mLogger->Log(LOG_START_HANDLED, logMsg);
716a0795c6fSMarcus Overhagen		break;
717a0795c6fSMarcus Overhagen
718a0795c6fSMarcus Overhagen	case BTimedEventQueue::B_STOP:
719a0795c6fSMarcus Overhagen		mLogger->Log(LOG_STOP_HANDLED, logMsg);
720a0795c6fSMarcus Overhagen		// stopping implies not handling any more buffers.  So, we flush all pending
721a0795c6fSMarcus Overhagen		// buffers out of the event queue before returning to the event loop.
722a0795c6fSMarcus Overhagen		EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, BTimedEventQueue::B_HANDLE_BUFFER);
723a0795c6fSMarcus Overhagen		break;
724a0795c6fSMarcus Overhagen
725a0795c6fSMarcus Overhagen	case BTimedEventQueue::B_SEEK:
726a0795c6fSMarcus Overhagen		// seeking the log doesn't make any sense, so we just log that we handled the seek
727a0795c6fSMarcus Overhagen		// and return without doing anything else
728a0795c6fSMarcus Overhagen		mLogger->Log(LOG_SEEK_HANDLED, logMsg);
729a0795c6fSMarcus Overhagen		break;
730a0795c6fSMarcus Overhagen
731a0795c6fSMarcus Overhagen	case BTimedEventQueue::B_WARP:
732a0795c6fSMarcus Overhagen		// similarly, time warps aren't meaningful to the logger, so just record it and return
733a0795c6fSMarcus Overhagen		mLogger->Log(LOG_WARP_HANDLED, logMsg);
734a0795c6fSMarcus Overhagen		break;
735a0795c6fSMarcus Overhagen
736a0795c6fSMarcus Overhagen	case BTimedEventQueue::B_DATA_STATUS:
737a0795c6fSMarcus Overhagen		// we really don't care about the producer's data status, but this is where
738a0795c6fSMarcus Overhagen		// we'd do something about it if we did.
739a0795c6fSMarcus Overhagen		logMsg.data_status.status = event->data;
740a0795c6fSMarcus Overhagen		mLogger->Log(LOG_DATA_STATUS_HANDLED, logMsg);
741a0795c6fSMarcus Overhagen		break;
742a0795c6fSMarcus Overhagen
743a0795c6fSMarcus Overhagen	default:
744a0795c6fSMarcus Overhagen		// hmm, someone enqueued a message that we don't understand.  log and ignore it.
745a0795c6fSMarcus Overhagen		logMsg.unknown.what = event->type;
746a0795c6fSMarcus Overhagen		mLogger->Log(LOG_HANDLE_UNKNOWN, logMsg);
747a0795c6fSMarcus Overhagen		break;
748a0795c6fSMarcus Overhagen	}
749a0795c6fSMarcus Overhagen}
750