From 5359f0d4ccab8979024dcbb7435ed6f272f2a677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 19 Aug 2004 16:00:09 +0000 Subject: [PATCH] added an addon manager directly from our media server, not finalized git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8609 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/input/AddOnManager.cpp | 339 +++++++++++++++++++++++++++++ src/servers/input/AddOnManager.h | 57 +++++ src/servers/input/InputServer.cpp | 24 +- src/servers/input/InputServer.h | 2 + src/servers/input/Jamfile | 2 + src/servers/input/TList.h | 129 +++++++++++ 6 files changed, 543 insertions(+), 10 deletions(-) create mode 100644 src/servers/input/AddOnManager.cpp create mode 100644 src/servers/input/AddOnManager.h create mode 100644 src/servers/input/TList.h diff --git a/src/servers/input/AddOnManager.cpp b/src/servers/input/AddOnManager.cpp new file mode 100644 index 0000000000..6d9af8c866 --- /dev/null +++ b/src/servers/input/AddOnManager.cpp @@ -0,0 +1,339 @@ +/* +** Copyright 2004, the OpenBeOS project. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +** +** Authors: Marcus Overhagen, Axel Dörfler +*/ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "AddOnManager.h" + +// #pragma mark ImageLoader + +/** The ImageLoader class is a convenience class to temporarily load + * an image file, and unload it on deconstruction automatically. + */ + +class ImageLoader { + public: + ImageLoader(BPath &path) + { + fImage = load_add_on(path.Path()); + } + + ~ImageLoader() + { + if (fImage >= B_OK) + unload_add_on(fImage); + } + + status_t InitCheck() const { return fImage; } + image_id Image() const { return fImage; } + + private: + image_id fImage; +}; + + +// #pragma mark - + + +AddOnManager::AddOnManager() + : + fLock("add-on manager") +{ +} + + +AddOnManager::~AddOnManager() +{ +} + + +void +AddOnManager::LoadState() +{ + RegisterAddOns(); +} + + +void +AddOnManager::SaveState() +{ +} + + +/*status_t +AddOnManager::GetDecoderForFormat(xfer_entry_ref *_decoderRef, + const media_format &format) +{ + if ((format.type == B_MEDIA_ENCODED_VIDEO + || format.type == B_MEDIA_ENCODED_AUDIO + || format.type == B_MEDIA_MULTISTREAM) + && format.Encoding() == 0) + return B_MEDIA_BAD_FORMAT; + if (format.type == B_MEDIA_NO_TYPE + || format.type == B_MEDIA_UNKNOWN_TYPE) + return B_MEDIA_BAD_FORMAT; + + + BAutolock locker(fLock); + + printf("AddOnManager::GetDecoderForFormat: searching decoder for encoding %ld\n", format.Encoding()); + + decoder_info *info; + for (fDecoderList.Rewind(); fDecoderList.GetNext(&info);) { + media_format *decoderFormat; + for (info->formats.Rewind(); info->formats.GetNext(&decoderFormat);) { + // check if the decoder matches the supplied format + if (!decoderFormat->Matches(&format)) + continue; + + printf("AddOnManager::GetDecoderForFormat: found decoder %s for encoding %ld\n", + info->ref.name, decoderFormat->Encoding()); + + *_decoderRef = info->ref; + return B_OK; + } + } + return B_ENTRY_NOT_FOUND; +} + + +status_t +AddOnManager::GetReaders(xfer_entry_ref *out_res, int32 *out_count, int32 max_count) +{ + BAutolock locker(fLock); + + *out_count = 0; + + fReaderList.Rewind(); + reader_info *info; + for (*out_count = 0; fReaderList.GetNext(&info) && *out_count <= max_count; *out_count += 1) + out_res[*out_count] = info->ref; + + return B_OK; +}*/ + + +status_t +AddOnManager::RegisterAddOn(BEntry &entry) +{ + BPath path(&entry); + + entry_ref ref; + status_t status = entry.GetRef(&ref); + if (status < B_OK) + return status; + + printf("AddOnManager::RegisterAddOn(): trying to load \"%s\"\n", path.Path()); + + ImageLoader loader(path); + if ((status = loader.InitCheck()) < B_OK) + return status; + + BEntry parent; + entry.GetParent(&parent); + BPath parentPath(&parent); + BString pathString = parentPath.Path(); + + if (pathString.FindFirst("input_server/devices")>0) { + BInputServerDevice *(*instantiate_func)(); + + if (get_image_symbol(loader.Image(), "instantiate_input_device", + B_SYMBOL_TYPE_TEXT, (void **)&instantiate_func) < B_OK) { + printf("AddOnManager::RegisterAddOn(): can't find instantiate_input_device in \"%s\"\n", + path.Path()); + return B_BAD_TYPE; + } + + BInputServerDevice *isd = (*instantiate_func)(); + if (isd == NULL) { + printf("AddOnManager::RegisterAddOn(): instantiate_input_device in \"%s\" returned NULL\n", + path.Path()); + return B_ERROR; + } + + RegisterDevice(isd, ref); + + } else if (pathString.FindFirst("input_server/filters")>0) { + BInputServerFilter *(*instantiate_func)(); + + if (get_image_symbol(loader.Image(), "instantiate_input_filter", + B_SYMBOL_TYPE_TEXT, (void **)&instantiate_func) < B_OK) { + printf("AddOnManager::RegisterAddOn(): can't find instantiate_input_filter in \"%s\"\n", + path.Path()); + return B_BAD_TYPE; + } + + BInputServerFilter *isf = (*instantiate_func)(); + if (isf == NULL) { + printf("AddOnManager::RegisterAddOn(): instantiate_input_filter in \"%s\" returned NULL\n", + path.Path()); + return B_ERROR; + } + + RegisterFilter(isf, ref); + + } else if (pathString.FindFirst("input_server/methods")>0) { + BInputServerMethod *(*instantiate_func)(); + + if (get_image_symbol(loader.Image(), "instantiate_input_method", + B_SYMBOL_TYPE_TEXT, (void **)&instantiate_func) < B_OK) { + printf("AddOnManager::RegisterAddOn(): can't find instantiate_input_method in \"%s\"\n", + path.Path()); + return B_BAD_TYPE; + } + + BInputServerMethod *ism = (*instantiate_func)(); + if (ism == NULL) { + printf("AddOnManager::RegisterAddOn(): instantiate_input_method in \"%s\" returned NULL\n", + path.Path()); + return B_ERROR; + } + + RegisterMethod(ism, ref); + + } + + return B_OK; +} + + +void +AddOnManager::RegisterAddOns() +{ + class IAHandler : public AddOnMonitorHandler { + private: + AddOnManager * fManager; + public: + IAHandler(AddOnManager * manager) { + fManager = manager; + } + virtual void AddOnCreated(const add_on_entry_info * entry_info) { + } + virtual void AddOnEnabled(const add_on_entry_info * entry_info) { + entry_ref ref; + make_entry_ref(entry_info->dir_nref.device, entry_info->dir_nref.node, + entry_info->name, &ref); + BEntry entry(&ref, false); + fManager->RegisterAddOn(entry); + } + virtual void AddOnDisabled(const add_on_entry_info * entry_info) { + } + virtual void AddOnRemoved(const add_on_entry_info * entry_info) { + } + }; + + const directory_which directories[] = { + B_USER_ADDONS_DIRECTORY, + B_COMMON_ADDONS_DIRECTORY, + B_BEOS_ADDONS_DIRECTORY, + }; + const char subDirectories[][24] = { +// "input_server/devices", + "input_server/filters", + "input_server/methods", + }; + fHandler = new IAHandler(this); + fAddOnMonitor = new AddOnMonitor(fHandler); + + node_ref nref; + BDirectory directory; + BPath path; + for (uint i = 0 ; i < sizeof(directories) / sizeof(directory_which) ; i++) + for (uint j = 0 ; j < 2 ; j++) { + if ((find_directory(directories[i], &path) == B_OK) + && (path.Append(subDirectories[j]) == B_OK) + && (directory.SetTo(path.Path()) == B_OK) + && (directory.GetNodeRef(&nref) == B_OK)) { + fHandler->AddDirectory(&nref); + } + } + + // ToDo: this is for our own convenience only, and should be removed + // in the final release + //if ((directory.SetTo("/boot/home/develop/openbeos/current/distro/x86.R1/beos/system/add-ons/media/plugins") == B_OK) + // && (directory.GetNodeRef(&nref) == B_OK)) { + // fHandler->AddDirectory(&nref); + //} +} + + +void +AddOnManager::RegisterDevice(BInputServerDevice *isd, const entry_ref &ref) +{ + BAutolock locker(fLock); + + device_info *pinfo; + for (fDeviceList.Rewind(); fDeviceList.GetNext(&pinfo);) { + if (!strcmp(pinfo->ref.name, ref.name)) { + // we already know this device + return; + } + } + + PRINT(("AddOnManager::RegisterDevice, name %s\n", ref.name)); + + device_info info; + info.ref = ref; + + fDeviceList.Insert(info); +} + + +void +AddOnManager::RegisterFilter(BInputServerFilter *filter, const entry_ref &ref) +{ + BAutolock locker(fLock); + + filter_info *pinfo; + for (fFilterList.Rewind(); fFilterList.GetNext(&pinfo);) { + if (!strcmp(pinfo->ref.name, ref.name)) { + // we already know this ref + return; + } + } + + PRINT(("%s, name %s\n", __PRETTY_FUNCTION__, ref.name)); + + filter_info info; + info.ref = ref; + + fFilterList.Insert(info); +} + + +void +AddOnManager::RegisterMethod(BInputServerMethod *method, const entry_ref &ref) +{ + BAutolock locker(fLock); + + method_info *pinfo; + for (fMethodList.Rewind(); fMethodList.GetNext(&pinfo);) { + if (!strcmp(pinfo->ref.name, ref.name)) { + // we already know this ref + return; + } + } + + PRINT(("%s, name %s\n", __PRETTY_FUNCTION__, ref.name)); + + method_info info; + info.ref = ref; + + fMethodList.Insert(info); +} + + diff --git a/src/servers/input/AddOnManager.h b/src/servers/input/AddOnManager.h new file mode 100644 index 0000000000..0b398b00b7 --- /dev/null +++ b/src/servers/input/AddOnManager.h @@ -0,0 +1,57 @@ +/* +** Copyright 2004, the OpenBeOS project. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +** +** Author : Jérôme Duval +** Original authors: Marcus Overhagen, Axel Dörfler +*/ +#ifndef _ADD_ON_MANAGER_H +#define _ADD_ON_MANAGER_H + +// Manager for input_server add-ons (devices, filters, methods) + +#include +#include +#include +#include +#include "AddOnMonitor.h" +#include "AddOnMonitorHandler.h" +#include "TList.h" + +class AddOnManager { + public: + AddOnManager(); + ~AddOnManager(); + + void LoadState(); + void SaveState(); + + private: + status_t RegisterAddOn(BEntry &entry); + void RegisterAddOns(); + + void RegisterDevice(BInputServerDevice *isd, const entry_ref &ref); + void RegisterFilter(BInputServerFilter *isf, const entry_ref &ref); + void RegisterMethod(BInputServerMethod *ism, const entry_ref &ref); + + private: + struct device_info { + entry_ref ref; + }; + struct filter_info { + entry_ref ref; + }; + struct method_info { + entry_ref ref; + }; + + BLocker fLock; + List fDeviceList; + List fFilterList; + List fMethodList; + + AddOnMonitorHandler *fHandler; + AddOnMonitor *fAddOnMonitor; +}; + +#endif // _ADD_ON_MANAGER_H diff --git a/src/servers/input/InputServer.cpp b/src/servers/input/InputServer.cpp index f616bc5c11..9671e755b0 100644 --- a/src/servers/input/InputServer.cpp +++ b/src/servers/input/InputServer.cpp @@ -33,14 +33,13 @@ #include - -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include #if DEBUG>=1 @@ -51,10 +50,10 @@ #define CALLED() ((void)0) #endif +#include "InputServer.h" #include "InputServerDeviceListEntry.h" #include "InputServerFilterListEntry.h" #include "InputServerMethodListEntry.h" -#include #include "InputServerTypes.h" // include app_server headers for communication @@ -109,9 +108,12 @@ InputServer::InputServer(void) : BApplication("application/x-vnd.OBOS-input_serv InitTestDevice(); + fAddOnManager = new AddOnManager(); + fAddOnManager->LoadState(); + // InitDevices(); - InitFilters(); - InitMethods(); +// InitFilters(); +// InitMethods(); } /* @@ -121,6 +123,8 @@ InputServer::InputServer(void) : BApplication("application/x-vnd.OBOS-input_serv InputServer::~InputServer(void) { CALLED(); + fAddOnManager->SaveState(); + delete fAddOnManager; } diff --git a/src/servers/input/InputServer.h b/src/servers/input/InputServer.h index 876ddd354b..c7ad7c668c 100644 --- a/src/servers/input/InputServer.h +++ b/src/servers/input/InputServer.h @@ -34,6 +34,7 @@ #include "InputServerDevice.h" #include "InputServerFilter.h" #include "InputServerMethod.h" +#include "AddOnManager.h" #include #include @@ -177,6 +178,7 @@ private: // added this to communicate via portlink BPortLink *serverlink; + AddOnManager *fAddOnManager; //fMouseState; }; diff --git a/src/servers/input/Jamfile b/src/servers/input/Jamfile index 54c28285ab..8189a1b8f9 100644 --- a/src/servers/input/Jamfile +++ b/src/servers/input/Jamfile @@ -12,6 +12,8 @@ Server input_server : InputServerFilter.cpp InputServerMethod.cpp + AddOnManager.cpp + # storage AddOnMonitor.cpp AddOnMonitorHandler.cpp diff --git a/src/servers/input/TList.h b/src/servers/input/TList.h new file mode 100644 index 0000000000..72a38bd2d3 --- /dev/null +++ b/src/servers/input/TList.h @@ -0,0 +1,129 @@ +#ifndef _MEDIA_T_LIST_H +#define _MEDIA_T_LIST_H + +#include + +template class List +{ +public: + List() + : item_max(INIT_COUNT), + item_count(0), + item_iter(-1), + items((value **)malloc(sizeof(value *) * INIT_COUNT)) + { + ASSERT(items); + } + + ~List() + { + MakeEmpty(); + free(items); + } + + List(const List &other) + { + *this = other; + } + + List &operator=(const List &other) + { + MakeEmpty(); + free(items); + item_max = other.item_max; + item_count = other.item_count; + items = (value **)malloc(sizeof(value *) * item_max); + ASSERT(items); + for (int i = 0; i < item_count; i++) { + items[i] = new value; + *items[i] = *other.items[i]; + } + return *this; + } + + bool Insert(const value &v) + { + if (item_count == item_max) { + item_max *= 2; + items = (value **)realloc(items, sizeof(value *) * item_max); + ASSERT(items); + } + items[item_count] = new value; + *items[item_count] = v; + item_count++; + return true; + } + + bool Get(int32 index, value **v) + { + if (index < 0 || index >= item_count) + return false; + *v = items[index]; + return true; + } + + bool Remove(int32 index) + { + if (index < 0 || index >= item_count) + return false; + delete items[index]; + item_count--; + items[index] = items[item_count]; + if (index == item_iter) + item_iter--; + return true; + } + + int Find(const value &v) + { + for (int i = 0; i < item_count; i++) + if (*items[i] == v) + return i; + return -1; + } + + int CountItems() + { + return item_count; + } + + bool IsEmpty() + { + return item_count == 0; + } + + void MakeEmpty() + { + if (items != 0) { + for (int i = 0; i < item_count; i++) { + delete items[i]; + } + item_count = 0; + } + } + + void Rewind() + { + item_iter = -1; + } + + bool GetNext(value **v) + { + item_iter++; + return Get(item_iter, v); + } + + bool RemoveCurrent() + { + return Remove(item_iter); + } + +private: + enum { INIT_COUNT=32 }; + int item_max; + int item_count; + int item_iter; + value **items; +}; + +#endif // _MEDIA_T_LIST_H