diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/service/svcmgr.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/service/svcmgr.cpp')
-rw-r--r-- | Src/Wasabi/api/service/svcmgr.cpp | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/Src/Wasabi/api/service/svcmgr.cpp b/Src/Wasabi/api/service/svcmgr.cpp new file mode 100644 index 00000000..78eec802 --- /dev/null +++ b/Src/Wasabi/api/service/svcmgr.cpp @@ -0,0 +1,365 @@ +#include <precomp.h> +#ifndef NOSVCMGR +#include "svcmgr.h" + +#ifdef WASABI_COMPILE_COMPONENTS +#include <api/wac/wac.h> +#include <api/wac/compon.h> +#endif + +#ifdef WASABI_COMPILE_SYSCB +#include <api/syscb/cbmgr.h> +#include <api/syscb/callbacks/syscb.h> +#include <api/syscb/callbacks/svccb.h> +#endif + +#include <bfc/multimap.h> +#include <bfc/map.h> +#include <bfc/critsec.h> + +static MultiMap<FOURCC, waServiceFactory> services;// list of factories by class +static Map<waServiceFactory*, GUID> ownermap; // who presented it +static Map<GUID, waServiceFactory*> services_by_guid;// unique services +static Map<void *, waServiceFactory*> lockmap; // who to tell when it's unlocked +//CUTstatic Map<void *, GUID> clientmap; // who locked it + +static CriticalSection cs; + +int ServiceManager::registerService(waServiceFactory *service, GUID owner) { + ASSERT(owner != INVALID_GUID); + if (owner == INVALID_GUID) return 0; + FOURCC svctype = service->getServiceType(); + cs.enter(); + if (!services.multiHaveItem(svctype, service)) { + services.multiAddItem(svctype, service); + + ownermap.addItem(service, owner); + + GUID svcguid = service->getGuid(); + if (svcguid != INVALID_GUID) services_by_guid.addItem(svcguid, service); + } + cs.leave(); + + service->serviceNotify(SvcNotify::ONREGISTERED); + + #ifdef WASABI_COMPILE_SYSCB + CallbackManager::issueCallback(SysCallback::SERVICE, + SvcCallback::ONREGISTER, + (int)svctype, reinterpret_cast<int>(service)); + #endif + + return 1; +} + +int ServiceManager::deregisterService(waServiceFactory *service, int internal) { + FOURCC svctype = service->getServiceType(); + // make sure it was there + cs.enter(); + if (services.multiHaveItem(svctype, service)) { + // make sure there aren't still services issued by this guy +// ASSERT(internal || !lockmap.reverseGetItem(service)); + services.multiDelItem(svctype, service); + ownermap.delItem(service); + services_by_guid.reverseDelItem(service); + } + cs.leave(); + service->serviceNotify(SvcNotify::ONDEREGISTERED); + + #ifdef WASABI_COMPILE_SYSCB + CallbackManager::issueCallback(SysCallback::SERVICE, + SvcCallback::ONDEREGISTER, + (int)svctype, reinterpret_cast<int>(service)); + #endif + + return 1; +} + +int ServiceManager::getNumServices(FOURCC svc_type) { + INCRITICALSECTION(cs); + return services.multiGetNumItems(svc_type); +} + +int ServiceManager::getNumServices() { + return services.getNumItems(); +} + +waServiceFactory *ServiceManager::enumService(int n) { + return services_by_guid.enumItemByPos(n, NULL); +} + +int ServiceManager::getNumOwners() { + return ownermap.getNumItems(); +} + +int ServiceManager::getNumServicesByGuid() { + return services_by_guid.getNumItems(); +} + +int ServiceManager::getNumLocks() { + return lockmap.getNumItems(); +} + +waServiceFactory *ServiceManager::enumService(FOURCC svc_type, int n) { + INCRITICALSECTION(cs); + waServiceFactory *ret = NULL; + services.multiGetItem(svc_type, n, &ret); + return ret; +} + +waServiceFactory *ServiceManager::getServiceByGuid(GUID guid) { + INCRITICALSECTION(cs); + if (guid == INVALID_GUID) return NULL; + waServiceFactory *ret=NULL; + services_by_guid.getItem(guid, &ret); + return ret; +} + +void ServiceManager::sendNotification(int msg, int param1, int param2) { + cs.enter(); + for (int x = 0; x < services.multiGetNumPairs(); x++) { + for (int y = 0; ; y++) { + waServiceFactory *svc; + if (!services.multiGetItemDirect(x, y, &svc)) { + break; + } + svc->serviceNotify(msg, param1, param2); + } + } + cs.leave(); +#ifdef WASABI_COMPILE_COMPONENTS + // also notify components + for (int i = 0; ; i++) { + WaComponent *wac = ComponentManager::enumComponent(i); + if (wac == NULL) break; + wac->onNotify(WAC_NOTIFY_SERVICE_NOTIFY, msg, param1, param2); + } +#endif + #ifdef WASABI_COMPILE_SYSCB + // and syscallbacks + CallbackManager::issueCallback(SysCallback::RUNLEVEL, msg); + #endif +} + +int ServiceManager::lock(waServiceFactory *owner, void *svcptr) { + INCRITICALSECTION(cs); + if (owner == NULL || svcptr == NULL) return 0; + // we allow multiple entries for same service + lockmap.addItem(svcptr, owner); + return 1; +} + +int ServiceManager::unlock(void *svcptr) { + if (svcptr == NULL) return 0; + + waServiceFactory *wsvc = NULL; + cs.enter(); + if (!lockmap.getItem(svcptr, &wsvc)) { + cs.leave(); + DebugString("WARNING: got unlock with no lock record!"); + return 0; + } + + int r = lockmap.delItem(svcptr); + ASSERT(r); + +//CUT // this might fail, client locking isn't enforceable +//CUT clientmap.delItem(svcptr); + + cs.leave(); + + return 1; +} + +int ServiceManager::clientLock(void *svcptr, GUID lockedby) { +//CUT INCRITICALSECTION(cs); +//CUT ASSERT(svcptr != NULL); +//CUT if (svcptr == NULL) return 0; +//CUT ASSERT(lockedby != INVALID_GUID); +//CUT if (lockedby == INVALID_GUID) return 0; +//CUT clientmap.addItem(svcptr, lockedby); + return 1; +} + +int ServiceManager::release(void *svcptr) { + if (svcptr == NULL) return 0; + + waServiceFactory *wsvc = NULL; + cs.enter(); // note cs getting locked twice via release+unlock + if (!lockmap.getItem(svcptr, &wsvc)) { + cs.leave(); + DebugString("WARNING: got release with no lock record!"); + return 0; + } + unlock(svcptr); + cs.leave(); + + ASSERT(wsvc != NULL); + return wsvc->releaseInterface(svcptr); +} + +#ifdef WASABI_COMPILE_COMPONENTS +GUID ServiceManager::getOwningComponent(void *svcptr) { + INCRITICALSECTION(cs); + GUID ret = INVALID_GUID; + waServiceFactory *svc=NULL; + if (lockmap.getItem(svcptr, &svc)) ownermap.getItem(svc, &ret); + return ret; +} + +GUID ServiceManager::getLockingComponent(void *svcptr) { + INCRITICALSECTION(cs); + GUID ret = INVALID_GUID; +//CUT clientmap.getItem(svcptr, &ret); + return ret; +} +#endif + +using namespace WaSvc; + +static struct { + FOURCC type; + const char *name; +} svc_names[] = { + { DEVICE, "Portable Device" }, + { FILEREADER, "File Reader" }, + { FILESELECTOR, "File Selector" }, + { IMAGEGENERATOR, "Image Generator" }, + { IMAGELOADER, "Image Loader" }, + { ITEMMANAGER, "Item Manager" }, + { MEDIACONVERTER, "Media Converter" }, + { MEDIACORE, "Media Core" }, + { PLAYLISTREADER, "Playlist Reader" }, + { PLAYLISTWRITER, "Playlist Writer" }, + { SCRIPTOBJECT, "Script Class" }, + { XMLPROVIDER, "XML Provider" }, + { DB, "Database" }, + { EVALUATOR, "Evaluator" }, + { COREADMIN, "Core Administrator" }, + { NONE, NULL }, // this one has to be last +}; + +const char *ServiceManager::getServiceTypeName(FOURCC svc_type) { + for (int i = 0; ; i++) { + if (svc_names[i].name == NULL) break; + if (svc_names[i].type == svc_type) return svc_names[i].name; + } + return NULL; +} + +FOURCC ServiceManager::safe_getServiceType(waServiceFactory *was) { +#ifndef _DEBUG + return 0; +#endif + FOURCC type = 0; + _TRY + { + type = was->getServiceType(); + } + _EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + OutputDebugString("EXCEPTION_EXECUTE_HANDLER\n"); + } + return type; +} + +const char *ServiceManager::safe_getServiceName(waServiceFactory *was) { +#ifndef _DEBUG + return 0; +#endif + const char *name = NULL; + _TRY + { + name = was->getServiceName(); + } + _EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + OutputDebugString("EXCEPTION_EXECUTE_HANDLER\n"); + } + return name; +} + +void ServiceManager::onShutdown() { +/* + ownermap.purge(); + services.purge(); + services_by_guid.purge(); + clientmap.purge(); +*/ + + int nlocks = lockmap.getNumPairs(); + if (nlocks <= 0) { + //lockmap.purge(); + #ifdef GEN_FF // i need this to have clean session restart, feel free to remove the ifdef if you fgeel that should always be done + ownermap.deleteAll(); + services.multiRemoveAll(); + services_by_guid.deleteAll(); + lockmap.deleteAll(); + #endif + return; + } + +#ifndef _DEBUG + DebugString("-----------------\n"); + for (int i = 0; i < nlocks; i++) { + void *ptr = lockmap.enumIndexByPos(i, NULL); ASSERT(ptr != NULL); + StringPrintf s("lock: %d type:'", (int)ptr); + +// GUID g = lockermap.enumItemByPos(i, INVALID_GUID);ASSERT(g != INVALID_GUID); +// s += g; +// WaComponent *wac = ComponentManager::getComponentFromGuid(g); + + waServiceFactory *was=NULL; + was = lockmap.enumItemByPos(i, NULL); + ASSERT(was != NULL); + FOURCC type = safe_getServiceType(was); + const char *tname = ServiceManager::getServiceTypeName(type); + if (tname != NULL) { + s += tname; + } else { + FOURCC v = BSWAP(type); + unsigned char bleh[5]=" "; + MEMCPY(bleh, &v, 4); + s += String((char *)bleh); + } + s += "' from service:'"; + s += safe_getServiceName(was); + +// s += " wac:"; +// if (wac) s += wac->getName(); +#ifdef WASABI_COMPILE_COMPONENTS + s += "' owned by:'"; + + GUID g = INVALID_GUID; + ownermap.getItem(was, &g); + if (g != INVALID_GUID) { + s += g; + WaComponent *wac = ComponentManager::getComponentFromGuid(g); + if (wac) s += wac->getName(); + } else s += "(unregistered)"; +#else + GUID g; +#endif + + s += "' registered lock to '"; + g = INVALID_GUID; + //clientmap.getItem(ptr, &g); + s += g; + + s += "'\n"; + DebugString(s.v()); + } + DebugString("-----------------\n"); +#endif +#ifdef GEN_FF // i need this to have clean session restart, feel free to remove the ifdef if you fgeel that should always be done + ownermap.deleteAll(); + services.multiRemoveAll(); + services_by_guid.deleteAll(); + lockmap.deleteAll(); +#endif +} + +int ServiceManager::isValidService(FOURCC svctype, waServiceFactory *service) { + INCRITICALSECTION(cs); + return services.multiHaveItem(svctype, service); +} +#endif
\ No newline at end of file |