123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- #include <precomp.h>
- #include <bfc/wasabi_std.h>
- #include "compon.h"
- //#include <api/wac/main.h> // CUT!
- #ifndef WASABINOMAINAPI
- #include <api/metadb/metadb.h>
- #include <api/wac/papi.h>
- #endif
- #include <api/script/objects/compoobj.h>
- #include <api/wndmgr/container.h>
- #include <api/skin/skinparse.h>
- #include <api/wac/wac.h>
- #include <api/script/objects/wacobj.h>
- #include <api/wnd/wndtrack.h>
- #include <api/script/objecttable.h>
- #include <api/config/items/cfgitemi.h>
- #include <bfc/loadlib.h>
- //#include <bfc/util/profiler.h>
- #include <api/locales/xlatstr.h>
- #include <bfc/file/recursedir.h>
- #include <api/service/svc_enum.h>
- #include <api/service/services.h>
- #include <api/service/servicei.h>
- #include <api/skin/skin.h>
- #include <api/script/scriptmgr.h>
- #include <bfc/parse/pathparse.h>
- #ifndef WASABINOMAINAPI
- #include <api/api1.h>
- #endif
- #include <api/application/wkc.h>
- #include <api/wndmgr/skinembed.h>
- #include <api/script/objects/compoobj.h>
- #include <api/wnd/usermsg.h>
- #include <bfc/util/inifile.h>
- class CShutdownCallback {
- public:
- virtual void rl_onShutdown()=0;
- };
- extern GUID baseGUID;
- static TList<GUID> loadlist, banlist;
- // compon.cpp : maintains the list of installed components, and installs
- // each one
- // keep a list of component pointers as well as instances
- class component_slot
- {
- public:
- #ifndef WASABINOMAINAPI
- component_slot(Library *_dll, WaComponent *_wac, ComponentAPI *_api, GUID g, const wchar_t *orig_path)
- : dll(_dll), wac(_wac), path(orig_path), guid(g), componentapi(_api) {
- #else
- component_slot(Library *_dll, WaComponent *_wac, GUID g, const wchar_t *orig_path)
- : dll(_dll), wac(_wac), path(orig_path), guid(g) {
- #endif
- int fnlen = wcslen(Wasabi::Std::filename(orig_path));
- path.trunc(-fnlen);
- postonregsvcs = 0;
- postoncreate = 0;
- loadearly = 0; // will be filled in later
- }
- ~component_slot() {
- #ifndef WASABINOMAINAPI
- if (dll != NULL) PAPI::destroyAPI(componentapi);
- #endif
- delete dll;
- }
- void registerServices() {
- #ifndef WASABINOMAINAPI
- if (!postonregsvcs) wac->registerServices(componentapi);
- #else
- if (!postonregsvcs) wac->registerServices(WASABI_API_SVC);
- #endif
- postonregsvcs = 1;
- }
- void onCreate() {
- if (!postoncreate) wac->onCreate();
- postoncreate = 1;
- }
- Library *dll;
- WaComponent *wac; // we don't delete this
- StringW path;
- GUID guid; // prevent spoofing
- #ifndef WASABINOMAINAPI
- ComponentAPI *componentapi;
- #endif
- int postoncreate;
- int postonregsvcs;
- int loadearly;
- };
- static PtrList<component_slot> components;
- /*static PtrList<cd_entry> cd_list;
- static PtrList<ComponentObject> co_list;*/
- // the minimum SDK version # we accept
- const int WA_COMPONENT_VER_MIN = WA_COMPONENT_VERSION;
- static int postComponentCommand(GUID guid, const wchar_t *command, int p1, int p2, void *ptr, int ptrlen, int waitforanswer);
- class ComponPostEntry {
- public:
- ComponPostEntry(GUID pguid, const wchar_t *pcommand, int pp1, int pp2, void *pptr, int pptrlen, int pwait) :
- guid(pguid), command(pcommand), p1(pp1), p2(pp2), ptr(pptr), ptrlen(pptrlen), waitforanswer(pwait),
- posted(0), result(0) { }
- GUID guid;
- StringW command;
- int p1, p2;
- void *ptr;
- int ptrlen;
- int waitforanswer;
- int posted;
- int result;
- };
- static PtrList<StringW> preloads;
- void ComponentManager::addStaticComponent(WaComponent *component) {
- GUID guid = component->getGUID();
- if (!checkGUID(guid)) return; // guid check (banlist etc.)
- #ifndef WASABINOMAINAPI
- // reuse main api *
- components.addItem(new component_slot(NULL, component, api, guid, NULL));
- #else
- components.addItem(new component_slot(NULL, component, guid, NULL));
- #endif
- }
- void ComponentManager::addPreloadComponent(const wchar_t *filename)
- {
- foreach(preloads)
- if (PATHEQL(filename, preloads.getfor()->getValue())) return;// no dups
- endfor
- preloads.addItem(new StringW(filename));
- }
- void ComponentManager::loadPreloads() {
- foreach(preloads)
- load(preloads.getfor()->getValue());
- endfor
- preloads.deleteAll();
- }
- void ComponentManager::load(const wchar_t *filename) {
- // ensure no duplicate filenames
- foreach(components)
- if (PATHEQL(filename, components.getfor()->dll->getName())) return;
- endfor
- #ifdef WA3COMPATIBILITY
- // let kernel controller test the file
- WasabiKernelController *wkc = Main::getKernelController();
- if (wkc && !wkc->testComponent(filename)) return;
- #endif
- // check if they have an ini (to get guid faster)
- StringW inifile = filename;
- const wchar_t *ext = Wasabi::Std::extension(inifile);
- int len = wcslen(ext);
- inifile.trunc(-len);
- inifile.cat(L"ini");
- IniFile ini(inifile);
- GUID ini_guid = ini.getGuid(L"component", L"guid");
- if (!checkGUID(ini_guid, TRUE)) return;
- // PR_ENTER2("load component", filename);
- // attach the DLL
- Library *dll = new Library(filename);
- if (!dll->load()) {
- delete dll;
- return;
- }
- // check the version of SDK it was compiled with
- WACGETVERSION wac_get_version = (WACGETVERSION)dll->getProcAddress("WAC_getVersion");
- if (wac_get_version == NULL) {
- delete dll;
- return;
- }
- int version = (*wac_get_version)();
- if (version < WA_COMPONENT_VER_MIN || // defined above
- version > WA_COMPONENT_VERSION) { // from wac.h
- delete dll;
- return;
- }
- // init the dll itself
- WACINIT wacinit = (WACINIT)dll->getProcAddress("WAC_init");
- if (wacinit != NULL) (*wacinit)(dll->getHandle());
- WACENUMCOMPONENT wec = (WACENUMCOMPONENT)dll->getProcAddress("WAC_enumComponent");
- if (wec == NULL) {
- delete dll;
- return;
- }
- // fetch the pointer
- WaComponent *wac = (*wec)(0);
- GUID guid = wac->getGUID();
- if (ini_guid != INVALID_GUID && guid != ini_guid) {
- delete dll;
- DebugString("guids didn't match! %s", filename);
- return;
- }
- // check if we want to load this GUID
- if (!checkGUID(guid)) {
- delete dll;
- return;
- }
- #ifndef WASABINOMAINAPI
- // allocate an api pointer bound to their GUID
- ComponentAPI *newapi = PAPI::createAPI(wac, guid);
- if (newapi == NULL) {
- delete dll;
- return;
- }
- #endif
- PathParserW pp(filename);
- StringW path;
- for (int i=0;i<pp.getNumStrings()-1;i++)
- {
- path.AppendFolder(pp.enumString(i));
- }
- wac->setComponentPath(path);
- // keep track of dll handles for shutdown
- components.addItem(new component_slot(dll, wac,
- #ifndef WASABINOMAINAPI
- newapi,
- #endif
- guid, filename));
- // PR_LEAVE();
- }
- const wchar_t *ComponentManager::getComponentPath(GUID g) {
- foreach(components)
- if (g == components.getfor()->guid) {
- return components.getfor()->path;
- }
- endfor
- return NULL;
- }
- void ComponentManager::startupDBs() {
- /* for (int i=0;i<components.getNumItems();i++)
- MetaDB::addComponentDB(components.enumItem(i)->wac);*/
- }
- void ComponentManager::shutdownDBs() {
- #ifndef WASABINOMAINAPI
- for (int i = 0; i < components.getNumItems(); i++) {
- //MetaDB::getBaseDB()->removeComponentDB(components[i]->wac);
- (static_cast<ComponentAPI1 *>(components[i]->componentapi))->shutdownDB();
- }
- #else
- //MULTIAPI-FIXME: solve the shutdownDB puzzle
- #endif
- }
- void ComponentManager::unloadAll() {
- // cable out! let 'er go!
- // deleteAllCD(); // deletes compwnds
- foreach(components)
- components.getfor()->wac->deregisterServices();
- endfor
- foreach(components)
- components.getfor()->wac->onDestroy();
- endfor
- components.deleteAll(); // free the DLLs, and kill their API *'s
- }
- int ComponentManager::checkGUID(GUID &g, int invalid_ok) {
- // no invalid guid
- if (!invalid_ok && g == INVALID_GUID) return FALSE;
- // check against banlist
- if (banlist.haveItem(g)) return FALSE;
- // check against load-only list
- if (loadlist.getNumItems() && !loadlist.haveItem(g)) return FALSE;
- // ensure no duplicate GUIDs
- foreach(components)
- if (g == components.getfor()->guid) {
- //CUT StringPrintf s("%s and %s", components.getfor()->dll->getName(), filename);
- //CUT Std::messageBox(s, "Duplicate component guid", MB_OK);
- return FALSE;
- }
- endfor
- // ok
- return TRUE;
- }
- WaComponent *ComponentManager::enumComponent(int component) {
- if (component < 0 || component >= components.getNumItems()) return NULL;
- return components[component]->wac;
- }
- void ComponentManager::loadAll(const wchar_t *path) {
- #if 0//CUT
- static const char *loadorder[] = {
- "wasabi.system/pngload.wac",
- "wasabi.player/core.wac",
- "metrics.wac", // so metrics dialog appears before the splash screen
- "winamp/winamp.wac", // so splash screen displays right after startup
- "winamp/pledit.wac",
- "winamp/library.wac",
- "preferences.wac", // so prefs has the system groups at the top
- "skinswitch.wac", // so skinswitch is the first non internal prefs screen, ignored if not present. fucko: need to modify prefs system so we don't need to load in any particular order
- NULL
- };
- for (int i = 0; loadorder[i] != NULL; i++) {
- StringPrintf fn("%s%s%s", WACDIR, DIRCHARSTR, loadorder[i]);
- ComponentManager::load(fn);
- }
- #endif
- RecurseDir dir(path, L"*.*");// have to do *.* to get subdirs
- while (dir.next()) {
- StringPathCombine fn(dir.getPath(), dir.getFilename());
- const wchar_t *ext = Wasabi::Std::extension(fn);
- if (!WCSICMP(ext, L"wac"))
- ComponentManager::load(fn);
- }
- }
- void ComponentManager::postLoad(int f) { // two-level startup procedure
- // note we're calling the slot, not the component directly
- // allow punk-ass bitches to load early if need be
- foreach(components)
- if ((components.getfor()->loadearly = !!components.getfor()->wac->onNotify(WAC_NOTIFY_LOADEARLY))) {
- components.getfor()->registerServices();
- }
- endfor
- foreach(components)
- if (!components.getfor()->loadearly)
- components.getfor()->registerServices();
- endfor
- foreach(components)
- components.getfor()->onCreate();
- endfor
- if (f) ObjectTable::loadExternalClasses();
- }
- void ComponentManager::broadcastNotify(int cmd, int param1, int param2) {
- foreach(components)
- if ((components.getfor()->loadearly = !!components.getfor()->wac->onNotify(WAC_NOTIFY_LOADEARLY, cmd, param1, param2)))
- components.getfor()->wac->onNotify(cmd, param1, param2);
- endfor
- foreach(components)
- if (!components.getfor()->loadearly)
- components.getfor()->wac->onNotify(cmd, param1, param2);
- endfor
- }
- void ComponentManager::sendNotify(GUID guid, int cmd, int param1, int param2) {
- WaComponent *wac = getComponentFromGuid(guid);
- if (wac)
- wac->onNotify(cmd, param1, param2);
- }
- int ComponentManager::sendCommand(GUID guid, const wchar_t *command, int p1, int p2, void *ptr, int ptrlen) {
- if (command == NULL) return 0;
- WaComponent *wac = getComponentFromGuid(guid);
- if (wac) return wac->onCommand(command, p1, p2, ptr, ptrlen);
- return 0;
- }
- int ComponentManager::postCommand(GUID guid, const wchar_t *command, int p1, int p2, void *ptr, int ptrlen, int waitforanswer) {
- #ifdef WA3COMPATIBILITY // todo: make thread id part of application api
- if(Std::getCurrentThreadId()==Main::getThreadId() && waitforanswer) {
- // if it is already the main thread calling, just pass the command to sendCommand
- return sendCommand(guid,command,p1,p2,ptr,ptrlen);
- }
- #endif
- ComponPostEntry *cpe=new ComponPostEntry(guid,command,p1,p2,ptr,ptrlen,waitforanswer);
- componPostEntries.addItem(cpe);
- #ifdef WIN32
- #ifdef WA3COMPATIBILITY // todo: make this a call to application api
- PostMessage(Main::gethWnd(),UMSG_COMPON_POSTMESSAGE,0,0); // ask the main thread to call mainthreadpostCommands();
- #endif
- #else
- PostMessage(None,UMSG_COMPON_POSTMESSAGE,0,0); // ask the main thread to call mainthreadpostCommands();
- #endif
- if(waitforanswer) {
- while(!cpe->posted) Sleep(1);
- int res=cpe->result;
- componPostEntries.removeItem(cpe);
- delete(cpe);
- return res;
- }
- return 0; // cpe will get deleted by mainthreadpostCommands();
- }
- void ComponentManager::broadcastCommand(const wchar_t *command, int p1, int p2, void *ptr, int ptrlen) {
- if (command == NULL) return;
- for (int i = 0; i < components.getNumItems(); i++) {
- components[i]->wac->onCommand(command, p1, p2, ptr, ptrlen);
- }
- }
- int ComponentManager::getNumComponents() {
- return components.getNumItems();
- }
- GUID ComponentManager::getComponentGUID(int c) {
- if (c >= components.getNumItems()) return INVALID_GUID;
- return components[c]->guid;
- }
- const wchar_t *ComponentManager::getComponentName(GUID g)
- {
- WaComponent *wac = getComponentFromGuid(g);
- if (wac)
- return wac->getName();
- return NULL;
- }
- CfgItem *ComponentManager::getCfgInterface(GUID g) {
- WaComponent *wac = getComponentFromGuid(g);
- if (wac == NULL) return NULL;
- return wac->getCfgInterface(0);
- }
- WaComponent *ComponentManager::getComponentFromGuid(GUID g) {
- if (g == INVALID_GUID) return NULL;
- for (int i=0;i<components.getNumItems();i++) {
- if (g == components[i]->guid)
- return components[i]->wac;
- }
- return NULL;
- }
- void ComponentManager::mainThread_handlePostCommands() {
- // critical section
- for(int i=0;i<componPostEntries.getNumItems();i++) {
- ComponPostEntry *cpe=componPostEntries[i];
- if(!cpe->posted) {
- sendCommand(cpe->guid,cpe->command.getValue(),cpe->p1,cpe->p2,cpe->ptr,cpe->ptrlen);
- if(cpe->waitforanswer) cpe->posted=1;
- else {
- delete cpe;
- componPostEntries.removeByPos(i);
- i--;
- }
- }
- }
- }
- PtrList<ComponPostEntry> ComponentManager::componPostEntries;
|