various timing related bugfixes
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3395 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -325,7 +325,7 @@ virtual status_t _Reserved_MediaNode_15(void *);
|
||||
int32 _mChangeCount; // deprecated
|
||||
int32 _mChangeCountReserved; // deprecated
|
||||
uint64 fKinds;
|
||||
media_node_id _unused;
|
||||
media_node_id fTimeSourceID;
|
||||
|
||||
BBufferProducer * fProducerThis;
|
||||
BBufferConsumer * fConsumerThis;
|
||||
|
||||
@@ -109,6 +109,7 @@ enum {
|
||||
NODE_TIME_WARP,
|
||||
NODE_PREROLL,
|
||||
NODE_SET_TIMESOURCE,
|
||||
NODE_GET_TIMESOURCE,
|
||||
NODE_REQUEST_COMPLETED,
|
||||
NODE_FINAL_RELEASE,
|
||||
|
||||
@@ -840,6 +841,15 @@ struct node_set_timesource_command : public command_data
|
||||
media_node_id timesource_id;
|
||||
};
|
||||
|
||||
struct node_get_timesource_request : public request_data
|
||||
{
|
||||
};
|
||||
|
||||
struct node_get_timesource_reply : public reply_data
|
||||
{
|
||||
media_node_id timesource_id;
|
||||
};
|
||||
|
||||
struct node_final_release_command : public command_data
|
||||
{
|
||||
};
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
#define IS_INVALID_SOURCE(_src) ((_src).port <= 0)
|
||||
#define IS_INVALID_DESTINATION(_dest) ((_dest).port <= 0)
|
||||
|
||||
#define NODE_UNREGISTERED_ID -2
|
||||
#define NODE_JUST_CREATED_ID -1
|
||||
#define NODE_UNREGISTERED_ID -2
|
||||
#define NODE_SYSTEM_TIMESOURCE_ID 1
|
||||
|
||||
#define BAD_MEDIA_SERVER_PORT -222
|
||||
#define BAD_MEDIA_ADDON_SERVER_PORT -444
|
||||
|
||||
@@ -49,6 +49,8 @@ public:
|
||||
status_t GetAllInputs(const media_node & node, List<media_input> *list);
|
||||
status_t PublishOutputs(const media_node & node, List<media_output> *list);
|
||||
status_t PublishInputs(const media_node & node, List<media_input> *list);
|
||||
|
||||
BTimeSource *MakeTimeSourceObject(media_node_id timesource_id);
|
||||
|
||||
private:
|
||||
friend class BMediaRoster;
|
||||
|
||||
@@ -531,7 +531,7 @@ AudioMixer::BufferReceived(BBuffer *buffer)
|
||||
|
||||
bigtime_t now = system_time(); // XXX debugging
|
||||
bigtime_t send = buffer->Header()->file_pos; // XXX debugging
|
||||
printf("buffer received at %10Ld, was send at %10Ld, delta %7Ld # ", now, send, now - send);
|
||||
// printf("buffer received at %10Ld, was send at %10Ld, delta %7Ld # ", now, send, now - send);
|
||||
|
||||
|
||||
// printf("2) should arrive at %20Ld, now %20Ld\n", buffer->Header()->start_time, TimeSource()->Now());
|
||||
@@ -544,6 +544,9 @@ AudioMixer::BufferReceived(BBuffer *buffer)
|
||||
buffer,
|
||||
BTimedEventQueue::B_RECYCLE_BUFFER);
|
||||
EventQueue()->AddEvent(event);
|
||||
|
||||
uint32 dummy;
|
||||
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
|
||||
}
|
||||
|
||||
|
||||
@@ -552,13 +555,13 @@ AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
|
||||
{
|
||||
media_header *hdr = buffer->Header();
|
||||
|
||||
printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), buffer->Header()->start_time, TimeSource()->Now(), lateness);
|
||||
// printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), buffer->Header()->start_time, TimeSource()->Now(), lateness);
|
||||
|
||||
// printf("3) should arrive at %20Ld, now %20Ld\n", buffer->Header()->start_time, TimeSource()->Now());
|
||||
|
||||
bigtime_t now = TimeSource()->Now();
|
||||
bigtime_t perf_time = hdr->start_time;
|
||||
bigtime_t how_late = now - perf_time - fLatency;
|
||||
// bigtime_t now = TimeSource()->Now();
|
||||
// bigtime_t perf_time = hdr->start_time;
|
||||
// bigtime_t how_late = now - perf_time - fLatency;
|
||||
|
||||
// check input
|
||||
int inputcount = fMixerInputs.CountItems();
|
||||
@@ -570,11 +573,11 @@ AudioMixer::HandleInputBuffer(BBuffer *buffer, bigtime_t lateness)
|
||||
if (channel->fInput.destination.id != hdr->destination)
|
||||
continue;
|
||||
|
||||
if (how_late > 0) {
|
||||
printf("Received buffer %Ld usecs late, lateness %Ld\n", how_late, lateness);
|
||||
if (lateness > 5000) {
|
||||
printf("Received buffer with lateness %Ld\n", lateness);
|
||||
if (RunMode() != B_OFFLINE && RunMode() != B_RECORDING) {
|
||||
printf("sending notify\n");
|
||||
NotifyLateProducer(channel->fInput.source, how_late, perf_time);
|
||||
// printf("sending notify\n");
|
||||
// NotifyLateProducer(channel->fInput.source, lateness, TimeSource()->Now());
|
||||
} else if (RunMode() == B_DROP_DATA) {
|
||||
printf("dropping buffer\n");
|
||||
return;
|
||||
@@ -618,7 +621,7 @@ void
|
||||
AudioMixer::SendNewBuffer(bigtime_t event_time)
|
||||
{
|
||||
bigtime_t start = system_time();
|
||||
BBuffer *outbuffer = fBufferGroup->RequestBuffer(fOutput.format.u.raw_audio.buffer_size, BufferDuration());
|
||||
BBuffer *outbuffer = fBufferGroup->RequestBuffer(fOutput.format.u.raw_audio.buffer_size, BufferDuration() / 4);
|
||||
bigtime_t delta = system_time() - start;
|
||||
if (delta > 200)
|
||||
printf("RequestBuffer took %Ld usec\n", delta);
|
||||
@@ -657,6 +660,8 @@ AudioMixer::ProducerDataStatus( const media_destination &for_whom,
|
||||
media_timed_event event(at_performance_time, BTimedEventQueue::B_DATA_STATUS,
|
||||
(void *)(&for_whom), BTimedEventQueue::B_NO_CLEANUP, status, 0, NULL);
|
||||
EventQueue()->AddEvent(event);
|
||||
uint32 dummy;
|
||||
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
|
||||
|
||||
// FIX_THIS
|
||||
// the for_whom destination is not being sent correctly - verify in HandleEvent loop
|
||||
@@ -680,7 +685,7 @@ AudioMixer::GetLatencyFor( const media_destination &for_whom, bigtime_t *out_lat
|
||||
*out_latency = EventLatency();
|
||||
*out_timesource = TimeSource()->ID();
|
||||
|
||||
printf("AudioMixer::GetLatencyFor %Ld\n", EventLatency());
|
||||
printf("AudioMixer::GetLatencyFor %Ld, timesource is %ld\n", *out_latency, *out_timesource);
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -1085,6 +1090,7 @@ AudioMixer::Connect( status_t error, const media_source &source, const media_des
|
||||
media_node_id id;
|
||||
FindLatencyFor(fOutput.destination, &fLatency, &id);
|
||||
printf("Downstream Latency is %Ld usecs\n", fLatency);
|
||||
fLatency += 6000;
|
||||
|
||||
// we need at least the length of a full output buffer's latency (I think?)
|
||||
|
||||
@@ -1102,8 +1108,6 @@ AudioMixer::Connect( status_t error, const media_source &source, const media_des
|
||||
|
||||
fInternalLatency = latency_end - latency_start;
|
||||
printf("Internal latency is %Ld usecs\n", fInternalLatency);
|
||||
fInternalLatency += 15000;
|
||||
printf("Internal latency is %Ld usecs\n", fInternalLatency);
|
||||
|
||||
delete mouse;
|
||||
|
||||
@@ -1248,7 +1252,7 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
|
||||
// if this is the first buffer, mark with the start time
|
||||
// we need this to calculate the other buffer times
|
||||
if (fStartTime == 0) {
|
||||
fStartTime = event->event_time;
|
||||
fStartTime = TimeSource()->RealTimeFor(event->event_time, 0);
|
||||
}
|
||||
|
||||
// count frames that have been played
|
||||
@@ -1258,9 +1262,11 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
|
||||
fFramesSent += framesperbuffer;
|
||||
|
||||
// calculate the start time for the next event and add the event
|
||||
bigtime_t nextevent = bigtime_t(fStartTime + double(fFramesSent / fOutput.format.u.raw_audio.frame_rate) * 1000000.0);
|
||||
bigtime_t nextevent = TimeSource()->PerformanceTimeFor(bigtime_t(fStartTime + double(fFramesSent / fOutput.format.u.raw_audio.frame_rate) * 1000000.0));
|
||||
media_timed_event nextBufferEvent(nextevent, SEND_NEW_BUFFER_EVENT);
|
||||
EventQueue()->AddEvent(nextBufferEvent);
|
||||
uint32 dummy;
|
||||
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1283,6 +1289,8 @@ AudioMixer::HandleEvent( const media_timed_event *event, bigtime_t lateness, boo
|
||||
// this->HandleEvent(&firstBufferEvent, 0, false);
|
||||
//
|
||||
EventQueue()->AddEvent(firstBufferEvent);
|
||||
uint32 dummy;
|
||||
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
|
||||
|
||||
// fStartTime = event->event_time;
|
||||
|
||||
|
||||
@@ -224,9 +224,11 @@ BMediaEventLooper::ControlLoop()
|
||||
// (see SetEventLatency()) and the scheduling latency (or, for real-time events,
|
||||
// only the scheduling latency).
|
||||
// XXX well, fix this later
|
||||
latency = fEventLatency + fSchedulingLatency;
|
||||
latency = fEventLatency + fSchedulingLatency;
|
||||
// printf("node %02d, latency %Ld\n", ID(), latency);
|
||||
|
||||
if (fEventQueue.HasEvents() && (TimeSource()->Now() - latency) >= fEventQueue.FirstEventTime()) {
|
||||
// printf("node %02d waiting for %12Ld that has already happened, now %12Ld\n", ID(), fEventQueue.FirstEventTime(), system_time());
|
||||
is_realtime = false;
|
||||
break;
|
||||
}
|
||||
@@ -237,6 +239,7 @@ BMediaEventLooper::ControlLoop()
|
||||
waituntil = B_INFINITE_TIMEOUT;
|
||||
if (fEventQueue.HasEvents()) {
|
||||
waituntil = TimeSource()->RealTimeFor(fEventQueue.FirstEventTime(), latency);
|
||||
// printf("node %02d waiting for %12Ld that will happen at %12Ld\n", ID(), fEventQueue.FirstEventTime(), waituntil);
|
||||
is_realtime = false;
|
||||
}
|
||||
if (fRealTimeQueue.HasEvents()) {
|
||||
@@ -251,7 +254,6 @@ BMediaEventLooper::ControlLoop()
|
||||
if (err == B_TIMED_OUT)
|
||||
break;
|
||||
}
|
||||
|
||||
/// we have timed out - so handle the next event
|
||||
media_timed_event event;
|
||||
if (is_realtime)
|
||||
@@ -259,10 +261,12 @@ BMediaEventLooper::ControlLoop()
|
||||
else
|
||||
err = fEventQueue.RemoveFirstEvent(&event);
|
||||
|
||||
// printf("node %02d handling %12Ld at %12Ld\n", ID(), event.event_time, system_time());
|
||||
|
||||
if (err == B_OK) {
|
||||
bigtime_t lateness;
|
||||
if (is_realtime)
|
||||
lateness = TimeSource()->RealTime() + fEventLatency - event.event_time;
|
||||
lateness = TimeSource()->RealTime() - event.event_time;
|
||||
else
|
||||
lateness = TimeSource()->Now() + fEventLatency - event.event_time;
|
||||
DispatchEvent(&event, lateness, is_realtime);
|
||||
|
||||
@@ -39,11 +39,13 @@ static char __copyright[] = "Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@O
|
||||
#include <FileInterface.h>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "MediaMisc.h"
|
||||
#include "MediaRosterEx.h"
|
||||
#include "DataExchange.h"
|
||||
#include "ServerInterface.h"
|
||||
#include "Notifications.h"
|
||||
#include "TimeSourceObject.h"
|
||||
#include "TimeSourceObjectManager.h"
|
||||
|
||||
// don't rename this one, it's used and exported for binary compatibility
|
||||
int32 BMediaNode::_m_changeTag = 0;
|
||||
@@ -207,8 +209,8 @@ BMediaNode::Node() const
|
||||
{
|
||||
CALLED();
|
||||
media_node temp;
|
||||
temp.node = ID();
|
||||
temp.port = ControlPort();
|
||||
temp.node = fNodeID;
|
||||
temp.port = fControlPort;
|
||||
temp.kind = Kinds();
|
||||
return temp;
|
||||
}
|
||||
@@ -230,35 +232,30 @@ BMediaNode::TimeSource() const
|
||||
// return the currently assigned time source
|
||||
if (fTimeSource != 0)
|
||||
return fTimeSource;
|
||||
|
||||
printf("BMediaNode::TimeSource node %ld enter\n", ID());
|
||||
|
||||
// If the node hasn't been assigned a time source
|
||||
// so far, we assign the system time source. This
|
||||
// can't be done in the BMediaNode constructor, since
|
||||
// a BTimeSource is also a BMediaNode and that would be
|
||||
// an infinite loop... loop... loop... loop...
|
||||
|
||||
BMediaRoster *roster = BMediaRoster::Roster();
|
||||
status_t rv;
|
||||
media_node clone;
|
||||
rv = roster->GetSystemTimeSource(&clone);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaNode::TimeSource: Error, GetSystemTimeSource failed\n");
|
||||
return NULL;
|
||||
}
|
||||
// If the node doesn't have a time source object, we need to create one.
|
||||
// If the node is still unregistered, we can't call MakeTimeSourceFor(),
|
||||
// but since the node does still have the default system time source, we
|
||||
// can use GetSystemTimeSource
|
||||
|
||||
BMediaNode *self = const_cast<BMediaNode *>(this);
|
||||
self->fTimeSource = roster->MakeTimeSourceFor(clone);
|
||||
if (fTimeSourceID == NODE_SYSTEM_TIMESOURCE_ID) {
|
||||
self->fTimeSource = _TimeSourceObjectManager->GetSystemTimeSource();
|
||||
} else {
|
||||
self->fTimeSource = MediaRosterEx(BMediaRoster::Roster())->MakeTimeSourceObject(fTimeSourceID);
|
||||
}
|
||||
ASSERT(fTimeSource == self->fTimeSource);
|
||||
|
||||
if (fTimeSource == 0) {
|
||||
FATAL("BMediaNode::TimeSource: Error, MakeTimeSourceFor failed\n");
|
||||
} else {
|
||||
ASSERT(fTimeSourceID == fTimeSource->ID());
|
||||
fTimeSource->AddMe(self);
|
||||
}
|
||||
|
||||
// rv = roster->ReleaseNode(clone);
|
||||
// if (rv != B_OK) {
|
||||
// FATAL("BMediaNode::TimeSource: Error, ReleaseNode failed\n");
|
||||
// }
|
||||
printf("BMediaNode::TimeSource node %ld leave\n", ID());
|
||||
|
||||
return fTimeSource;
|
||||
}
|
||||
@@ -339,7 +336,7 @@ BMediaNode::TimerExpired(bigtime_t notifyPoint,
|
||||
BMediaNode::BMediaNode(const char *name)
|
||||
{
|
||||
TRACE("BMediaNode::BMediaNode: name '%s'\n", name);
|
||||
_InitObject(name, -1, 0);
|
||||
_InitObject(name, NODE_JUST_CREATED_ID, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -365,6 +362,11 @@ BMediaNode::WaitForMessage(bigtime_t waitUntil,
|
||||
return size; // returns the error code
|
||||
}
|
||||
|
||||
if (message == -1) {
|
||||
//printf("BMediaNode::WaitForMessage dummy received\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
TRACE("BMediaNode::WaitForMessage %#lx, node %ld, this %p\n", message, fNodeID, this);
|
||||
|
||||
if (message > NODE_MESSAGE_START && message < NODE_MESSAGE_END) {
|
||||
@@ -512,32 +514,6 @@ BMediaNode::SetTimeSource(BTimeSource *time_source)
|
||||
|
||||
// we just trip into debugger, code that tries to do this is broken.
|
||||
debugger("BMediaNode::SetTimeSource() can't be used to set a timesource, use BMediaRoster::SetTimeSourceFor()!\n");
|
||||
|
||||
/*
|
||||
FATAL("BMediaNode::SetTimeSource used to set a time source for this node\n");
|
||||
|
||||
// the functionality here is only to
|
||||
// support those people that don't
|
||||
// use the roster to set a time source
|
||||
|
||||
// some stupid code to do a stupid thing that should not be done
|
||||
BMediaNode *newnode = time_source->Acquire();
|
||||
BTimeSource *newsource = dynamic_cast<BTimeSource *>(newnode);
|
||||
if (newsource == NULL) {
|
||||
FATAL("BMediaNode::SetTimeSource can't dynamic_cast into timesource\n");
|
||||
newnode->Release();
|
||||
return;
|
||||
}
|
||||
if (fTimeSource) {
|
||||
fTimeSource->RemoveMe(this);
|
||||
fTimeSource->Release();
|
||||
newsource->AddMe(this);
|
||||
printf("#### BMediaNode::SetTimeSource: node %ld has been assigned time source %ld\n", ID(), time_source->ID());
|
||||
|
||||
}
|
||||
fTimeSource = newsource;
|
||||
//BMediaRoster::Roster()->StartTimeSource(fTimeSource->Node(), fTimeSource->RealTime());
|
||||
*/
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
@@ -553,7 +529,7 @@ BMediaNode::HandleMessage(int32 message,
|
||||
switch (message) {
|
||||
case NODE_FINAL_RELEASE:
|
||||
{
|
||||
const node_final_release_command *command = static_cast<const node_final_release_command *>(data);
|
||||
// const node_final_release_command *command = static_cast<const node_final_release_command *>(data);
|
||||
// This is called by the media server to delete the object
|
||||
// after is has been released by all nodes that are using it.
|
||||
// We forward the function to the BMediaRoster, since the
|
||||
@@ -619,51 +595,39 @@ BMediaNode::HandleMessage(int32 message,
|
||||
case NODE_SET_TIMESOURCE:
|
||||
{
|
||||
const node_set_timesource_command *command = static_cast<const node_set_timesource_command *>(data);
|
||||
BMediaRoster *roster;
|
||||
BTimeSource *newsource;
|
||||
media_node clone;
|
||||
status_t rv;
|
||||
TRACE("NODE_SET_TIMESOURCE, node %ld, timesource %ld\n", fNodeID, command->timesource_id);
|
||||
roster = BMediaRoster::Roster();
|
||||
|
||||
printf("NODE_SET_TIMESOURCE, node %ld, timesource %ld enter\n", fNodeID, command->timesource_id);
|
||||
|
||||
fTimeSourceID = command->timesource_id;
|
||||
|
||||
// Time sources are not reference counted. But since
|
||||
// BMediaRoster::GetNodeFor() will create a clone of
|
||||
// any node, we will need to release it!
|
||||
rv = roster->GetNodeFor(command->timesource_id, &clone);
|
||||
if (rv != B_OK) {
|
||||
FATAL("NODE_SET_TIMESOURCE: Error, GetNodeFor failed\n");
|
||||
return B_OK;
|
||||
}
|
||||
newsource = roster->MakeTimeSourceFor(clone);
|
||||
if (newsource == 0) {
|
||||
FATAL("NODE_SET_TIMESOURCE: Error, MakeTimeSourceFor failed\n");
|
||||
roster->ReleaseNode(clone); // release cloned node
|
||||
return B_OK;
|
||||
}
|
||||
roster->ReleaseNode(clone); // release cloned node
|
||||
if (fTimeSource) {
|
||||
// as this node already had a timesource, we need
|
||||
// we need to remove this node from time source control
|
||||
fTimeSource->RemoveMe(this);
|
||||
// Then released the time source
|
||||
// Then release the time source
|
||||
fTimeSource->Release();
|
||||
// now the new one is assigned
|
||||
fTimeSource = newsource;
|
||||
// we add this node to the time source controll
|
||||
fTimeSource->AddMe(this);
|
||||
// and call the SetTimeSource hook function to notify
|
||||
// any derived class
|
||||
SetTimeSource(fTimeSource);
|
||||
} else {
|
||||
// the new time source is assigned to this node
|
||||
fTimeSource = newsource;
|
||||
// we add this node to the time source controll
|
||||
fTimeSource->AddMe(this);
|
||||
// force next call to TimeSource() to create a new object
|
||||
fTimeSource = 0;
|
||||
}
|
||||
TRACE("BMediaNode::HandleMessage NODE_SET_TIMESOURCE: node %ld has been assigned time source %ld\n", ID(), fTimeSource->ID());
|
||||
printf("BMediaNode::HandleMessage NODE_SET_TIMESOURCE: node %ld has been assigned time source %ld\n", ID(), fTimeSource->ID());
|
||||
|
||||
//roster->StartTimeSource(fTimeSource->Node(), fTimeSource->RealTime());
|
||||
|
||||
// create new time source object
|
||||
fTimeSource = TimeSource();
|
||||
// and call the SetTimeSource hook function to notify
|
||||
// any derived class
|
||||
SetTimeSource(fTimeSource);
|
||||
|
||||
printf("NODE_SET_TIMESOURCE, node %ld, timesource %ld leave\n", fNodeID, command->timesource_id);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case NODE_GET_TIMESOURCE:
|
||||
{
|
||||
const node_get_timesource_request *request = static_cast<const node_get_timesource_request *>(data);
|
||||
node_get_timesource_reply reply;
|
||||
reply.timesource_id = fTimeSourceID;
|
||||
request->SendReply(B_OK, &reply, sizeof(reply));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -888,7 +852,6 @@ BMediaNode::_InitObject(const char *name, media_node_id id, uint64 kinds)
|
||||
TRACE("BMediaNode::_InitObject: nodeid %ld, this %p\n", id, this);
|
||||
|
||||
fNodeID = id;
|
||||
fTimeSource = NULL;
|
||||
fRefCount = 1;
|
||||
fName[0] = 0;
|
||||
if (name) {
|
||||
@@ -907,6 +870,14 @@ BMediaNode::_InitObject(const char *name, media_node_id id, uint64 kinds)
|
||||
|
||||
// create control port
|
||||
fControlPort = create_port(64, fName);
|
||||
|
||||
// nodes are assigned the system time source by default
|
||||
fTimeSourceID = NODE_SYSTEM_TIMESOURCE_ID;
|
||||
|
||||
// We can't create the timesource object here, because
|
||||
// every timesource is a BMediaNode, which would result
|
||||
// in infinite recursions
|
||||
fTimeSource = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -563,24 +563,54 @@ BTimeSource *
|
||||
BMediaRoster::MakeTimeSourceFor(const media_node & for_node)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
BTimeSource *source;
|
||||
|
||||
TRACE("BMediaRoster::MakeTimeSourceFor enter, node %ld, port %ld, kind %#lx\n", for_node.node, for_node.port, for_node.kind);
|
||||
|
||||
if (0 == (for_node.kind & B_TIME_SOURCE)) {
|
||||
//FATAL("BMediaRoster::MakeTimeSourceFor, node %ld is not a timesource!\n", for_node.node);
|
||||
// XXX It appears that Cortex calls this function on every node, and expects
|
||||
// XXX to be returned a system time source if the for_node is not a timesource
|
||||
media_node clone;
|
||||
GetSystemTimeSource(&clone);
|
||||
source = _TimeSourceObjectManager->GetTimeSource(clone);
|
||||
// ReleaseNode(clone);
|
||||
} else {
|
||||
source = _TimeSourceObjectManager->GetTimeSource(for_node);
|
||||
if (IS_INVALID_NODE(for_node)) {
|
||||
FATAL("BMediaRoster::MakeTimeSourceFor: for_node invalid\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRACE("BMediaRoster::MakeTimeSourceFor leave, node %ld, port %ld, kind %#lx\n", source->Node().node, source->Node().port, source->Node().kind);
|
||||
printf("BMediaRoster::MakeTimeSourceFor: node %ld enter\n", for_node.node);
|
||||
|
||||
// MakeTimeSourceFor() returns a BTimeSource object
|
||||
// corresponding to the specified node's time source.
|
||||
|
||||
node_get_timesource_request request;
|
||||
node_get_timesource_reply reply;
|
||||
BTimeSource *source;
|
||||
status_t rv;
|
||||
|
||||
rv = QueryPort(for_node.port, NODE_GET_TIMESOURCE, &request, sizeof(request), &reply, sizeof(reply));
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRoster::MakeTimeSourceFor: request failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
source = MediaRosterEx(this)->MakeTimeSourceObject(reply.timesource_id);
|
||||
|
||||
printf("BMediaRoster::MakeTimeSourceFor: node %ld leave\n", for_node.node);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
BTimeSource *
|
||||
BMediaRosterEx::MakeTimeSourceObject(media_node_id timesource_id)
|
||||
{
|
||||
BTimeSource *source;
|
||||
media_node clone;
|
||||
status_t rv;
|
||||
|
||||
rv = GetNodeFor(timesource_id, &clone);
|
||||
if (rv != B_OK) {
|
||||
FATAL("BMediaRosterEx::MakeTimeSourceObject: GetNodeFor failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
source = _TimeSourceObjectManager->GetTimeSource(clone);
|
||||
if (source == NULL) {
|
||||
FATAL("BMediaRosterEx::MakeTimeSourceObject: GetTimeSource failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//ReleaseNode(clone);
|
||||
|
||||
return source;
|
||||
}
|
||||
@@ -1686,6 +1716,10 @@ BMediaRoster::SetTimeSourceFor(media_node_id node,
|
||||
media_node clone;
|
||||
status_t rv, result;
|
||||
|
||||
TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source);
|
||||
|
||||
printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld enter\n", node, time_source);
|
||||
|
||||
// we need to get a clone of the node to have a port id
|
||||
rv = GetNodeFor(node, &clone);
|
||||
if (rv != B_OK) {
|
||||
@@ -1693,8 +1727,6 @@ BMediaRoster::SetTimeSourceFor(media_node_id node,
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE("BMediaRoster::SetTimeSourceFor: node %ld will be assigned time source %ld\n", node, time_source);
|
||||
|
||||
// we just send the request to set time_source-id as timesource to the node,
|
||||
// the NODE_SET_TIMESOURCE handler code will do the real assignment
|
||||
result = B_OK;
|
||||
@@ -1713,6 +1745,8 @@ BMediaRoster::SetTimeSourceFor(media_node_id node,
|
||||
result = B_ERROR;
|
||||
}
|
||||
|
||||
printf("BMediaRoster::SetTimeSourceFor: node %ld time source %ld leave\n", node, time_source);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -452,14 +452,16 @@ _SoundPlayNode::LateNoticeReceived(const media_source& what, bigtime_t how_much,
|
||||
// not properly reporting their latency, but there's not much we can do about
|
||||
// that at the moment, so we try to start producing buffers earlier to
|
||||
// compensate.
|
||||
mInternalLatency += how_much;
|
||||
|
||||
|
||||
// mInternalLatency += how_much;
|
||||
|
||||
// if (mInternalLatency > 50000)
|
||||
// mInternalLatency = 50000;
|
||||
|
||||
SetEventLatency(mLatency + mInternalLatency);
|
||||
// SetEventLatency(mLatency + mInternalLatency);
|
||||
|
||||
fprintf(stderr, "\tincreasing latency to %Ld\n", mLatency + mInternalLatency);
|
||||
// fprintf(stderr, "\tincreasing latency to %Ld\n", mLatency + mInternalLatency);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -574,7 +576,7 @@ _SoundPlayNode::SendNewBuffer(
|
||||
bool realTimeEvent)
|
||||
{
|
||||
CALLED();
|
||||
printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), event->event_time, TimeSource()->Now(), lateness);
|
||||
// printf("latency = %12Ld, event = %12Ld, sched = %5Ld, arrive at %12Ld, now %12Ld, current lateness %12Ld\n", EventLatency() + SchedulingLatency(), EventLatency(), SchedulingLatency(), event->event_time, TimeSource()->Now(), lateness);
|
||||
|
||||
// printf("1) should arrive at %20Ld, now %20Ld\n", event->event_time, TimeSource()->Now());
|
||||
|
||||
@@ -586,12 +588,12 @@ _SoundPlayNode::SendNewBuffer(
|
||||
// arrive at it's destination. The MediaEventLooper should have scheduled us early enough
|
||||
// (based on EventLatency() and the SchedulingLatency()) to make this possible.
|
||||
|
||||
bigtime_t scheduling_latency = SchedulingLatency();
|
||||
// bigtime_t scheduling_latency = SchedulingLatency();
|
||||
|
||||
if (lateness > 0) {
|
||||
if (lateness > 5000) {
|
||||
printf("_SoundPlayNode::SendNewBuffer, event sheduled too late, lateness is %Ld\n", lateness);
|
||||
mInternalLatency += 1000;
|
||||
SetEventLatency(mLatency + mInternalLatency);
|
||||
// mInternalLatency += 1000;
|
||||
// SetEventLatency(mLatency + mInternalLatency);
|
||||
}
|
||||
|
||||
// skip buffer creation if output not enabled
|
||||
@@ -642,13 +644,12 @@ _SoundPlayNode::SendNewBuffer(
|
||||
|
||||
// The buffer is on its way; now schedule the next one to go
|
||||
// nextEvent is the time at which the buffer should arrive at it's destination
|
||||
bigtime_t nextEvent = mStartTime + bigtime_t((1000000LL * mFramesSent) / mOutput.format.u.raw_audio.frame_rate);
|
||||
bigtime_t nextEvent = TimeSource()->PerformanceTimeFor(mStartTime + bigtime_t((1000000LL * mFramesSent) / mOutput.format.u.raw_audio.frame_rate));
|
||||
media_timed_event nextBufferEvent(nextEvent, SEND_NEW_BUFFER_EVENT);
|
||||
if (TimeSource()->Now() + mLatency > nextEvent) {
|
||||
printf("SendNewBuffer: already %Ld usec too late for new buffer\n", TimeSource()->Now() + mLatency - nextEvent);
|
||||
}
|
||||
// printf("0) should arrive at %20Ld, now %20Ld\n", nextEvent, TimeSource()->Now());
|
||||
EventQueue()->AddEvent(nextBufferEvent);
|
||||
uint32 dummy;
|
||||
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -688,8 +689,8 @@ _SoundPlayNode::HandleStart(
|
||||
// and fire off the first "produce a buffer" event.
|
||||
|
||||
mFramesSent = 0;
|
||||
mStartTime = event->event_time;
|
||||
media_timed_event firstBufferEvent(mStartTime, SEND_NEW_BUFFER_EVENT);
|
||||
mStartTime = TimeSource()->RealTimeFor(event->event_time, 0);
|
||||
media_timed_event firstBufferEvent(event->event_time, SEND_NEW_BUFFER_EVENT);
|
||||
|
||||
// Alternatively, we could call HandleEvent() directly with this event, to avoid a trip through
|
||||
// the event queue, like this:
|
||||
@@ -697,6 +698,8 @@ _SoundPlayNode::HandleStart(
|
||||
// this->HandleEvent(&firstBufferEvent, 0, false);
|
||||
//
|
||||
EventQueue()->AddEvent(firstBufferEvent);
|
||||
uint32 dummy;
|
||||
write_port(ControlPort(), -1, &dummy, sizeof(dummy));
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
@@ -758,7 +761,7 @@ _SoundPlayNode::AllocateBuffers()
|
||||
DPRINTF("\tcreating group of %ld buffers, size = %lu\n", count, size);
|
||||
|
||||
if (count < 3)
|
||||
count == 3;
|
||||
count = 3;
|
||||
|
||||
mBufferGroup = new BBufferGroup(size, count);
|
||||
}
|
||||
@@ -770,7 +773,7 @@ _SoundPlayNode::FillNextBuffer(bigtime_t event_time)
|
||||
|
||||
// get a buffer from our buffer group
|
||||
bigtime_t start = system_time();
|
||||
BBuffer* buf = mBufferGroup->RequestBuffer(mOutput.format.u.raw_audio.buffer_size, BufferDuration());
|
||||
BBuffer* buf = mBufferGroup->RequestBuffer(mOutput.format.u.raw_audio.buffer_size, BufferDuration() / 4);
|
||||
bigtime_t delta = system_time() - start;
|
||||
if (delta > 200)
|
||||
printf("RequestBuffer took %Ld usec\n", delta);
|
||||
@@ -779,6 +782,7 @@ _SoundPlayNode::FillNextBuffer(bigtime_t event_time)
|
||||
// buffer and go on to the next, to avoid locking up the control thread
|
||||
if (!buf)
|
||||
{
|
||||
printf("RequestBuffer failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -563,8 +563,16 @@ BSoundPlayer::Init(
|
||||
// set the producer's time source to be the "default" time source, which
|
||||
// the Mixer uses too.
|
||||
|
||||
roster->GetTimeSource(&timeSource);
|
||||
roster->SetTimeSourceFor(_m_node->Node().node, timeSource.node);
|
||||
err = roster->GetTimeSource(&timeSource);
|
||||
if(err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't GetTimeSource\n");
|
||||
goto the_end;
|
||||
}
|
||||
err = roster->SetTimeSourceFor(_m_node->Node().node, timeSource.node);
|
||||
if(err != B_OK) {
|
||||
TRACE("BSoundPlayer::Init: Couldn't SetTimeSourceFor\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if(!input) {
|
||||
err = roster->GetFreeInputsFor(*node, &_input, 1,
|
||||
@@ -598,6 +606,8 @@ BSoundPlayer::Init(
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
printf("BSoundPlayer node %ld has timesource %ld\n", _m_node->Node().node, _m_node->TimeSource()->Node().node);
|
||||
|
||||
the_end:
|
||||
TRACE("BSoundPlayer::Init: %s\n", strerror(err));
|
||||
SetInitError(err);
|
||||
|
||||
@@ -96,7 +96,7 @@ BTimeSource::PerformanceTimeFor(bigtime_t real_time)
|
||||
while (GetTime(&last_perf_time, &last_real_time, &last_drift) != B_OK)
|
||||
snooze(1);
|
||||
|
||||
return (bigtime_t)(last_perf_time + (real_time - last_real_time) * last_drift);
|
||||
return last_perf_time + (bigtime_t)((real_time - last_real_time) * last_drift);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ BTimeSource::RealTimeFor(bigtime_t performance_time,
|
||||
while (GetTime(&last_perf_time, &last_real_time, &last_drift) != B_OK)
|
||||
snooze(1);
|
||||
|
||||
return (bigtime_t)(last_real_time + (performance_time - last_perf_time) / last_drift) - with_latency;
|
||||
return last_real_time - with_latency + (bigtime_t)((performance_time - last_perf_time) / last_drift);
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ BTimeSource::GetTime(bigtime_t *performance_time,
|
||||
// *drift = 1.0f;
|
||||
// return B_OK;
|
||||
// }
|
||||
//printf("BTimeSource::GetTime timesource %ld, index %ld, perf %16Ld, real %16Ld, drift %2.2f\n", ID(), index, *performance_time, *real_time, *drift);
|
||||
// printf("BTimeSource::GetTime timesource %ld, index %ld, perf %16Ld, real %16Ld, drift %2.2f\n", ID(), index, *performance_time, *real_time, *drift);
|
||||
|
||||
TRACE_TIMESOURCE("BTimeSource::GetTime timesource %ld, perf %16Ld, real %16Ld, drift %2.2f\n", ID(), *performance_time, *real_time, *drift);
|
||||
return B_OK;
|
||||
|
||||
@@ -18,25 +18,30 @@ TimeSourceObject::TimeSourceObject(const media_node &node)
|
||||
: BMediaNode("some timesource object", node.node, node.kind),
|
||||
BTimeSource(node.node)
|
||||
{
|
||||
// printf("TimeSourceObject::TimeSourceObject enter, id = %ld\n", id);
|
||||
printf("TimeSourceObject::TimeSourceObject enter, id = %ld\n", node.node);
|
||||
if (fControlPort > 0)
|
||||
delete_port(fControlPort);
|
||||
fControlPort = node.port;
|
||||
ASSERT(fNodeID == node.node);
|
||||
ASSERT(fKinds == node.kind);
|
||||
|
||||
|
||||
if (node.node == NODE_SYSTEM_TIMESOURCE_ID) {
|
||||
strcpy(fName, "System Clock");
|
||||
} else {
|
||||
live_node_info lni;
|
||||
if (B_OK == BMediaRoster::Roster()->GetLiveNodeInfo(node, &lni)) {
|
||||
strcpy(fName, lni.name);
|
||||
} else {
|
||||
sprintf(fName, "timesource %ld", node.node);
|
||||
}
|
||||
}
|
||||
|
||||
AddNodeKind(NODE_KIND_SHADOW_TIMESOURCE);
|
||||
AddNodeKind(NODE_KIND_NO_REFCOUNTING);
|
||||
fControlPort = SHADOW_TIMESOURCE_CONTROL_PORT; // XXX if we don't do this, we get a infinite loop somewhere. This needs to be debugged
|
||||
|
||||
// printf("TimeSourceObject::TimeSourceObject leave, node id %ld\n", fNodeID);
|
||||
printf("TimeSourceObject::TimeSourceObject leave, node id %ld\n", fNodeID);
|
||||
}
|
||||
|
||||
/* virtual */ status_t
|
||||
@@ -66,9 +71,8 @@ TimeSourceObject::DeleteHook(BMediaNode *node)
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
SystemTimeSourceObject::SystemTimeSourceObject(const media_node &node)
|
||||
: BMediaNode("System Clock", node.node, node.kind),
|
||||
: BMediaNode("System Clock", node.node, node.kind),
|
||||
TimeSourceObject(node)
|
||||
{
|
||||
// printf("SystemTimeSourceObject::SystemTimeSourceObject enter, id = %ld\n", id);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <Autolock.h>
|
||||
#include "TimeSourceObjectManager.h"
|
||||
#include "TimeSourceObject.h"
|
||||
#include "MediaMisc.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
@@ -23,8 +24,7 @@ namespace BPrivate {
|
||||
namespace media {
|
||||
|
||||
TimeSourceObjectManager::TimeSourceObjectManager()
|
||||
: fSystemTimeSource(0),
|
||||
fSystemTimeSourceID(0)
|
||||
: fSystemTimeSource(0)
|
||||
{
|
||||
CALLED();
|
||||
fLock = new BLocker("timesource object manager locker");
|
||||
@@ -50,6 +50,38 @@ TimeSourceObjectManager::~TimeSourceObjectManager()
|
||||
delete fMap;
|
||||
}
|
||||
|
||||
void
|
||||
TimeSourceObjectManager::InitSystemTimeSource()
|
||||
{
|
||||
BAutolock lock(fLock);
|
||||
|
||||
if (fSystemTimeSource != 0)
|
||||
return;
|
||||
|
||||
printf("TimeSourceObjectManager::InitSystemTimeSource enter\n");
|
||||
|
||||
media_node node;
|
||||
node.node = NODE_SYSTEM_TIMESOURCE_ID;
|
||||
node.port = SYSTEM_TIMESOURCE_CONTROL_PORT;
|
||||
node.kind = B_TIME_SOURCE;
|
||||
|
||||
fSystemTimeSource = new SystemTimeSourceObject(node);
|
||||
|
||||
printf("TimeSourceObjectManager::InitSystemTimeSource leave\n");
|
||||
}
|
||||
|
||||
|
||||
BTimeSource *
|
||||
TimeSourceObjectManager::GetSystemTimeSource()
|
||||
{
|
||||
BAutolock lock(fLock);
|
||||
|
||||
if (fSystemTimeSource == 0)
|
||||
InitSystemTimeSource();
|
||||
|
||||
return dynamic_cast<BTimeSource *>(fSystemTimeSource->Acquire());
|
||||
}
|
||||
|
||||
/* BMediaRoster::MakeTimeSourceFor does use this function to request
|
||||
* a time source object. If it is already in memory, it will be
|
||||
* Acquired(), if not, a new TimeSourceObject will be created.
|
||||
@@ -62,20 +94,10 @@ TimeSourceObjectManager::GetTimeSource(const media_node &node)
|
||||
|
||||
// printf("TimeSourceObjectManager::GetTimeSource, node id %ld\n", node.node);
|
||||
|
||||
if (fSystemTimeSource == 0) {
|
||||
media_node clone;
|
||||
status_t rv;
|
||||
// XXX this clone is never released
|
||||
rv = BMediaRoster::Roster()->GetSystemTimeSource(&clone);
|
||||
if (rv != B_OK) {
|
||||
FATAL("TimeSourceObjectManager::GetTimeSource, GetSystemTimeSource failed\n");
|
||||
return NULL;
|
||||
}
|
||||
fSystemTimeSource = new SystemTimeSourceObject(clone);
|
||||
fSystemTimeSourceID = fSystemTimeSource->ID();
|
||||
}
|
||||
if (fSystemTimeSource == 0)
|
||||
InitSystemTimeSource();
|
||||
|
||||
if (node.node == fSystemTimeSourceID)
|
||||
if (NODE_SYSTEM_TIMESOURCE_ID == node.node)
|
||||
return dynamic_cast<BTimeSource *>(fSystemTimeSource->Acquire());
|
||||
|
||||
BTimeSource **pts;
|
||||
|
||||
@@ -18,13 +18,16 @@ public:
|
||||
~TimeSourceObjectManager();
|
||||
|
||||
BTimeSource *GetTimeSource(const media_node &node);
|
||||
BTimeSource *GetSystemTimeSource();
|
||||
void ObjectDeleted(BTimeSource *timesource);
|
||||
|
||||
private:
|
||||
void InitSystemTimeSource();
|
||||
|
||||
private:
|
||||
Map<media_node_id,BTimeSource *> *fMap;
|
||||
BLocker *fLock;
|
||||
BTimeSource *fSystemTimeSource;
|
||||
media_node_id fSystemTimeSourceID;
|
||||
};
|
||||
|
||||
}; // namespace media
|
||||
|
||||
@@ -69,6 +69,8 @@ status_t
|
||||
_event_queue_imp::AddEvent(const media_timed_event &event)
|
||||
{
|
||||
BAutolock lock(fLock);
|
||||
|
||||
// printf(" adding %12Ld at %12Ld\n", event.event_time, system_time());
|
||||
|
||||
if (event.type <= 0) {
|
||||
return B_BAD_VALUE;
|
||||
|
||||
@@ -463,7 +463,7 @@ DefaultManager::ConnectMixerToOutput()
|
||||
roster->PrerollNode(mixer);
|
||||
roster->PrerollNode(soundcard);
|
||||
|
||||
ts = roster->MakeTimeSourceFor(timesource);
|
||||
ts = roster->MakeTimeSourceFor(mixer);
|
||||
start_at = ts->Now() + 50000;
|
||||
roster->StartNode(mixer, start_at);
|
||||
roster->StartNode(soundcard, start_at);
|
||||
|
||||
@@ -211,7 +211,6 @@ NodeManager::SetNodeCreator(media_node_id nodeid, team_id creator)
|
||||
BAutolock lock(fLocker);
|
||||
registered_node *rn;
|
||||
bool b;
|
||||
status_t rv;
|
||||
|
||||
TRACE("NodeManager::SetNodeCreator node %ld, creator %ld\n", nodeid, creator);
|
||||
|
||||
|
||||
@@ -181,8 +181,10 @@ ServerApp::StartSystemTimeSource()
|
||||
|
||||
// register a dummy node
|
||||
media_node node;
|
||||
rv = gNodeManager->RegisterNode(&node.node, -1, 0, "System Clock", B_TIME_SOURCE, SYSTEM_TIMESOURCE_CONTROL_PORT, BPrivate::media::team);
|
||||
rv = gNodeManager->RegisterNode(&node.node, -1, 0, "System Clock", B_TIME_SOURCE, SYSTEM_TIMESOURCE_CONTROL_PORT, BPrivate::media::team);
|
||||
ASSERT(rv == B_OK);
|
||||
|
||||
ASSERT(node.node == NODE_SYSTEM_TIMESOURCE_ID);
|
||||
|
||||
printf("StartSystemTimeSource setting as default\n");
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ MediaAddonServer::AddOnAdded(const char *path, ino_t file_node)
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("MediaAddonServer::AddOnAdded: loading addon %d now...\n", id);
|
||||
TRACE("MediaAddonServer::AddOnAdded: loading addon %ld now...\n", id);
|
||||
|
||||
addon = _DormantNodeManager->GetAddon(id);
|
||||
if (addon == NULL) {
|
||||
@@ -455,7 +455,7 @@ MediaAddonServer::InstantiateAutostartFlavors(AddOnInfo *info)
|
||||
printf("trying autostart of node %ld, index %ld\n", info->id, index);
|
||||
rv = info->addon->AutoStart(index, &outNode, &outInternalID, &outHasMore);
|
||||
if (rv == B_OK) {
|
||||
printf("started node\n",index);
|
||||
printf("started node %ld\n",index);
|
||||
|
||||
// XXX IncrementAddonFlavorInstancesCount
|
||||
|
||||
@@ -483,7 +483,6 @@ MediaAddonServer::AddOnRemoved(ino_t file_node)
|
||||
media_addon_id *tempid;
|
||||
media_addon_id id;
|
||||
AddOnInfo *info;
|
||||
int32 *tempflavorcount;
|
||||
int32 oldflavorcount;
|
||||
// XXX locking?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user