aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/service/svcmgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/api/service/svcmgr.cpp')
-rw-r--r--Src/Wasabi/api/service/svcmgr.cpp365
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