Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

69
Src/timer/Factory.cpp Normal file
View file

@ -0,0 +1,69 @@
#include "Factory.h"
#include "api.h"
#include "timerapi.h"
TimerApi *timer_svc = 0;
static const char serviceName[] = "Timer Service";
void Factory::Stop()
{
delete timer_svc;
timer_svc=0;
}
FOURCC Factory::GetServiceType()
{
return WaSvc::UNIQUE;
}
const char *Factory::GetServiceName()
{
return serviceName;
}
GUID Factory::GetGUID()
{
return timerApiServiceGuid;
}
void *Factory::GetInterface(int global_lock)
{
if (!timer_svc)
timer_svc = new TimerApi;
// if (global_lock)
// WASABI_API_SVC->service_lock(this, (void *)ifc);
return timer_svc;
}
int Factory::SupportNonLockingInterface()
{
return 1;
}
int Factory::ReleaseInterface(void *ifc)
{
//WASABI_API_SVC->service_unlock(ifc);
return 1;
}
const char *Factory::GetTestString()
{
return 0;
}
int Factory::ServiceNotify(int msg, int param1, int param2)
{
return 1;
}
#define CBCLASS Factory
START_DISPATCH;
CB(WASERVICEFACTORY_GETSERVICETYPE, GetServiceType)
CB(WASERVICEFACTORY_GETSERVICENAME, GetServiceName)
CB(WASERVICEFACTORY_GETGUID, GetGUID)
CB(WASERVICEFACTORY_GETINTERFACE, GetInterface)
CB(WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface)
CB(WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface)
CB(WASERVICEFACTORY_GETTESTSTRING, GetTestString)
CB(WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify)
END_DISPATCH;
#undef CBCLASS

24
Src/timer/Factory.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include "api.h"
#include <api/service/waservicefactory.h>
#include <api/service/services.h>
class Factory : public waServiceFactory
{
public:
FOURCC GetServiceType();
const char *GetServiceName();
GUID GetGUID();
void *GetInterface(int global_lock);
int SupportNonLockingInterface();
int ReleaseInterface(void *ifc);
const char *GetTestString();
int ServiceNotify(int msg, int param1, int param2);
void Stop();
protected:
RECVS_DISPATCH;
};

View file

@ -0,0 +1,68 @@
#include "ScriptFactory.h"
#include "api.h"
#include "ScriptObjectService.h"
static ScriptObjectService svc;
static const char serviceName[] = "Timer Maki Object";
// GUID of our service factory, not the GUID of the maki object
// {538A1D71-74B0-4fbf-877A-241D10A937F3}
static const GUID timer_maki_guid =
{ 0x538a1d71, 0x74b0, 0x4fbf, { 0x87, 0x7a, 0x24, 0x1d, 0x10, 0xa9, 0x37, 0xf3 } };
FOURCC ScriptFactory::GetServiceType()
{
return svc.getServiceType();
}
const char *ScriptFactory::GetServiceName()
{
return serviceName;
}
GUID ScriptFactory::GetGUID()
{
return timer_maki_guid;
}
void *ScriptFactory::GetInterface(int global_lock)
{
// if (global_lock)
// WASABI_API_SVC->service_lock(this, (void *)ifc);
return &svc;
}
int ScriptFactory::SupportNonLockingInterface()
{
return 1;
}
int ScriptFactory::ReleaseInterface(void *ifc)
{
//WASABI_API_SVC->service_unlock(ifc);
return 1;
}
const char *ScriptFactory::GetTestString()
{
return 0;
}
int ScriptFactory::ServiceNotify(int msg, int param1, int param2)
{
return 1;
}
#define CBCLASS ScriptFactory
START_DISPATCH;
CB(WASERVICEFACTORY_GETSERVICETYPE, GetServiceType)
CB(WASERVICEFACTORY_GETSERVICENAME, GetServiceName)
CB(WASERVICEFACTORY_GETGUID, GetGUID)
CB(WASERVICEFACTORY_GETINTERFACE, GetInterface)
CB(WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface)
CB(WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface)
CB(WASERVICEFACTORY_GETTESTSTRING, GetTestString)
CB(WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify)
END_DISPATCH;
#undef CBCLASS

24
Src/timer/ScriptFactory.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include "api.h"
#include <api/service/waservicefactory.h>
#include <api/service/services.h>
class ScriptFactory : public waServiceFactory
{
public:
FOURCC GetServiceType();
const char *GetServiceName();
GUID GetGUID();
void *GetInterface(int global_lock);
int SupportNonLockingInterface();
int ReleaseInterface(void *ifc);
const char *GetTestString();
int ServiceNotify(int msg, int param1, int param2);
void Stop();
protected:
RECVS_DISPATCH;
};

View file

