From 3ba329f7bfaa2c97cb49bb95c650240cd7f7cdca Mon Sep 17 00:00:00 2001 From: beveloper Date: Mon, 12 Aug 2002 19:38:19 +0000 Subject: [PATCH] Start using a class for management and (perhaps later) caching of dormant media nodes git-svn-id: file:///srv/svn/repos/haiku/trunk/current@719 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/media/DormantNodeManager.cpp | 264 +++++++++++++++++++++++++- 1 file changed, 259 insertions(+), 5 deletions(-) diff --git a/src/kits/media/DormantNodeManager.cpp b/src/kits/media/DormantNodeManager.cpp index 42e5839b9a..d0750f5599 100644 --- a/src/kits/media/DormantNodeManager.cpp +++ b/src/kits/media/DormantNodeManager.cpp @@ -1,7 +1,261 @@ -/* +/* + * Copyright 2002, Marcus Overhagen. All rights reserved. + * Distributed under the terms of the MIT License. + */ +/* This is a management class for dormant media nodes. + * It is private to the media kit and only accessed by the BMediaRoster class + * and the media_addon_server. + * It handles loading/unloading of dormant nodes. + * + * Dormant media nodes can be instantiated on demand. The reside on harddisk in the + * directories /boot/beos/system/add-ons/media and /boot/home/config/add-ons/media + * Multiple media nodes can be included in one file, they can be accessed using the + * BMediaAddOn that each file implements. + * The BMediaAddOn allows getting a list of supported flavors. Each flavor represents + * a media node. + * The media_addon_server does the initial scanning of files and getting the list + * of supported flavors. It uses the flavor_info to do this, and reports the list + * of flavors to the media_server packed into individual dormant_media_node + * structures. + */ + +#include +#include +#include +#include +#include +#include +#include "debug.h" #include "DormantNodeManager.h" - -static DormantNodeManager manager; -DormantNodeManager *_DormantNodeManager = &manager; -*/ \ No newline at end of file + +static BPrivate::media::DormantNodeManager manager; +BPrivate::media::DormantNodeManager *_DormantNodeManager = &manager; + +namespace BPrivate { +namespace media { + +DormantNodeManager::DormantNodeManager() +{ + fLock = new BLocker(); + fAddonmap = new Map; +} + + +DormantNodeManager::~DormantNodeManager() +{ + delete fLock; + + // force unloading all currently loaded images + loaded_addon_info *info; + for (int32 index = 0; fAddonmap->GetPointerAt(index,&info); index++) { + printf("Forcing unload of add-on %d with usecount %d\n",info->addon, info->usecount); + UnloadAddon(info->addon, info->image); + } + + delete fAddonmap; +} + + +BMediaAddOn * +DormantNodeManager::TryGetAddon(media_addon_id id) +{ + loaded_addon_info *info; + BMediaAddOn *addon; + + fLock->Lock(); + if (fAddonmap->GetPointer(id,&info)) { + info->usecount += 1; + addon = info->addon; + ASSERT(id == addon->AddonID()); + } else { + addon = NULL; + } + fLock->Unlock(); + return addon; +} + + +BMediaAddOn * +DormantNodeManager::GetAddon(media_addon_id id) +{ + BMediaAddOn *addon; + + // first try to use a already loaded add-on + addon = TryGetAddon(id); + if (addon) + return addon; + + // Be careful, we avoid locking here! + + // ok, it's not loaded, try to get the path + BPath path; + if (B_OK != FindAddonPath(&path, id)) { + printf("can't find path for add-on %d\n",id); + return NULL; + } + + // try to load it + BMediaAddOn *newaddon; + image_id image; + if (B_OK != LoadAddon(&newaddon, &image, path.Path(), id)) { + printf("can't load add-on %d from path %s\n",id, path.Path()); + return NULL; + } + + // ok, we successfully loaded it. Now lock and insert it into the map, + // or unload it if the map already contains one that was loaded by another + // thread at the same time + fLock->Lock(); + addon = TryGetAddon(id); + if (addon) { + UnloadAddon(newaddon, image); + } else { + // we use the loaded one + addon = newaddon; + // and save it into the list + loaded_addon_info info; + info.addon = newaddon; + info.image = image; + info.usecount = 1; + fAddonmap->Insert(id, info); + } + fLock->Unlock(); + ASSERT(addon->Addon() == id); + return addon; +} + + +void +DormantNodeManager::PutAddon(media_addon_id id) +{ + loaded_addon_info *info; + BMediaAddOn *addon; + image_id image; + bool unload; + + fLock->Lock(); + if (!fAddonmap->GetPointer(id, &info)) { + printf("failed to put add-on %d\n",id); + fLock->Unlock(); + return; + } + info->usecount -= 1; + unload = (info->usecount == 0); + if (unload) { + addon = info->addon; + image = info->image; + unload = true; + fAddonmap->Remove(id); + } + fLock->Unlock(); + + if (unload) + UnloadAddon(addon, image); +} + + +media_addon_id +DormantNodeManager::RegisterAddon(const char *path) +{ +/* + xfer_server_register_mediaaddon msg; + xfer_server_register_mediaaddon_reply reply; + port_id port; + status_t rv; + int32 code; + port = find_port("media_server port"); + if (port <= B_OK) + return; + msg.reply_port = _PortPool->GetPort(); + rv = write_port(port, SERVER_REGISTER_MEDIAADDON, &msg, sizeof(msg)); + if (rv != B_OK) { + _PortPool->PutPort(msg.reply_port); + return; + } + rv = read_port(msg.reply_port, &code, &reply, sizeof(reply)); + _PortPool->PutPort(msg.reply_port); + if (rv < B_OK) + return; + fAddon = reply.addonid; +*/ +} + + +void +DormantNodeManager::UnregisterAddon(media_addon_id id) +{ +/* + if (_fAddon != 0) { + xfer_server_unregister_mediaaddon msg; + port_id port; + port = find_port("media_server port"); + if (port <= B_OK) + return; + msg.addonid = _fAddon; + write_port(port, SERVER_UNREGISTER_MEDIAADDON, &msg, sizeof(msg)); + } +*/ +} + + +status_t +DormantNodeManager::FindAddonPath(BPath *path, media_addon_id id) +{ +} + + +status_t +DormantNodeManager::LoadAddon(BMediaAddOn **newaddon, image_id *newimage, const char *path, media_addon_id id) +{ + BMediaAddOn *(*make_addon)(image_id you); + BMediaAddOn *addon; + image_id image; + status_t rv; + + image = load_add_on(path); + if (image < B_OK) { + printf("loading failed %lx %s\n", image, strerror(image)); + return B_ERROR; + } + + rv = get_image_symbol(image, "make_media_addon", B_SYMBOL_TYPE_TEXT, (void**)&make_addon); + if (rv < B_OK) { + printf("loading failed, function not found %lx %s\n", rv, strerror(rv)); + unload_add_on(image); + return B_ERROR; + } + + addon = make_addon(image); + if (addon == 0) { + printf("creating BMediaAddOn failed\n"); + unload_add_on(image); + return B_ERROR; + } + + ASSERT(addon->Image() == image); // this should be true for a well behaving add-on + + // everything ok + *newaddon = addon; + *newimage = image; + + // we are a friend class of BMediaAddOn and initilize these member variables + addon->fAddon = id; + addon->fImage = image; + + return B_OK; +} + + +void +DormantNodeManager::UnloadAddon(BMediaAddOn *addon, image_id image) +{ + ASSERT(addon); + ASSERT(addon->Image() == image); // if this failes, something bad happends to the add-on + delete addon; + unload_add_on(image); +} + +}; // namespace media +}; // namespace BPrivate +