diff options
Diffstat (limited to 'Src/Wasabi/api/wac')
-rw-r--r-- | Src/Wasabi/api/wac/compdb.h | 28 | ||||
-rw-r--r-- | Src/Wasabi/api/wac/compon.cpp | 480 | ||||
-rw-r--r-- | Src/Wasabi/api/wac/compon.h | 56 | ||||
-rw-r--r-- | Src/Wasabi/api/wac/main.h | 134 | ||||
-rw-r--r-- | Src/Wasabi/api/wac/papi.h | 12 | ||||
-rw-r--r-- | Src/Wasabi/api/wac/wac.h | 266 | ||||
-rw-r--r-- | Src/Wasabi/api/wac/waclient.cpp | 347 |
7 files changed, 1323 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wac/compdb.h b/Src/Wasabi/api/wac/compdb.h new file mode 100644 index 00000000..9985d971 --- /dev/null +++ b/Src/Wasabi/api/wac/compdb.h @@ -0,0 +1,28 @@ +#ifndef __COMP_DB_H +#define __COMP_DB_H + +#define DB_DENY 0 +#define DB_ALLOW 1 + +#define DB_READ 0 +#define DB_WRITE 1 +#define DB_DELETE 2 +#define DB_GETSCANNER 3 +#define DB_DROPINDEX 4 + +#define DB_ERROR 0 +#define DB_SUCCESS 1 +#define DB_NOSUCHFIELD 2 +#define DB_RECORDNOTFOUND 3 +#define DB_UNKNOWNDATATYPE 4 +#define DB_DATATYPEMISMATCH 5 +#define DB_OPERATIONDENIED 6 +#define DB_INVALIDGUID 7 +#define DB_EMPTYFIELD 8 +#define DB_NOTAVAILABLE 9 + +#define DB_ENDOFENUM 0 +#define DB_FOUND TRUE +#define DB_NOTFOUND FALSE + +#endif diff --git a/Src/Wasabi/api/wac/compon.cpp b/Src/Wasabi/api/wac/compon.cpp new file mode 100644 index 00000000..12f66313 --- /dev/null +++ b/Src/Wasabi/api/wac/compon.cpp @@ -0,0 +1,480 @@ +#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; diff --git a/Src/Wasabi/api/wac/compon.h b/Src/Wasabi/api/wac/compon.h new file mode 100644 index 00000000..3dcae3b4 --- /dev/null +++ b/Src/Wasabi/api/wac/compon.h @@ -0,0 +1,56 @@ +//PORTABLE +#ifndef _COMPON_H +#define _COMPON_H + +#include <bfc/wasabi_std.h> +#include <bfc/string/bfcstring.h> +#include <bfc/ptrlist.h> + +class ifc_canvas; +class CfgItem; // see cfgitem.h +class CompWnd; +class ComponentObject; +class Container; +class WaComponent; +class ComponPostEntry; + + +class ComponentManager { +public: + static void addStaticComponent(WaComponent *component); + static void addPreloadComponent(const wchar_t *filename); + static void loadPreloads(); + + static void loadAll(const wchar_t *path); + + static void postLoad(int f=TRUE); + + static void unloadAll(); + + static int checkGUID(GUID &g, int invalid_ok=FALSE); // boolean of if we should load it + + static WaComponent *enumComponent(int component); + + static void broadcastNotify(int cmd, int param1=0, int param2=0); + static void sendNotify(GUID guid, int cmd, int param1=0, int param2=0); + static int sendCommand(GUID guid, const wchar_t *command, int p1=0, int p2=0, void *ptr=NULL, int ptrlen=0); + static int postCommand(GUID guid, const wchar_t *command, int p1, int p2, void *ptr, int ptrlen, int waitforanswer); + static void broadcastCommand(const wchar_t *command, int p1=0, int p2=0, void *ptr=NULL, int ptrlen=0); + static int getNumComponents(); + static GUID getComponentGUID(int c); + static const wchar_t *getComponentName(GUID g); + static CfgItem *getCfgInterface(GUID g); + static WaComponent *getComponentFromGuid(GUID g); + + static void load(const wchar_t *filename); + + static const wchar_t *getComponentPath(GUID g); + + static void startupDBs(); + static void shutdownDBs(); + + static void mainThread_handlePostCommands(); + static PtrList<ComponPostEntry> componPostEntries; +}; + +#endif diff --git a/Src/Wasabi/api/wac/main.h b/Src/Wasabi/api/wac/main.h new file mode 100644 index 00000000..b77cb00a --- /dev/null +++ b/Src/Wasabi/api/wac/main.h @@ -0,0 +1,134 @@ +// THIS FILE SHOULD FUCKING DISAPPEAR DAMMIT + +//NONPORTABLE -- HWND and HINSTANCE references +#ifndef _MAIN_H +#define _MAIN_H + +#warning don't include me + +#include <bfc/std.h> +#include <bfc/string/string.h> +#include <bfc/ptrlist.h> + +#define WM_SYSTRAY WM_USER+1102 //FG> Arbitrary value. Would probably be better with a registered message +#define WM_SETSKIN WM_USER+0x1000 + +class Systray; +class MetricsCallback; +class ScriptObjectManager; +class CfgItem; +class api_window; +class GenWnd; +class WasabiKernelController; +class CoreHandle; +class CompCommandEntry; +class Layout; + +class Main { +public: + friend class WasabiKernel; + static HINSTANCE gethInstance(); + static HWND gethWnd(); + static DWORD getThreadId(); + static WasabiKernelController *getKernelController(); + static int isMaximized(); + static int isMinimized(); + static int minimizeWnd(); + static int restoreWnd(); + static int invalidate(); + + static void outputDebugString(int severity, const char *string); + static void outputDebugString(const char *string) { + outputDebugString(0, string); + } + + // sets the ownerwnd title + static void setWindowTitle(const wchar_t *text); + + // status + static void setOverlayText(const wchar_t *text, int interval);//displays then reverts + static void setTrayTipText(const wchar_t *text); // set systrem tray icon tooltip text + + // ontop status + static void setOnTop(BOOL set); + static BOOL getOnTop(); + + // systray + // 0 = nothing + // 1 = taskbar + // 2 = systray + // 3 = both :) + static void setIconMode(int mode); + + // skin + static void setSkinDelayed(const wchar_t *skinName); + + // path to wasabi.dll + static const wchar_t *getWasabiPath(); + // path to main EXE + static const wchar_t *getMainAppPath(); + + static GUID getGuid(); + + static void shutdown(); + static void cancelShutdown(); + + static void savePosition(); + + static void navigateUrl(const wchar_t *url); // displays in minibrowser if present, otherwise launch external + + static int appContextMenu(api_window *parent, BOOL canScale, BOOL canAlpha); + static int thingerContextMenu(api_window *parent); + + static void doAction(int action, int param=0); + static void doMenu(const wchar_t *which); + + static void processCommandLine(const wchar_t *cmdLine); + + static void setSkinsPath(const wchar_t *path); + static const wchar_t *getSkinsPath(); + + static GenWnd *getGenericWnd(); + static int isShutingDown(); + + static HICON smallicon; + static HICON bigicon; + static bool ontop; + static Systray *systray; + static GenWnd *genericwnd; + static int shuting_down; + + // maintains a stack of modal windows so basewnds can discard messages in WM_MOUSEACTIVATE, should only be used by MsgboxWnd & ModalWnd when we write it ;) + static api_window *getModalWnd(); + static void pushModalWnd(api_window *wnd); + static int popModalWnd(api_window *wnd); + + static void metrics_addCallback(MetricsCallback *); + static void metrics_delCallback(MetricsCallback *); + static int metrics_getDelta(); + static int metrics_setDelta(int newdelta); + + static int isInetAvailable(); //return 1 if connected, 0 if not available + + static String lastwindowtitle; + static int taskbaractive; + + static CoreHandle *getMainCoreHandle(); + static CoreHandle *mainCoreHandle; + + static const wchar_t *getCommandLine(); + static String commandLine; + static String skinspath; + + static int revert_on_error; + static int cancel_shutdown; + static PtrList<api_window> ontoplist; + static void saveTopMosts(); + static void restoreTopMosts(); + static int onMouseWheel(int l, int a); + +private: + static int isRASActive(); +}; + +#endif diff --git a/Src/Wasabi/api/wac/papi.h b/Src/Wasabi/api/wac/papi.h new file mode 100644 index 00000000..73ac11d7 --- /dev/null +++ b/Src/Wasabi/api/wac/papi.h @@ -0,0 +1,12 @@ +#ifndef _PAPI_H +#define _PAPI_H + +class ComponentAPI; +class WaComponent; + +namespace PAPI { + ComponentAPI *createAPI(WaComponent *, GUID owner, GUID*config=NULL); + void destroyAPI(ComponentAPI *); +}; + +#endif diff --git a/Src/Wasabi/api/wac/wac.h b/Src/Wasabi/api/wac/wac.h new file mode 100644 index 00000000..d19f5615 --- /dev/null +++ b/Src/Wasabi/api/wac/wac.h @@ -0,0 +1,266 @@ +#ifndef _WAC_H +#define _WAC_H + +#include <api/wac/compdb.h>//CUT +#include <bfc/ptrlist.h> +#include <api/config/items/cfgitemi.h> + +class ifc_canvas; // see canvas.h +class CfgItem; // see cfgitem +class CfgItemI; +class ComponentAPI; // see api.h +class api_window; // see rootwnd.h +class LoadableResource; // see below + +// this tells wasabi what version of the SDK we're compiled with +// this number will be incremented every once in a while. when it is, you'll +// have to recompile +// 5 -> build #471 +// 6 -> build rc1 +// 7 -> build 484 (rc5) +// 8 -> Winamp 5.23 (build 608) +// 9 -> Winamp 5.4 +#define WA_COMPONENT_VERSION 9 + +#define DB_DENY 0 +#define DB_ALLOW 1 + +// commands for onNotify below + +#define WAC_NOTIFY_NOP 0 + +#define WAC_NOTIFY_ACTIVATE 10 +#define WAC_NOTIFY_DEACTIVATE 20 + +#define WAC_NOTIFY_FULLSCREEN 30 +#define WAC_NOTIFY_RESTORE 40 + +#define WAC_NOTIFY_ENTERRESIZE 50 +#define WAC_NOTIFY_LEAVERESIZE 51 + +#define WAC_NOTIFY_SYSTRAYDONE 60 +#define WAC_NOTIFY_POPUPDONE 61 + +#define WAC_NOTIFY_BASETEXTUREWINDOW 78 + +#define WAC_NOTIFY_LOADEARLY 90 + +#define WAC_NOTIFY_MENU_COMMAND 10000 + +// this message is sent when service runlevel notifies are sent +// param1 = msg +// param2 = param1 +// param3 = param2 +#define WAC_NOTIFY_SERVICE_NOTIFY 100 + +#define WAC_NOTIFY_SKINUNLOADING 0xE300 // before unloading current skin +#define WAC_NOTIFY_SWITCHINGSKIN 0xE301 // right after unloading current skin and right before loading new one, getSkinName/Path points to new skin +#define WAC_NOTIFY_SKINELEMENTSLOADED 0xE302 // after skin elements definitions are loaded +#define WAC_NOTIFY_BEFORELOADINGSKINELEMENTS 0xE303 // before skin elements definitions are loaded, trap this to load your elements/groups and let people override them +#define WAC_NOTIFY_SKINGUILOADED 0xE304 // after skin GUI objects are loaded from xml +#define WAC_NOTIFY_SKINLOADED 0xE305 // after skin is fully loaded + +enum { + RSF_STATIC=0, + RSF_RELATIVETOWAC=1, + RSF_RELATIVETOTHEME=2, +}; + +// ----------- + +#include <bfc/dispatch.h> + +class NOVTABLE WaComponent : public Dispatchable { +public: + // provide your component name & other info here + const wchar_t *getName() { return _call(GETNAME, (wchar_t *)NULL); } + GUID getGUID() { return _call(GETGUID, INVALID_GUID); } + +#ifdef WASABINOMAINAPI + void registerServices(api_service *a) { _voidcall(REGISTERSERVICES2, a); } +#else + void registerServices(ComponentAPI *a) { _voidcall(REGISTERSERVICES, a); } +#endif + void deregisterServices() { _voidcall(DEREGISTERSERVICES); } + + void onCreate() { _voidcall(ONCREATE); } + void onDestroy() { _voidcall(ONDESTROY); } +//DEPRECATED: will go away + api_window *createWindow(int n, api_window *parentWnd) { return _call(CREATEWINDOW, (api_window*)NULL, n, parentWnd); } + + int onNotify(int cmd, int param1=0, int param2=0, int param3=0, int param4=0){ + return _call(ONNOTIFY, 0, cmd, param1, param2, param3, param4); + } + // everything after cmd is for future expansion + int onCommand(const wchar_t *cmd, int param1, int param2, void *ptr, int ptrlen){ + return _call(ONCOMMAND, 0, cmd, param1, param2, ptr, ptrlen); + } + + // gets the CfgItem * from WAComponentClient + CfgItem *getCfgInterface(int n) { + return _call(GETCFGINTERFACE, (CfgItem*)NULL, n); + } + + // saves the OSMODULEHANDLE of your WAC for you + void setOSModuleHandle(OSMODULEHANDLE modulehandle) { + _voidcall(SETOSMODULEHANDLE, modulehandle); + } + OSMODULEHANDLE getOSModuleHandle() { + return _call(GETOSMODULEHANDLE, (OSMODULEHANDLE)0); + } + // saves the path of your WAC for you + void setComponentPath(const wchar_t *path) { + _voidcall(SETPATH, path); + } + const wchar_t *getComponentPath() { + return _call(GETPATH, (const wchar_t *)NULL); + } + + enum { + GETNAME=100, + GETGUID=120, + REGISTERSERVICES=200, + REGISTERSERVICES2=210, + ONCREATE=400, + ONDESTROY=410, + CREATEWINDOW=420, + ONNOTIFY=500, + ONCOMMAND=600, + GETCFGINTERFACE=800, + SETHINSTANCE=900, SETOSMODULEHANDLE=900, // note dups for back-compat + GETHINSTANCE=910, GETOSMODULEHANDLE=910, // note dups for back-compat + DEREGISTERSERVICES=1000, + SETPATH=1100, + GETPATH=1200, + }; +}; + +// hides the dispatchable interface +class NOVTABLE WaComponentI : public WaComponent { +protected: + WaComponentI() {} // protect constructor +public: + virtual const wchar_t *getName()=0; + virtual GUID getGUID()=0; + +#ifdef WASABINOMAINAPI + virtual void registerServices(api_service *)=0; +#else + virtual void registerServices(ComponentAPI *)=0; +#endif + virtual int RegisterServicesSafeModeOk()=0; + virtual void deregisterServices()=0; + + virtual void onCreate()=0; + virtual void onDestroy()=0; + + virtual api_window *createWindow(int n, api_window *parentWnd)=0; //DEPRECATED + + virtual int onNotify(int cmd, int param1, int param2, int param3, int param4)=0; + virtual int onCommand(const wchar_t *cmd, int param1, int param2, void *ptr, int ptrlen)=0; + + virtual CfgItem *getCfgInterface(int n)=0; + + virtual void setOSModuleHandle(OSMODULEHANDLE moduleHandle)=0; + virtual OSMODULEHANDLE getOSModuleHandle()=0; + virtual void setComponentPath(const wchar_t *path)=0; + virtual const wchar_t *getComponentPath()=0; + +private: + virtual void internal_onDestroy()=0; + virtual int internal_onNotify(int cmd, int param1, int param2, int param3, int param4)=0; // calls thru to onNotify after processing + RECVS_DISPATCH; +}; + +class waServiceFactoryI; + +/** +*/ +class NOVTABLE WAComponentClient : public WaComponentI, public CfgItemI +{ +protected: + WAComponentClient(const wchar_t *name=NULL); +public: + virtual ~WAComponentClient() {} + + // provide your component name & other info here + virtual const wchar_t *getName(); //OVERRIDE ME (or just set name in constructor) + virtual GUID getGUID()=0; // be sure to override this one //OVERRIDE ME + +#ifdef WASABINOMAINAPI + void registerServices(api_service *); // don't override +#else + void registerServices(ComponentAPI *); // don't override +#endif + int RegisterServicesSafeModeOk(); + void deregisterServices(); // don't override + + // override these to receive notifications + virtual void onRegisterServices() {}// register extra services here + virtual void onCreate() {} // init stuff + virtual void onDestroy() {} // destroy everything here, not in ~ +//DEPRECATED: will go away +// this is moving to svc_wndcreate + virtual api_window *createWindow(int n, api_window *parentWnd) { return NULL; } + + // OVERRIDE ME for various events + virtual int onNotify(int cmd, int param1, int param2, int param3, int param4) { return 0; } + // everything after cmd is for future expansion + virtual int onCommand(const wchar_t *cmd, int param1, int param2, void *ptr, int ptrlen) { return 0; } + + // config ptr... you can override this and provide a different * + // otherwise 'this' will be returned + virtual CfgItem *getCfgInterface(int n); + + // saves the OSMODULEHANDLE of your WAC for you + void setOSModuleHandle(OSMODULEHANDLE moduleHandle) { OSModuleHandle = moduleHandle; }; + OSMODULEHANDLE getOSModuleHandle() { return OSModuleHandle; } + void setComponentPath(const wchar_t *path) { componentpath = path; }; + const wchar_t *getComponentPath() { return componentpath; } + OSMODULEHANDLE gethInstance() { return getOSModuleHandle(); } //DEPRECATED + + // various options to register during your constructor, like services, + // skin parts, and autopop guids. just register them and forget them + + void registerService(waServiceFactoryI* service); + void registerSkinFile(const wchar_t *filename, int relative=RSF_RELATIVETOWAC); + + /* benski> cut + void registerAutoPopup(GUID guid, const wchar_t *description, const wchar_t *prefered_container=NULL, int container_required=FALSE); + void registerAutoPopup(const wchar_t *groupid, const wchar_t *description, const wchar_t *container_layout=NULL, int container_required=FALSE); + void registerCfgItem(CfgItemI *cfgitem, int autodelete=FALSE); + void registerExtension(const wchar_t *extension, const wchar_t *description, const wchar_t *family=NULL); + void registerCallback(SysCallback *_callback, void *_param = NULL); + void registerPrefGroup(const wchar_t *groupname, const wchar_t *dest, GUID pref_guid, GUID pref_guid_parent=INVALID_GUID);*/ + // or register your own resource types here + void registerResource(LoadableResource *res); + + virtual void onSkinLoaded() {} + +private: + virtual void internal_onDestroy(); + virtual int internal_onNotify(int cmd, int param1, int param2, int param3, int param4); + OSMODULEHANDLE OSModuleHandle; + int postregisterservices; // if 1, onRegisterServices has been called + PtrList<LoadableResource> resources; + StringW componentpath; +}; + +extern "C" { + typedef void (*WACINIT)(OSMODULEHANDLE); + typedef UINT (*WACGETVERSION)(void); // returns the interface version component was compiled with + typedef WaComponent *(*WACENUMCOMPONENT)(int n); +}; + +class LoadableResource { +public: + virtual ~LoadableResource() {} + + virtual int deleteOnShutdown() { return TRUE; } // return FALSE if you're static + + virtual void onRegisterServices() {} + virtual void onDeregisterServices() {} // unload during this one + virtual void beforeLoadingSkinElements() {} +}; + +#endif diff --git a/Src/Wasabi/api/wac/waclient.cpp b/Src/Wasabi/api/wac/waclient.cpp new file mode 100644 index 00000000..3cc394c8 --- /dev/null +++ b/Src/Wasabi/api/wac/waclient.cpp @@ -0,0 +1,347 @@ +// the glue! +#include <precomp.h> +#include <wasabicfg.h> +#include <bfc/assert.h> +#include "wac.h" + +#include <api/service/servicei.h> +#include <api/memmgr/api_memmgr.h> + +#ifndef STATIC_COMPONENT +extern WAComponentClient *the; + +#ifndef WASABINOMAINAPI +ComponentAPI *api; // we do NOT delete this on shutdown!!! +#endif + +OSMODULEHANDLE g_modulehandle; +#endif //STATIC_COMPONENT + +WAComponentClient::WAComponentClient(const wchar_t *name) : + CfgItemI(name) { + OSModuleHandle = NULL; +} + +const wchar_t *WAComponentClient::getName() { + return cfgitem_getName(); +} + +#ifdef WASABINOMAINAPI +void WAComponentClient::registerServices(api_service *_serviceapi) +{ + serviceApi = _serviceapi; + + waServiceFactory *sf = serviceApi->service_getServiceByGuid(applicationApiServiceGuid); + if (sf) applicationApi = reinterpret_cast<api_application*>(sf->getInterface()); + +#ifdef WASABI_COMPILE_SYSCB + sf = serviceApi->service_getServiceByGuid(syscbApiServiceGuid); + if (sf) sysCallbackApi = reinterpret_cast<api_syscb *>(sf->getInterface()); +#endif + + sf = serviceApi->service_getServiceByGuid(memMgrApiServiceGuid); + if (sf) memmgrApi = reinterpret_cast<api_memmgr *>(sf->getInterface()); + +#ifdef WASABI_COMPILE_CONFIG + sf = serviceApi->service_getServiceByGuid(configApiServiceGuid); + if (sf) configApi = reinterpret_cast<api_config *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_IMGLDR + sf = serviceApi->service_getServiceByGuid(imgLdrApiServiceGuid); + if (sf) imgLoaderApi = reinterpret_cast<imgldr_api *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_FONTS + sf = serviceApi->service_getServiceByGuid(fontApiServiceGuid); + if (sf) fontApi = reinterpret_cast<api_font *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_FILEREADER + sf = serviceApi->service_getServiceByGuid(fileReaderApiServiceGuid); + if (sf) fileApi = reinterpret_cast<api_fileReader *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_LOCALES + sf = serviceApi->service_getServiceByGuid(localesApiServiceGuid); + if (sf) localesApi = reinterpret_cast<api_locales *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_TIMERS + sf = serviceApi->service_getServiceByGuid(timerApiServiceGuid); + if (sf) timerApi = reinterpret_cast<timer_api *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_WND + sf = serviceApi->service_getServiceByGuid(wndApiServiceGuid); + if (sf) wndApi = reinterpret_cast<wnd_api *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_WNDMGR + sf = serviceApi->service_getServiceByGuid(wndMgrApiServiceGuid); + if (sf) wndManagerApi = reinterpret_cast<wndmgr_api *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_COMPONENTS +#endif + +#ifdef WASABI_COMPILE_METADB +#endif + +#ifdef WASABI_COMPILE_SCRIPT + sf = serviceApi->service_getServiceByGuid(makiApiServiceGuid); + if (sf) makiApi = reinterpret_cast<api_maki *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_SKIN + sf = serviceApi->service_getServiceByGuid(skinApiServiceGuid); + if (sf) skinApi = reinterpret_cast<api_skin *>(sf->getInterface()); +#endif + +#ifdef WASABI_COMPILE_MAKIDEBUG + sf = serviceApi->service_getServiceByGuid(makiDebugApiServiceGuid); + if (sf) debugApi = reinterpret_cast<api_makiDebugger *>(sf->getInterface()); +#endif + +#else +void WAComponentClient::registerServices(ComponentAPI *_api) { + // save API * + api = _api; +#endif + + // propagate name from component to cfgitemi + if (cfgitem_getName() == NULL) CfgItemI::setName(WaComponent::getName()); + + // register resources + foreach(resources) + resources.getfor()->onRegisterServices(); + endfor + + // our CfgItem GUID defaults to our component GUID + cfgitem_setGUID(getGUID()); + + // by default, peg us under "Installed Components" in config + // {99CFD75C-1CA7-49e5-B8C0-7D78AA443C10} + const GUID installed_guid = + { 0x99cfd75c, 0x1ca7, 0x49e5, { 0xb8, 0xc0, 0x7d, 0x78, 0xaa, 0x44, 0x3c, 0x10 } }; + if (cfgitem_getParentGuid() == INVALID_GUID) + setParentGuid(installed_guid); + + WASABI_API_CONFIG->config_registerCfgItem(this); + + // allow overridden component class to do stuff + onRegisterServices(); +} + +int WAComponentClient::RegisterServicesSafeModeOk() +{ + return 1; +} + +void WAComponentClient::deregisterServices() { + foreach(resources) + resources.getfor()->onDeregisterServices(); + endfor + WASABI_API_CONFIG->config_deregisterCfgItem(this); +} + +CfgItem *WAComponentClient::getCfgInterface(int n) { + if (n == 0) return this; + return NULL; +} + +class RegService : public LoadableResource { +public: + RegService(waServiceFactoryI *sf) : factory(sf) {} + + virtual void onRegisterServices() { + WASABI_API_SVC->service_register(factory); + } + virtual void onDeregisterServices() { + WASABI_API_SVC->service_deregister(factory); + } + +private: + waServiceFactoryI *factory; +}; + +void WAComponentClient::registerService(waServiceFactoryI* service) { + registerResource(new RegService(service)); +} + +class SkinPart : public LoadableResource { +public: + SkinPart(const wchar_t *name, int rel) : filename(name), id(-1), relative(rel) {} + + void beforeLoadingSkinElements() { + ASSERT(!filename.isempty()); + StringW fn(filename); + switch (relative) { + case RSF_RELATIVETOWAC: + fn.prepend(the->getComponentPath());// api->path_getComponentPath()); + break; + case RSF_RELATIVETOTHEME: { + wchar_t theme[WA_MAX_PATH]=L""; + WASABI_API_CONFIG->getStringPrivate(L"theme", theme, WA_MAX_PATH, L"default"); + StringW path = WASABI_API_APP->path_getAppPath(); + path.AppendPath(L"themes"); + path.AppendPath(theme); + fn = StringPathCombine(path, fn); + } + break; + } + id = WASABI_API_SKIN->loadSkinFile(fn); + } + virtual void onDeregisterServices() { + if (id >= 0 && WASABI_API_SKIN) WASABI_API_SKIN->unloadSkinPart(id); + id = -1; + } + +private: + StringW filename; + int id; + int relative; +}; + +void WAComponentClient::registerSkinFile(const wchar_t *filename, int relative) +{ + registerResource(new SkinPart(filename, relative)); +} + +void WAComponentClient::registerResource(LoadableResource *res) { + ASSERT(!resources.haveItem(res)); + resources.addItem(res); + if (postregisterservices) res->onRegisterServices(); +} + +void WAComponentClient::internal_onDestroy() { + onDestroy(); + foreach(resources) + if (resources.getfor()->deleteOnShutdown()) delete resources.getfor(); + endfor + resources.removeAll(); +} + +int WAComponentClient::internal_onNotify(int cmd, int param1, int param2, int param3, int param4) { + switch (cmd) { + case WAC_NOTIFY_BEFORELOADINGSKINELEMENTS: + foreach(resources) + resources.getfor()->beforeLoadingSkinElements(); + endfor + break; + case WAC_NOTIFY_SKINLOADED: + onSkinLoaded(); + break; + } + return onNotify(cmd, param1, param2, param3, param4); +} + +#ifndef STATIC_COMPONENT +extern "C" { + +__declspec(dllexport) UINT WAC_getVersion(void) { + return WA_COMPONENT_VERSION; +} + +__declspec(dllexport) int WAC_init(OSMODULEHANDLE moduleHandle) { + the->setOSModuleHandle(moduleHandle); + if (g_modulehandle == NULL) g_modulehandle = moduleHandle; + return TRUE; +} + +__declspec(dllexport) WaComponent *WAC_enumComponent(int n) { + return the; +} + +} // end extern "C" +#endif + +#define CBCLASS WaComponentI +START_DISPATCH; + CB(GETNAME, getName); + CB(GETGUID, getGUID); +#ifndef WASABINOMAINAPI + VCB(REGISTERSERVICES, registerServices); +#else + VCB(REGISTERSERVICES2, registerServices); +#endif + CB(15, RegisterServicesSafeModeOk) + VCB(DEREGISTERSERVICES, deregisterServices); + VCB(ONCREATE, onCreate); + VCB(ONDESTROY, internal_onDestroy); + CB(CREATEWINDOW, createWindow); + CB(ONNOTIFY, internal_onNotify); + CB(ONCOMMAND, onCommand); + CB(GETCFGINTERFACE, getCfgInterface); + VCB(SETOSMODULEHANDLE, setOSModuleHandle); + CB(GETOSMODULEHANDLE, getOSModuleHandle); + VCB(SETPATH, setComponentPath); + CB(GETPATH, getComponentPath); +END_DISPATCH; +#undef CBCLASS + +#ifdef WASABINOMAINAPI + +api_application *applicationApi = NULL; +api_service *serviceApi = NULL; +api_syscb *sysCallbackApi = NULL; + + +api_memmgr *memmgrApi = NULL; + +#ifdef WASABI_COMPILE_CONFIG +api_config *configApi = NULL; +#endif + +#ifdef WASABI_COMPILE_IMGLDR +imgldr_api *imgLoaderApi = NULL; +#endif + +#ifdef WASABI_COMPILE_FONTS +api_font *fontApi = NULL; +#endif + + +#ifdef WASABI_COMPILE_FILEREADER +api_fileReader *fileApi = NULL; +#endif + +#ifdef WASABI_COMPILE_LOCALES +api_locales *localesApi = NULL; +#endif + +#ifdef WASABI_COMPILE_TIMERS +timer_api *timerApi = NULL; +#endif + +#ifdef WASABI_COMPILE_WND +wnd_api *wndApi = NULL; +#endif + +#ifdef WASABI_COMPILE_WNDMGR +wndmgr_api *wndManagerApi = NULL; +#endif + +#ifdef WASABI_COMPILE_COMPONENTS +#endif + +#ifdef WASABI_COMPILE_METADB +#endif + +#ifdef WASABI_COMPILE_SCRIPT +api_maki *makiApi = NULL; +#endif + +#ifdef WASABI_COMPILE_SKIN +api_skin *skinApi; +#endif + +#ifdef WASABI_COMPILE_MAKIDEBUG +api_makiDebugger *debugApi = NULL; +#endif + +#ifdef WASABI_COMPILE_MEDIACORE +api_core *coreApi = NULL; +#endif + +#endif // ifdef WASABINOMAINAPI
\ No newline at end of file |