@ -0,0 +1,29 @@
#include "ScriptObjectService.h"
#include <api/script/objects/rootobjcontroller.h>
#include "STimer.h"
ScriptObjectController *script_root=0;
extern TimerScriptController _timerController;
ScriptObjectController *ScriptObjectService::getController(int n)
{
if (n == 0)
return &_timerController;
return 0;
}
void ScriptObjectService::onRegisterClasses(ScriptObjectController *rootController)
{
script_root = rootController;
}
#define CBCLASS ScriptObjectService
START_DISPATCH;
CB(GETCONTROLLER, getController);
VCB(ONREGISTER, onRegisterClasses);
END_DISPATCH;
#undef CBCLASS

View file

@ -0,0 +1,11 @@
#pragma once
#include <api/service/svcs/svc_scriptobj.h>
class ScriptObjectService : public svc_scriptObject
{
public:
ScriptObjectController *getController(int n);
void onRegisterClasses(ScriptObjectController *rootController);
protected:
RECVS_DISPATCH;
};

17
Src/timer/api.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef NULLSOFT_API_TIMER_H
#define NULLSOFT_API_TIMER_H
#include <api/config/api_config.h>
#define WASABI_API_CONFIG configApi
#include <api/syscb/api_syscb.h>
#define WASABI_API_SYSCB sysCallbackApi
#include <api/script/api_maki.h>
#define WASABI_API_MAKI makiApi
#include "timerapi.h"
extern TimerApi *timer_svc;
#define WASABI_API_TIMER timer_svc
#endif // !NULLSOFT_API_TIMER_H

92
Src/timer/main.cpp Normal file
View file

@ -0,0 +1,92 @@
#include "api.h"
#include "../nu/ServiceWatcher.h"
#include "../Agave/Component/ifc_wa5component.h"
#include <api/service/waServiceFactory.h>
#include "Factory.h"
#include "ScriptFactory.h"
Factory factory;
static ScriptFactory scriptFactory;
api_config *WASABI_API_CONFIG = 0;
api_syscb *WASABI_API_SYSCB = 0;
api_service *WASABI_API_SVC = 0;
api_maki *WASABI_API_MAKI = 0;
static ServiceWatcher serviceWatcher;
class TimerComponent : public ifc_wa5component
{
public:
void RegisterServices(api_service *service);
int RegisterServicesSafeModeOk();
void DeregisterServices(api_service *service);
protected:
RECVS_DISPATCH;
};
template <class api_t>
api_t *GetService(GUID serviceGUID)
{
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(serviceGUID);
if (sf)
return (api_t *)sf->getInterface();
else
return 0;
}
inline void ReleaseService(GUID serviceGUID, void *service)
{
if (service)
{
waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(serviceGUID);
if (sf)
sf->releaseInterface(service);
}
}
void TimerComponent::RegisterServices(api_service *service)
{
WASABI_API_SVC = service;
WASABI_API_SYSCB = GetService<api_syscb>(syscbApiServiceGuid);
serviceWatcher.WatchWith(WASABI_API_SVC);
serviceWatcher.WatchFor(&WASABI_API_CONFIG, configApiServiceGuid);
serviceWatcher.WatchFor(&WASABI_API_MAKI, makiApiServiceGuid);
service->service_register(&factory);
service->service_register(&scriptFactory);
// register for service callbacks in case any of these don't exist yet
WASABI_API_SYSCB->syscb_registerCallback(&serviceWatcher);
}
int TimerComponent::RegisterServicesSafeModeOk()
{
return 1;
}
void TimerComponent::DeregisterServices(api_service *service)
{
service->service_deregister(&factory);
service->service_deregister(&scriptFactory);
serviceWatcher.StopWatching();
serviceWatcher.Clear();
ReleaseService(configApiServiceGuid, WASABI_API_CONFIG);
ReleaseService(syscbApiServiceGuid, WASABI_API_SYSCB);
ReleaseService(makiApiServiceGuid, WASABI_API_MAKI);
factory.Stop();
}
TimerComponent timerComponent;
extern "C" __declspec(dllexport) ifc_wa5component *GetWinamp5SystemComponent()
{
return &timerComponent;
}
#define CBCLASS TimerComponent
START_DISPATCH;
VCB(API_WA5COMPONENT_REGISTERSERVICES, RegisterServices)
CB(15, RegisterServicesSafeModeOk)
VCB(API_WA5COMPONENT_DEREEGISTERSERVICES, DeregisterServices)
END_DISPATCH;
#undef CBCLASS

14
Src/timer/resource.h Normal file
View file

@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by timer.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

175
Src/timer/stimer.cpp Normal file
View file

