winamp/Src/timer/tmultiplex.cpp
2024-09-24 14:54:57 +02:00

129 lines
4.1 KiB
C++

#include "tmultiplex.h"
#include <api/timer/timerclient.h>
#include <assert.h>
VirtualTimer::VirtualTimer(TimerClient *_client, intptr_t _id, api_dependent *depend) :
client(_client), id(_id), dep(depend)
{
name = client->timerclient_getName();
mclient = client->timerclient_getMasterClient();
}
MainTimerMultiplexer::MainTimerMultiplexer() {
setClient(this);
}
MainTimerMultiplexer::~MainTimerMultiplexer() {
/*
foreach(timerclients)
VirtualTimer *vt = timerclients.getfor();
//DebugString("TIMER MULTIPLEXER WARNING: TimerClient %X (%s) was not deregistered\n", vt->client, vt->name.getValue());
endfor;
*/
// NOTE: if you get a crash here, someone probably had a timer event outstanding
// or didn't call down in timerclient_timerCallback()
// Also this is guaranteed to happen if one of your timerclient objects (ie: a wnd) was not deleted
// eventho your DLL has been unloaded. the watched pointer will remain watched instead of unregistering
// itself from its viewers. DependentViewerI (one of our direct ancestors) will try to dereference that pointer in
// order to signal it that a viewer was detached, and it will crash.
timerclients.deleteAll();
}
void MainTimerMultiplexer::add(TimerClient *client, intptr_t id, int ms) {
remove(client, id);
api_dependent *d = client->timerclient_getDependencyPtr();
assert(d != NULL);
VirtualTimer *t = new VirtualTimer(client, id, d);
timerclients.addItem(t);
viewer_addViewItem(d);
if (t->mclient) {
d = t->mclient->timerclient_getDependencyPtr();
ASSERT(d != NULL);
viewer_addViewItem(d);
}
addTimer(ms, static_cast<void *>(t));
}
void MainTimerMultiplexer::remove(TimerClient *client, intptr_t id) {
while (masters.haveItem(client)) masters.removeItem(client);
for (int i=0;i<timerclients.getNumItems();i++) {
VirtualTimer *t = timerclients.enumItem(i);
masters.removeItem(t->mclient);//BU store mclient on VirtualTimer now
if (t->client == client && (t->id == id || id == -1)) {
viewer_delViewItem(t->dep);
timerclients.removeByPos(i);
removeTimer(static_cast<void *>(t));
delete t;
i--;
}
}
}
int MainTimerMultiplexer::isValidTimerClientPtr(TimerClient *tc, api_dependent *dep) {
// try {
__try {
api_dependent *d = tc->timerclient_getDependencyPtr();
if (d != dep) return 0;
//} catch (...) {
} __except (1) {
return 0;
}
return 1;
}
void MainTimerMultiplexer::onMultiplexedTimer(void *data, int skip, int mssincelasttimer) {
assert(data != NULL);
VirtualTimer *t = static_cast<VirtualTimer *>(data);
if (!isValidTimerClientPtr(t->client, t->dep)) {
//DebugString("TIMER MULTIPLEXER WARNING: TimerClient %X (%s) is no longer valid! (%d)\n", t->client, t->name.getValue(), t->id);
remove(t->client, -1);
t->client = 0;
} else {
TimerClient *mc = t->client->timerclient_getMasterClient();
if (mc) masters.addItem(mc);
t->client->timerclient_setSkipped(skip);
t->client->timerclient_setTimerDelay(mssincelasttimer);
t->client->timerclient_timerCallback(t->id);
// -----------------------------------------------------------------------
// WARNING
//
// below this line, you can no longer assume that t is pointing at valid
// memory, because timerCallback can eventually call remove
// -----------------------------------------------------------------------
}
}
void MainTimerMultiplexer::onServerTimer() {
TimerMultiplexer::onServerTimer();
TimerClient *last = NULL;
for (int i=0;i<masters.getNumItems();i++) {
TimerClient *t = masters.enumItem(i);
if (t == last) continue;
t->timerclient_onMasterClientMultiplex();
last = t;
}
masters.removeAll();
}
int MainTimerMultiplexer::haveClient(TimerClient *client) {
for (int i=0;i<timerclients.getNumItems();i++)
{
VirtualTimer *vt = timerclients.enumItem(i);
if (vt && vt->client == client)
return 1;
}
return 0;
}
int MainTimerMultiplexer::viewer_onItemDeleted(api_dependent *item) {
for (int i=0;i<timerclients.getNumItems();i++) {
VirtualTimer *vt = timerclients.enumItem(i);
if (vt->dep == item) {
remove(vt->client, -1);
return 1;
}
}
return 1;
}