@ -0,0 +1,175 @@
#include "api.h"
#include "stimer.h"
#include <api/script/objcontroller.h>
#include <api/script/objects/rootobj.h>
#include "Factory.h"
extern Factory factory;
STimer::STimer() {
getScriptObject()->vcpu_setInterface(timerGuid, (void *)static_cast<STimer *>(this));
getScriptObject()->vcpu_setClassName(L"Timer");
getScriptObject()->vcpu_setController(timerController);
delay = 1000;
started = 0;
}
STimer::~STimer() {
}
void STimer::setDelay(int d) {
delay = d;
if (started)
timerclient_setTimer(STIMER_ID, getDelay());
}
int STimer::getDelay(void) {
return delay;
}
void STimer::start(void) {
if (started) { stop(); }
timerclient_setTimer(STIMER_ID, getDelay());
started = 1;
}
void STimer::stop(void) {
if (!started) return;
timerclient_killTimer(STIMER_ID);
started = 0;
}
void STimer::onTimer(void)
{
if (started)
{
script_onTimer(SCRIPT_CALL, getScriptObject());
}
}
void STimer::timerclient_timerCallback(int id)
{
if (id == STIMER_ID)
onTimer();
}
int STimer::isRunning() {
return started;
}
extern ScriptObjectController *script_root;
TimerScriptController _timerController;
TimerScriptController *timerController=&_timerController;
// -- Functions table -------------------------------------
function_descriptor_struct TimerScriptController::exportedFunction[] = {
{L"setDelay", 1, (void*)STimer::script_setDelay },
{L"getDelay", 0, (void*)STimer::script_getDelay },
{L"start", 0, (void*)STimer::script_start },
{L"stop", 0, (void*)STimer::script_stop },
{L"onTimer", 0, (void*)STimer::script_onTimer },
{L"isRunning",0, (void*)STimer::script_isRunning },
{L"getSkipped",0, (void*)STimer::script_getSkipped },
};
// --------------------------------------------------------
const wchar_t *TimerScriptController::getClassName() {
return L"Timer";
}
const wchar_t *TimerScriptController::getAncestorClassName() {
return L"Object";
}
ScriptObjectController *TimerScriptController::getAncestorController() {
return script_root;
}
ScriptObject *TimerScriptController::instantiate() {
if (!WASABI_API_TIMER)
{
WASABI_API_TIMER = (TimerApi *)factory.GetInterface(0);
}
STimer *s = new STimer;
ASSERT(s != NULL);
return s->getScriptObject();
}
void TimerScriptController::destroy(ScriptObject *o) {
STimer *s = static_cast<STimer *>(o->vcpu_getInterface(timerGuid));
ASSERT(s != NULL);
delete s;
}
void *TimerScriptController::encapsulate(ScriptObject *o) {
return NULL; // no encapsulation for timer yet
}
void TimerScriptController::deencapsulate(void *o) {
}
int TimerScriptController::getNumFunctions() {
return sizeof(exportedFunction) / sizeof(function_descriptor_struct);
}
const function_descriptor_struct *TimerScriptController::getExportedFunctions() {
return exportedFunction;
}
GUID TimerScriptController::getClassGuid() {
return timerGuid;
}
scriptVar STimer::script_onTimer(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
SCRIPT_FUNCTION_INIT;
PROCESS_HOOKS0(o, timerController);
SCRIPT_FUNCTION_CHECKABORTEVENT;
SCRIPT_EXEC_EVENT0(o);
}
static bool isNumeric(int t)
{
return (t == SCRIPT_INT || t == SCRIPT_BOOLEAN || t == SCRIPT_FLOAT || t == SCRIPT_DOUBLE);
}
scriptVar STimer::script_setDelay(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar d) {
SCRIPT_FUNCTION_INIT;
ASSERT(isNumeric(d.type));
STimer *t = static_cast<STimer *>(o->vcpu_getInterface(timerGuid));
if (t) t->setDelay(d.data.idata);
RETURN_SCRIPT_VOID;
}
scriptVar STimer::script_getDelay(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
SCRIPT_FUNCTION_INIT;
STimer *t = static_cast<STimer *>(o->vcpu_getInterface(timerGuid));
if (t) return MAKE_SCRIPT_INT(t->getDelay());
RETURN_SCRIPT_ZERO;
}
scriptVar STimer::script_start(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
SCRIPT_FUNCTION_INIT;
STimer *t = static_cast<STimer *>(o->vcpu_getInterface(timerGuid));
if (t) t->start();
RETURN_SCRIPT_VOID;
}
scriptVar STimer::script_stop(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
SCRIPT_FUNCTION_INIT;
STimer *t = static_cast<STimer *>(o->vcpu_getInterface(timerGuid));
if (t) t->stop();
RETURN_SCRIPT_VOID;
}
scriptVar STimer::script_isRunning(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
SCRIPT_FUNCTION_INIT;
STimer *t = static_cast<STimer *>(o->vcpu_getInterface(timerGuid));
if (t) return MAKE_SCRIPT_BOOLEAN(t->isRunning());
RETURN_SCRIPT_ZERO;
}
scriptVar STimer::script_getSkipped(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
SCRIPT_FUNCTION_INIT;
STimer *t = static_cast<STimer *>(o->vcpu_getInterface(timerGuid));
if (t) return MAKE_SCRIPT_INT(t->timerclient_getSkipped());
RETURN_SCRIPT_ZERO;
}

76
Src/timer/stimer.h Normal file
View file

@ -0,0 +1,76 @@
//PORTABLE
#ifndef _STIMER_H
#define _STIMER_H
#include <api/script/objects/rootobject.h>
#include <api/script/objects/rootobj.h>
#include <api/timer/timerclient.h>
#define STIMER_PARENT RootObjectInstance
// {5D0C5BB6-7DE1-4b1f-A70F-8D1659941941}
static const GUID timerGuid =
{ 0x5d0c5bb6, 0x7de1, 0x4b1f, { 0xa7, 0xf, 0x8d, 0x16, 0x59, 0x94, 0x19, 0x41 } };
class TimerScriptController : public ScriptObjectControllerI {
public:
virtual const wchar_t *getClassName();
virtual const wchar_t *getAncestorClassName();
virtual ScriptObjectController *getAncestorController();
virtual int getNumFunctions();
virtual const function_descriptor_struct *getExportedFunctions();
virtual GUID getClassGuid();
virtual ScriptObject *instantiate();
virtual void destroy(ScriptObject *o);
virtual void *encapsulate(ScriptObject *o);
virtual void deencapsulate(void *o);
private:
static function_descriptor_struct exportedFunction[];
};
extern TimerScriptController *timerController;
#ifndef _NOSTUDIO
#define STIMER_ID 2481
class STimer : public STIMER_PARENT, public TimerClientDI {
public:
STimer();
virtual ~STimer();
void start(void);
void stop(void);
int getDelay(void);
void setDelay(int d);
void onTimer(void);
int isRunning();
void timerclient_timerCallback(int id);
private:
int delay;
int started;
#else
class STimer : public STIMER_SCRIPTPARENT {
#endif
public:
static scriptVar script_onTimer(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
static scriptVar script_setDelay(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar d);
static scriptVar script_getDelay(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
static scriptVar script_start(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
static scriptVar script_stop(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
static scriptVar script_isRunning(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
static scriptVar script_getSkipped(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
};
#endif

76
Src/timer/timer.rc Normal file
View file

@ -0,0 +1,76 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

40
Src/timer/timer.sln Normal file
View file

@ -0,0 +1,40 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29424.173
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "timer", "timer.vcxproj", "{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bfc", "..\Wasabi\bfc\bfc.vcxproj", "{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Debug|Win32.ActiveCfg = Debug|Win32
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Debug|Win32.Build.0 = Debug|Win32
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Debug|x64.ActiveCfg = Debug|x64
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Debug|x64.Build.0 = Debug|x64
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Release|Win32.ActiveCfg = Release|Win32
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Release|Win32.Build.0 = Release|Win32
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Release|x64.ActiveCfg = Release|x64
{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}.Release|x64.Build.0 = Release|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.ActiveCfg = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.Build.0 = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.ActiveCfg = Debug|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.Build.0 = Debug|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.ActiveCfg = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.Build.0 = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.ActiveCfg = Release|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5A4ED350-80C8-4501-87C2-26BBC67EAD28}
EndGlobalSection
EndGlobal

282
Src/timer/timer.vcxproj Normal file
View file

@ -0,0 +1,282 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C7C45E25-5C76-4F59-AEBD-992CEC2A5C2E}</ProjectGuid>
<RootNamespace>timer</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetExt>.w5s</TargetExt>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetExt>.w5s</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetExt>.w5s</TargetExt>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<TargetExt>.w5s</TargetExt>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnabled>false</VcpkgEnabled>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TIMER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x86_Debug\$(ProjectName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;TIMER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x64_Debug\$(ProjectName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TIMER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..;../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;TIMER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\Wasabi\bfc\bfc.vcxproj">
<Project>{d0ec862e-dddd-4f4f-934f-b75dc9062dc1}</Project>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\nu\ServiceWatcher.cpp" />
<ClCompile Include="..\Wasabi\api\script\objcontroller.cpp" />
<ClCompile Include="..\Wasabi\api\script\objects\rootobj.cpp" />
<ClCompile Include="..\Wasabi\api\script\objects\rootobjcbx.cpp" />
<ClCompile Include="..\Wasabi\api\script\scriptobji.cpp" />
<ClCompile Include="..\Wasabi\api\script\scriptobjx.cpp" />
<ClCompile Include="..\Wasabi\api\timer\timerclient.cpp" />
<ClCompile Include="Factory.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="ScriptFactory.cpp" />
<ClCompile Include="ScriptObjectService.cpp" />
<ClCompile Include="stimer.cpp" />
<ClCompile Include="timerapi.cpp" />
<ClCompile Include="timermul.cpp" />
<ClCompile Include="tmultiplex.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h" />
<ClInclude Include="Factory.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="ScriptFactory.h" />
<ClInclude Include="ScriptObjectService.h" />
<ClInclude Include="stimer.h" />
<ClInclude Include="timerapi.h" />
<ClInclude Include="timermul.h" />
<ClInclude Include="tmultiplex.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="timer.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="Factory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Wasabi\api\script\objcontroller.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Wasabi\api\script\objects\rootobj.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Wasabi\api\script\objects\rootobjcbx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ScriptFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ScriptObjectService.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Wasabi\api\script\scriptobji.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Wasabi\api\script\scriptobjx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\nu\ServiceWatcher.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stimer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="timerapi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Wasabi\api\timer\timerclient.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="timermul.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tmultiplex.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Factory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ScriptFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ScriptObjectService.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stimer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="timerapi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="timermul.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="tmultiplex.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{dc3ff9be-ed5b-4440-a237-bd67ac1d61ba}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{196e3323-cdec-4d80-91b1-c5896e275321}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{691078fc-f387-4cdb-aa1b-f1d6a961cf0d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="timer.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

32
Src/timer/timerapi.cpp Normal file
View file

@ -0,0 +1,32 @@
#include "api.h"
#include "timerapi.h"
#include "tmultiplex.h"
//timer_api *timerApi = NULL;
TimerApi::TimerApi()
{
}
TimerApi::~TimerApi()
{
multiplex.shutdown();
}
TimerToken TimerApi::timer_add(TimerClient *client, intptr_t id, int ms)
{
multiplex.add(client, id, ms);
return id;
}
void TimerApi::timer_remove(TimerClient *client, TimerToken id)
{
multiplex.remove(client, id);
}
#define CBCLASS TimerApi
START_DISPATCH;
CB(TIMER_API_ADD, timer_add);
VCB(TIMER_API_REMOVE, timer_remove);
END_DISPATCH;
#undef CBCLASS

21
Src/timer/timerapi.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef __TIMER_SVC_H
#define __TIMER_SVC_H
#include <api/timer/api_timer.h>
#include "tmultiplex.h"
class TimerApi : public timer_api
{
public:
TimerApi();
~TimerApi();
virtual TimerToken timer_add(TimerClient *client, intptr_t id, int ms);
virtual void timer_remove(TimerClient *client, TimerToken token = -1);
protected:
MainTimerMultiplexer multiplex;
RECVS_DISPATCH;
};
#endif

370
Src/timer/timermul.cpp Normal file
View file

@ -0,0 +1,370 @@
#include <bfc/platform/platform.h>
#include "timermul.h"
#include <api.h>
#include <api/config/items/attribs.h>
#include <api/config/items/cfgitem.h>
// {9149C445-3C30-4e04-8433-5A518ED0FDDE}
const GUID uioptions_guid =
{ 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } };
PtrListQuickSorted<MultiplexerServer, MultiplexerServerComparatorTID> servers_tid;
PtrListQuickSorted<MultiplexerServer, MultiplexerServerComparatorTID> servers_mux;
TimerMultiplexer::TimerMultiplexer() {
timerset = 0;
nslices = 0;
resolution = -1;
check_resolution = true;
client = NULL;
curslice = 0;
running_timer = NULL;
uioptions = NULL;
justexited = 0;
firstevent = 1;
resetTimer(50); // initial, is changed for config value on first event
}
TimerMultiplexer::~TimerMultiplexer() {
doShutdown();
}
void TimerMultiplexer::setClient(TimerMultiplexerClient *_client) {
client = _client;
}
void TimerMultiplexer::addTimer(int ms, void *data) {
//if (ms < 0) { DebugString("Timer with negative delay set, ignored coz the time machine service isn't ready yet\n"); }
MultiplexedTimer *t = new MultiplexedTimer(ms, data);
if (ms >= MAX_TIMER_DELAY) {
lptimers.addItem(t);
t->nexttick = Wasabi::Std::getTickCount() + t->ms;
} else {
timers.addItem(t);
if (nslices > 0)
distribute(t);
}
}
void TimerMultiplexer::removeTimer(void *data) {
if (running_timer && running_timer->data == data)
running_timer = NULL;
int i;
for (i=0;i<timers.getNumItems();i++) {
MultiplexedTimer *t = timers.enumItem(i);
if (t->data == data) {
removeFromWheel(t);
timers.removeByPos(i);
delete t;
return;
}
}
for (i=0;i<lptimers.getNumItems();i++) {
MultiplexedTimer *t = lptimers.enumItem(i);
if (t->data == data) {
removeFromLowPrecision(t);
delete t;
return;
}
}
}
void TimerMultiplexer::setResolution(int ms) {
resolution = ms;
}
void TimerMultiplexer::shutdown() {
doShutdown();
}
void TimerMultiplexer::doShutdown() {
timers.deleteAll();
wheel.deleteAll();
lptimers.deleteAll();
if (timerset) {
MultiplexerServer *s = servers_mux.findItem((const wchar_t *)this);
if (s) {
#ifdef WIN32
KillTimer(NULL, s->getId());
#elif defined(LINUX)
#endif
}
timerset = 0;
}
}
void TimerMultiplexer::checkResolution(DWORD now) {
if (check_resolution == true)
{
if (WASABI_API_CONFIG)
{
if (uioptions == NULL)
{
uioptions = WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid);
if (uioptions)
{
ifc_dependent *ui_change = uioptions->getDependencyPtr();
ui_change->dependent_regViewer(this, 1);
}
}
check_resolution = uioptions?false:true;
int nresolution = uioptions ? _intVal(uioptions, L"Multiplexed timers resolution") : DEF_RES;
nresolution = MAX(10, MIN(MAX_TIMER_DELAY/LOW_RES_DIV, nresolution));
if (nresolution != resolution) {
resetTimer(nresolution);
resolution = nresolution;
resetWheel();
}
}
}
}
VOID CALLBACK timerMultiplexerServerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
MultiplexerServer *s = servers_tid.findItem((const wchar_t *)&idEvent);
if (s) s->getMultiplexer()->onServerTimer();
}
void TimerMultiplexer::resetTimer(int newresolution) {
if (timerset) {
MultiplexerServer *s = servers_mux.findItem((const wchar_t *)this);
if (s)
KillTimer(NULL, s->getId());
}
// linux port implements settimer
UINT_PTR id = SetTimer(NULL, 0, newresolution, timerMultiplexerServerProc);
MultiplexerServer *s = servers_mux.findItem((const wchar_t *)this);
if (!s) {
s = new MultiplexerServer(this, (UINT)id);
servers_mux.addItem(s);
servers_tid.addItem(s);
} else {
s->setId(id);
servers_tid.sort();
}
timerset = 1;
}
PtrList<MultiplexedTimer> *TimerMultiplexer::getSlice(int n) {
ASSERT(nslices > 0);
return wheel.enumItem(n % nslices);
}
void TimerMultiplexer::resetWheel() {
wheel.deleteAll();
nslices = MAX_TIMER_DELAY / resolution;
for (int i=0;i<nslices;i++)
wheel.addItem(new PtrList< MultiplexedTimer >);
curslice = 0;
distributeAll();
}
void TimerMultiplexer::distributeAll() {
for (int i=0;i<timers.getNumItems();i++) {
distribute(timers.enumItem(i));
}
}
void TimerMultiplexer::distribute(MultiplexedTimer *t) {
ASSERT(t != NULL);
int delay = t->ms;
int slice = delay / resolution + curslice;
PtrList<MultiplexedTimer> *l = getSlice(slice);
ASSERT(l != NULL);
l->addItem(t);
}
void TimerMultiplexer::onServerTimer() {
justexited = 0;
DWORD now = Wasabi::Std::getTickCount();
checkResolution(now);
runCurSlice(now);
if ((curslice % (nslices/LOW_RES_DIV)) == 0) { // execute low precision timers every MAX_TIMER_DELAY/LOW_RES_DIV
runLowPrecisionTimers(now);
}
if (!justexited) {
curslice++;
curslice %= nslices;
}
justexited = 1;
if (firstevent) {
firstevent = 0;
checkResolution(Wasabi::Std::getTickCount());
}
}
void TimerMultiplexer::runCurSlice(DWORD now) {
//DebugString("Running slice %d\n", curslice);
PtrList<MultiplexedTimer> *slice = getSlice(curslice);
ASSERT(slice != NULL);
// mark them clean
int i;
for (i=0;i<slice->getNumItems();i++)
slice->enumItem(i)->flag = 0;
// run events
int n;
do {
n = 0;
for (i=0;i<slice->getNumItems();i++) {
MultiplexedTimer *t = slice->enumItem(i);
if (t == NULL) break; // do not remove this line even if you think it's useless
// t might have been removed by a previous runTimer in this slice, so see if it's still here and if not, ignore
if (!timers.haveItem(t)) { slice->removeItem(t); i--; continue; }
if (t->flag == 1) continue;
t->flag = 1;
int lastdelay = MAX(0, (int)(now - t->lastmscount));
DWORD last = t->lastmscount;
if (last == 0) last = now;
t->lastmscount = now;
t->lastdelay = lastdelay;
running_timer = t;
runTimer(now, last, t, slice, i);
// -----------------------------------------------------------------------
// WARNING
//
// below this line, you can no longer assume that t is pointing at valid
// memory, because runTimer can eventually call removeTimer
// -----------------------------------------------------------------------
n++;
}
} while (n > 0);
}
void TimerMultiplexer::runTimer(DWORD now, DWORD last, MultiplexedTimer *t, PtrList<MultiplexedTimer> *slice, int pos) {
int nextslice = curslice + t->ms / resolution;
int spent = now - last;
int lost = spent - t->ms;
if (lost > 0) {
t->lost += (float)lost / (float)t->ms;
}
PtrList<MultiplexedTimer> *next = getSlice(nextslice);
ASSERT(next != NULL);
if (slice == next) {
nextslice++;
next = getSlice(nextslice);
}
slice->removeByPos(pos);
next->addItem(t);
int skip = (int)t->lost;
t->lost -= (int)t->lost;
if (client) {
client->onMultiplexedTimer(t->data, skip, t->lastdelay);
// -----------------------------------------------------------------------
// WARNING
//
// below this line, you can no longer assume that t is pointing at valid
// memory, because onMultiplexedTimer can eventually call removeTimer
// -----------------------------------------------------------------------
}
}
void TimerMultiplexer::removeFromWheel(MultiplexedTimer *t) {
for (int i=0;i<nslices;i++) {
PtrList<MultiplexedTimer> *slice = getSlice(i);
for (int j=0;j<slice->getNumItems();j++) {
if (slice->enumItem(j) == t) {
slice->removeByPos(j);
j--;
}
}
}
}
void TimerMultiplexer::removeFromLowPrecision(MultiplexedTimer *t) {
for (int i=0;i<lptimers.getNumItems();i++) {
if (lptimers.enumItem(i) == t) {
lptimers.removeByPos(i);
i--;
}
}
}
void TimerMultiplexer::runLowPrecisionTimers(DWORD now) {
int restart;
do {
restart = 0;
for (int i=0;i<lptimers.getNumItems();i++) {
MultiplexedTimer *t = lptimers.enumItem(i);
if (t->nexttick < now) {
if (client) {
running_timer = t;
t->lost += (now - t->nexttick) / t->ms;
int skip = (int)t->lost;
t->lost -= skip; // remove integer part
DWORD last = t->lastmscount;
t->lastdelay = now-last;
t->lastmscount = now;
t->nexttick = t->nexttick+(t->ms)*(skip+1);
client->onMultiplexedTimer(t->data, skip, t->lastdelay);
// -----------------------------------------------------------------------
// WARNING
//
// below this line, you can no longer assume that t is pointing at valid
// memory, because onMultiplexedTimer can eventually call removeTimer
// -----------------------------------------------------------------------
}
if (running_timer == NULL) { // onMultiplexedTimer called removeTimer
restart =1;
break;
}
}
}
} while (restart);
}
int TimerMultiplexer::getNumTimers() {
return timers.getNumItems();
}
int TimerMultiplexer::getNumTimersLP() {
return lptimers.getNumItems();
}
int TimerMultiplexer::dependentViewer_callback(ifc_dependent *item, const GUID *classguid, int cb, intptr_t param1, intptr_t param2 , void *ptr, size_t ptrlen)
{
if (param1 == CfgItem::Event_ATTRIBUTE_CHANGED)
{
check_resolution=true;
}
else if (param1 == CfgItem::Event_ATTRIBUTE_REMOVED)
{
uioptions=0;
}
return 1;
}
#define CBCLASS TimerMultiplexer
START_DISPATCH;
CB(DEPENDENTVIEWER_CALLBACK, dependentViewer_callback)
END_DISPATCH;
#undef CBCLASS

145
Src/timer/timermul.h Normal file
View file

@ -0,0 +1,145 @@
#ifndef __TIMER_MULTIPLEXER_H
#define __TIMER_MULTIPLEXER_H
#include <bfc/common.h>
#include <bfc/ptrlist.h>
#include <api/dependency/api_dependentviewer.h>
// FG> not too sure how to get a callback for attribute change, if anyone wants to change it be my guest ;)
#define RESOLUTION_CHECK_DELAY 1000 // check for resolution changes every second
// if uioptions CfgItem not found, use this value for resolution
#define DEF_RES 20
// below MAX_TIMER_DELAY, timer are multiplexed using a 'wheel' algorithm (mem used = MAX_TIMER_DELAY/resolution * sizeof(PtrList) + ntimers*sizeof(MultiplexedTimer), but fast (no lookup) )
// above MAX_TIMER_DELAY, resolution drops to MAX_TIMER_DELAY/LOW_RES_DIV and uses ntimers*sizeof(MultiplexedTimer) bytes
#define MAX_TIMER_DELAY 1000 // keep this dividable by LOW_RES_DIV please
#define LOW_RES_DIV 4
class CfgItem;
class api_config;
class TimerMultiplexerClient {
public:
virtual void onMultiplexedTimer(void *data, int skip, int mssincelast)=0;
};
class MultiplexedTimer {
public:
MultiplexedTimer(int _ms, void *_data) : ms(_ms), data(_data) {
nexttick=0;
flag=0;
lost = 0;
lastmscount=0;
lastdelay=0;
}
virtual ~MultiplexedTimer() { }
int ms;
void *data;
DWORD nexttick; // only used by low precision timers
int flag; // only used by hi precision timers
float lost; // only used by hi precision timers
DWORD lastmscount;
int lastdelay;
};
class TimerMultiplexer : public ifc_dependentviewer
{
public:
TimerMultiplexer();
virtual ~TimerMultiplexer();
virtual void setClient(TimerMultiplexerClient *client);
virtual void onServerTimer();
virtual void addTimer(int ms, void *data);
virtual void removeTimer(void *data);
virtual void setResolution(int ms);
virtual void shutdown();
virtual int getNumTimers();
virtual int getNumTimersLP();
private:
void checkResolution(DWORD now);
void resetTimer(int newresolution);
void resetWheel();
void distributeAll();
void distribute(MultiplexedTimer *t);
void runCurSlice(DWORD now);
void runTimer(DWORD now, DWORD last, MultiplexedTimer *t, PtrList<MultiplexedTimer> *slice, int pos);
void removeFromWheel(MultiplexedTimer *t);
void runLowPrecisionTimers(DWORD now);
void removeFromLowPrecision(MultiplexedTimer *t);
void doShutdown();
PtrList<MultiplexedTimer> *getSlice(int n);
TimerMultiplexerClient *client;
int resolution;
bool check_resolution;
int timerset;
int curslice;
int nslices;
int justexited;
int firstevent;
PtrList< PtrList< MultiplexedTimer > > wheel;
PtrList< MultiplexedTimer > timers;
PtrList< MultiplexedTimer > lptimers;
MultiplexedTimer *running_timer;
int dependentViewer_callback(ifc_dependent *item, const GUID *classguid, int cb, intptr_t param1 = 0, intptr_t param2 = 0, void *ptr = NULL, size_t ptrlen = 0);
CfgItem *uioptions;
RECVS_DISPATCH;
};
class MultiplexerServer {
public:
MultiplexerServer(TimerMultiplexer *mux, UINT tid) : m_mux(mux), m_tid(tid) {}
virtual ~MultiplexerServer() {}
TimerMultiplexer *getMultiplexer() { return m_mux; }
UINT_PTR getId() { return m_tid; }
void setId(UINT_PTR id) { m_tid = id; }
private:
TimerMultiplexer *m_mux;
UINT_PTR m_tid;
};
class MultiplexerServerComparatorTID {
public:
// comparator for sorting
static int compareItem(MultiplexerServer *p1, MultiplexerServer* p2) {
if (p1->getId() < p2->getId()) return -1;
if (p1->getId() > p2->getId()) return 1;
return 0;
}
// comparator for searching
static int compareAttrib(const wchar_t *attrib, MultiplexerServer *item) {
if (*((UINT *)attrib) < item->getId()) return -1;
if (*((UINT *)attrib) < item->getId()) return 1;
return 0;
}
};
class MultiplexerServerComparatorMux{
public:
// comparator for sorting
static int compareItem(MultiplexerServer *p1, MultiplexerServer* p2) {
if (p1->getMultiplexer() < p2->getMultiplexer()) return -1;
if (p1->getMultiplexer() > p2->getMultiplexer()) return 1;
return 0;
}
// comparator for searching
static int compareAttrib(const wchar_t *attrib, MultiplexerServer *item) {
if ((TimerMultiplexer *)attrib < item->getMultiplexer()) return -1;
if ((TimerMultiplexer *)attrib < item->getMultiplexer()) return 1;
return 0;
}
};
#endif

128
Src/timer/tmultiplex.cpp Normal file
View file

@ -0,0 +1,128 @@
#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;
}

45
Src/timer/tmultiplex.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef __MAIN_TIMERMULTIPLEXER_H
#define __MAIN_TIMERMULTIPLEXER_H
#include "timermul.h"
#include <bfc/depend.h>
#include <bfc/string/StringW.h>
#include <api/timer/timerclient.h>
class VirtualTimer
{
public:
VirtualTimer(TimerClient *_client, intptr_t _id, api_dependent *depend);
virtual ~VirtualTimer() { }
TimerClient *client, *mclient;
api_dependent *dep;
StringW name;
intptr_t id;
};
class MainTimerMultiplexer : public TimerMultiplexer, public TimerMultiplexerClient, public DependentViewerI {
public:
MainTimerMultiplexer();
virtual ~MainTimerMultiplexer();
virtual void add(TimerClient *client, intptr_t id, int ms);
virtual void remove(TimerClient *client, intptr_t id);
virtual void onMultiplexedTimer(void *data, int skip, int mssincelast);
virtual void onServerTimer();
virtual int viewer_onItemDeleted(api_dependent *item);
private:
int isValidTimerClientPtr(TimerClient *tc, api_dependent *dep);
int haveClient(TimerClient *client);
PtrList<VirtualTimer> timerclients;
PtrListQuickSortedByPtrVal<TimerClient> masters;
};
#endif

39
Src/timer/version.rc2 Normal file
View file

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION WINAMP_PRODUCTVER
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp 5.x System Component"
VALUE "FileVersion", STR_WINAMP_PRODUCTVER
VALUE "InternalName", "timer.w5s"
VALUE "LegalCopyright", "Copyright © 2005-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "timer.w5s"
VALUE "ProductName", "Winamp Timer API & Scripting Support Service"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END