From 9dec23104287e2fd592cc14148b43fb28a6e1d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 5 Dec 2009 11:11:28 +0000 Subject: [PATCH] Sorry for this large commit in advance; it's not really possible to divide this into smaller parts: media_addon_server: * Removed (broken) use of (broken and inefficient) home-brewn Map, and List classes. This also fixes a crash on shutdown when used with the malloc_debug implementation. It's using stl::vector, and stl::map now instead. _shared_buffer_list: * Renamed _shared_buffer_list to SharedBufferList, and put it into the BPrivate namespace. Also, made a class out of it. * Separated shared buffer list creation from cloning. * Enlarged maximum number of buffers to something that is not that evil, but actually uses the space it has (ie. is a useful multiple of shared_buffer_info that fills a multiple of B_PAGE_SIZE as much as possible). * No longer drops into the debugger if the * The list that is currently used is very inefficient for the features it provides though (no change there). _buffer_id_cache: * Renamed to BufferCache, and put it into the private namespace * It now deletes its buffers on deletion; since the BBufferConsumer will be gone, too, at this point, there is little chance that there are still buffers in use. * Also, it's now using std::map instead of the (see above) Map class. BBuffer: * Got rid of the fBufferID member. Misc.: * Got rid of the global "team" variable; the media kit is now using the private app kit's current_team() now. * Added a lot of missing error checks (mostly memory allocations). * Renamed fields like "flavorid" to flavor_id, renamed "dfi_*" fields to something more detailed. * Moved ServerInterface.h from src/servers/media/ to headers/private/media. * Notifications.h was not self contained. * Added missing licenses. * Lots of cleanups, and coding style fixes. What this doesn't fix: * Bug #4954 which started all this (this comes next, though) * Deinitialization is broken, as the PortPool is uninitialized too early, and still used afterwards. * The strange add-on monitoring code in the media_addon_server git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34500 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/media/Buffer.h | 14 +- headers/os/media/BufferConsumer.h | 4 +- headers/os/media/BufferGroup.h | 8 +- headers/private/media/DataExchange.h | 30 +- headers/private/media/Notifications.h | 23 +- headers/private/media/PortPool.h | 22 +- headers/private/media/ServerInterface.h | 72 ++ headers/private/media/SharedBufferList.h | 95 +-- src/kits/media/Buffer.cpp | 73 +- src/kits/media/BufferCache.cpp | 59 ++ src/kits/media/BufferCache.h | 38 + src/kits/media/BufferConsumer.cpp | 342 +++++---- src/kits/media/BufferGroup.cpp | 52 +- src/kits/media/BufferIdCache.cpp | 45 -- src/kits/media/BufferIdCache.h | 25 - src/kits/media/DataExchange.cpp | 75 +- src/kits/media/DormantNodeManager.cpp | 43 +- src/kits/media/Jamfile | 9 +- src/kits/media/MediaAddOn.cpp | 24 +- src/kits/media/MediaRoster.cpp | 250 +++---- src/kits/media/Notifications.cpp | 124 ++-- src/kits/media/SharedBufferList.cpp | 463 +++++++----- src/servers/media/BufferManager.cpp | 77 +- src/servers/media/BufferManager.h | 20 +- src/servers/media/DefaultManager.cpp | 76 +- src/servers/media/NodeManager.cpp | 139 ++-- src/servers/media/NodeManager.h | 25 +- src/servers/media/ServerInterface.h | 63 -- src/servers/media/media_server.cpp | 131 ++-- src/servers/media_addon/Jamfile | 4 - src/servers/media_addon/main.cpp | 890 ++++++++++++----------- 31 files changed, 1767 insertions(+), 1548 deletions(-) create mode 100644 headers/private/media/ServerInterface.h create mode 100644 src/kits/media/BufferCache.cpp create mode 100644 src/kits/media/BufferCache.h delete mode 100644 src/kits/media/BufferIdCache.cpp delete mode 100644 src/kits/media/BufferIdCache.h delete mode 100644 src/servers/media/ServerInterface.h diff --git a/headers/os/media/Buffer.h b/headers/os/media/Buffer.h index 80e9255a7f..801927ae14 100644 --- a/headers/os/media/Buffer.h +++ b/headers/os/media/Buffer.h @@ -9,7 +9,10 @@ #include -struct _shared_buffer_list; +namespace BPrivate { + class BufferCache; + class SharedBufferList; +} struct buffer_clone_info { @@ -54,8 +57,8 @@ public: size_t Size(); private: - friend struct _buffer_id_cache; - friend struct _shared_buffer_list; + friend class BPrivate::BufferCache; + friend class BPrivate::SharedBufferList; friend class BMediaRoster; friend class BBufferProducer; friend class BBufferConsumer; @@ -73,15 +76,14 @@ private: void SetHeader(const media_header* header); media_header fMediaHeader; - _shared_buffer_list* fBufferList; + BPrivate::SharedBufferList* fBufferList; area_id fArea; void* fData; size_t fOffset; size_t fSize; - media_buffer_id fBufferID; int32 fFlags; - uint32 _reserved[11]; + uint32 _reserved[12]; }; diff --git a/headers/os/media/BufferConsumer.h b/headers/os/media/BufferConsumer.h index f1748ff897..a02bfbcc3a 100644 --- a/headers/os/media/BufferConsumer.h +++ b/headers/os/media/BufferConsumer.h @@ -13,9 +13,9 @@ class BBuffer; class BBufferGroup; class BRegion; -class _buffer_id_cache; namespace BPrivate { + class BufferCache; namespace media { class BMediaRosterEx; } @@ -147,7 +147,7 @@ private: private: media_type fConsumerType; - _buffer_id_cache* fBufferCache; + BPrivate::BufferCache* fBufferCache; BBufferGroup* fDeleteBufferGroup; uint32 _reserved[14]; }; diff --git a/headers/os/media/BufferGroup.h b/headers/os/media/BufferGroup.h index 674b2767b5..8a88db50b1 100644 --- a/headers/os/media/BufferGroup.h +++ b/headers/os/media/BufferGroup.h @@ -10,7 +10,9 @@ class BBuffer; -struct _shared_buffer_list; +namespace BPrivate { + struct SharedBufferList; +} class BBufferGroup { @@ -53,12 +55,12 @@ private: status_t _Init(); private: - friend struct _shared_buffer_list; + friend struct BPrivate::SharedBufferList; status_t fInitError; status_t fRequestError; int32 fBufferCount; - _shared_buffer_list* fBufferList; + BPrivate::SharedBufferList* fBufferList; sem_id fReclaimSem; uint32 _reserved[9]; diff --git a/headers/private/media/DataExchange.h b/headers/private/media/DataExchange.h index 323835ed2c..180274303d 100644 --- a/headers/private/media/DataExchange.h +++ b/headers/private/media/DataExchange.h @@ -286,8 +286,8 @@ enum { }; struct addonserver_instantiate_dormant_node_request : request_data { - media_addon_id addonid; - int32 flavorid; + media_addon_id addon_id; + int32 flavor_id; team_id creator_team; }; @@ -605,8 +605,8 @@ struct server_set_node_creator_reply : reply_data { }; struct server_change_addon_flavor_instances_count_request : request_data { - media_addon_id addonid; - int32 flavorid; + media_addon_id addon_id; + int32 flavor_id; int32 delta; // must be +1 or -1 team_id team; }; @@ -624,17 +624,17 @@ struct server_register_node_request : request_data { }; struct server_register_node_reply : reply_data { - media_node_id nodeid; + media_node_id node_id; }; struct server_unregister_node_request : request_data { - media_node_id nodeid; + media_node_id node_id; team_id team; }; struct server_unregister_node_reply : reply_data { - media_addon_id addonid; - int32 flavorid; + media_addon_id addon_id; + int32 flavor_id; }; struct server_get_live_node_info_request : request_data { @@ -669,11 +669,11 @@ struct server_node_id_for_request : request_data { }; struct server_node_id_for_reply : reply_data { - media_node_id nodeid; + media_node_id node_id; }; struct server_get_node_for_request : request_data { - media_node_id nodeid; + media_node_id node_id; team_id team; }; @@ -713,7 +713,7 @@ struct server_rescan_defaults_command : command_data { }; struct addonserver_rescan_mediaaddon_flavors_command : command_data { - media_addon_id addonid; + media_addon_id addon_id; }; struct addonserver_rescan_finished_notify_command : command_data { @@ -724,15 +724,15 @@ struct server_register_mediaaddon_request : request_data { }; struct server_register_mediaaddon_reply : reply_data { - media_addon_id addonid; + media_addon_id addon_id; }; struct server_unregister_mediaaddon_command : command_data { - media_addon_id addonid; + media_addon_id addon_id; }; struct server_get_mediaaddon_ref_request : request_data { - media_addon_id addonid; + media_addon_id addon_id; }; struct server_get_mediaaddon_ref_reply : reply_data { @@ -757,7 +757,7 @@ struct server_register_buffer_reply : reply_data { struct server_unregister_buffer_command : command_data { team_id team; - media_buffer_id bufferid; + media_buffer_id buffer_id; }; struct server_rewindtypes_request : request_data { diff --git a/headers/private/media/Notifications.h b/headers/private/media/Notifications.h index 3ef54bc10a..cfc2307edc 100644 --- a/headers/private/media/Notifications.h +++ b/headers/private/media/Notifications.h @@ -1,11 +1,14 @@ -/* +/* * Copyright 2002, Marcus Overhagen. All rights reserved. * Distributed under the terms of the MIT License. */ - #ifndef _NOTIFICATIONS_H #define _NOTIFICATIONS_H + +#include + + namespace BPrivate { namespace media { namespace notifications { @@ -15,7 +18,7 @@ namespace notifications { * The notifications marked with "N" are only send when the * media_node specific BMediaRoster::StartWatching() is used * and the notification belongs to the watched node. - * + * * In addition, anyone watching a specific node will also receive * error notifications generated by BMediaNode::ReportError() * @@ -35,13 +38,13 @@ namespace notifications { * B_MEDIA_NODE_STOPPED N "node", "when" * B_MEDIA_FLAVORS_CHANGED "be:addon_id", "be:new_count", "be:gone_count" */ - + // used for BMediaRoster::StartWatching() parameter validation bool IsValidNotificationRequest(bool node_specific, int32 notification); // called by BMediaRoster::StartWatching() status_t Register(const BMessenger ¬ifyHandler, const media_node &node, int32 notification); - + // called by BMediaRoster::StopWatching() status_t Unregister(const BMessenger ¬ifyHandler, const media_node &node, int32 notification); @@ -54,20 +57,20 @@ namespace notifications { void ConnectionBroken(const media_source &source, const media_destination &destination); void BuffersCreated(area_info *areas, int32 count); void BuffersDeleted(const media_buffer_id *ids, int32 count); - + // called by BMediaNode::NodeStopped() void NodeStopped(const media_node &node, bigtime_t when); // called by BControllable::BroadcastChangedParameter() status_t ParameterChanged(const media_node &node, int32 parameterid); - + // called by BControllable::SetParameterWeb() void WebChanged(const media_node &node); - + // called by BControllable::BroadcastNewParameterValue() status_t NewParameterValue(const media_node &node, int32 parameterid, bigtime_t when, const void *param, size_t paramsize); - - // called by the media_addon_server AFTER a flavor change has been + + // called by the media_addon_server AFTER a flavor change has been // handled. NOT CALLED by BMediaAddOn::NotifyFlavorChange() void FlavorsChanged(media_addon_id addonid, int32 newcount, int32 gonecount); diff --git a/headers/private/media/PortPool.h b/headers/private/media/PortPool.h index 3f174ff45b..9dcca98983 100644 --- a/headers/private/media/PortPool.h +++ b/headers/private/media/PortPool.h @@ -1,30 +1,28 @@ -/*********************************************************************** - * Copyright (c) 2002 Marcus Overhagen. All Rights Reserved. - * This file may be used under the terms of the OpenBeOS License. - * - * A pool of kernel ports - ***********************************************************************/ +/* + * Copyright 2002, Marcus Overhagen. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ #ifndef _POOL_PORT_H_ #define _POOL_PORT_H_ -class PortPool -{ + +class PortPool { public: PortPool(); ~PortPool(); - + port_id GetPort(); - void PutPort(port_id port); + void PutPort(port_id port); private: void Lock(); void Unlock(); - struct PortInfo - { + struct PortInfo { port_id port; bool used; }; + PortInfo * pool; int count; int maxcount; diff --git a/headers/private/media/ServerInterface.h b/headers/private/media/ServerInterface.h new file mode 100644 index 0000000000..fa9bedd810 --- /dev/null +++ b/headers/private/media/ServerInterface.h @@ -0,0 +1,72 @@ +/* + * Copyright 2002, Marcus Overhagen. All Rights Reserved. + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _SERVER_INTERFACE_H_ +#define _SERVER_INTERFACE_H_ + + +#include +#include +#include +#include + + +enum { + ADDONSERVER_INSTANTIATE_DORMANT_NODE, + SERVER_REGISTER_MEDIAADDON, + SERVER_UNREGISTER_MEDIAADDON, + SERVER_GET_MEDIAADDON_REF, + SERVER_REGISTER_DORMANT_NODE, + SERVER_GET_DORMANT_NODES, + SERVER_GET_DORMANT_FLAVOR_INFO, + END +}; + + +struct xfer_server_get_dormant_flavor_info { + media_addon_id addon; + int32 flavor_id; + port_id reply_port; +}; + +struct xfer_server_get_dormant_flavor_info_reply { + status_t result; + type_code type; // the flatten type_code + size_t flattened_size; + char flattened_data[1]; + // a flattened dormant_flavor_info, flattened_size large +}; + +struct xfer_server_get_dormant_nodes { + int32 max_count; + bool has_input; + media_format input_format; + bool has_output; + media_format output_format; + bool has_name; + char name[B_MEDIA_NAME_LENGTH + 1]; // 1 for a trailing "*" + uint64 require_kinds; + uint64 deny_kinds; + port_id reply_port; +}; + +struct xfer_server_get_dormant_nodes_reply { + status_t result; + int32 count; + // if count > 0, a second reply containing count dormant_node_infos + // is send +}; + +struct xfer_server_register_dormant_node { + media_addon_id purge_id; + // if > 0, server must first remove all dormant_flavor_infos + // belonging to that id + type_code type; // the flatten type_code + size_t flattened_size; + char flattened_data[1]; + // a flattened dormant_flavor_info, flattened_size large +}; + +#endif // _SERVER_INTERFACE_H_ diff --git a/headers/private/media/SharedBufferList.h b/headers/private/media/SharedBufferList.h index 4921593b95..ead919ec98 100644 --- a/headers/private/media/SharedBufferList.h +++ b/headers/private/media/SharedBufferList.h @@ -1,53 +1,66 @@ -/*********************************************************************** - * Copyright (c) 2002 Marcus Overhagen. All Rights Reserved. - * This file may be used under the terms of the OpenBeOS License. - * - * Used for BBufferGroup and BBuffer management across teams - ***********************************************************************/ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002, Marcus Overhagen. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ #ifndef _SHARED_BUFFER_LIST_H_ #define _SHARED_BUFFER_LIST_H_ + #include -// created in the media server, cloned into -// each BBufferGroup (visible in all address spaces / teams) -struct _shared_buffer_list -{ - struct _shared_buffer_info - { - media_buffer_id id; - BBuffer * buffer; - bool reclaimed; - // the reclaim_sem belonging to the BBufferGroup of this BBuffer - // also used as a unique identifier of the group - sem_id reclaim_sem; + +namespace BPrivate { + + +class SharedBufferList { +public: + static area_id Create(SharedBufferList** _list); + static SharedBufferList* Get(area_id area); + + void Put(); + void DeleteGroupAndPut(sem_id groupReclaimSem); + + status_t Lock(); + status_t Unlock(); + + status_t AddBuffer(sem_id groupReclaimSem, + BBuffer* buffer); + status_t RequestBuffer(sem_id groupReclaimSem, + int32 buffersInGroup, size_t size, + media_buffer_id wantID, BBuffer** _buffer, + bigtime_t timeout); + status_t RecycleBuffer(BBuffer* buffer); + status_t GetBufferList(sem_id groupReclaimSem, + int32 bufferCount, BBuffer** buffers); + +private: + struct _shared_buffer_info { + media_buffer_id id; + BBuffer* buffer; + bool reclaimed; + // The reclaim_sem belonging to the BBufferGroup of this BBuffer + // is also used as a unique identifier of the group + sem_id reclaim_sem; }; - enum { MAX_BUFFER = 666 }; // this fixed limit is probably very evil - sem_id locker_sem; - int32 locker_atom; - - // always only the first "buffercount" entries in the "info" array are used - int32 buffercount; - _shared_buffer_info info[MAX_BUFFER]; + enum { kMaxBuffers = 2047 }; + // 16 bytes per buffer, 8 pages in total (one entry less for the list) - status_t AddBuffer(sem_id group_reclaim_sem, BBuffer *buffer); - status_t RequestBuffer(sem_id group_reclaim_sem, int32 buffers_in_group, size_t size, media_buffer_id wantID, BBuffer **buffer, bigtime_t timeout); - status_t GetBufferList(sem_id group_reclaim_sem, int32 buf_count, BBuffer **out_buffers); - status_t RecycleBuffer(BBuffer *buffer); - - - status_t Init(); + status_t _Init(); + void _RequestBufferInOtherGroups( + sem_id groupReclaimSem, media_buffer_id id); - static _shared_buffer_list *Clone(area_id id = -1); - void Terminate(sem_id group_reclaim_sem); - void Unmap(); +private: + sem_id fSemaphore; + vint32 fAtom; - status_t Lock(); - status_t Unlock(); - - // used by RequestBuffer, call this one with the list locked! - void RequestBufferInOtherGroups(sem_id group_reclaim_sem, media_buffer_id id); + _shared_buffer_info fInfos[kMaxBuffers]; + int32 fCount; }; -#endif + +} // namespace BPrivate + + +#endif // _SHARED_BUFFER_LIST_H_ diff --git a/src/kits/media/Buffer.cpp b/src/kits/media/Buffer.cpp index 7d27338a13..c8781e9cf5 100644 --- a/src/kits/media/Buffer.cpp +++ b/src/kits/media/Buffer.cpp @@ -1,3 +1,8 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + /* * Copyright (c) 2002, 2003 Marcus Overhagen * @@ -24,12 +29,12 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - * */ #include +#include #include #include "debug.h" @@ -37,9 +42,6 @@ #include "SharedBufferList.h" -namespace BPrivate { namespace media { - extern team_id team; -} } using namespace BPrivate::media; @@ -49,11 +51,11 @@ using namespace BPrivate::media; buffer_clone_info::buffer_clone_info() { CALLED(); - buffer = 0; - area = 0; - offset = 0; - size = 0; - flags = 0; + buffer = 0; + area = 0; + offset = 0; + size = 0; + flags = 0; } @@ -122,11 +124,11 @@ BBuffer::CloneInfo() const CALLED(); buffer_clone_info info; - info.buffer = fBufferID; - info.area = fArea; - info.offset = fOffset; - info.size = fSize; - info.flags = fFlags; + info.buffer = fMediaHeader.buffer; + info.area = fArea; + info.offset = fOffset; + info.size = fSize; + info.flags = fFlags; return info; } @@ -137,7 +139,6 @@ BBuffer::ID() { CALLED(); return fMediaHeader.buffer; - //return fBufferID; } @@ -181,20 +182,21 @@ BBuffer::Size() } -// #pragma mark - private BBuffer +// #pragma mark - private BBuffer BBuffer::BBuffer(const buffer_clone_info& info) : - // must all be NULL/0 if not correct initialized - fBufferList(NULL), + // must all be NULL/0 if not correctly initialized + fBufferList(NULL), fData(NULL), - fSize(0), - fBufferID(0) - // must be 0 if not registered + fSize(0) { CALLED(); + fMediaHeader.buffer = 0; + // must be 0 if not registered + // special case for BSmallBuffer if (info.area == 0 && info.buffer == 0) return; @@ -208,7 +210,7 @@ BBuffer::BBuffer(const buffer_clone_info& info) return; } - fBufferList = _shared_buffer_list::Clone(areaReply.area); + fBufferList = BPrivate::SharedBufferList::Get(areaReply.area); if (fBufferList == NULL) { ERROR("BBuffer::BBuffer: _shared_buffer_list::Clone() failed\n"); return; @@ -217,7 +219,7 @@ BBuffer::BBuffer(const buffer_clone_info& info) server_register_buffer_request request; server_register_buffer_reply reply; - request.team = team; + request.team = BPrivate::current_team(); request.info = info; // ask media_server to register this buffer, @@ -241,10 +243,11 @@ BBuffer::BBuffer(const buffer_clone_info& info) // the response from media server contains enough information // to clone the memory for this buffer - fBufferID = reply.info.buffer; fSize = reply.info.size; fFlags = reply.info.flags; fOffset = reply.info.offset; + fMediaHeader.size_used = 0; + fMediaHeader.buffer = reply.info.buffer; fArea = clone_area("a cloned BBuffer", &fData, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.info.area); @@ -256,28 +259,26 @@ BBuffer::BBuffer(const buffer_clone_info& info) } fData = (char*)fData + fOffset; - fMediaHeader.size_used = 0; - fMediaHeader.buffer = fBufferID; } BBuffer::~BBuffer() { CALLED(); + // unmap the BufferList if (fBufferList != NULL) - fBufferList->Unmap(); + fBufferList->Put(); // unmap the Data if (fData != NULL) { delete_area(fArea); - // ask media_server to unregister the buffer - // when the last clone of this buffer is gone, - // media_server will also remove it's cached area + // Ask media_server to unregister the buffer when the last clone of + // this buffer is gone, media_server will also remove its cached area. server_unregister_buffer_command cmd; - cmd.team = team; - cmd.bufferid = fBufferID; + cmd.team = BPrivate::current_team(); + cmd.buffer_id = fMediaHeader.buffer; SendToServer(SERVER_UNREGISTER_BUFFER, &cmd, sizeof(cmd)); } } @@ -287,14 +288,14 @@ void BBuffer::SetHeader(const media_header* header) { CALLED(); + ASSERT(header->buffer == fMediaHeader.buffer); + if (header->buffer != fMediaHeader.buffer) + debugger("oops"); fMediaHeader = *header; - -// TODO: why can't we do this without crash? what's wrong? -// fMediaHeader.buffer = fBufferID; } -// #pragma mark - public BSmallBuffer +// #pragma mark - public BSmallBuffer static const buffer_clone_info sSmallBufferInfo; diff --git a/src/kits/media/BufferCache.cpp b/src/kits/media/BufferCache.cpp new file mode 100644 index 0000000000..10947df56b --- /dev/null +++ b/src/kits/media/BufferCache.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002, Marcus Overhagen. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + + +//! A cache for BBuffers to be received by BBufferConsumer::BufferReceived(). + + +#include "BufferCache.h" + +#include + +#include "debug.h" + + +namespace BPrivate { + + +BufferCache::BufferCache() +{ +} + + +BufferCache::~BufferCache() +{ + for (BufferMap::iterator iterator = fMap.begin(); iterator != fMap.end(); + iterator++) { + delete iterator->second; + } +} + + +BBuffer* +BufferCache::GetBuffer(media_buffer_id id) +{ + BufferMap::iterator found = fMap.find(id); + if (found != fMap.end()) + return found->second; + + buffer_clone_info info; + info.buffer = id; + BBuffer* buffer = new(std::nothrow) BBuffer(info); + if (buffer == NULL) + return NULL; + + try { + fMap.insert(std::make_pair(id, buffer)); + } catch (std::bad_alloc& exception) { + delete buffer; + return NULL; + } + + return buffer; +} + + +} // namespace BPrivate diff --git a/src/kits/media/BufferCache.h b/src/kits/media/BufferCache.h new file mode 100644 index 0000000000..228b52991a --- /dev/null +++ b/src/kits/media/BufferCache.h @@ -0,0 +1,38 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002, Marcus Overhagen. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _BUFFER_CACHE_H_ +#define _BUFFER_CACHE_H_ + + +#include + +#include + + +class BBuffer; + + +namespace BPrivate { + + +class BufferCache { +public: + BufferCache(); + ~BufferCache(); + + BBuffer* GetBuffer(media_buffer_id id); + +private: + typedef std::map BufferMap; + + BufferMap fMap; +}; + + +} // namespace BPrivate + + +#endif // _BUFFER_CACHE_H_ diff --git a/src/kits/media/BufferConsumer.cpp b/src/kits/media/BufferConsumer.cpp index 04b9a8141e..8713b39958 100644 --- a/src/kits/media/BufferConsumer.cpp +++ b/src/kits/media/BufferConsumer.cpp @@ -24,37 +24,35 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - * */ + +#include "BufferCache.h" #include + +#include + #include #include #include -#include //for debugging -#include -#include "debug.h" -#include "MediaMisc.h" -#include "DataExchange.h" -#include "BufferIdCache.h" +#include + +#include +#include +#include + -/************************************************************* - * protected BBufferConsumer - *************************************************************/ -/* virtual */ BBufferConsumer::~BBufferConsumer() { CALLED(); delete fBufferCache; - if (fDeleteBufferGroup) - delete fDeleteBufferGroup; + delete fDeleteBufferGroup; } -/************************************************************* - * public BBufferConsumer - *************************************************************/ +// #pragma mark - public BBufferConsumer + media_type BBufferConsumer::ConsumerType() @@ -64,97 +62,97 @@ BBufferConsumer::ConsumerType() } -/* static */ status_t -BBufferConsumer::RegionToClipData(const BRegion *region, - int32 *format, - int32 *ioSize, - void *data) +/*static*/ status_t +BBufferConsumer::RegionToClipData(const BRegion* region, int32* _format, + int32 *_size, void* data) { CALLED(); - - status_t rv; - int count; - count = *ioSize / sizeof(int16); - rv = BBufferProducer::clip_region_to_shorts(region, static_cast(data), count, &count); - *ioSize = count * sizeof(int16); - *format = BBufferProducer::B_CLIP_SHORT_RUNS; - - return rv; + int count = *_size / sizeof(int16); + status_t status = BBufferProducer::clip_region_to_shorts(region, + static_cast(data), count, &count); + + *_size = count * sizeof(int16); + *_format = BBufferProducer::B_CLIP_SHORT_RUNS; + + return status; } -/************************************************************* - * protected BBufferConsumer - *************************************************************/ -/* explicit */ -BBufferConsumer::BBufferConsumer(media_type consumer_type) : +// #pragma mark - protected BBufferConsumer + + +BBufferConsumer::BBufferConsumer(media_type consumerType) + : BMediaNode("called by BBufferConsumer"), - fConsumerType(consumer_type), - fBufferCache(new _buffer_id_cache), + fConsumerType(consumerType), + fBufferCache(new BPrivate::BufferCache), fDeleteBufferGroup(0) { CALLED(); - + AddNodeKind(B_BUFFER_CONSUMER); } -/* static */ void -BBufferConsumer::NotifyLateProducer(const media_source &what_source, - bigtime_t how_much, - bigtime_t performance_time) +/*static*/ void +BBufferConsumer::NotifyLateProducer(const media_source& whatSource, + bigtime_t howMuch, bigtime_t performanceTime) { CALLED(); - if (IS_INVALID_SOURCE(what_source)) + if (IS_INVALID_SOURCE(whatSource)) return; producer_late_notice_received_command command; - command.source = what_source; - command.how_much = how_much; - command.performance_time = performance_time; - - SendToPort(what_source.port, PRODUCER_LATE_NOTICE_RECEIVED, &command, sizeof(command)); + command.source = whatSource; + command.how_much = howMuch; + command.performance_time = performanceTime; + + SendToPort(whatSource.port, PRODUCER_LATE_NOTICE_RECEIVED, &command, + sizeof(command)); } status_t -BBufferConsumer::SetVideoClippingFor(const media_source &output, - const media_destination &destination, - const int16 *shorts, - int32 short_count, - const media_video_display_info &display, - void *user_data, - int32 *change_tag, - void *_reserved_) +BBufferConsumer::SetVideoClippingFor(const media_source& output, + const media_destination& destination, const int16* shorts, int32 shortCount, + const media_video_display_info& display, void* userData, int32* _changeTag, + void *_reserved_) { CALLED(); if (IS_INVALID_SOURCE(output)) return B_MEDIA_BAD_SOURCE; if (IS_INVALID_DESTINATION(destination)) return B_MEDIA_BAD_DESTINATION; - if (short_count > int(B_MEDIA_MESSAGE_SIZE - sizeof(producer_video_clipping_changed_command)) / 2) - debugger("BBufferConsumer::SetVideoClippingFor short_count too large (8000 limit)\n"); - - producer_video_clipping_changed_command *command; - size_t size; - status_t rv; + if (shortCount > int(B_MEDIA_MESSAGE_SIZE + - sizeof(producer_video_clipping_changed_command)) / 2) { + debugger("BBufferConsumer::SetVideoClippingFor short_count too large " + "(8000 limit)\n"); + } + + producer_video_clipping_changed_command* command; + size_t size = sizeof(producer_video_clipping_changed_command) + + shortCount * sizeof(short); + command + = static_cast(malloc(size)); + if (command == NULL) + return B_NO_MEMORY; - size = sizeof(producer_video_clipping_changed_command) + short_count * sizeof(short); - command = static_cast(malloc(size)); command->source = output; command->destination = destination; command->display = display; - command->user_data = user_data; + command->user_data = userData; command->change_tag = NewChangeTag(); - command->short_count = short_count; - memcpy(command->shorts, shorts, short_count * sizeof(short)); - if (change_tag != NULL) - *change_tag = command->change_tag; - - rv = SendToPort(output.port, PRODUCER_VIDEO_CLIPPING_CHANGED, command, size); + command->short_count = shortCount; + memcpy(command->shorts, shorts, shortCount * sizeof(short)); + if (_changeTag != NULL) + *_changeTag = command->change_tag; + + status_t status = SendToPort(output.port, PRODUCER_VIDEO_CLIPPING_CHANGED, + command, size); + free(command); - return rv; + return status; } @@ -173,7 +171,7 @@ BBufferConsumer::SetOutputEnabled(const media_source &source, return B_MEDIA_BAD_DESTINATION; producer_enable_output_command command; - + command.source = source; command.destination = destination; command.enabled = enabled; @@ -181,7 +179,7 @@ BBufferConsumer::SetOutputEnabled(const media_source &source, command.change_tag = NewChangeTag(); if (change_tag != NULL) *change_tag = command.change_tag; - + return SendToPort(source.port, PRODUCER_ENABLE_OUTPUT, &command, sizeof(command)); } @@ -201,7 +199,7 @@ BBufferConsumer::RequestFormatChange(const media_source &source, return B_MEDIA_BAD_DESTINATION; producer_format_change_requested_command command; - + command.source = source; command.destination = destination; command.format = to_format; @@ -209,7 +207,7 @@ BBufferConsumer::RequestFormatChange(const media_source &source, command.change_tag = NewChangeTag(); if (change_tag != NULL) *change_tag = command.change_tag; - + return SendToPort(source.port, PRODUCER_FORMAT_CHANGE_REQUESTED, &command, sizeof(command)); } @@ -224,46 +222,41 @@ BBufferConsumer::RequestAdditionalBuffer(const media_source &source, return B_MEDIA_BAD_SOURCE; producer_additional_buffer_requested_command command; - + command.source = source; command.prev_buffer = prev_buffer->ID(); command.prev_time = 0; command.has_seek_tag = false; - //command.prev_tag = - + //command.prev_tag = + return SendToPort(source.port, PRODUCER_ADDITIONAL_BUFFER_REQUESTED, &command, sizeof(command)); } status_t -BBufferConsumer::RequestAdditionalBuffer(const media_source &source, - bigtime_t start_time, - void *_reserved) +BBufferConsumer::RequestAdditionalBuffer(const media_source& source, + bigtime_t startTime, void *_reserved) { CALLED(); if (IS_INVALID_SOURCE(source)) return B_MEDIA_BAD_SOURCE; producer_additional_buffer_requested_command command; - + command.source = source; command.prev_buffer = 0; - command.prev_time = start_time; + command.prev_time = startTime; command.has_seek_tag = false; - //command.prev_tag = - - return SendToPort(source.port, PRODUCER_ADDITIONAL_BUFFER_REQUESTED, &command, sizeof(command)); + + return SendToPort(source.port, PRODUCER_ADDITIONAL_BUFFER_REQUESTED, + &command, sizeof(command)); } status_t BBufferConsumer::SetOutputBuffersFor(const media_source &source, - const media_destination &destination, - BBufferGroup *group, - void *user_data, - int32 *change_tag, - bool will_reclaim, - void *_reserved_) + const media_destination &destination, BBufferGroup *group, void *user_data, + int32 *change_tag, bool will_reclaim, void *_reserved_) { CALLED(); @@ -271,10 +264,10 @@ BBufferConsumer::SetOutputBuffersFor(const media_source &source, return B_MEDIA_BAD_SOURCE; if (IS_INVALID_DESTINATION(destination)) return B_MEDIA_BAD_DESTINATION; - + producer_set_buffer_group_command *command; BBuffer **buffers; - int32 buffer_count; + int32 buffer_count; size_t size; status_t rv; @@ -284,8 +277,8 @@ BBufferConsumer::SetOutputBuffersFor(const media_source &source, if (B_OK != group->CountBuffers(&buffer_count)) return B_ERROR; } - - if (buffer_count != 0) { + + if (buffer_count != 0) { buffers = new BBuffer * [buffer_count]; if (B_OK != group->GetBufferList(buffer_count, buffers)) { delete [] buffers; @@ -309,11 +302,11 @@ BBufferConsumer::SetOutputBuffersFor(const media_source &source, if (change_tag != NULL) *change_tag = command->change_tag; - + rv = SendToPort(source.port, PRODUCER_SET_BUFFER_GROUP, command, size); free(command); - if (rv == B_OK) { + if (rv == B_OK) { if (fDeleteBufferGroup) // XXX will leak memory if port write failed delete fDeleteBufferGroup; fDeleteBufferGroup = will_reclaim ? NULL : group; @@ -323,10 +316,8 @@ BBufferConsumer::SetOutputBuffersFor(const media_source &source, status_t -BBufferConsumer::SendLatencyChange(const media_source &source, - const media_destination &destination, - bigtime_t my_new_latency, - uint32 flags) +BBufferConsumer::SendLatencyChange(const media_source& source, + const media_destination& destination, bigtime_t newLatency, uint32 flags) { CALLED(); if (IS_INVALID_SOURCE(source)) @@ -335,37 +326,36 @@ BBufferConsumer::SendLatencyChange(const media_source &source, return B_MEDIA_BAD_DESTINATION; producer_latency_changed_command command; - + command.source = source; command.destination = destination; - command.latency = my_new_latency; + command.latency = newLatency; command.flags = flags; - - TRACE("###### BBufferConsumer::SendLatencyChange: latency from %ld/%ld to %ld/%ld changed to %Ld\n", - source.port, source.id, destination.port, destination.id, my_new_latency); - - return SendToPort(source.port, PRODUCER_LATENCY_CHANGED, &command, sizeof(command)); + + TRACE("###### BBufferConsumer::SendLatencyChange: latency from %ld/%ld to " + "%ld/%ld changed to %Ld\n", source.port, source.id, destination.port, + destination.id, newLatency); + + return SendToPort(source.port, PRODUCER_LATENCY_CHANGED, &command, + sizeof(command)); } -/************************************************************* - * protected BBufferConsumer - *************************************************************/ -/* virtual */ status_t -BBufferConsumer::HandleMessage(int32 message, - const void *data, - size_t size) +status_t +BBufferConsumer::HandleMessage(int32 message, const void* data, size_t size) { PRINT(4, "BBufferConsumer::HandleMessage %#lx, node %ld\n", message, ID()); status_t rv; switch (message) { case CONSUMER_ACCEPT_FORMAT: { - const consumer_accept_format_request *request = static_cast(data); + const consumer_accept_format_request* request + = static_cast(data); + consumer_accept_format_reply reply; reply.format = request->format; - rv = AcceptFormat(request->dest, &reply.format); - request->SendReply(rv, &reply, sizeof(reply)); + status_t status = AcceptFormat(request->dest, &reply.format); + request->SendReply(status, &reply, sizeof(reply)); return B_OK; } @@ -390,12 +380,17 @@ BBufferConsumer::HandleMessage(int32 message, case CONSUMER_BUFFER_RECEIVED: { - const consumer_buffer_received_command *command = static_cast(data); - BBuffer *buffer; - buffer = fBufferCache->GetBuffer(command->buffer); + const consumer_buffer_received_command* command + = static_cast(data); + + BBuffer* buffer = fBufferCache->GetBuffer(command->buffer); buffer->SetHeader(&command->header); - PRINT(4, "calling BBufferConsumer::BufferReceived buffer %ld at perf %Ld and TimeSource()->Now() is %Ld\n", buffer->Header()->buffer, buffer->Header()->start_time, TimeSource()->Now()); - //printf("BBufferConsumer::BufferReceived node %2ld, buffer %2ld, start_time %12Ld with lateness %6Ld\n", ID(), buffer->Header()->buffer, buffer->Header()->start_time, TimeSource()->Now() - buffer->Header()->start_time); + + PRINT(4, "calling BBufferConsumer::BufferReceived buffer %ld at " + "perf %Ld and TimeSource()->Now() is %Ld\n", + buffer->Header()->buffer, buffer->Header()->start_time, + TimeSource()->Now()); + BufferReceived(buffer); return B_OK; } @@ -425,7 +420,7 @@ BBufferConsumer::HandleMessage(int32 message, request->SendReply(rv, &reply, sizeof(reply)); return B_OK; } - + case CONSUMER_DISCONNECTED: { const consumer_disconnected_request *request = static_cast(data); @@ -464,8 +459,7 @@ BBufferConsumer::HandleMessage(int32 message, request->SendReply(rv, &reply, sizeof(reply)); return B_OK; } - - }; + } return B_ERROR; } @@ -482,9 +476,9 @@ BBufferConsumer::SeekTagRequested(const media_destination &destination, return B_ERROR; } -/************************************************************* - * private BBufferConsumer - *************************************************************/ + +// #pragma mark - private BBufferConsumer + /* not implemented: @@ -493,7 +487,9 @@ BBufferConsumer::BBufferConsumer(const BBufferConsumer &clone) BBufferConsumer & BBufferConsumer::operator=(const BBufferConsumer &clone) */ -/* deprecated function for R4 */ + +/*! Deprecated function for BeOS R4. +*/ /* static */ status_t BBufferConsumer::SetVideoClippingFor(const media_source &output, const int16 *shorts, @@ -506,7 +502,7 @@ BBufferConsumer::SetVideoClippingFor(const media_source &output, return B_MEDIA_BAD_SOURCE; if (short_count > int(B_MEDIA_MESSAGE_SIZE - sizeof(producer_video_clipping_changed_command)) / 2) debugger("BBufferConsumer::SetVideoClippingFor short_count too large (8000 limit)\n"); - + producer_video_clipping_changed_command *command; size_t size; status_t rv; @@ -522,19 +518,19 @@ BBufferConsumer::SetVideoClippingFor(const media_source &output, memcpy(command->shorts, shorts, short_count * sizeof(short)); if (change_tag != NULL) *change_tag = command->change_tag; - + rv = SendToPort(output.port, PRODUCER_VIDEO_CLIPPING_CHANGED, command, size); free(command); return rv; } -/* deprecated function for R4 */ -/* static */ status_t -BBufferConsumer::RequestFormatChange(const media_source &source, - const media_destination &destination, - media_format *in_to_format, - int32 *change_tag) +/*! Deprecated function for BeOS R4. +*/ +/*static*/ status_t +BBufferConsumer::RequestFormatChange(const media_source& source, + const media_destination& destination, media_format* format, + int32* _changeTag) { CALLED(); if (IS_INVALID_SOURCE(source)) @@ -543,57 +539,59 @@ BBufferConsumer::RequestFormatChange(const media_source &source, return B_MEDIA_BAD_DESTINATION; producer_format_change_requested_command command; - + command.source = source; command.destination = destination; - command.format = *in_to_format; + command.format = *format; command.user_data = 0; command.change_tag = NewChangeTag(); - if (change_tag != NULL) - *change_tag = command.change_tag; - - return SendToPort(source.port, PRODUCER_FORMAT_CHANGE_REQUESTED, &command, sizeof(command)); + if (_changeTag != NULL) + *_changeTag = command.change_tag; + + return SendToPort(source.port, PRODUCER_FORMAT_CHANGE_REQUESTED, &command, + sizeof(command)); } -/* deprecated function for R4 */ -/* static */ status_t -BBufferConsumer::SetOutputEnabled(const media_source &source, - bool enabled, - int32 *change_tag) +/*! Deprecated function for BeOS R4. +*/ +/*static*/ status_t +BBufferConsumer::SetOutputEnabled(const media_source& source, bool enabled, + int32* _changeTag) { CALLED(); if (IS_INVALID_SOURCE(source)) return B_MEDIA_BAD_SOURCE; producer_enable_output_command command; - + command.source = source; command.destination = media_destination::null; command.enabled = enabled; command.user_data = 0; command.change_tag = NewChangeTag(); - if (change_tag != NULL) - *change_tag = command.change_tag; - - return SendToPort(source.port, PRODUCER_ENABLE_OUTPUT, &command, sizeof(command)); + if (_changeTag != NULL) + *_changeTag = command.change_tag; + + return SendToPort(source.port, PRODUCER_ENABLE_OUTPUT, &command, + sizeof(command)); } -status_t BBufferConsumer::_Reserved_BufferConsumer_0(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_1(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_2(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_3(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_4(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_5(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_6(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_7(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_8(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_9(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_10(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_11(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_12(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_13(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_14(void *) { return B_ERROR; } -status_t BBufferConsumer::_Reserved_BufferConsumer_15(void *) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_0(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_1(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_2(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_3(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_4(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_5(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_6(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_7(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_8(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_9(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_10(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_11(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_12(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_13(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_14(void*) { return B_ERROR; } +status_t BBufferConsumer::_Reserved_BufferConsumer_15(void*) { return B_ERROR; } diff --git a/src/kits/media/BufferGroup.cpp b/src/kits/media/BufferGroup.cpp index cc2618e7e1..7131551c1e 100644 --- a/src/kits/media/BufferGroup.cpp +++ b/src/kits/media/BufferGroup.cpp @@ -43,9 +43,9 @@ BBufferGroup::BBufferGroup(size_t size, int32 count, uint32 placement, CALLED(); if (_Init() != B_OK) return; - + // This one is easy. We need to create "count" BBuffers, - // each one "size" bytes large. They all go into one + // each one "size" bytes large. They all go into one // area, with "placement" and "lock" attributes. // The BBuffers created will clone the area, and // then we delete our area. This way BBuffers are @@ -57,7 +57,7 @@ BBufferGroup::BBufferGroup(size_t size, int32 count, uint32 placement, "&& placement != B_ANY_KERNEL_ADDRESS (0x%08lx)\n", placement); placement = B_ANY_ADDRESS; } - + // first we roundup for a better placement in memory size_t allocSize = (size + 63) & ~63; @@ -76,7 +76,7 @@ BBufferGroup::BBufferGroup(size_t size, int32 count, uint32 placement, buffer_clone_info info; - for (int32 i = 0; i < count; i++) { + for (int32 i = 0; i < count; i++) { info.area = bufferArea; info.offset = i * allocSize; info.size = size; @@ -95,7 +95,7 @@ BBufferGroup::BBufferGroup() CALLED(); if (_Init() != B_OK) return; - + // this one simply creates an empty BBufferGroup } @@ -105,16 +105,16 @@ BBufferGroup::BBufferGroup(int32 count, const media_buffer_id* buffers) CALLED(); if (_Init() != B_OK) return; - + // TODO: we need to make sure that a media_buffer_id is only added // once to each group - // this one creates "BBuffer"s from "media_buffer_id"s passed + // this one creates "BBuffer"s from "media_buffer_id"s passed // by the application. buffer_clone_info info; - for (int32 i = 0; i < count; i++) { + for (int32 i = 0; i < count; i++) { info.buffer = buffers[i]; fInitError = AddBuffer(info); @@ -127,8 +127,8 @@ BBufferGroup::BBufferGroup(int32 count, const media_buffer_id* buffers) BBufferGroup::~BBufferGroup() { CALLED(); - if (fBufferList) - fBufferList->Terminate(fReclaimSem); + if (fBufferList != NULL) + fBufferList->DeleteGroupAndPut(fReclaimSem); delete_sem(fReclaimSem); } @@ -188,7 +188,7 @@ BBufferGroup::RequestBuffer(size_t size, bigtime_t timeout) if (size <= 0) return NULL; - + BBuffer *buffer; status_t status; @@ -207,7 +207,7 @@ BBufferGroup::RequestBuffer(BBuffer* buffer, bigtime_t timeout) CALLED(); if (fInitError != B_OK) return B_NO_INIT; - + if (buffer == NULL) return B_BAD_VALUE; @@ -215,7 +215,7 @@ BBufferGroup::RequestBuffer(BBuffer* buffer, bigtime_t timeout) status = fBufferList->RequestBuffer(fReclaimSem, fBufferCount, 0, 0, &buffer, timeout); fRequestError = status; - + return status; } @@ -249,7 +249,7 @@ BBufferGroup::GetBufferList(int32 bufferCount, BBuffer** _buffers) CALLED(); if (fInitError != B_OK) return B_NO_INIT; - + if (bufferCount <= 0 || bufferCount > fBufferCount) return B_BAD_VALUE; @@ -264,7 +264,7 @@ BBufferGroup::WaitForBuffers() if (fInitError != B_OK) return B_NO_INIT; - // TODO: this function is not really useful anyway, and will + // TODO: this function is not really useful anyway, and will // not work exactly as documented, but it is close enough if (fBufferCount < 0) @@ -281,7 +281,7 @@ BBufferGroup::WaitForBuffers() ; if (status != B_OK) return status; - + // we need to release the "fReclaimSem" now, else we would block // requesting of new buffers @@ -297,7 +297,7 @@ BBufferGroup::ReclaimAllBuffers() return B_NO_INIT; // because additional BBuffers might get added to this group betweeen - // acquire and release + // acquire and release int32 count = fBufferCount; if (count < 0) @@ -313,10 +313,10 @@ BBufferGroup::ReclaimAllBuffers() do { status = acquire_sem_etc(fReclaimSem, count, 0, 0); } while (status == B_INTERRUPTED); - + if (status != B_OK) return status; - + // we need to release the "fReclaimSem" now, else we would block // requesting of new buffers @@ -333,7 +333,7 @@ BBufferGroup::AddBuffersTo(BMessage* message, const char* name, bool needLock) CALLED(); if (fInitError != B_OK) return B_NO_INIT; - + // BeOS R4 legacy API. Implemented as a wrapper around GetBufferList // "needLock" is ignored, GetBufferList will do locking @@ -342,17 +342,17 @@ BBufferGroup::AddBuffersTo(BMessage* message, const char* name, bool needLock) if (name == NULL || strlen(name) == 0) return B_BAD_VALUE; - + BBuffer** buffers; int32 count; - + count = fBufferCount; buffers = new BBuffer * [count]; status_t status = GetBufferList(count, buffers); if (status != B_OK) goto end; - + for (int32 i = 0; i < count; i++) { status = message->AddInt32(name, int32(buffers[i]->ID())); if (status != B_OK) @@ -377,7 +377,7 @@ status_t BBufferGroup::_Init() { CALLED(); - + // some defaults in case we drop out early fBufferList = 0; fInitError = B_ERROR; @@ -404,9 +404,9 @@ BBufferGroup::_Init() return fInitError; } - fBufferList = _shared_buffer_list::Clone(areaReply.area); + fBufferList = BPrivate::SharedBufferList::Get(areaReply.area); if (fBufferList == NULL) { - ERROR("BBufferGroup::InitBufferGroup: _shared_buffer_list::Clone " + ERROR("BBufferGroup::InitBufferGroup: SharedBufferList::Get() " "failed\n"); fInitError = B_ERROR; return fInitError; diff --git a/src/kits/media/BufferIdCache.cpp b/src/kits/media/BufferIdCache.cpp deleted file mode 100644 index 70b14f93d6..0000000000 --- a/src/kits/media/BufferIdCache.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2002 Marcus Overhagen. All Rights Reserved. - * This file may be used under the terms of the OpenBeOS License. - * - * A cache for BBuffers to be received by - * BBufferConsumer::BufferReceived() - ***********************************************************************/ - -#include -#include "BufferIdCache.h" -#include "debug.h" - -// XXX we are not allowed to delete BBuffer objects when they are not recycled - -_buffer_id_cache::_buffer_id_cache() -{ -} - -_buffer_id_cache::~_buffer_id_cache() -{ - // XXX deleting buffers here is not save, too -/* - fMap.Rewind(); - BBuffer **buffer; - while (fMap.GetNext(&buffer)) { - fMap.RemoveCurrent(); - delete *buffer; - } -*/ -} - -BBuffer * -_buffer_id_cache::GetBuffer(media_buffer_id id) -{ - BBuffer **buffer; - if (fMap.Get(id, &buffer)) - return *buffer; - - buffer_clone_info ci; - ci.buffer = id; - BBuffer *buf = new BBuffer(ci); - - fMap.Insert(id, buf); - return buf; -} diff --git a/src/kits/media/BufferIdCache.h b/src/kits/media/BufferIdCache.h deleted file mode 100644 index 859fa33121..0000000000 --- a/src/kits/media/BufferIdCache.h +++ /dev/null @@ -1,25 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2002 Marcus Overhagen. All Rights Reserved. - * This file may be used under the terms of the OpenBeOS License. - * - * A cache for BBuffers to be received by - * BBufferConsumer::BufferReceived() - ***********************************************************************/ -#ifndef _BUFFER_ID_CACHE_H_ -#define _BUFFER_ID_CACHE_H_ - -#include "TMap.h" - -class _buffer_id_cache -{ -public: - _buffer_id_cache(); - ~_buffer_id_cache(); - - BBuffer *GetBuffer(media_buffer_id id); - -private: - Map fMap; -}; - -#endif diff --git a/src/kits/media/DataExchange.cpp b/src/kits/media/DataExchange.cpp index 4e777e2de6..ddb48ff041 100644 --- a/src/kits/media/DataExchange.cpp +++ b/src/kits/media/DataExchange.cpp @@ -1,52 +1,54 @@ -/* +/* * Copyright 2002-2007, Marcus Overhagen. All rights reserved. * Distributed under the terms of the MIT License. */ -#include -#include + +#include + #include #include + +#include +#include + #include "debug.h" #include "PortPool.h" #include "MediaMisc.h" -#include "DataExchange.h" #include "ServerInterface.h" + #define TIMEOUT 15000000 // 15 seconds timeout! + namespace BPrivate { namespace media { - -team_id team; - namespace dataexchange { -BMessenger *MediaServerMessenger; + +BMessenger* MediaServerMessenger; static port_id MediaServerPort; static port_id MediaAddonServerPort; void find_media_server_port(); void find_media_addon_server_port(); -static BMessenger * GetMediaServerMessenger() { - static BMessenger * messenger = new BMessenger(B_MEDIA_SERVER_SIGNATURE); +static BMessenger* +GetMediaServerMessenger() +{ + static BMessenger* messenger = new BMessenger(B_MEDIA_SERVER_SIGNATURE); return MediaServerMessenger = messenger; } -class initit -{ +class initit { public: initit() { MediaServerMessenger = 0; find_media_server_port(); find_media_addon_server_port(); - - thread_info info; - get_thread_info(find_thread(NULL), &info); - team = info.team; } + ~initit() { delete MediaServerMessenger; @@ -55,7 +57,8 @@ public: initit _initit; -void find_media_server_port() +void +find_media_server_port() { MediaServerPort = find_port(MEDIA_SERVER_PORT_NAME); if (MediaServerPort < 0) { @@ -64,7 +67,9 @@ void find_media_server_port() } } -void find_media_addon_server_port() + +void +find_media_addon_server_port() { MediaAddonServerPort = find_port(MEDIA_ADDON_SERVER_PORT_NAME); if (MediaAddonServerPort < 0) { @@ -84,7 +89,8 @@ request_data::SendReply(status_t result, reply_data *reply, int replysize) const // BMessage based data exchange with the media_server -status_t SendToServer(BMessage *msg) +status_t +SendToServer(BMessage *msg) { status_t rv; rv = GetMediaServerMessenger()->SendMessage(msg, static_cast(NULL), TIMEOUT); @@ -96,7 +102,7 @@ status_t SendToServer(BMessage *msg) } -status_t +status_t QueryServer(BMessage &request, BMessage &reply) { status_t status = GetMediaServerMessenger()->SendMessage(&request, &reply, TIMEOUT, TIMEOUT); @@ -110,32 +116,37 @@ QueryServer(BMessage &request, BMessage &reply) // Raw data based data exchange with the media_server -status_t SendToServer(int32 msgcode, command_data *msg, int size) +status_t +SendToServer(int32 msgcode, command_data *msg, int size) { return SendToPort(MediaServerPort, msgcode, msg, size); } -status_t QueryServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) +status_t +QueryServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) { return QueryPort(MediaServerPort, msgcode, request, requestsize, reply, replysize); } // Raw data based data exchange with the media_addon_server -status_t SendToAddonServer(int32 msgcode, command_data *msg, int size) +status_t +SendToAddonServer(int32 msgcode, command_data *msg, int size) { return SendToPort(MediaAddonServerPort, msgcode, msg, size); } -status_t QueryAddonServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) +status_t +QueryAddonServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) { return QueryPort(MediaAddonServerPort, msgcode, request, requestsize, reply, replysize); } // Raw data based data exchange with the media_server -status_t SendToPort(port_id sendport, int32 msgcode, command_data *msg, int size) +status_t +SendToPort(port_id sendport, int32 msgcode, command_data *msg, int size) { status_t rv; @@ -162,7 +173,8 @@ status_t SendToPort(port_id sendport, int32 msgcode, command_data *msg, int size } -status_t QueryPort(port_id requestport, int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) +status_t +QueryPort(port_id requestport, int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) { status_t rv; int32 code; @@ -170,7 +182,7 @@ status_t QueryPort(port_id requestport, int32 msgcode, request_data *request, in request->reply_port = _PortPool->GetPort(); rv = write_port_etc(requestport, msgcode, request, requestsize, B_RELATIVE_TIMEOUT, TIMEOUT); - + if (rv != B_OK) { ERROR("QueryPort: write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, requestport, rv, strerror(rv)); if (rv == B_BAD_PORT_ID && requestport == MediaServerPort) { @@ -198,11 +210,10 @@ status_t QueryPort(port_id requestport, int32 msgcode, request_data *request, in if (rv < B_OK) { ERROR("QueryPort: read_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, request->reply_port, rv, strerror(rv)); } - + return (rv < B_OK) ? rv : reply->result; } -}; // dataexchange -}; // media -}; // BPrivate - +} // dataexchange +} // media +} // BPrivate diff --git a/src/kits/media/DormantNodeManager.cpp b/src/kits/media/DormantNodeManager.cpp index 9b4c1133bf..87ed2ff55b 100644 --- a/src/kits/media/DormantNodeManager.cpp +++ b/src/kits/media/DormantNodeManager.cpp @@ -34,10 +34,10 @@ * * 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 + * 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. + * 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 @@ -80,7 +80,7 @@ DormantNodeManager::~DormantNodeManager() ERROR("Forcing unload of add-on id %ld with usecount %ld\n", info->addon->AddonID(), info->usecount); UnloadAddon(info->addon, info->image); } - + delete fAddonmap; } @@ -108,14 +108,14 @@ BMediaAddOn * DormantNodeManager::GetAddon(media_addon_id id) { BMediaAddOn *addon; - + TRACE("DormantNodeManager::GetAddon, id %ld\n",id); - + // 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 @@ -124,7 +124,7 @@ DormantNodeManager::GetAddon(media_addon_id id) ERROR("DormantNodeManager::GetAddon: can't find path for add-on %ld\n",id); return NULL; } - + // try to load it BMediaAddOn *newaddon; image_id image; @@ -132,7 +132,7 @@ DormantNodeManager::GetAddon(media_addon_id id) ERROR("DormantNodeManager::GetAddon: can't load add-on %ld 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 @@ -162,7 +162,7 @@ DormantNodeManager::PutAddonDelayed(media_addon_id id) // We must make sure that the media-add-on stays in memory // a couple of seconds longer. - UNIMPLEMENTED(); + UNIMPLEMENTED(); } void @@ -174,7 +174,7 @@ DormantNodeManager::PutAddon(media_addon_id id) bool unload; TRACE("DormantNodeManager::PutAddon, id %ld\n",id); - + fLock->Lock(); if (!fAddonmap->Get(id, &info)) { ERROR("DormantNodeManager::PutAddon: failed to find add-on %ld\n",id); @@ -204,9 +204,9 @@ DormantNodeManager::RegisterAddon(const char *path) status_t rv; int32 code; entry_ref tempref; - + TRACE("DormantNodeManager::RegisterAddon, path %s\n",path); - + rv = get_ref_for_path(path, &tempref); if (rv != B_OK) { ERROR("DormantNodeManager::RegisterAddon failed, couldn't get ref for path %s\n",path); @@ -232,9 +232,10 @@ DormantNodeManager::RegisterAddon(const char *path) return 0; } - TRACE("DormantNodeManager::RegisterAddon finished with id %ld\n",reply.addonid); + TRACE("DormantNodeManager::RegisterAddon finished with id %ld\n", + reply.addon_id); - return reply.addonid; + return reply.addon_id; } // For use by media_addon_server only @@ -250,7 +251,7 @@ DormantNodeManager::UnregisterAddon(media_addon_id id) port = find_port(MEDIA_SERVER_PORT_NAME); if (port <= B_OK) return; - msg.addonid = id; + msg.addon_id = id; write_port(port, SERVER_UNREGISTER_MEDIAADDON, &msg, sizeof(msg)); } @@ -267,7 +268,7 @@ DormantNodeManager::FindAddonPath(BPath *path, media_addon_id id) port = find_port(MEDIA_SERVER_PORT_NAME); if (port <= B_OK) return B_ERROR; - msg.addonid = id; + msg.addon_id = id; msg.reply_port = _PortPool->GetPort(); rv = write_port(port, SERVER_GET_MEDIAADDON_REF, &msg, sizeof(msg)); if (rv != B_OK) { @@ -291,33 +292,33 @@ DormantNodeManager::LoadAddon(BMediaAddOn **newaddon, image_id *newimage, const BMediaAddOn *addon; image_id image; status_t rv; - + image = load_add_on(path); if (image < B_OK) { ERROR("DormantNodeManager::LoadAddon: loading failed, error %lx (%s), path %s\n", image, strerror(image), path); return B_ERROR; } - + rv = get_image_symbol(image, "make_media_addon", B_SYMBOL_TYPE_TEXT, (void**)&make_addon); if (rv < B_OK) { ERROR("DormantNodeManager::LoadAddon: loading failed, function not found, error %lx (%s)\n", rv, strerror(rv)); unload_add_on(image); return B_ERROR; } - + addon = make_addon(image); if (addon == 0) { ERROR("DormantNodeManager::LoadAddon: creating BMediaAddOn failed\n"); unload_add_on(image); return B_ERROR; } - + ASSERT(addon->ImageID() == 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 initialize these member variables addon->fAddon = id; addon->fImage = image; diff --git a/src/kits/media/Jamfile b/src/kits/media/Jamfile index fdc7ab82b7..ff8c723c67 100644 --- a/src/kits/media/Jamfile +++ b/src/kits/media/Jamfile @@ -7,17 +7,12 @@ if $(TARGET_PLATFORM) != haiku { # We need the public media headers also when not compiling for Haiku. } -UsePrivateHeaders media shared ; +UsePrivateHeaders app media shared ; if $(CHECK_MALLOC) { SubDirC++Flags -D_NO_INLINE_ASM -fcheck-memory-usage ; } -# That's ugly. The header (ServerInterface.h) should reside in -# headers/private/media. -SubDirHdrs [ FDirName $(HAIKU_TOP) src servers media ] ; -SubDirSysHdrs $(SUBDIR) ; # for the Old*.h headers - SharedLibrary libmedia.so : # Private Media Kit !missing_symbols.cpp @@ -52,7 +47,7 @@ SharedLibrary libmedia.so : TimeSource.cpp # Internal Functionality - BufferIdCache.cpp + BufferCache.cpp DataExchange.cpp DefaultMediaTheme.cpp DormantNodeManager.cpp diff --git a/src/kits/media/MediaAddOn.cpp b/src/kits/media/MediaAddOn.cpp index a48b2746d0..fee37715c4 100644 --- a/src/kits/media/MediaAddOn.cpp +++ b/src/kits/media/MediaAddOn.cpp @@ -104,7 +104,7 @@ dormant_flavor_info::dormant_flavor_info() } -/* virtual */ +/* virtual */ dormant_flavor_info::~dormant_flavor_info() { delete [] name; @@ -182,7 +182,7 @@ dormant_flavor_info::operator=(const flavor_info &clone) // initialize node_info with default values from dormant_node_info constructor dormant_node_info defaultValues; node_info = defaultValues; - + return *this; } @@ -284,7 +284,7 @@ dormant_flavor_info::Flatten(void *buffer, if (size < FlattenedSize()) return B_ERROR; - char *buf = (char *)buffer; + char *buf = (char *)buffer; int32 nameLength = name ? (int32)strlen(name) : -1; int32 infoLength = info ? (int32)strlen(info) : -1; int32 inFormatCount = 0; @@ -362,7 +362,7 @@ dormant_flavor_info::Unflatten(type_code c, if (size < 8) return B_ERROR; - const char *buf = (const char *)buffer; + const char *buf = (const char *)buffer; int32 nameLength; int32 infoLength; @@ -409,7 +409,7 @@ dormant_flavor_info::Unflatten(type_code c, } int32 count; - + kinds = *(uint64*)buf; buf += sizeof(uint64); flavor_flags = *(uint32*)buf; buf += sizeof(uint32); internal_id = *(int32*)buf; buf += sizeof(int32); @@ -423,12 +423,12 @@ dormant_flavor_info::Unflatten(type_code c, if (!in_formats) return B_NO_MEMORY; // XXX FIXME! we should not!!! make flat copies of media_format - memcpy(const_cast(in_formats), buf, count * sizeof(media_format)); + memcpy(const_cast(in_formats), buf, count * sizeof(media_format)); in_format_count = count; } buf += count * sizeof(media_format); // XXX not save } - + count = *(int32*)buf; buf += sizeof(int32); out_format_flags = *(uint32*)buf; buf += sizeof(uint32); @@ -438,14 +438,14 @@ dormant_flavor_info::Unflatten(type_code c, if (!out_formats) return B_NO_MEMORY; // XXX FIXME! we should not!!! make flat copies of media_format - memcpy(const_cast(out_formats), buf, count * sizeof(media_format)); + memcpy(const_cast(out_formats), buf, count * sizeof(media_format)); out_format_count = count; } buf += count * sizeof(media_format); // XXX not save } node_info = *(dormant_node_info*)buf; buf += sizeof(dormant_node_info); - + return B_OK; } @@ -453,7 +453,7 @@ dormant_flavor_info::Unflatten(type_code c, * public BMediaAddOn *************************************************************/ -/* explicit */ +/* explicit */ BMediaAddOn::BMediaAddOn(image_id image) : fImage(image), fAddon(0) @@ -462,7 +462,7 @@ BMediaAddOn::BMediaAddOn(image_id image) : } -/* virtual */ +/* virtual */ BMediaAddOn::~BMediaAddOn() { CALLED(); @@ -617,7 +617,7 @@ BMediaAddOn::NotifyFlavorChange() return B_ERROR; addonserver_rescan_mediaaddon_flavors_command command; - command.addonid = fAddon; + command.addon_id = fAddon; return SendToAddonServer(ADDONSERVER_RESCAN_MEDIAADDON_FLAVORS, &command, sizeof(command)); } diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index c484373ef0..21914cd33f 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -31,7 +31,6 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - * */ @@ -39,7 +38,7 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " "Overhagen "; -//#define DEBUG 7 + #include #include @@ -56,6 +55,8 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " #include #include +#include + #include "debug.h" #include "MediaRosterEx.h" #include "MediaMisc.h" @@ -68,39 +69,43 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " namespace BPrivate { namespace media { - // the BMediaRoster destructor is private, - // but _DefaultDeleter is a friend class of - // the BMediaRoster an thus can delete it - class DefaultDeleter +// the BMediaRoster destructor is private, +// but _DefaultDeleter is a friend class of +// the BMediaRoster an thus can delete it +class DefaultDeleter { +public: + ~DefaultDeleter() { - public: - ~DefaultDeleter() - { - if (BMediaRoster::sDefaultInstance) { - BMediaRoster::sDefaultInstance->Lock(); - BMediaRoster::sDefaultInstance->Quit(); - } + if (BMediaRoster::sDefaultInstance != NULL) { + BMediaRoster::sDefaultInstance->Lock(); + BMediaRoster::sDefaultInstance->Quit(); } - }; + } +}; + +} // namespace media +} // namespace BPrivate -} } // BPrivate::media using namespace BPrivate::media; + // DefaultDeleter will delete the BMediaRoster object in it's destructor. DefaultDeleter _deleter; + BMediaRosterEx::BMediaRosterEx(status_t* _error) - : BMediaRoster() + : + BMediaRoster() { - status_t rv; // register this application with the media server server_register_app_request request; server_register_app_reply reply; - request.team = team; + request.team = BPrivate::current_team(); request.messenger = BMessenger(NULL, this); - rv = QueryServer(SERVER_REGISTER_APP, &request, sizeof(request), &reply, - sizeof(reply)); - if (rv != B_OK) + + status_t status = QueryServer(SERVER_REGISTER_APP, &request, + sizeof(request), &reply, sizeof(reply)); + if (status != B_OK) *_error = B_MEDIA_SYSTEM_FAILURE; else *_error = B_OK; @@ -110,11 +115,9 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error) status_t BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node) { - BMediaAddOn *addon; - media_addon_id addonid; - int32 flavorid; - addon = node->AddOn(&flavorid); - if (!addon) { + int32 flavorID; + BMediaAddOn* addon = node->AddOn(&flavorID); + if (addon == NULL) { // NOTE: This node could have been created by an application, // it does not mean there is an error. // TODO: this check incorrectly triggers on BeOS R5 BT848 node @@ -122,54 +125,55 @@ BMediaRosterEx::SaveNodeConfiguration(BMediaNode* node) "from BMediaAddOn!\n", node->ID()); return B_ERROR; } - addonid = addon->AddonID(); + + media_addon_id addonID = addon->AddonID(); // TODO: fix this printf("### BMediaRosterEx::SaveNodeConfiguration should save addon-id " - "%ld, flavor-id %ld config NOW!\n", addonid, flavorid); + "%ld, flavor-id %ld config NOW!\n", addonID, flavorID); return B_OK; } status_t -BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, - BMessage *out_msg) +BMediaRosterEx::LoadNodeConfiguration(media_addon_id addonID, int32 flavorID, + BMessage *_msg) { // TODO: fix this - out_msg->MakeEmpty(); // to be fully R5 compliant + _msg->MakeEmpty(); // to be fully R5 compliant printf("### BMediaRosterEx::LoadNodeConfiguration should load addon-id " - "%ld, flavor-id %ld config NOW!\n", addonid, flavorid); + "%ld, flavor-id %ld config NOW!\n", addonID, flavorID); return B_OK; } status_t -BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonid, - int32 flavorid) +BMediaRosterEx::IncrementAddonFlavorInstancesCount(media_addon_id addonID, + int32 flavorID) { server_change_addon_flavor_instances_count_request request; server_change_addon_flavor_instances_count_reply reply; - request.addonid = addonid; - request.flavorid = flavorid; + request.addon_id = addonID; + request.flavor_id = flavorID; request.delta = 1; - request.team = team; + request.team = BPrivate::current_team(); return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); } status_t -BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonid, - int32 flavorid) +BMediaRosterEx::DecrementAddonFlavorInstancesCount(media_addon_id addonID, + int32 flavorID) { server_change_addon_flavor_instances_count_request request; server_change_addon_flavor_instances_count_reply reply; - request.addonid = addonid; - request.flavorid = flavorid; + request.addon_id = addonID; + request.flavor_id = flavorID; request.delta = -1; - request.team = team; + request.team = BPrivate::current_team(); return QueryServer(SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, &request, sizeof(request), &reply, sizeof(reply)); } @@ -200,7 +204,7 @@ BMediaRosterEx::GetNode(node_type type, media_node* out_node, status_t rv; request.type = type; - request.team = team; + request.team = BPrivate::current_team(); rv = QueryServer(SERVER_GET_NODE, &request, sizeof(request), &reply, sizeof(reply)); if (rv != B_OK) @@ -565,7 +569,7 @@ BMediaRoster::GetAudioOutput(media_node* _node, int32* _inputID, _inputName); } - + status_t BMediaRoster::GetTimeSource(media_node* _node) { @@ -673,8 +677,8 @@ BMediaRoster::GetNodeFor(media_node_id node, media_node* clone) server_get_node_for_reply reply; status_t rv; - request.nodeid = node; - request.team = team; + request.node_id = node; + request.team = BPrivate::current_team(); rv = QueryServer(SERVER_GET_NODE_FOR, &request, sizeof(request), &reply, sizeof(reply)); @@ -720,7 +724,7 @@ BMediaRoster::ReleaseNode(const media_node& node) if (node.kind & NODE_KIND_NO_REFCOUNTING) { printf("BMediaRoster::ReleaseNode, trying to release reference " "counting disabled timesource, node %ld, port %ld, team %ld\n", - node.node, node.port, team); + node.node, node.port, BPrivate::current_team()); return B_OK; } @@ -729,16 +733,16 @@ BMediaRoster::ReleaseNode(const media_node& node) status_t rv; request.node = node; - request.team = team; + request.team = BPrivate::current_team(); TRACE("BMediaRoster::ReleaseNode, node %ld, port %ld, team %ld\n", - node.node, node.port, team); + node.node, node.port, BPrivate::current_team()); rv = QueryServer(SERVER_RELEASE_NODE, &request, sizeof(request), &reply, sizeof(reply)); if (rv != B_OK) { ERROR("BMediaRoster::ReleaseNode FAILED, node %ld, port %ld, team " - "%ld!\n", node.node, node.port, team); + "%ld!\n", node.node, node.port, BPrivate::current_team()); } return rv; } @@ -1159,7 +1163,7 @@ BMediaRoster::StopNode(const media_node& node, bigtime_t atPerformanceTime, return SendToPort(node.port, NODE_STOP, &command, sizeof(command)); } - + status_t BMediaRoster::SeekNode(const media_node& node, bigtime_t toMediaTime, bigtime_t atPerformanceTime) @@ -1213,7 +1217,7 @@ BMediaRoster::StartTimeSource(const media_node& node, bigtime_t atRealTime) return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); } - + status_t BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime, bool immediate) @@ -1250,7 +1254,7 @@ BMediaRoster::StopTimeSource(const media_node& node, bigtime_t atRealTime, return write_port(node.port, TIMESOURCE_OP, &msg, sizeof(msg)); } - + status_t BMediaRoster::SeekTimeSource(const media_node& node, bigtime_t toPerformanceTime, bigtime_t atRealTime) @@ -1312,7 +1316,7 @@ BMediaRoster::SetRunModeNode(const media_node& node, BMediaNode::run_mode mode) return write_port(node.port, NODE_SET_RUN_MODE, &msg, sizeof(msg)); } - + status_t BMediaRoster::PrerollNode(const media_node& node) { @@ -1880,8 +1884,8 @@ BMediaRoster::RegisterNode(BMediaNode* node) status_t -BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonid, - int32 flavorid) +BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonID, + int32 flavorID) { CALLED(); if (node == NULL) @@ -1890,27 +1894,24 @@ BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonid, // some sanity check // I'm not sure if the media kit warrants to call BMediaNode::AddOn() here. // Perhaps we don't need it. - { - BMediaAddOn *addon; - int32 addon_flavor_id; - media_addon_id addon_id; - addon_flavor_id = 0; - addon = node->AddOn(&addon_flavor_id); - addon_id = addon ? addon->AddonID() : -1; - ASSERT(addonid == addon_id); - ASSERT(flavorid == addon_flavor_id); - } + DEBUG_ONLY( + int32 testFlavorID; + BMediaAddOn* addon = node->AddOn(&testFlavorID); + + ASSERT(addonID == addon != NULL ? addon->AddonID() : -1); + ASSERT(flavorID == testFlavorID); + ); status_t rv; server_register_node_request request; server_register_node_reply reply; - request.addon_id = addonid; - request.addon_flavor_id = flavorid; + request.addon_id = addonID; + request.addon_flavor_id = flavorID; strcpy(request.name, node->Name()); request.kinds = node->Kinds(); request.port = node->ControlPort(); - request.team = team; + request.team = BPrivate::current_team(); TRACE("BMediaRoster::RegisterNode: sending SERVER_REGISTER_NODE: port " "%ld, kinds 0x%Lx, team %ld, name '%s'\n", request.port, request.kinds, @@ -1928,9 +1929,9 @@ BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonid, "finished\n"); // we are a friend class of BMediaNode and initialize this member variable - node->fNodeID = reply.nodeid; - ASSERT(reply.nodeid == node->Node().node); - ASSERT(reply.nodeid == node->ID()); + node->fNodeID = reply.node_id; + ASSERT(reply.node_id == node->Node().node); + ASSERT(reply.node_id == node->ID()); // call the callback node->NodeRegistered(); @@ -1964,19 +1965,18 @@ BMediaRosterEx::RegisterNode(BMediaNode* node, media_addon_id addonid, PublishOutputs(node->Node(), &list); } } - if (node->Kinds() & B_BUFFER_CONSUMER) { - BBufferConsumer *bc; - bc = dynamic_cast(node); - if (bc) { + if ((node->Kinds() & B_BUFFER_CONSUMER) != 0) { + BBufferConsumer* consumer = dynamic_cast(node); + if (consumer != NULL) { List list; - if (B_OK == GetAllInputs(bc, &list)) + if (GetAllInputs(consumer, &list) == B_OK) PublishInputs(node->Node(), &list); } } TRACE("BMediaRoster::RegisterNode: sending NodesCreated\n"); - BPrivate::media::notifications::NodesCreated(&reply.nodeid, 1); + BPrivate::media::notifications::NodesCreated(&reply.node_id, 1); TRACE("BMediaRoster::RegisterNode: finished\n"); @@ -2005,7 +2005,7 @@ BMediaRoster::UnregisterNode(BMediaNode* node) if (node->fKinds & NODE_KIND_NO_REFCOUNTING) { TRACE("BMediaRoster::UnregisterNode, trying to unregister reference " "counting disabled timesource, node %ld, port %ld, team %ld\n", - node->ID(), node->ControlPort(), team); + node->ID(), node->ControlPort(), BPrivate::current_team()); return B_OK; } if (node->ID() == NODE_UNREGISTERED_ID) { @@ -2030,11 +2030,11 @@ BMediaRoster::UnregisterNode(BMediaNode* node) server_unregister_node_reply reply; status_t rv; - request.nodeid = node->ID(); - request.team = team; + request.node_id = node->ID(); + request.team = BPrivate::current_team(); // send a notification - BPrivate::media::notifications::NodesDeleted(&request.nodeid, 1); + BPrivate::media::notifications::NodesDeleted(&request.node_id, 1); rv = QueryServer(SERVER_UNREGISTER_NODE, &request, sizeof(request), &reply, sizeof(reply)); @@ -2044,17 +2044,17 @@ BMediaRoster::UnregisterNode(BMediaNode* node) return rv; } - if (reply.addonid != -1) { + if (reply.addon_id != -1) { // Small problem here, we can't use DormantNodeManager::PutAddon(), as // UnregisterNode() is called by a dormant node itself (by the // destructor). // The add-on that contains the node needs to remain in memory until the // destructor execution is finished. // DormantNodeManager::PutAddonDelayed() will delay unloading. - _DormantNodeManager->PutAddonDelayed(reply.addonid); + _DormantNodeManager->PutAddonDelayed(reply.addon_id); rv = MediaRosterEx(this)->DecrementAddonFlavorInstancesCount( - reply.addonid, reply.flavorid); + reply.addon_id, reply.flavor_id); if (rv != B_OK) { ERROR("BMediaRoster::UnregisterNode: " "DecrementAddonFlavorInstancesCount() failed\n"); @@ -2275,16 +2275,16 @@ BMediaRoster::GetDormantNodes(dormant_node_info* _info, int32* _count, if (port <= B_OK) return B_ERROR; - msg.maxcount = *_count; + msg.max_count = *_count; msg.has_input = hasInput != NULL; if (hasInput != NULL) { // TODO: we should not make a flat copy of media_format - msg.inputformat = *hasInput; + msg.input_format = *hasInput; } msg.has_output = hasOutput != NULL; if (hasOutput != NULL) { // TODO: we should not make a flat copy of media_format - msg.outputformat = *hasOutput; + msg.output_format = *hasOutput; } msg.has_name = name != NULL; @@ -2459,7 +2459,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonID, int32 flavorID, TRACE("BMediaRosterEx::InstantiateDormantNode: addon-id %ld, flavor_id " "%ld instanciated as node %ld, port %ld in team %ld\n", addonID, - flavorID, _node->node, _node->port, team); + flavorID, _node->node, _node->port, BPrivate::current_team()); return B_OK; } @@ -2548,9 +2548,9 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, addonserver_instantiate_dormant_node_request request; addonserver_instantiate_dormant_node_reply reply; - request.addonid = info.addon; - request.flavorid = info.flavor_id; - request.creator_team = team; + request.addon_id = info.addon; + request.flavor_id = info.flavor_id; + request.creator_team = BPrivate::current_team(); // creator team is allowed to also release global nodes rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); @@ -2568,7 +2568,7 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, return B_OK; } - + status_t BMediaRoster::InstantiateDormantNode(const dormant_node_info& info, media_node* _node) @@ -2611,44 +2611,44 @@ BMediaRosterEx::GetDormantFlavorInfo(media_addon_id addonID, int32 flavorID, if (_flavor == NULL) return B_BAD_VALUE; - xfer_server_get_dormant_flavor_info msg; - xfer_server_get_dormant_flavor_info_reply *reply; - port_id port; - status_t rv; - int32 code; - - port = find_port(MEDIA_SERVER_PORT_NAME); - if (port < B_OK) + port_id port = find_port(MEDIA_SERVER_PORT_NAME); + if (port < 0) return B_ERROR; - reply = (xfer_server_get_dormant_flavor_info_reply*)malloc(16000); + xfer_server_get_dormant_flavor_info_reply* reply + = (xfer_server_get_dormant_flavor_info_reply*)malloc(16300); if (reply == NULL) return B_NO_MEMORY; + xfer_server_get_dormant_flavor_info msg; msg.addon = addonID; msg.flavor_id = flavorID; msg.reply_port = _PortPool->GetPort(); - rv = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, sizeof(msg)); - if (rv != B_OK) { + status_t status = write_port(port, SERVER_GET_DORMANT_FLAVOR_INFO, &msg, + sizeof(msg)); + if (status != B_OK) { free(reply); _PortPool->PutPort(msg.reply_port); - return rv; + return status; } - rv = read_port(msg.reply_port, &code, reply, 16000); + + int32 code; + status = read_port(msg.reply_port, &code, reply, 16000); _PortPool->PutPort(msg.reply_port); - if (rv < B_OK) { + if (status < B_OK) { free(reply); - return rv; + return status; } - if (reply->result == B_OK) - rv = _flavor->Unflatten(reply->dfi_type, &reply->dfi, reply->dfi_size); - else - rv = reply->result; + if (reply->result == B_OK) { + status = _flavor->Unflatten(reply->type, &reply->flattened_data, + reply->flattened_size); + } else + status = reply->result; free(reply); - return rv; + return status; } @@ -2855,20 +2855,20 @@ BMediaRoster::SniffRef(const entry_ref& file, uint64 requireNodeKinds, return B_BAD_VALUE; BMimeType aMimeType; - + dormant_node_info nodes[30]; int32 count = 30; int32 highestCapability = -1; float capability; - + media_node node; - + // Get all dormant nodes using GetDormantNodes if (GetDormantNodes(nodes, &count, NULL, NULL, NULL, requireNodeKinds | B_FILE_INTERFACE, 0) == B_OK) { // Call SniffRefFor on each node that matches requireNodeKinds for (int32 i=0;i #include + +#include + #include "debug.h" #include "DataExchange.h" -#include "Notifications.h" + namespace BPrivate { namespace media { - -extern team_id team; - namespace notifications { + status_t -Register(const BMessenger ¬ifyHandler, const media_node &node, int32 notification) +Register(const BMessenger& notifyHandler, const media_node& node, + int32 notification) { CALLED(); BMessage msg(MEDIA_SERVER_REQUEST_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification); - msg.AddInt32(NOTIFICATION_PARAM_TEAM, team); + msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team()); msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler); msg.AddData("node", B_RAW_TYPE, &node, sizeof(node)); + return BPrivate::media::dataexchange::SendToServer(&msg); } status_t -Unregister(const BMessenger ¬ifyHandler, const media_node &node, int32 notification) +Unregister(const BMessenger& notifyHandler, const media_node& node, + int32 notification) { CALLED(); BMessage msg(MEDIA_SERVER_CANCEL_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, notification); - msg.AddInt32(NOTIFICATION_PARAM_TEAM, team); + msg.AddInt32(NOTIFICATION_PARAM_TEAM, BPrivate::current_team()); msg.AddMessenger(NOTIFICATION_PARAM_MESSENGER, notifyHandler); msg.AddData("node", B_RAW_TYPE, &node, sizeof(node)); + return BPrivate::media::dataexchange::SendToServer(&msg); } +/*! Transmits the error code specified by \a what to anyone who's receiving + notifications from this node. If \a info isn't \c NULL, it's used as a + model message for the error notification message. + The message field "be:node_id" will contain the node ID. +*/ status_t -ReportError(const media_node &node, BMediaNode::node_error what, const BMessage * info) +ReportError(const media_node& node, BMediaNode::node_error what, + const BMessage* info) { - /* Transmits the error code specified by whichError to anyone that's receiving notifications from - * this node. If info isn't NULL, it's used as a model message for the error notification message. - * The message field "be:node_id" will contain the node ID. - */ CALLED(); BMessage msg; - if (info) + if (info != NULL) msg = *info; + msg.what = MEDIA_SERVER_SEND_NOTIFICATIONS; msg.AddInt32(NOTIFICATION_PARAM_WHAT, what); msg.AddInt32("be:node_id", node.node); msg.AddData("node", B_RAW_TYPE, &node, sizeof(node)); + return BPrivate::media::dataexchange::SendToServer(&msg); } void -NodesCreated(const media_node_id *ids, int32 count) +NodesCreated(const media_node_id* ids, int32 count) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); @@ -103,12 +115,13 @@ NodesCreated(const media_node_id *ids, int32 count) for (int32 i = 0; i < count; i++) { msg.AddInt32("media_node_id", ids[i]); } + BPrivate::media::dataexchange::SendToServer(&msg); } void -NodesDeleted(const media_node_id *ids, int32 count) +NodesDeleted(const media_node_id* ids, int32 count) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); @@ -116,12 +129,14 @@ NodesDeleted(const media_node_id *ids, int32 count) for (int32 i = 0; i < count; i++) { msg.AddInt32("media_node_id", ids[i]); } + BPrivate::media::dataexchange::SendToServer(&msg); } void -ConnectionMade(const media_input &input, const media_output &output, const media_format &format) +ConnectionMade(const media_input& input, const media_output& output, + const media_format& format) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); @@ -129,24 +144,27 @@ ConnectionMade(const media_input &input, const media_output &output, const media msg.AddData("input", B_RAW_TYPE, &input, sizeof(input)); msg.AddData("output", B_RAW_TYPE, &output, sizeof(output)); msg.AddData("format", B_RAW_TYPE, &format, sizeof(format)); + BPrivate::media::dataexchange::SendToServer(&msg); } void -ConnectionBroken(const media_source &source, const media_destination &destination) +ConnectionBroken(const media_source& source, + const media_destination& destination) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_CONNECTION_BROKEN); msg.AddData("source", B_RAW_TYPE, &source, sizeof(source)); msg.AddData("destination", B_RAW_TYPE, &destination, sizeof(destination)); + BPrivate::media::dataexchange::SendToServer(&msg); } void -BuffersCreated(area_info *areas, int32 count) +BuffersCreated(area_info* areas, int32 count) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); @@ -154,12 +172,13 @@ BuffersCreated(area_info *areas, int32 count) for (int32 i = 0; i < count; i++) { msg.AddData("clone_info", B_RAW_TYPE, &areas[i], sizeof(area_info)); } + BPrivate::media::dataexchange::SendToServer(&msg); } void -BuffersDeleted(const media_buffer_id *ids, int32 count) +BuffersDeleted(const media_buffer_id* ids, int32 count) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); @@ -167,12 +186,14 @@ BuffersDeleted(const media_buffer_id *ids, int32 count) for (int32 i = 0; i < count; i++) { msg.AddInt32("media_buffer_id", ids[i]); } + BPrivate::media::dataexchange::SendToServer(&msg); } void -FormatChanged(const media_source &source, const media_destination &destination, const media_format &format) +FormatChanged(const media_source& source, const media_destination& destination, + const media_format& format) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); @@ -180,74 +201,81 @@ FormatChanged(const media_source &source, const media_destination &destination, msg.AddData("source", B_RAW_TYPE, &source, sizeof(source)); msg.AddData("destination", B_RAW_TYPE, &destination, sizeof(destination)); msg.AddData("format", B_RAW_TYPE, &format, sizeof(format)); + BPrivate::media::dataexchange::SendToServer(&msg); } status_t -ParameterChanged(const media_node &node, int32 parameterid) +ParameterChanged(const media_node& node, int32 parameterID) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_PARAMETER_CHANGED); msg.AddData("node", B_RAW_TYPE, &node, sizeof(node)); - msg.AddInt32("parameter", parameterid); + msg.AddInt32("parameter", parameterID); + return BPrivate::media::dataexchange::SendToServer(&msg); } void -WebChanged(const media_node &node) +WebChanged(const media_node& node) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_WEB_CHANGED); msg.AddData("node", B_RAW_TYPE, &node, sizeof(node)); + BPrivate::media::dataexchange::SendToServer(&msg); } status_t -NewParameterValue(const media_node &node, int32 parameterid, bigtime_t when, const void *param, size_t paramsize) +NewParameterValue(const media_node& node, int32 parameterID, bigtime_t when, + const void* param, size_t paramsize) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_NEW_PARAMETER_VALUE); msg.AddData("node", B_RAW_TYPE, &node, sizeof(node)); - msg.AddInt32("parameter", parameterid); + msg.AddInt32("parameter", parameterID); msg.AddInt64("when", when); msg.AddData("value", B_RAW_TYPE, param, paramsize); + return BPrivate::media::dataexchange::SendToServer(&msg); } void -FlavorsChanged(media_addon_id addonid, int32 newcount, int32 gonecount) +FlavorsChanged(media_addon_id addOnID, int32 newCount, int32 goneCount) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_FLAVORS_CHANGED); - msg.AddInt32("be:addon_id", addonid); - msg.AddInt32("be:new_count", newcount); - msg.AddInt32("be:gone_count", gonecount); + msg.AddInt32("be:addon_id", addOnID); + msg.AddInt32("be:new_count", newCount); + msg.AddInt32("be:gone_count", goneCount); + BPrivate::media::dataexchange::SendToServer(&msg); } void -NodeStopped(const media_node &node, bigtime_t when) +NodeStopped(const media_node& node, bigtime_t when) { CALLED(); BMessage msg(MEDIA_SERVER_SEND_NOTIFICATIONS); msg.AddInt32(NOTIFICATION_PARAM_WHAT, B_MEDIA_NODE_STOPPED); msg.AddData("node", B_RAW_TYPE, &node, sizeof(node)); msg.AddInt64("when", when); + BPrivate::media::dataexchange::SendToServer(&msg); } -// XXX missing: B_MEDIA_TRANSPORT_STATE /* "state", "location", "realtime" */ -// XXX missing: B_MEDIA_DEFAULT_CHANGED /* "default", "node" */ +// TODO: missing: B_MEDIA_TRANSPORT_STATE: "state", "location", "realtime" +// TODO: missing: B_MEDIA_DEFAULT_CHANGED: "default", "node" bool @@ -266,7 +294,7 @@ IsValidNotificationRequest(bool node_specific, int32 notification) case B_MEDIA_DEFAULT_CHANGED: case B_MEDIA_FLAVORS_CHANGED: return true; - + // only valid for node specific watching case B_MEDIA_PARAMETER_CHANGED: case B_MEDIA_FORMAT_CHANGED: @@ -274,13 +302,13 @@ IsValidNotificationRequest(bool node_specific, int32 notification) case B_MEDIA_NEW_PARAMETER_VALUE: case B_MEDIA_NODE_STOPPED: return node_specific; - + // everything else is invalid default: return false; } } -}; // namespace notifications -}; // namespace media -}; // namespace BPrivate +} // namespace notifications +} // namespace media +} // namespace BPrivate diff --git a/src/kits/media/SharedBufferList.cpp b/src/kits/media/SharedBufferList.cpp index 4c0955ef7f..b7e8ed2ced 100644 --- a/src/kits/media/SharedBufferList.cpp +++ b/src/kits/media/SharedBufferList.cpp @@ -1,213 +1,241 @@ -/*********************************************************************** - * Copyright (c) 2002 Marcus Overhagen. All Rights Reserved. - * This file may be used under the terms of the OpenBeOS License. - * - * Used for BBufferGroup and BBuffer management across teams - ***********************************************************************/ -#include +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002, Marcus Overhagen. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + + +/*! Used for BBufferGroup and BBuffer management across teams. + Created in the media server, cloned into each BBufferGroup (visible in + all address spaces). +*/ + +// TODO: don't use a simple list! + + +#include + #include -#include "SharedBufferList.h" + +#include + #include "debug.h" -status_t -_shared_buffer_list::Init() +namespace BPrivate { + + +/*static*/ area_id +SharedBufferList::Create(SharedBufferList** _list) { CALLED(); - locker_atom = 0; - locker_sem = create_sem(0,"shared buffer list lock"); - if (locker_sem < B_OK) - return (status_t) locker_sem; - for (int i = 0; i < MAX_BUFFER; i++) { - info[i].id = -1; - info[i].buffer = 0; - info[i].reclaim_sem = 0; - info[i].reclaimed = false; + size_t size = (sizeof(SharedBufferList) + (B_PAGE_SIZE - 1)) + & ~(B_PAGE_SIZE - 1); + SharedBufferList* list; + + area_id area = create_area("shared buffer list", (void**)&list, + B_ANY_ADDRESS, size, B_LAZY_LOCK, B_READ_AREA | B_WRITE_AREA); + if (area < 0) + return area; + + status_t status = list->_Init(); + if (status != B_OK) { + delete_area(area); + return status; } - return B_OK; + + return area; } -_shared_buffer_list * -_shared_buffer_list::Clone(area_id id) + +/*static*/ SharedBufferList* +SharedBufferList::Get(area_id id) { CALLED(); - // if id == -1, we are in the media_server team, - // and create the initial list, else we clone it + // TODO: map this only once per team! - _shared_buffer_list *adr; - status_t status; - - if (id == -1) { - size_t size = ((sizeof(_shared_buffer_list)) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1); - status = create_area("shared buffer list",(void **)&adr,B_ANY_ADDRESS,size,B_LAZY_LOCK,B_READ_AREA | B_WRITE_AREA); - if (status >= B_OK) { - status = adr->Init(); - if (status != B_OK) - delete_area(area_for(adr)); - } - } else { - status = clone_area("shared buffer list clone", (void **)&adr, B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, id); - if (status < B_OK) { - ERROR("_shared_buffer_list::Clone() clone area: %ld err = %s\n", id, strerror(status)); - } + SharedBufferList* list; + area_id area = clone_area("shared buffer list clone", (void**)&list, + B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, id); + if (area < 0) { + ERROR("SharedBufferList::Clone() clone area: %ld err = %s\n", id, + strerror(area)); + return NULL; } - - return (status < B_OK) ? NULL : adr; + + return list; } + void -_shared_buffer_list::Unmap() +SharedBufferList::Put() { CALLED(); - // unmap the memory used by this struct - // XXX is this save? - area_id id; - id = area_for(this); - if (id >= B_OK) - delete_area(id); + + area_id area = area_for(this); + if (area >= 0) + delete_area(area); } + +/*! Deletes all BBuffers of the group specified by \a groupReclaimSem, then + unmaps the list from memory. +*/ void -_shared_buffer_list::Terminate(sem_id group_reclaim_sem) +SharedBufferList::DeleteGroupAndPut(sem_id groupReclaimSem) { CALLED(); - // delete all BBuffers of this group, then unmap from memory + if (Lock() == B_OK) { + for (int32 i = 0; i < fCount; i++) { + if (fInfos[i].reclaim_sem == groupReclaimSem) { + // delete the associated buffer + delete fInfos[i].buffer; - if (Lock() != B_OK) { // better not try to access the list unlocked - // but at least try to unmap the memory - Unmap(); - return; - } - - for (int32 i = 0; i < buffercount; i++) { - if (info[i].reclaim_sem == group_reclaim_sem) { - // delete the associated buffer - delete info[i].buffer; - // decrement buffer count by one - buffercount--; - // fill the gap in the list with the last entry - if (buffercount > 0) { - info[i] = info[buffercount]; - i--; // make sure we check this entry again + // Decrement buffer count by one, and fill the gap + // in the list with its last entry + fCount--; + if (fCount > 0) + fInfos[i--] = fInfos[fCount]; } } + + Unlock(); } - - Unlock(); - - Unmap(); + + Put(); } + status_t -_shared_buffer_list::Lock() -{ - if (atomic_add(&locker_atom, 1) > 0) { +SharedBufferList::Lock() +{ + if (atomic_add(&fAtom, 1) > 0) { status_t status; - while (B_INTERRUPTED == (status = acquire_sem(locker_sem))) - ; - return status; // will only return != B_OK if the media_server crashed or quit + do { + status = acquire_sem(fSemaphore); + } while (status == B_INTERRUPTED); + + return status; } return B_OK; } + status_t -_shared_buffer_list::Unlock() -{ - if (atomic_add(&locker_atom, -1) > 1) - return release_sem(locker_sem); // will only return != B_OK if the media_server crashed or quit +SharedBufferList::Unlock() +{ + if (atomic_add(&fAtom, -1) > 1) + return release_sem(fSemaphore); + return B_OK; } + status_t -_shared_buffer_list::AddBuffer(sem_id group_reclaim_sem, BBuffer *buffer) +SharedBufferList::AddBuffer(sem_id groupReclaimSem, BBuffer* buffer) { CALLED(); - + if (buffer == NULL) return B_BAD_VALUE; - if (Lock() != B_OK) - return B_ERROR; - - if (buffercount == MAX_BUFFER) { + status_t status = Lock(); + if (status != B_OK) + return status; + + if (fCount == kMaxBuffers) { Unlock(); - debugger("we are doomed"); - return B_ERROR; + return B_MEDIA_TOO_MANY_BUFFERS; } - info[buffercount].id = buffer->ID(); - info[buffercount].buffer = buffer; - info[buffercount].reclaim_sem = group_reclaim_sem; - info[buffercount].reclaimed = true; - buffercount++; + fInfos[fCount].id = buffer->ID(); + fInfos[fCount].buffer = buffer; + fInfos[fCount].reclaim_sem = groupReclaimSem; + fInfos[fCount].reclaimed = true; + fCount++; - status_t status1 = release_sem_etc(group_reclaim_sem,1,B_DO_NOT_RESCHEDULE); - status_t status2 = Unlock(); + status = release_sem_etc(groupReclaimSem, 1, B_DO_NOT_RESCHEDULE); + if (status != B_OK) + return status; - return (status1 == B_OK && status2 == B_OK) ? B_OK : B_ERROR; + return Unlock(); } -status_t -_shared_buffer_list::RequestBuffer(sem_id group_reclaim_sem, int32 buffers_in_group, size_t size, media_buffer_id wantID, BBuffer **buffer, bigtime_t timeout) + +status_t +SharedBufferList::RequestBuffer(sem_id groupReclaimSem, int32 buffersInGroup, + size_t size, media_buffer_id wantID, BBuffer** _buffer, bigtime_t timeout) { CALLED(); - // we always search for a buffer from the group indicated by group_reclaim_sem first - // if "size" != 0, we search for a buffer that is "size" bytes or larger - // if "wantID" != 0, we search for a buffer with this id - // if "*buffer" != NULL, we search for a buffer at this address - // if we found a buffer, we also need to mark it in all other groups as requested - // and also once need to acquire the reclaim_sem of the other groups - - status_t status; - uint32 acquire_flags; - int32 count; + // We always search for a buffer from the group indicated by groupReclaimSem + // first. + // If "size" != 0, we search for a buffer that is "size" bytes or larger. + // If "wantID" != 0, we search for a buffer with this ID. + // If "*_buffer" != NULL, we search for a buffer at this address. + // + // If we found a buffer, we also need to mark it in all other groups as + // requested and also once need to acquire the reclaim_sem of the other + // groups + + uint32 acquireFlags; if (timeout <= 0) { timeout = 0; - acquire_flags = B_RELATIVE_TIMEOUT; - } else if (timeout != B_INFINITE_TIMEOUT) { - timeout += system_time(); - acquire_flags = B_ABSOLUTE_TIMEOUT; + acquireFlags = B_RELATIVE_TIMEOUT; + } else if (timeout == B_INFINITE_TIMEOUT) { + acquireFlags = B_RELATIVE_TIMEOUT; } else { - //timeout is B_INFINITE_TIMEOUT - acquire_flags = B_RELATIVE_TIMEOUT; + timeout += system_time(); + acquireFlags = B_ABSOLUTE_TIMEOUT; } - - // with each itaration we request one more buffer, since we need to skip the buffers that don't fit the request - count = 1; - + + // With each itaration we request one more buffer, since we need to skip + // the buffers that don't fit the request + int32 count = 1; + do { - while (B_INTERRUPTED == (status = acquire_sem_etc(group_reclaim_sem, count, acquire_flags, timeout))) - ; + status_t status; + do { + status = acquire_sem_etc(groupReclaimSem, count, acquireFlags, + timeout); + } while (status == B_INTERRUPTED); + if (status != B_OK) return status; - // try to exit savely if the lock fails - if (Lock() != B_OK) { - ERROR("_shared_buffer_list:: RequestBuffer: Lock failed\n"); - release_sem_etc(group_reclaim_sem, count, 0); + // try to exit savely if the lock fails + status = Lock(); + if (status != B_OK) { + ERROR("SharedBufferList:: RequestBuffer: Lock failed: %s\n", + strerror(status)); + release_sem_etc(groupReclaimSem, count, 0); return B_ERROR; } - - for (int32 i = 0; i < buffercount; i++) { - // we need a BBuffer from the group, and it must be marked as reclaimed - if (info[i].reclaim_sem == group_reclaim_sem && info[i].reclaimed) { - if ( - (size != 0 && size <= info[i].buffer->SizeAvailable()) || - (*buffer != 0 && info[i].buffer == *buffer) || - (wantID != 0 && info[i].id == wantID) - ) { + + for (int32 i = 0; i < fCount; i++) { + // We need a BBuffer from the group, and it must be marked as + // reclaimed + if (fInfos[i].reclaim_sem == groupReclaimSem + && fInfos[i].reclaimed) { + if ((size != 0 && size <= fInfos[i].buffer->SizeAvailable()) + || (*_buffer != 0 && fInfos[i].buffer == *_buffer) + || (wantID != 0 && fInfos[i].id == wantID)) { // we found a buffer - info[i].reclaimed = false; - *buffer = info[i].buffer; + fInfos[i].reclaimed = false; + *_buffer = fInfos[i].buffer; + // if we requested more than one buffer, release the rest - if (count > 1) - release_sem_etc(group_reclaim_sem, count - 1, B_DO_NOT_RESCHEDULE); - - // and mark all buffers with the same ID as requested in all other buffer groups - RequestBufferInOtherGroups(group_reclaim_sem, info[i].buffer->ID()); + if (count > 1) { + release_sem_etc(groupReclaimSem, count - 1, + B_DO_NOT_RESCHEDULE); + } + + // And mark all buffers with the same ID as requested in + // all other buffer groups + _RequestBufferInOtherGroups(groupReclaimSem, + fInfos[i].buffer->ID()); Unlock(); return B_OK; @@ -215,107 +243,140 @@ _shared_buffer_list::RequestBuffer(sem_id group_reclaim_sem, int32 buffers_in_gr } } - release_sem_etc(group_reclaim_sem, count, B_DO_NOT_RESCHEDULE); + release_sem_etc(groupReclaimSem, count, B_DO_NOT_RESCHEDULE); if (Unlock() != B_OK) { - ERROR("_shared_buffer_list:: RequestBuffer: unlock failed\n"); + ERROR("SharedBufferList:: RequestBuffer: unlock failed\n"); return B_ERROR; } // prepare to request one more buffer next time count++; - } while (count <= buffers_in_group); + } while (count <= buffersInGroup); - ERROR("_shared_buffer_list:: RequestBuffer: no buffer found\n"); + ERROR("SharedBufferList:: RequestBuffer: no buffer found\n"); return B_ERROR; } -void -_shared_buffer_list::RequestBufferInOtherGroups(sem_id group_reclaim_sem, media_buffer_id id) -{ - for (int32 i = 0; i < buffercount; i++) { - // find buffers with same id, but belonging to other groups - if (info[i].id == id && info[i].reclaim_sem != group_reclaim_sem) { - - // and mark them as requested - // XXX this can deadlock if BBuffers with same media_buffer_id - // XXX exist in more than one BBufferGroup, and RequestBuffer() - // XXX is called on both groups (which should not be done). - status_t status; - while (B_INTERRUPTED == (status = acquire_sem(info[i].reclaim_sem))) - ; - // try to skip entries that belong to crashed teams - if (status != B_OK) - continue; - - if (info[i].reclaimed == false) { - ERROR("_shared_buffer_list:: RequestBufferInOtherGroups BBuffer %p, id = %ld not reclaimed while requesting\n", info[i].buffer, id); - continue; - } - - info[i].reclaimed = false; - } - } -} status_t -_shared_buffer_list::RecycleBuffer(BBuffer *buffer) +SharedBufferList::RecycleBuffer(BBuffer* buffer) { CALLED(); - - int reclaimed_count; - -// media_buffer_id id = buffer->ID(); - media_buffer_id id = buffer->fBufferID; + + media_buffer_id id = buffer->ID(); if (Lock() != B_OK) return B_ERROR; - reclaimed_count = 0; - for (int32 i = 0; i < buffercount; i++) { + int32 reclaimedCount = 0; + + for (int32 i = 0; i < fCount; i++) { // find the buffer id, and reclaim it in all groups it belongs to - if (info[i].id == id) { - reclaimed_count++; - if (info[i].reclaimed) { - ERROR("_shared_buffer_list::RecycleBuffer, BBuffer %p, id = %ld already reclaimed\n", buffer, id); + if (fInfos[i].id == id) { + reclaimedCount++; + if (fInfos[i].reclaimed) { + ERROR("SharedBufferList::RecycleBuffer, BBuffer %p, id = %ld " + "already reclaimed\n", buffer, id); DEBUG_ONLY(debugger("buffer already reclaimed")); continue; } - info[i].reclaimed = true; - release_sem_etc(info[i].reclaim_sem, 1, B_DO_NOT_RESCHEDULE); + fInfos[i].reclaimed = true; + release_sem_etc(fInfos[i].reclaim_sem, 1, B_DO_NOT_RESCHEDULE); } } + if (Unlock() != B_OK) return B_ERROR; - - if (reclaimed_count == 0) { - ERROR("shared_buffer_list::RecycleBuffer, BBuffer %p, id = %ld NOT reclaimed\n", buffer, id); + + if (reclaimedCount == 0) { + ERROR("shared_buffer_list::RecycleBuffer, BBuffer %p, id = %ld NOT " + "reclaimed\n", buffer, id); return B_ERROR; } return B_OK; } -status_t -_shared_buffer_list::GetBufferList(sem_id group_reclaim_sem, int32 buf_count, BBuffer **out_buffers) + +/*! Returns exactly \a bufferCount buffers from the group specified via its + \a groupReclaimSem if successful. +*/ +status_t +SharedBufferList::GetBufferList(sem_id groupReclaimSem, int32 bufferCount, + BBuffer** buffers) { CALLED(); - int32 found; - - found = 0; - if (Lock() != B_OK) return B_ERROR; - for (int32 i = 0; i < buffercount; i++) - if (info[i].reclaim_sem == group_reclaim_sem) { - out_buffers[found++] = info[i].buffer; - if (found == buf_count) + int32 found = 0; + + for (int32 i = 0; i < fCount; i++) + if (fInfos[i].reclaim_sem == groupReclaimSem) { + buffers[found++] = fInfos[i].buffer; + if (found == bufferCount) break; } - + if (Unlock() != B_OK) return B_ERROR; - return (found == buf_count) ? B_OK : B_ERROR; + return found == bufferCount ? B_OK : B_ERROR; } + +status_t +SharedBufferList::_Init() +{ + CALLED(); + + fSemaphore = create_sem(0, "shared buffer list lock"); + if (fSemaphore < 0) + return fSemaphore; + + fAtom = 0; + + for (int32 i = 0; i < kMaxBuffers; i++) { + fInfos[i].id = -1; + } + + return B_OK; +} + + +/*! Used by RequestBuffer, call this one with the list locked! +*/ +void +SharedBufferList::_RequestBufferInOtherGroups(sem_id groupReclaimSem, + media_buffer_id id) +{ + for (int32 i = 0; i < fCount; i++) { + // find buffers with same id, but belonging to other groups + if (fInfos[i].id == id && fInfos[i].reclaim_sem != groupReclaimSem) { + // and mark them as requested + // TODO: this can deadlock if BBuffers with same media_buffer_id + // exist in more than one BBufferGroup, and RequestBuffer() + // is called on both groups (which should not be done). + status_t status; + do { + status = acquire_sem(fInfos[i].reclaim_sem); + } while (status == B_INTERRUPTED); + + // try to skip entries that belong to crashed teams + if (status != B_OK) + continue; + + if (fInfos[i].reclaimed == false) { + ERROR("SharedBufferList:: RequestBufferInOtherGroups BBuffer " + "%p, id = %ld not reclaimed while requesting\n", + fInfos[i].buffer, id); + continue; + } + + fInfos[i].reclaimed = false; + } + } +} + + +} // namespace BPrivate diff --git a/src/servers/media/BufferManager.cpp b/src/servers/media/BufferManager.cpp index 6dd3a59619..2f821c30bc 100644 --- a/src/servers/media/BufferManager.cpp +++ b/src/servers/media/BufferManager.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright 2002, Marcus Overhagen. All rights reserved. * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. @@ -15,28 +15,30 @@ BufferManager::BufferManager() : - fSharedBufferList(_shared_buffer_list::Clone()), + fSharedBufferList(NULL), + fSharedBufferListArea(-1), fNextBufferID(1), fLocker("buffer manager locker") { - fSharedBufferListID = area_for(fSharedBufferList); + fSharedBufferListArea + = BPrivate::SharedBufferList::Create(&fSharedBufferList); } BufferManager::~BufferManager() { - fSharedBufferList->Unmap(); + fSharedBufferList->Put(); } area_id -BufferManager::SharedBufferListID() +BufferManager::SharedBufferListArea() { - return fSharedBufferListID; + return fSharedBufferListArea; } -status_t +status_t BufferManager::RegisterBuffer(team_id team, media_buffer_id bufferID, size_t* _size, int32* _flags, size_t* _offset, area_id* _area) { @@ -55,7 +57,7 @@ BufferManager::RegisterBuffer(team_id team, media_buffer_id bufferID, *_area = info->area; *_offset = info->offset; - *_size = info->size, + *_size = info->size, *_flags = info->flags; return B_OK; @@ -69,7 +71,7 @@ BufferManager::RegisterBuffer(team_id team, size_t size, int32 flags, BAutolock lock(fLocker); TRACE("RegisterBuffer team = %ld, area = %ld, offset = %ld, size = %ld\n", team, area, offset, size); - + area_id clonedArea = _CloneArea(area); if (clonedArea < 0) { ERROR("RegisterBuffer: failed to clone buffer! error = %#lx, team = " @@ -84,14 +86,19 @@ BufferManager::RegisterBuffer(team_id team, size_t size, int32 flags, info.offset = offset; info.size = size; info.flags = flags; - info.teams.insert(team); - *_bufferID = info.id; - - fBufferInfoMap.Put(info.id, info); + try { + info.teams.insert(team); + if (fBufferInfoMap.Put(info.id, info) != B_OK) + throw std::bad_alloc(); + } catch (std::bad_alloc& exception) { + _ReleaseClonedArea(clonedArea); + return B_NO_MEMORY; + } TRACE("RegisterBuffer: done, bufferID = %ld\n", info.id); + *_bufferID = info.id; return B_OK; } @@ -100,12 +107,12 @@ status_t BufferManager::UnregisterBuffer(team_id team, media_buffer_id bufferID) { BAutolock lock(fLocker); - TRACE("UnregisterBuffer: team = %ld, bufferid = %ld\n", team, bufferID); + TRACE("UnregisterBuffer: team = %ld, bufferID = %ld\n", team, bufferID); buffer_info* info; if (!fBufferInfoMap.Get(bufferID, info)) { ERROR("UnregisterBuffer: failed to unregister buffer! team = %ld, " - "bufferid = %ld\n", team, bufferID); + "bufferID = %ld\n", team, bufferID); return B_ERROR; } @@ -114,7 +121,7 @@ BufferManager::UnregisterBuffer(team_id team, media_buffer_id bufferID) "bufferID = %ld\n", team, bufferID); return B_ERROR; } - + info->teams.erase(team); TRACE("UnregisterBuffer: team = %ld removed from bufferID = %ld\n", team, @@ -146,7 +153,7 @@ BufferManager::CleanupTeam(team_id team) if (entry.value.teams.empty()) { PRINT(1, "BufferManager::CleanupTeam: removing buffer id %ld that " - "has no teams\n", entry.key); + "has no teams\n", entry.key.GetHashCode()); _ReleaseClonedArea(entry.value.area); iterator.Remove(); } @@ -182,14 +189,16 @@ BufferManager::Dump() area_id BufferManager::_CloneArea(area_id area) { - clone_info* info; - if (fCloneInfoMap.Get(area, info)) { - // we have already cloned this particular area - TRACE("BufferManager::_CloneArea() area %ld has already been cloned " - "(id %ld)\n", area, info->clone); + { + clone_info* info; + if (fCloneInfoMap.Get(area, info)) { + // we have already cloned this particular area + TRACE("BufferManager::_CloneArea() area %ld has already been " + "cloned (id %ld)\n", area, info->clone); - info->ref_count++; - return info->clone; + info->ref_count++; + return info->clone; + } } void* address; @@ -199,16 +208,22 @@ BufferManager::_CloneArea(area_id area) TRACE("BufferManager::_CloneArea() cloned area %ld, clone id %ld\n", area, clonedArea); - if (clonedArea >= 0) { - clone_info info; - info.clone = clonedArea; - info.ref_count = 1; + if (clonedArea < 0) + return clonedArea; - fCloneInfoMap.Put(area, info); - fSourceInfoMap.Put(clonedArea, area); + clone_info info; + info.clone = clonedArea; + info.ref_count = 1; + + if (fCloneInfoMap.Put(area, info) == B_OK) { + if (fSourceInfoMap.Put(clonedArea, area) == B_OK) + return clonedArea; + + fCloneInfoMap.Remove(area); } - return clonedArea; + delete_area(clonedArea); + return B_NO_MEMORY; } diff --git a/src/servers/media/BufferManager.h b/src/servers/media/BufferManager.h index 41a9ecfa25..3ce688ba3f 100644 --- a/src/servers/media/BufferManager.h +++ b/src/servers/media/BufferManager.h @@ -1,4 +1,4 @@ -/* +/* * Copyright 2002, Marcus Overhagen. All rights reserved. * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. @@ -13,16 +13,18 @@ #include -struct _shared_buffer_list; +namespace BPrivate { + class SharedBufferList; +} class BufferManager { public: BufferManager(); ~BufferManager(); - - area_id SharedBufferListID(); - + + area_id SharedBufferListArea(); + status_t RegisterBuffer(team_id team, media_buffer_id bufferID, size_t* _size, int32* _flags, size_t* _offset, area_id* _area); @@ -56,7 +58,7 @@ private: int32 flags; std::set teams; }; - + template struct id_hash { id_hash() : @@ -84,7 +86,7 @@ private: { return fID; } - + id_hash& operator=(const id_hash& other) { fID = other.fID; @@ -99,8 +101,8 @@ private: typedef HashMap, clone_info> CloneInfoMap; typedef HashMap, area_id> SourceInfoMap; - _shared_buffer_list* fSharedBufferList; - area_id fSharedBufferListID; + BPrivate::SharedBufferList* fSharedBufferList; + area_id fSharedBufferListArea; media_buffer_id fNextBufferID; BLocker fLocker; BufferInfoMap fBufferInfoMap; diff --git a/src/servers/media/DefaultManager.cpp b/src/servers/media/DefaultManager.cpp index 8896cb5e90..decf4188b0 100644 --- a/src/servers/media/DefaultManager.cpp +++ b/src/servers/media/DefaultManager.cpp @@ -1,7 +1,11 @@ -/* +/* * Copyright 2002, 2003 Marcus Overhagen, Jérôme Duval. All rights reserved. * Distributed under the terms of the MIT License. */ + + +#include "DefaultManager.h" + #include #include #include @@ -12,7 +16,7 @@ #include #include #include -#include "DefaultManager.h" + #include "DormantNodeManager.h" #include "NodeManager.h" #include "debug.h" @@ -74,12 +78,12 @@ DefaultManager::LoadState() BPath path; if((err = find_directory(B_USER_SETTINGS_DIRECTORY, &path))!=B_OK) return err; - + path.Append(kDefaultManagerSettingsDirectory); path.Append(kDefaultManagerSettingsFile); - + BFile file(path.Path(), B_READ_ONLY); - + uint32 category_count; if (file.Read(fBeginHeader, sizeof(uint32)*3) < (int32)sizeof(uint32)*3) return B_ERROR; @@ -119,20 +123,20 @@ DefaultManager::SaveState(NodeManager *node_manager) if ((err = create_directory(path.Path(), 0755)) != B_OK) return err; path.Append(kDefaultManagerSettingsFile); - + BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE); - + uint32 default_types[] = {kMsgTypeVideoIn, kMsgTypeVideoOut, kMsgTypeAudioIn, kMsgTypeAudioOut}; uint32 media_node_ids[] = {fPhysicalVideoIn, fPhysicalVideoOut, fPhysicalAudioIn, fPhysicalAudioOut}; for (uint32 i=0; iAddInt32(kDefaultManagerType, default_types[i]); - + // we call the node manager to have more infos about nodes dormant_node_info info; media_node node; entry_ref ref; - if (node_manager->GetCloneForId(&node, media_node_ids[i], be_app->Team()) != B_OK) + if (node_manager->GetCloneForID(&node, media_node_ids[i], be_app->Team()) != B_OK) continue; if (node_manager->GetDormantNodeInfo(&info, node) != B_OK) continue; @@ -147,17 +151,17 @@ DefaultManager::SaveState(NodeManager *node_manager) settings->AddInt32(kDefaultManagerInput, default_types[i] == kMsgTypeAudioOut ? fPhysicalAudioOutInputID : 0); settings->AddString(kDefaultManagerFlavorName, info.name); settings->AddString(kDefaultManagerPath, path.Path()); - + list.AddItem(settings); TRACE("message %s added\n", info.name); } - + if (file.Write(fBeginHeader, sizeof(uint32)*3) < (int32)sizeof(uint32)*3) return B_ERROR; int32 category_count = list.CountItems(); if (file.Write(&category_count, sizeof(uint32)) < (int32)sizeof(uint32)) return B_ERROR; - + for (int32 i = 0; i < category_count; i++) { BMessage *settings = (BMessage *)list.ItemAt(i); uint32 default_type; @@ -173,7 +177,7 @@ DefaultManager::SaveState(NodeManager *node_manager) } if (file.Write(fEndHeader, sizeof(uint32)*3) < (int32)sizeof(uint32)*3) return B_ERROR; - + return B_OK; } @@ -201,14 +205,14 @@ DefaultManager::Set(media_node_id node_id, const char *input_name, int32 input_i return B_OK; case TIME_SOURCE: return B_ERROR; - + case SYSTEM_TIME_SOURCE: //called by the media_server's ServerApp::StartSystemTimeSource() { ASSERT(fSystemTimeSource == -1); fSystemTimeSource = node_id; return B_OK; } - + default: { ERROR("DefaultManager::Set Error: called with unknown type %d\n", type); @@ -233,7 +237,7 @@ DefaultManager::Get(media_node_id *nodeid, char *input_name, int32 *inputid, nod return B_NAME_NOT_FOUND; *nodeid = fPhysicalAudioIn; return B_OK; - + case VIDEO_OUTPUT: // output: nodeid if (fPhysicalVideoOut == -1) return B_NAME_NOT_FOUND; @@ -266,7 +270,7 @@ DefaultManager::Get(media_node_id *nodeid, char *input_name, int32 *inputid, nod else *nodeid = fSystemTimeSource; return B_OK; - + case SYSTEM_TIME_SOURCE: *nodeid = fSystemTimeSource; return B_OK; @@ -299,7 +303,7 @@ void DefaultManager::RescanThread() { printf("DefaultManager::RescanThread() enter\n"); - + // We do not search for the system time source, // it should already exist ASSERT(fSystemTimeSource != -1); @@ -307,7 +311,7 @@ DefaultManager::RescanThread() if (fPhysicalVideoOut == -1) { FindPhysical(&fPhysicalVideoOut, kMsgTypeVideoOut, false, B_MEDIA_RAW_VIDEO); FindPhysical(&fPhysicalVideoOut, kMsgTypeVideoOut, false, B_MEDIA_ENCODED_VIDEO); - } + } if (fPhysicalVideoIn == -1) { FindPhysical(&fPhysicalVideoIn, kMsgTypeVideoIn, true, B_MEDIA_RAW_VIDEO); FindPhysical(&fPhysicalVideoIn, kMsgTypeVideoIn, true, B_MEDIA_ENCODED_VIDEO); @@ -332,7 +336,7 @@ DefaultManager::RescanThread() } else { ERROR("DefaultManager: Did not try to connect mixer and soundcard\n"); } - + addonserver_rescan_finished_notify_command cmd; SendToAddonServer(ADDONSERVER_RESCAN_FINISHED_NOTIFY, &cmd, sizeof(cmd)); @@ -375,8 +379,8 @@ DefaultManager::FindPhysical(volatile media_node_id *id, uint32 default_type, bo memset(&format, 0, sizeof(format)); format.type = type; count = MAX_NODE_INFOS; - rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, - isInput ? NULL : &format, isInput ? &format : NULL, NULL, + rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, + isInput ? NULL : &format, isInput ? &format : NULL, NULL, isInput ? B_BUFFER_PRODUCER | B_PHYSICAL_INPUT : B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT); if (rv != B_OK || count < 1) { ERROR("Couldn't find physical %s %s node\n", isAudio ? "audio" : "video", isInput ? "input" : "output"); @@ -384,7 +388,7 @@ DefaultManager::FindPhysical(volatile media_node_id *id, uint32 default_type, bo } for (int i = 0; i < count; i++) TRACE("info[%d].name %s\n", i, info[i].name); - + for (int i = 0; i < count; i++) { if (isAudio) { if (isInput) { @@ -406,7 +410,7 @@ DefaultManager::FindPhysical(volatile media_node_id *id, uint32 default_type, bo if (0 == strcmp(info[i].name, "DV Output")) // skip the Firewire audio driver continue; } - } + } if(msg) { // we have a default info msg dormant_node_info dninfo; if(BMediaRoster::Roster()->GetDormantNodeFor(info[i].node, &dninfo) != B_OK) { @@ -419,13 +423,13 @@ DefaultManager::FindPhysical(volatile media_node_id *id, uint32 default_type, bo continue; } BPath path; - if((_DormantNodeManager->FindAddonPath(&path, dninfo.addon)!=B_OK) + if((_DormantNodeManager->FindAddonPath(&path, dninfo.addon)!=B_OK) || (path != msgPath)) { ERROR("Doesn't match : path\n"); continue; } } - TRACE("Default physical %s %s \"%s\" created!\n", + TRACE("Default physical %s %s \"%s\" created!\n", isAudio ? "audio" : "video", isInput ? "input" : "output", info[i].name); *id = info[i].node.node; if(msg && isAudio && !isInput) @@ -442,7 +446,7 @@ DefaultManager::FindTimeSource() media_format input; /* a physical audio output has a logical data input (DAC)*/ int32 count; status_t rv; - + /* First try to use the current default physical audio out */ if (fPhysicalAudioOut != -1) { @@ -462,7 +466,7 @@ DefaultManager::FindTimeSource() } else { printf("Default DAC node does not exist!\n"); } - + /* Now try to find another physical audio out node */ memset(&input, 0, sizeof(input)); @@ -472,7 +476,7 @@ DefaultManager::FindTimeSource() if (rv == B_OK && count >= 1) { for (int i = 0; i < count; i++) printf("info[%d].name %s\n", i, info[i].name); - + for (int i = 0; i < count; i++) { // The BeOS R5 None Out node pretend to be a physical time source, that is pretty dumb if (0 == strcmp(info[i].name, "None Out")) // skip the Null audio driver @@ -486,8 +490,8 @@ DefaultManager::FindTimeSource() } } else { printf("Couldn't find DAC timesource node\n"); - } - + } + /* XXX we might use other audio or video clock timesources */ } @@ -526,7 +530,7 @@ DefaultManager::ConnectMixerToOutput() bigtime_t start_at; int32 count; status_t rv; - + roster = BMediaRoster::Roster(); rv = roster->GetNodeFor(fPhysicalAudioOut, &soundcard); @@ -558,13 +562,13 @@ DefaultManager::ConnectMixerToOutput() rv = B_ERROR; goto finish; } - + for (int32 i = 0; i < count; i++) { input = inputs[i]; if(input.destination.id == fPhysicalAudioOutInputID) break; } - + for (int i = 0; i < 6; i++) { switch (i) { case 0: @@ -636,13 +640,13 @@ DefaultManager::ConnectMixerToOutput() roster->SetTimeSourceFor(soundcard.node, timesource.node); roster->PrerollNode(mixer); roster->PrerollNode(soundcard); - + ts = roster->MakeTimeSourceFor(mixer); start_at = ts->Now() + 50000; roster->StartNode(mixer, start_at); roster->StartNode(soundcard, start_at); ts->Release(); - + finish: roster->ReleaseNode(mixer); roster->ReleaseNode(soundcard); diff --git a/src/servers/media/NodeManager.cpp b/src/servers/media/NodeManager.cpp index 8f55e3cf7e..cb39afd610 100644 --- a/src/servers/media/NodeManager.cpp +++ b/src/servers/media/NodeManager.cpp @@ -77,7 +77,7 @@ NodeManager::RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32 BAutolock lock(fLocker); bool b; registered_node rn; - rn.nodeid = fNextNodeID; + rn.node_id = fNextNodeID; rn.addon_id = addon_id; rn.addon_flavor_id = addon_flavor_id; strcpy(rn.name, name); @@ -87,7 +87,7 @@ NodeManager::RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32 rn.creator = -1; // will be set later rn.globalrefcount = 1; rn.teamrefcount.Insert(team, 1); - + b = fRegisteredNodeMap->Insert(fNextNodeID, rn); ASSERT(b); *nodeid = fNextNodeID; @@ -194,12 +194,12 @@ NodeManager::DecrementGlobalRefCount(media_node_id nodeid, team_id team) ASSERT(b); } rn->globalrefcount -= 1; - + if (rn->globalrefcount == 0) { printf("NodeManager::DecrementGlobalRefCount: detected released node is now unused, node %ld\n", nodeid); FinalReleaseNode(nodeid); } - + TRACE("NodeManager::DecrementGlobalRefCount leave: node %ld, team %ld, count %ld, globalcount %ld\n", nodeid, team, debug_count, rn->globalrefcount); return B_OK; } @@ -218,12 +218,12 @@ NodeManager::SetNodeCreator(media_node_id nodeid, team_id creator) ERROR("NodeManager::SetNodeCreator: node %ld not found\n", nodeid); return B_ERROR; } - + if (rn->creator != -1) { ERROR("NodeManager::SetNodeCreator: node %ld is already assigned creator %ld\n", nodeid, rn->creator); return B_ERROR; } - + rn->creator = creator; return B_OK; } @@ -253,47 +253,52 @@ NodeManager::FinalReleaseNode(media_node_id nodeid) status_t -NodeManager::GetCloneForId(media_node *node, media_node_id nodeid, team_id team) +NodeManager::GetCloneForID(media_node* node, media_node_id nodeID, team_id team) { BAutolock lock(fLocker); - registered_node *rn; - bool b; - TRACE("NodeManager::GetCloneForId enter: node %ld team %ld\n", nodeid, team); + TRACE("NodeManager::GetCloneForID enter: node %ld team %ld\n", nodeID, + team); - if (B_OK != IncrementGlobalRefCount(nodeid, team)) { - ERROR("NodeManager::GetCloneForId: couldn't increment ref count, node %ld team %ld\n", nodeid, team); + if (IncrementGlobalRefCount(nodeID, team) != B_OK) { + ERROR("NodeManager::GetCloneForID: couldn't increment ref count, " + "node %ld team %ld\n", nodeID, team); return B_ERROR; } - b = fRegisteredNodeMap->Get(nodeid, &rn); - if (!b) { - ERROR("NodeManager::GetCloneForId: node %ld not found\n", nodeid); - DecrementGlobalRefCount(nodeid, team); + registered_node* registeredNode; + if (!fRegisteredNodeMap->Get(nodeID, ®isteredNode)) { + ERROR("NodeManager::GetCloneForID: node %ld not found\n", nodeID); + DecrementGlobalRefCount(nodeID, team); return B_ERROR; } - node->node = rn->nodeid; - node->port = rn->port; - node->kind = rn->kinds; + node->node = registeredNode->node_id; + node->port = registeredNode->port; + node->kind = registeredNode->kinds; - TRACE("NodeManager::GetCloneForId leave: node %ld team %ld\n", nodeid, team); + TRACE("NodeManager::GetCloneForID leave: node %ld team %ld\n", nodeID, + team); return B_OK; } -/* This function locates the default "node" for the requested "type" and returnes a clone. - * If the requested type is AUDIO_OUTPUT_EX, also "input_name" and "input_id" need to be set and returned, - * as this is required by BMediaRoster::GetAudioOutput(media_node *out_node, int32 *out_input_id, BString *out_input_name) - */ +/*! This function locates the default "node" for the requested "type" and + returns a clone. + If the requested type is AUDIO_OUTPUT_EX, also "input_name" and "input_id" + need to be set and returned, as this is required by + BMediaRoster::GetAudioOutput(media_node *out_node, int32 *out_input_id, + BString *out_input_name). +*/ status_t -NodeManager::GetClone(media_node *node, char *input_name, int32 *input_id, node_type type, team_id team) +NodeManager::GetClone(media_node *node, char *input_name, int32 *input_id, + node_type type, team_id team) { BAutolock lock(fLocker); status_t status; media_node_id id; TRACE("NodeManager::GetClone enter: team %ld, type %d (%s)\n", team, type, get_node_type(type)); - + status = GetDefaultNode(&id, input_name, input_id, type); if (status != B_OK) { ERROR("NodeManager::GetClone: couldn't GetDefaultNode, team %ld, type %d (%s)\n", team, type, get_node_type(type)); @@ -302,9 +307,9 @@ NodeManager::GetClone(media_node *node, char *input_name, int32 *input_id, node_ } ASSERT(id > 0); - status = GetCloneForId(node, id, team); + status = GetCloneForID(node, id, team); if (status != B_OK) { - ERROR("NodeManager::GetClone: couldn't GetCloneForId, id %ld, team %ld, type %d (%s)\n", id, team, type, get_node_type(type)); + ERROR("NodeManager::GetClone: couldn't GetCloneForID, id %ld, team %ld, type %d (%s)\n", id, team, type, get_node_type(type)); *node = media_node::null; return status; } @@ -366,37 +371,39 @@ NodeManager::PublishOutputs(const media_node &node, const media_output *outputs, status_t -NodeManager::FindNodeId(media_node_id *nodeid, port_id port) +NodeManager::FindNodeID(media_node_id* nodeID, port_id port) { BAutolock lock(fLocker); registered_node *rn; for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { if (rn->port == port) { - *nodeid = rn->nodeid; - TRACE("NodeManager::FindNodeId found port %ld, node %ld\n", port, *nodeid); + *nodeID = rn->node_id; + TRACE("NodeManager::FindNodeID found port %ld, node %ld\n", port, + *nodeID); return B_OK; } media_output *output; for (rn->outputlist.Rewind(); rn->outputlist.GetNext(&output); ) { if (output->source.port == port) { - *nodeid = rn->nodeid; - TRACE("NodeManager::FindNodeId found output port %ld, node %ld\n", port, *nodeid); + *nodeID = rn->node_id; + TRACE("NodeManager::FindNodeID found output port %ld, node %ld\n", port, *nodeid); return B_OK; } } media_input *input; for (rn->inputlist.Rewind(); rn->inputlist.GetNext(&input); ) { if (input->destination.port == port) { - *nodeid = rn->nodeid; - TRACE("NodeManager::FindNodeId found input port %ld, node %ld\n", port, *nodeid); + *nodeID = rn->node_id; + TRACE("NodeManager::FindNodeID found input port %ld, node %ld\n", port, *nodeid); return B_OK; } } } - ERROR("NodeManager::FindNodeId failed, port %ld\n", port); + ERROR("NodeManager::FindNodeID failed, port %ld\n", port); return B_ERROR; } + status_t NodeManager::GetDormantNodeInfo(dormant_node_info *node_info, const media_node &node) { @@ -404,7 +411,7 @@ NodeManager::GetDormantNodeInfo(dormant_node_info *node_info, const media_node & // XXX not sure if this is correct registered_node *rn; for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { - if (rn->nodeid == node.node) { + if (rn->node_id == node.node) { if (rn->addon_id == -1 && node.node != NODE_SYSTEM_TIMESOURCE_ID) { // This function must return an error if the node is application owned TRACE("NodeManager::GetDormantNodeInfo NODE IS APPLICATION OWNED! node %ld, addon_id %ld, addon_flavor_id %ld, name \"%s\"\n", node.node, rn->addon_id, rn->addon_flavor_id, rn->name); return B_ERROR; @@ -422,13 +429,14 @@ NodeManager::GetDormantNodeInfo(dormant_node_info *node_info, const media_node & return B_ERROR; } + status_t NodeManager::GetLiveNodeInfo(live_node_info *live_info, const media_node &node) { BAutolock lock(fLocker); registered_node *rn; for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { - if (rn->nodeid == node.node) { + if (rn->node_id == node.node) { ASSERT(node.port == rn->port); ASSERT((node.kind & NODE_KIND_COMPARE_MASK) == (rn->kinds & NODE_KIND_COMPARE_MASK)); live_info->node = node; @@ -451,7 +459,7 @@ NodeManager::GetInstances(media_node_id *node_ids, int32* count, int32 maxcount, *count = 0; for (fRegisteredNodeMap->Rewind(); (maxcount > 0) && fRegisteredNodeMap->GetNext(&rn); ) { if (rn->addon_id == addon_id && rn->addon_flavor_id == addon_flavor_id) { - node_ids[*count] = rn->nodeid; + node_ids[*count] = rn->node_id; *count += 1; maxcount -= 1; } @@ -467,7 +475,7 @@ NodeManager::GetLiveNodes(Stack *livenodes, int32 maxcount, cons BAutolock lock(fLocker); registered_node *rn; int namelen; - + TRACE("NodeManager::GetLiveNodes: maxcount %ld, in-format %p, out-format %p, name %s, require_kinds 0x%Lx\n", maxcount, inputformat, outputformat, (name ? name : "NULL"), require_kinds); @@ -513,7 +521,7 @@ NodeManager::GetLiveNodes(Stack *livenodes, int32 maxcount, cons } live_node_info lni; - lni.node.node = rn->nodeid; + lni.node.node = rn->node_id; lni.node.port = rn->port; lni.node.kind = rn->kinds; lni.hint_point = BPoint(0, 0); @@ -526,16 +534,17 @@ NodeManager::GetLiveNodes(Stack *livenodes, int32 maxcount, cons return B_OK; } -/* Add media_node_id of all live nodes to the message - * int32 "media_node_id" (multiple items) - */ + +/*! Add media_node_id of all live nodes to the message + int32 "media_node_id" (multiple items) +*/ status_t NodeManager::GetLiveNodes(BMessage *msg) { BAutolock lock(fLocker); registered_node *rn; for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { - msg->AddInt32("media_node_id", rn->nodeid); + msg->AddInt32("media_node_id", rn->node_id); } return B_OK; } @@ -544,16 +553,16 @@ NodeManager::GetLiveNodes(BMessage *msg) * Registration of BMediaAddOns **********************************************************************/ -void +void NodeManager::RegisterAddon(const entry_ref &ref, media_addon_id *newid) { BAutolock lock(fLocker); media_addon_id id; id = fNextAddOnID; fNextAddOnID += 1; - + printf("NodeManager::RegisterAddon: ref-name \"%s\", assigning id %ld\n", ref.name, id); - + fAddonPathMap->Insert(id, ref); *newid = id; } @@ -579,7 +588,7 @@ NodeManager::GetAddonRef(entry_ref *ref, media_addon_id id) *ref = *tempref; return B_OK; } - + return B_ERROR; } @@ -592,7 +601,7 @@ void NodeManager::AddDormantFlavorInfo(const dormant_flavor_info &dfi) { BAutolock lock(fLocker); - + printf("NodeManager::AddDormantFlavorInfo, addon-id %ld, flavor-id %ld, name \"%s\", flavor-name \"%s\", flavor-info \"%s\"\n", dfi.node_info.addon, dfi.node_info.flavor_id, dfi.node_info.name, dfi.name, dfi.info); // Try to find the addon-id/flavor-id in the list. @@ -670,8 +679,8 @@ NodeManager::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 fl ERROR("NodeManager::IncrementAddonFlavorInstancesCount addonid %ld, flavorid %ld maximum (or more) instances already exist\n", addonid, flavorid); return B_ERROR; // maximum (or more) instances already exist } - - bool b; + + bool b; int32 *count; b = dafi->TeamInstancesCount.Get(team, &count); if (b) { @@ -697,7 +706,7 @@ NodeManager::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 fl if (dafi->AddonID != addonid || dafi->AddonFlavorID != flavorid) continue; - bool b; + bool b; int32 *count; b = dafi->TeamInstancesCount.Get(team, &count); if (!b) { @@ -728,7 +737,7 @@ NodeManager::CleanupDormantFlavorInfos() // XXX FlavorsChanged(media_addon_id addonid, int32 newcount, int32 gonecount) } -status_t +status_t NodeManager::GetDormantNodes(dormant_node_info * out_info, int32 * io_count, const media_format * has_input /* = NULL */, @@ -751,7 +760,7 @@ NodeManager::GetDormantNodes(dormant_node_info * out_info, namelen = 0; } - maxcount = *io_count; + maxcount = *io_count; *io_count = 0; for (fDormantAddonFlavorList->Rewind(); (*io_count < maxcount) && fDormantAddonFlavorList->GetNext(&dafi); ) { if (!dafi->InfoValid) @@ -788,7 +797,7 @@ NodeManager::GetDormantNodes(dormant_node_info * out_info, if (!hasit) continue; } - + out_info[*io_count] = dfi->node_info; *io_count += 1; } @@ -796,7 +805,7 @@ NodeManager::GetDormantNodes(dormant_node_info * out_info, return B_OK; } -status_t +status_t NodeManager::GetDormantFlavorInfoFor(media_addon_id addon, int32 flavor_id, dormant_flavor_info *outFlavor) @@ -807,7 +816,7 @@ NodeManager::GetDormantFlavorInfoFor(media_addon_id addon, if (dafi->AddonID == addon && dafi->AddonFlavorID == flavor_id && dafi->InfoValid == true) { *outFlavor = dafi->Info; return B_OK; - } + } } return B_ERROR; } @@ -867,9 +876,9 @@ NodeManager::CleanupTeam(team_id team) PRINT(1, "NodeManager::CleanupTeam: team %ld\n", team); // XXX send notifications after removing nodes - + // Cleanup node references - + registered_node *rn; for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { // if the gone team was the creator of some global dormant node instance, we now invalidate that @@ -901,11 +910,11 @@ NodeManager::CleanupTeam(team_id team) fRegisteredNodeMap->RemoveCurrent(); } } - + // Cleanup addon references dormant_addon_flavor_info *dafi; for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) { - bool b; + bool b; int32 *count; b = dafi->TeamInstancesCount.Get(team, &count); if (b) { @@ -946,7 +955,7 @@ NodeManager::Dump() { BAutolock lock(fLocker); printf("\n"); - + /* for each addon-id, the addon path map contains an entry_ref */ printf("NodeManager: addon path map follows:\n"); @@ -966,7 +975,7 @@ NodeManager::Dump() registered_node *rn; for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { printf(" node-id %ld, addon-id %ld, addon-flavor-id %ld, port %ld, creator %ld, team %ld, kinds %#08Lx, name \"%s\"\n", - rn->nodeid, rn->addon_id, rn->addon_flavor_id, rn->port, rn->creator, rn->team, rn->kinds, rn->name); + rn->node_id, rn->addon_id, rn->addon_flavor_id, rn->port, rn->creator, rn->team, rn->kinds, rn->name); printf(" teams (refcount): "); team_id *team; int32 *refcount; @@ -993,7 +1002,7 @@ NodeManager::Dump() printf("NodeManager: list end\n"); printf("\n"); - /* + /* */ printf("NodeManager: dormant flavor list follows:\n"); dormant_addon_flavor_info *dafi; diff --git a/src/servers/media/NodeManager.h b/src/servers/media/NodeManager.h index e9bc53de09..8c21022e5b 100644 --- a/src/servers/media/NodeManager.h +++ b/src/servers/media/NodeManager.h @@ -1,4 +1,4 @@ -/* +/* * Copyright 2002, Marcus Overhagen. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -10,7 +10,7 @@ struct registered_node { - media_node_id nodeid; + media_node_id node_id; media_addon_id addon_id; int32 addon_flavor_id; char name[B_MEDIA_NAME_LENGTH]; @@ -26,11 +26,11 @@ struct registered_node { struct dormant_addon_flavor_info { media_addon_id AddonID; - int32 AddonFlavorID; + int32 AddonFlavorID; int32 MaxInstancesCount; int32 GlobalInstancesCount; - + Map TeamInstancesCount; bool InfoValid; @@ -47,23 +47,24 @@ public: status_t LoadState(); status_t SaveState(); - + void Dump(); /* Management of system wide default nodes */ status_t SetDefaultNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input); - status_t GetDefaultNode(media_node_id *nodeid, char *input_name, int32 *input_id, node_type type); + status_t GetDefaultNode(media_node_id* nodeID, char* name, int32* id, + node_type type); status_t RescanDefaultNodes(); /* Management of live nodes */ status_t RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32 addon_flavor_id, const char *name, uint64 kinds, port_id port, team_id team); status_t UnregisterNode(media_addon_id *addonid, int32 *flavorid, media_node_id nodeid, team_id team); - status_t GetCloneForId(media_node *node, media_node_id nodeid, team_id team); + status_t GetCloneForID(media_node* node, media_node_id nodeID, team_id team); status_t GetClone(media_node *node, char *input_name, int32 *input_id, node_type type, team_id team); status_t ReleaseNode(const media_node &node, team_id team); status_t PublishInputs(const media_node &node, const media_input *inputs, int32 count); status_t PublishOutputs(const media_node &node, const media_output *outputs, int32 count); - status_t FindNodeId(media_node_id *nodeid, port_id port); + status_t FindNodeID(media_node_id* nodeID, port_id port); status_t GetLiveNodeInfo(live_node_info *live_info, const media_node &node); status_t GetInstances(media_node_id *node_ids, int32* count, int32 maxcount, media_addon_id addon_id, int32 addon_flavor_id); status_t GetLiveNodes(Stack *livenodes, int32 maxcount, const media_format *inputformat = NULL, const media_format *outputformat = NULL, const char* name = NULL, uint64 require_kinds = 0); @@ -80,8 +81,8 @@ public: void RegisterAddon(const entry_ref &ref, media_addon_id *newid); void UnregisterAddon(media_addon_id id); - - void AddDormantFlavorInfo(const dormant_flavor_info &dfi); + + void AddDormantFlavorInfo(const dormant_flavor_info &dfi); void InvalidateDormantFlavorInfo(media_addon_id id); void RemoveDormantFlavorInfo(media_addon_id id); void CleanupDormantFlavorInfos(); @@ -103,11 +104,11 @@ public: dormant_flavor_info *outFlavor); void CleanupTeam(team_id team); - + private: media_addon_id fNextAddOnID; media_node_id fNextNodeID; - + BLocker *fLocker; List *fDormantAddonFlavorList; Map *fAddonPathMap; diff --git a/src/servers/media/ServerInterface.h b/src/servers/media/ServerInterface.h deleted file mode 100644 index 23da9f84f5..0000000000 --- a/src/servers/media/ServerInterface.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _SERVER_INTERFACE_H_ -#define _SERVER_INTERFACE_H_ - -#include -#include -#include -#include - -enum { - ADDONSERVER_INSTANTIATE_DORMANT_NODE, - SERVER_REGISTER_MEDIAADDON, - SERVER_UNREGISTER_MEDIAADDON, - SERVER_GET_MEDIAADDON_REF, - SERVER_REGISTER_DORMANT_NODE, - SERVER_GET_DORMANT_NODES, - SERVER_GET_DORMANT_FLAVOR_INFO, - END -}; - -struct xfer_server_get_dormant_flavor_info -{ - media_addon_id addon; - int32 flavor_id; - port_id reply_port; -}; - -struct xfer_server_get_dormant_flavor_info_reply -{ - status_t result; - type_code dfi_type; // the flatten type_code - size_t dfi_size; - char dfi[1]; // a flattened dormant_flavor_info, dfi_size large -}; - -struct xfer_server_get_dormant_nodes -{ - int32 maxcount; - bool has_input; - media_format inputformat; - bool has_output; - media_format outputformat; - bool has_name; - char name[B_MEDIA_NAME_LENGTH + 1]; // 1 for a trailing "*" - uint64 require_kinds; - uint64 deny_kinds; - port_id reply_port; -}; - -struct xfer_server_get_dormant_nodes_reply -{ - status_t result; - int32 count; // if count > 0, a second reply containing count dormant_node_infos is send -}; - -struct xfer_server_register_dormant_node -{ - media_addon_id purge_id; // if > 0, server must first remove all dormant_flavor_infos belonging to that id - type_code dfi_type; // the flatten type_code - size_t dfi_size; - char dfi[1]; // a flattened dormant_flavor_info, dfi_size large -}; - -#endif diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index ec21c354dd..0ce2a309e5 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -27,10 +27,15 @@ * */ + /* to comply with the license above, do not remove the following line */ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 " "Marcus Overhagen "; + +#include +#include + #include #include #include @@ -40,9 +45,6 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 " #include #include -#include -#include - #include "AddOnManager.h" #include "AppManager.h" #include "BufferManager.h" @@ -56,12 +58,6 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 " #include "debug.h" #include "media_server.h" -/* - * - * An implementation of a new media_server for the OpenBeOS MediaKit - * Started by Marcus Overhagen on 2001-10-25 - * - */ AddOnManager * gAddOnManager; AppManager * gAppManager; @@ -217,7 +213,7 @@ ServerApp::ArgvReceived(int32 argc, char **argv) void ServerApp::StartAddonServer() -{ +{ // Try to launch media_addon_server by mime signature. // If it fails (for example on the Live CD, where the executable // hasn't yet been mimesetted), try from this application's @@ -225,7 +221,7 @@ ServerApp::StartAddonServer() status_t err = be_roster->Launch(B_MEDIA_ADDON_SERVER_SIGNATURE); if (err == B_OK) return; - + app_info info; BEntry entry; BDirectory dir; @@ -310,10 +306,10 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) ASSERT(request->delta == 1 || request->delta == -1); if (request->delta == 1) { rv = gNodeManager->IncrementAddonFlavorInstancesCount( - request->addonid, request->flavorid, request->team); + request->addon_id, request->flavor_id, request->team); } else { rv = gNodeManager->DecrementAddonFlavorInstancesCount( - request->addonid, request->flavorid, request->team); + request->addon_id, request->flavor_id, request->team); } request->SendReply(rv, &reply, sizeof(reply)); break; @@ -352,7 +348,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) = (server_get_mediaaddon_ref_request *)data; server_get_mediaaddon_ref_reply reply; entry_ref tempref; - reply.result = gNodeManager->GetAddonRef(&tempref, msg->addonid); + reply.result = gNodeManager->GetAddonRef(&tempref, msg->addon_id); reply.ref = tempref; write_port(msg->reply_port, 0, &reply, sizeof(reply)); break; @@ -363,7 +359,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) const server_node_id_for_request *request = reinterpret_cast(data); server_node_id_for_reply reply; - rv = gNodeManager->FindNodeId(&reply.nodeid, request->port); + rv = gNodeManager->FindNodeID(&reply.node_id, request->port); request->SendReply(rv, &reply, sizeof(reply)); break; } @@ -432,7 +428,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) const server_get_node_for_request *request = reinterpret_cast(data); server_get_node_for_reply reply; - rv = gNodeManager->GetCloneForId(&reply.clone, request->nodeid, + rv = gNodeManager->GetCloneForID(&reply.clone, request->node_id, request->team); request->SendReply(rv, &reply, sizeof(reply)); break; @@ -453,7 +449,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) const server_register_node_request *request = reinterpret_cast(data); server_register_node_reply reply; - rv = gNodeManager->RegisterNode(&reply.nodeid, request->addon_id, + rv = gNodeManager->RegisterNode(&reply.node_id, request->addon_id, request->addon_flavor_id, request->name, request->kinds, request->port, request->team); request->SendReply(rv, &reply, sizeof(reply)); @@ -466,8 +462,8 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) = reinterpret_cast( data); server_unregister_node_reply reply; - rv = gNodeManager->UnregisterNode(&reply.addonid, &reply.flavorid, - request->nodeid, request->team); + rv = gNodeManager->UnregisterNode(&reply.addon_id, &reply.flavor_id, + request->node_id, request->team); request->SendReply(rv, &reply, sizeof(reply)); break; } @@ -588,7 +584,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) server_register_mediaaddon_request *msg = (server_register_mediaaddon_request *)data; server_register_mediaaddon_reply reply; - gNodeManager->RegisterAddon(msg->ref, &reply.addonid); + gNodeManager->RegisterAddon(msg->ref, &reply.addon_id); write_port(msg->reply_port, 0, &reply, sizeof(reply)); break; } @@ -597,20 +593,22 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) { server_unregister_mediaaddon_command *msg = (server_unregister_mediaaddon_command *)data; - gNodeManager->UnregisterAddon(msg->addonid); + gNodeManager->UnregisterAddon(msg->addon_id); break; } case SERVER_REGISTER_DORMANT_NODE: { - xfer_server_register_dormant_node *msg - = (xfer_server_register_dormant_node *)data; - dormant_flavor_info dfi; + xfer_server_register_dormant_node* msg + = (xfer_server_register_dormant_node*)data; if (msg->purge_id > 0) gNodeManager->InvalidateDormantFlavorInfo(msg->purge_id); - rv = dfi.Unflatten(msg->dfi_type, &(msg->dfi), msg->dfi_size); - ASSERT(rv == B_OK); - gNodeManager->AddDormantFlavorInfo(dfi); + + dormant_flavor_info dormantFlavorInfo; + status_t status = dormantFlavorInfo.Unflatten(msg->type, + msg->flattened_data, msg->flattened_size); + if (status == B_OK) + gNodeManager->AddDormantFlavorInfo(dormantFlavorInfo); break; } @@ -618,24 +616,29 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) { xfer_server_get_dormant_nodes *msg = (xfer_server_get_dormant_nodes *)data; + xfer_server_get_dormant_nodes_reply reply; - dormant_node_info * infos = new dormant_node_info[msg->maxcount]; - reply.count = msg->maxcount; - reply.result = gNodeManager->GetDormantNodes( - infos, - &reply.count, - msg->has_input ? &msg->inputformat : NULL, - msg->has_output ? &msg->outputformat : NULL, - msg->has_name ? msg->name : NULL, - msg->require_kinds, - msg->deny_kinds); + reply.count = msg->max_count; + + dormant_node_info* infos + = new(std::nothrow) dormant_node_info[reply.count]; + if (infos != NULL) { + reply.result = gNodeManager->GetDormantNodes(infos, + &reply.count, msg->has_input ? &msg->input_format : NULL, + msg->has_output ? &msg->output_format : NULL, + msg->has_name ? msg->name : NULL, msg->require_kinds, + msg->deny_kinds); + } else + reply.result = B_NO_MEMORY; + if (reply.result != B_OK) reply.count = 0; write_port(msg->reply_port, 0, &reply, sizeof(reply)); - if (reply.count > 0) - write_port(msg->reply_port, 0, infos, reply.count - * sizeof(dormant_node_info)); - delete [] infos; + if (reply.count > 0) { + write_port(msg->reply_port, 0, infos, + reply.count * sizeof(dormant_node_info)); + } + delete[] infos; break; } @@ -643,40 +646,48 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) { xfer_server_get_dormant_flavor_info *msg = (xfer_server_get_dormant_flavor_info *)data; - dormant_flavor_info dfi; + dormant_flavor_info dormantFlavorInfo; status_t rv; rv = gNodeManager->GetDormantFlavorInfoFor(msg->addon, - msg->flavor_id, &dfi); + msg->flavor_id, &dormantFlavorInfo); if (rv != B_OK) { xfer_server_get_dormant_flavor_info_reply reply; reply.result = rv; write_port(msg->reply_port, 0, &reply, sizeof(reply)); } else { - xfer_server_get_dormant_flavor_info_reply *reply; - int replysize; - replysize = sizeof(xfer_server_get_dormant_flavor_info_reply) - + dfi.FlattenedSize(); - reply = (xfer_server_get_dormant_flavor_info_reply *)malloc( - replysize); + size_t replySize + = sizeof(xfer_server_get_dormant_flavor_info_reply) + + dormantFlavorInfo.FlattenedSize(); + xfer_server_get_dormant_flavor_info_reply* reply + = (xfer_server_get_dormant_flavor_info_reply*)malloc( + replySize); + if (reply != NULL) { + reply->type = dormantFlavorInfo.TypeCode(); + reply->flattened_size = dormantFlavorInfo.FlattenedSize(); + reply->result = dormantFlavorInfo.Flatten( + reply->flattened_data, reply->flattened_size); - reply->dfi_size = dfi.FlattenedSize(); - reply->dfi_type = dfi.TypeCode(); - reply->result = dfi.Flatten(reply->dfi, reply->dfi_size); - write_port(msg->reply_port, 0, reply, replysize); - free(reply); + write_port(msg->reply_port, 0, reply, replySize); + free(reply); + } else { + xfer_server_get_dormant_flavor_info_reply reply; + reply.result = B_NO_MEMORY; + write_port(msg->reply_port, 0, &reply, sizeof(reply)); + } } break; } case SERVER_SET_NODE_CREATOR: { - const server_set_node_creator_request *request - = reinterpret_cast( + const server_set_node_creator_request* request + = reinterpret_cast( data); server_set_node_creator_reply reply; - rv = gNodeManager->SetNodeCreator(request->node, request->creator); - request->SendReply(rv, &reply, sizeof(reply)); + status_t status = gNodeManager->SetNodeCreator(request->node, + request->creator); + request->SendReply(status, &reply, sizeof(reply)); break; } @@ -687,7 +698,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) const server_get_shared_buffer_area_request *>(data); server_get_shared_buffer_area_reply reply; - reply.area = gBufferManager->SharedBufferListID(); + reply.area = gBufferManager->SharedBufferListArea(); request->SendReply(B_OK, &reply, sizeof(reply)); break; } @@ -722,7 +733,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) const server_unregister_buffer_command *cmd = reinterpret_cast< const server_unregister_buffer_command *>(data); - gBufferManager->UnregisterBuffer(cmd->team, cmd->bufferid); + gBufferManager->UnregisterBuffer(cmd->team, cmd->buffer_id); break; } diff --git a/src/servers/media_addon/Jamfile b/src/servers/media_addon/Jamfile index 49f607947f..e127b1ca47 100644 --- a/src/servers/media_addon/Jamfile +++ b/src/servers/media_addon/Jamfile @@ -6,10 +6,6 @@ UsePrivateHeaders media shared ; AddResources media_addon_server : media_addon_server.rdef ; -# That's ugly. The header (ServerInterface.h) should reside in -# headers/private/media. -SubDirHdrs [ FDirName $(HAIKU_TOP) src servers media ] ; - Server media_addon_server : main.cpp MediaFilePlayer.cpp diff --git a/src/servers/media_addon/main.cpp b/src/servers/media_addon/main.cpp index df65d262a6..21e520bc22 100644 --- a/src/servers/media_addon/main.cpp +++ b/src/servers/media_addon/main.cpp @@ -1,3 +1,8 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + /* * Copyright (c) 2002-2004, Marcus Overhagen * All rights reserved. @@ -12,7 +17,7 @@ * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL @@ -23,9 +28,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define BUILDING_MEDIA_ADDON 1 +#include #include +#include #include #include @@ -40,83 +46,121 @@ #include #include -#include "debug.h" -#include "DataExchange.h" -#include "DormantNodeManager.h" +#include +#include +#include +#include +#include +#include +#include +#include + #include "MediaFilePlayer.h" -#include "MediaMisc.h" -#include "MediaRosterEx.h" -#include "MediaSounds.h" -#include "Notifications.h" -#include "ServerInterface.h" #include "SystemTimeSource.h" -#include "TMap.h" //#define USER_ADDON_PATH "../add-ons/media" -void DumpFlavorInfo(const flavor_info *info); + +typedef std::vector NodeVector; + struct AddOnInfo { - media_addon_id id; - bool wants_autostart; - int32 flavor_count; - - List active_flavors; + media_addon_id id; + bool wants_autostart; + int32 flavor_count; - BMediaAddOn *addon; + NodeVector active_flavors; + + BMediaAddOn* addon; // if != NULL, need to call _DormantNodeManager->PutAddon(id) }; + class MediaAddonServer : BApplication { public: - MediaAddonServer(const char *sig); - virtual ~MediaAddonServer(); - virtual void ReadyToRun(); - virtual bool QuitRequested(); - virtual void MessageReceived(BMessage *msg); - + MediaAddonServer(const char* signature); + virtual ~MediaAddonServer(); + virtual void ReadyToRun(); + virtual bool QuitRequested(); + virtual void MessageReceived(BMessage* message); + private: - void WatchDir(BEntry *dir); - void AddOnAdded(const char *path, ino_t file_node); - void AddOnRemoved(ino_t file_node); - void HandleMessage(int32 code, const void *data, size_t size); + void _WatchDir(BEntry* dir); + void _AddOnAdded(const char* path, ino_t fileNode); + void _AddOnRemoved(ino_t fileNode); + void _HandleMessage(int32 code, const void* data, + size_t size); - void PutAddonIfPossible(AddOnInfo *info); - void InstantiatePhysicalInputsAndOutputs(AddOnInfo *info); - void InstantiateAutostartFlavors(AddOnInfo *info); - void DestroyInstantiatedFlavors(AddOnInfo *info); - - void ScanAddOnFlavors(BMediaAddOn *addon); + void _PutAddonIfPossible(AddOnInfo& info); + void _InstantiatePhysicalInputsAndOutputs( + AddOnInfo& info); + void _InstantiateAutostartFlavors(AddOnInfo& info); + void _DestroyInstantiatedFlavors(AddOnInfo& info); - port_id ControlPort() const { return fControlPort; } + void _ScanAddOnFlavors(BMediaAddOn* addOn); - static int32 _ControlThread(void *arg); + port_id _ControlPort() const { return fControlPort; } - Map *fFileMap; - Map *fInfoMap; + static status_t _ControlThread(void* arg); - BMediaRoster *fMediaRoster; - ino_t fSystemAddOnsNode; - ino_t fUserAddOnsNode; - port_id fControlPort; - thread_id fControlThread; - bool fStartup; - bool fStartupSound; - - typedef BApplication inherited; +private: + typedef std::map FileMap; + typedef std::map InfoMap; + + FileMap fFileMap; + InfoMap fInfoMap; + + BMediaRoster* fMediaRoster; + ino_t fSystemAddOnsNode; + ino_t fUserAddOnsNode; + port_id fControlPort; + thread_id fControlThread; + bool fStartup; + bool fStartupSound; }; -MediaAddonServer::MediaAddonServer(const char *sig) - : BApplication(sig), +#if DEBUG >= 2 +static void +DumpFlavorInfo(const flavor_info* info) +{ + printf(" name = %s\n", info->name); + printf(" info = %s\n", info->info); + printf(" internal_id = %ld\n", info->internal_id); + printf(" possible_count = %ld\n", info->possible_count); + printf(" flavor_flags = 0x%lx", info->flavor_flags); + if (info->flavor_flags & B_FLAVOR_IS_GLOBAL) printf(" B_FLAVOR_IS_GLOBAL"); + if (info->flavor_flags & B_FLAVOR_IS_LOCAL) printf(" B_FLAVOR_IS_LOCAL"); + printf("\n"); + printf(" kinds = 0x%Lx", info->kinds); + if (info->kinds & B_BUFFER_PRODUCER) printf(" B_BUFFER_PRODUCER"); + if (info->kinds & B_BUFFER_CONSUMER) printf(" B_BUFFER_CONSUMER"); + if (info->kinds & B_TIME_SOURCE) printf(" B_TIME_SOURCE"); + if (info->kinds & B_CONTROLLABLE) printf(" B_CONTROLLABLE"); + if (info->kinds & B_FILE_INTERFACE) printf(" B_FILE_INTERFACE"); + if (info->kinds & B_ENTITY_INTERFACE) printf(" B_ENTITY_INTERFACE"); + if (info->kinds & B_PHYSICAL_INPUT) printf(" B_PHYSICAL_INPUT"); + if (info->kinds & B_PHYSICAL_OUTPUT) printf(" B_PHYSICAL_OUTPUT"); + if (info->kinds & B_SYSTEM_MIXER) printf(" B_SYSTEM_MIXER"); + printf("\n"); + printf(" in_format_count = %ld\n", info->in_format_count); + printf(" out_format_count = %ld\n", info->out_format_count); +} +#endif + + +// #pragma mark - + + +MediaAddonServer::MediaAddonServer(const char* signature) + : + BApplication(signature), fStartup(true), fStartupSound(true) { CALLED(); fMediaRoster = BMediaRoster::Roster(); - fFileMap = new Map; - fInfoMap = new Map; fControlPort = create_port(64, MEDIA_ADDON_SERVER_PORT_NAME); fControlThread = spawn_thread(_ControlThread, "media_addon_server control", B_NORMAL_PRIORITY + 2, this); @@ -129,75 +173,14 @@ MediaAddonServer::~MediaAddonServer() CALLED(); delete_port(fControlPort); - status_t err; - wait_for_thread(fControlThread,&err); + wait_for_thread(fControlThread, NULL); // unregister all media add-ons - media_addon_id *id; - for (fFileMap->Rewind(); fFileMap->GetNext(&id); ) - _DormantNodeManager->UnregisterAddon(*id); + FileMap::iterator iterator = fFileMap.begin(); + for (; iterator != fFileMap.end(); iterator++) + _DormantNodeManager->UnregisterAddon(iterator->second); // TODO: unregister system time source - - delete fFileMap; - delete fInfoMap; -} - - -void -MediaAddonServer::HandleMessage(int32 code, const void *data, size_t size) -{ - switch (code) { - case ADDONSERVER_INSTANTIATE_DORMANT_NODE: - { - const addonserver_instantiate_dormant_node_request *request = static_cast(data); - addonserver_instantiate_dormant_node_reply reply; - status_t rv; - rv = MediaRosterEx(fMediaRoster)->InstantiateDormantNode(request->addonid, request->flavorid, request->creator_team, &reply.node); - request->SendReply(rv, &reply, sizeof(reply)); - break; - } - - case ADDONSERVER_RESCAN_MEDIAADDON_FLAVORS: - { - const addonserver_rescan_mediaaddon_flavors_command *command = static_cast(data); - BMediaAddOn *addon; - addon = _DormantNodeManager->GetAddon(command->addonid); - if (!addon) { - ERROR("rescan flavors: Can't find a addon object for id %d\n",(int)command->addonid); - break; - } - ScanAddOnFlavors(addon); - _DormantNodeManager->PutAddon(command->addonid); - break; - } - - case ADDONSERVER_RESCAN_FINISHED_NOTIFY: - if (fStartupSound) { - system_beep(MEDIA_SOUNDS_STARTUP); - fStartupSound = false; - } - break; - - default: - ERROR("media_addon_server: received unknown message code %#08lx\n",code); - } -} - - -int32 -MediaAddonServer::_ControlThread(void *arg) -{ - char data[B_MEDIA_MESSAGE_SIZE]; - MediaAddonServer *app; - ssize_t size; - int32 code; - - app = (MediaAddonServer *)arg; - while ((size = read_port_etc(app->ControlPort(), &code, data, sizeof(data), 0, 0)) > 0) - app->HandleMessage(code, data, size); - - return 0; } @@ -216,7 +199,7 @@ MediaAddonServer::ReadyToRun() // commands for instantiation ASSERT(fStartup == true); - + // The very first thing to do is to create the system time source, // register it with the server, and make it the default SYSTEM_TIME_SOURCE BMediaNode *timeSource = new SystemTimeSource; @@ -249,7 +232,7 @@ MediaAddonServer::ReadyToRun() BEntry entry(path.Path()); entry.GetNodeRef(&nref); fSystemAddOnsNode = nref.node; - WatchDir(&entry); + _WatchDir(&entry); #ifdef USER_ADDON_PATH entry.SetTo(USER_ADDON_PATH); @@ -260,23 +243,19 @@ MediaAddonServer::ReadyToRun() #endif entry.GetNodeRef(&nref); fUserAddOnsNode = nref.node; - WatchDir(&entry); + _WatchDir(&entry); fStartup = false; - AddOnInfo *info; + InfoMap::iterator iterator = fInfoMap.begin(); + for (; iterator != fInfoMap.end(); iterator++) + _InstantiatePhysicalInputsAndOutputs(iterator->second); - fInfoMap->Rewind(); - while (fInfoMap->GetNext(&info)) - InstantiatePhysicalInputsAndOutputs(info); + for (iterator = fInfoMap.begin(); iterator != fInfoMap.end(); iterator++) + _InstantiateAutostartFlavors(iterator->second); - fInfoMap->Rewind(); - while (fInfoMap->GetNext(&info)) - InstantiateAutostartFlavors(info); - - fInfoMap->Rewind(); - while (fInfoMap->GetNext(&info)) - PutAddonIfPossible(info); + for (iterator = fInfoMap.begin(); iterator != fInfoMap.end(); iterator++) + _PutAddonIfPossible(iterator->second); server_rescan_defaults_command cmd; SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd)); @@ -288,11 +267,12 @@ MediaAddonServer::QuitRequested() { CALLED(); - AddOnInfo *info; - fInfoMap->Rewind(); - while(fInfoMap->GetNext(&info)) { - DestroyInstantiatedFlavors(info); - PutAddonIfPossible(info); + InfoMap::iterator iterator = fInfoMap.begin(); + for (; iterator != fInfoMap.end(); iterator++) { + AddOnInfo& info = iterator->second; + + _DestroyInstantiatedFlavors(info); + _PutAddonIfPossible(info); } return true; @@ -300,22 +280,167 @@ MediaAddonServer::QuitRequested() void -MediaAddonServer::ScanAddOnFlavors(BMediaAddOn *addon) +MediaAddonServer::MessageReceived(BMessage* message) { - AddOnInfo *info; - int32 oldflavorcount; - int32 newflavorcount; - media_addon_id addon_id; - port_id port; - status_t rv; - bool b; + switch (message->what) { + case MEDIA_ADDON_SERVER_PLAY_MEDIA: + { + const char* name; + const char* type; + if (message->FindString(MEDIA_NAME_KEY, &name) != B_OK + || message->FindString(MEDIA_TYPE_KEY, &type) != B_OK) { + message->SendReply(B_ERROR); + break; + } - ASSERT(addon); + PlayMediaFile(type, name); + message->SendReply((uint32)B_OK); + // TODO: don't know which reply is expected + return; + } + + case B_NODE_MONITOR: + { + switch (message->FindInt32("opcode")) { + case B_ENTRY_CREATED: + { + const char *name; + entry_ref ref; + ino_t node; + BEntry e; + BPath p; + message->FindString("name", &name); + message->FindInt64("node", &node); + message->FindInt32("device", &ref.device); + message->FindInt64("directory", &ref.directory); + ref.set_name(name); + e.SetTo(&ref,false);// build a BEntry for the created file/link/dir + e.GetPath(&p); // get the path to the file/link/dir + e.SetTo(&ref,true); // travese links to see + if (e.IsFile()) { // if it's a link to a file, or a file + if (!message->FindBool("nowait")) { + // TODO: wait 5 seconds if this is a regular notification + // because the file creation may not be finshed when the + // notification arrives (very ugly, how can we fix this?) + // this will also fail if copying takes longer than 5 seconds + snooze(5000000); + } + _AddOnAdded(p.Path(), node); + } + return; + } + case B_ENTRY_REMOVED: + { + ino_t node; + message->FindInt64("node", &node); + _AddOnRemoved(node); + return; + } + case B_ENTRY_MOVED: + { + ino_t from; + ino_t to; + message->FindInt64("from directory", &from); + message->FindInt64("to directory", &to); + if (fSystemAddOnsNode == from || fUserAddOnsNode == from) { + message->ReplaceInt32("opcode", B_ENTRY_REMOVED); + message->AddInt64("directory", from); + MessageReceived(message); + } + if (fSystemAddOnsNode == to || fUserAddOnsNode == to) { + message->ReplaceInt32("opcode", B_ENTRY_CREATED); + message->AddInt64("directory", to); + message->AddBool("nowait", true); + MessageReceived(message); + } + return; + } + } + break; + } + + default: + BApplication::MessageReceived(message); + break; + } +} + + +void +MediaAddonServer::_HandleMessage(int32 code, const void* data, size_t size) +{ + switch (code) { + case ADDONSERVER_INSTANTIATE_DORMANT_NODE: + { + const addonserver_instantiate_dormant_node_request* request + = static_cast< + const addonserver_instantiate_dormant_node_request*>(data); + addonserver_instantiate_dormant_node_reply reply; + + status_t status + = MediaRosterEx(fMediaRoster)->InstantiateDormantNode( + request->addon_id, request->flavor_id, + request->creator_team, &reply.node); + request->SendReply(status, &reply, sizeof(reply)); + break; + } + + case ADDONSERVER_RESCAN_MEDIAADDON_FLAVORS: + { + const addonserver_rescan_mediaaddon_flavors_command* command + = static_cast< + const addonserver_rescan_mediaaddon_flavors_command*>(data); + BMediaAddOn* addon + = _DormantNodeManager->GetAddon(command->addon_id); + if (addon == NULL) { + ERROR("rescan flavors: Can't find a addon object for id %d\n", + (int)command->addon_id); + break; + } + _ScanAddOnFlavors(addon); + _DormantNodeManager->PutAddon(command->addon_id); + break; + } + + case ADDONSERVER_RESCAN_FINISHED_NOTIFY: + if (fStartupSound) { + system_beep(MEDIA_SOUNDS_STARTUP); + fStartupSound = false; + } + break; + + default: + ERROR("media_addon_server: received unknown message code %#08lx\n", + code); + break; + } +} + + +status_t +MediaAddonServer::_ControlThread(void* _server) +{ + MediaAddonServer* server = (MediaAddonServer*)_server; + + char data[B_MEDIA_MESSAGE_SIZE]; + ssize_t size; + int32 code; + while ((size = read_port_etc(server->_ControlPort(), &code, data, + sizeof(data), 0, 0)) > 0) + server->_HandleMessage(code, data, size); + + return B_OK; +} + + +void +MediaAddonServer::_ScanAddOnFlavors(BMediaAddOn* addon) +{ ASSERT(addon->AddonID() > 0); - TRACE("MediaAddonServer::ScanAddOnFlavors: id %ld\n", addon->AddonID()); + TRACE("MediaAddonServer::_ScanAddOnFlavors: id %ld\n", addon->AddonID()); - port = find_port(MEDIA_SERVER_PORT_NAME); + port_id port = find_port(MEDIA_SERVER_PORT_NAME); if (port <= B_OK) { ERROR("couldn't find media_server port\n"); return; @@ -323,119 +448,125 @@ MediaAddonServer::ScanAddOnFlavors(BMediaAddOn *addon) // cache the media_addon_id in a local variable to avoid // calling BMediaAddOn::AddonID() too often - addon_id = addon->AddonID(); + media_addon_id addonID = addon->AddonID(); // update the cached flavor count, get oldflavorcount and newflavorcount - b = fInfoMap->Get(addon_id, &info); - ASSERT(b); - oldflavorcount = info->flavor_count; - newflavorcount = addon->CountFlavors(); - info->flavor_count = newflavorcount; - TRACE("%ld old flavors, %ld new flavors\n", oldflavorcount, newflavorcount); + InfoMap::iterator found = fInfoMap.find(addonID); + ASSERT(found != fInfoMap.end()); + + AddOnInfo& info = found->second; + int32 oldFlavorCount = info.flavor_count; + int32 newFlavorCount = addon->CountFlavors(); + info.flavor_count = newFlavorCount; + + TRACE("%ld old flavors, %ld new flavors\n", oldflavorcount, newFlavorCount); // during the first update (i == 0), the server removes old dormant_flavor_infos - for (int i = 0; i < newflavorcount; i++) { - const flavor_info *info; - TRACE("flavor %d:\n",i); - if (B_OK != addon->GetFlavorAt(i, &info)) { - ERROR("MediaAddonServer::ScanAddOnFlavors GetFlavorAt failed for index %d!\n", i); + for (int i = 0; i < newFlavorCount; i++) { + const flavor_info* flavorInfo; + TRACE("flavor %d:\n", i); + if (addon->GetFlavorAt(i, &flavorInfo) != B_OK) { + ERROR("MediaAddonServer::_ScanAddOnFlavors GetFlavorAt failed for " + "index %d!\n", i); continue; } - #if DEBUG >= 2 - DumpFlavorInfo(info); - #endif +#if DEBUG >= 2 + DumpFlavorInfo(flavorInfo); +#endif - dormant_flavor_info dfi; - dfi = *info; - dfi.node_info.addon = addon_id; - dfi.node_info.flavor_id = info->internal_id; - strncpy(dfi.node_info.name, info->name, B_MEDIA_NAME_LENGTH - 1); - dfi.node_info.name[B_MEDIA_NAME_LENGTH - 1] = 0; + dormant_flavor_info dormantFlavorInfo; + dormantFlavorInfo = *flavorInfo; + dormantFlavorInfo.node_info.addon = addonID; + dormantFlavorInfo.node_info.flavor_id = flavorInfo->internal_id; + strlcpy(dormantFlavorInfo.node_info.name, flavorInfo->name, + B_MEDIA_NAME_LENGTH); - xfer_server_register_dormant_node *msg; - size_t flattensize; - size_t msgsize; + size_t flattenedSize = dormantFlavorInfo.FlattenedSize(); + size_t messageSize = flattenedSize + + sizeof(xfer_server_register_dormant_node); + xfer_server_register_dormant_node* message + = (xfer_server_register_dormant_node*)malloc(messageSize); + if (message == NULL) + break; - flattensize = dfi.FlattenedSize(); - msgsize = flattensize + sizeof(xfer_server_register_dormant_node); - msg = (xfer_server_register_dormant_node *) malloc(msgsize); - - // the server should remove previously registered "dormant_flavor_info"s + // The server should remove previously registered "dormant_flavor_info"s // during the first update, but after the first iteration, we don't // want the server to anymore remove old dormant_flavor_infos - msg->purge_id = (i == 0) ? addon_id : 0; + message->purge_id = i == 0 ? addonID : 0; - msg->dfi_type = dfi.TypeCode(); - msg->dfi_size = flattensize; - dfi.Flatten(&(msg->dfi),flattensize); + message->type = dormantFlavorInfo.TypeCode(); + message->flattened_size = flattenedSize; + dormantFlavorInfo.Flatten(message->flattened_data, flattenedSize); - rv = write_port(port, SERVER_REGISTER_DORMANT_NODE, msg, msgsize); - if (rv != B_OK) { - ERROR("MediaAddonServer::ScanAddOnFlavors: couldn't register dormant node\n"); + status_t status = write_port(port, SERVER_REGISTER_DORMANT_NODE, + message, messageSize); + if (status != B_OK) { + ERROR("MediaAddonServer::_ScanAddOnFlavors: couldn't register " + "dormant node: %s\n", strerror(status)); } - free(msg); + free(message); } - // XXX parameter list is (media_addon_id addonid, int32 newcount, int32 gonecount) - // XXX we currently pretend that all old flavors have been removed, this could - // XXX probably be done in a smarter way - BPrivate::media::notifications::FlavorsChanged(addon_id, newflavorcount, - oldflavorcount); + // TODO: we currently pretend that all old flavors have been removed, this + // could probably be done in a smarter way + BPrivate::media::notifications::FlavorsChanged(addonID, newFlavorCount, + oldFlavorCount); } void -MediaAddonServer::AddOnAdded(const char *path, ino_t file_node) +MediaAddonServer::_AddOnAdded(const char* path, ino_t fileNode) { - TRACE("\n\nMediaAddonServer::AddOnAdded: path %s\n",path); + TRACE("\n\nMediaAddonServer::_AddOnAdded: path %s\n", path); - BMediaAddOn *addon; - media_addon_id id; - - id = _DormantNodeManager->RegisterAddon(path); + media_addon_id id = _DormantNodeManager->RegisterAddon(path); if (id <= 0) { - ERROR("MediaAddonServer::AddOnAdded: failed to register add-on %s\n", path); + ERROR("MediaAddonServer::_AddOnAdded: failed to register add-on %s\n", + path); return; } - TRACE("MediaAddonServer::AddOnAdded: loading addon %ld now...\n", id); + TRACE("MediaAddonServer::_AddOnAdded: loading addon %ld now...\n", id); - addon = _DormantNodeManager->GetAddon(id); + BMediaAddOn* addon = _DormantNodeManager->GetAddon(id); if (addon == NULL) { - ERROR("MediaAddonServer::AddOnAdded: failed to get add-on %s\n", path); + ERROR("MediaAddonServer::_AddOnAdded: failed to get add-on %s\n", path); _DormantNodeManager->UnregisterAddon(id); return; } - TRACE("MediaAddonServer::AddOnAdded: loading finished, id %ld\n", id); + TRACE("MediaAddonServer::_AddOnAdded: loading finished, id %ld\n", id); - // put file's inode and addon's id into map - fFileMap->Insert(file_node, id); + try { + // put file's inode and addon's id into map + fFileMap.insert(std::make_pair(fileNode, id)); - // also create AddOnInfo struct and get a pointer so - // we can modify it - AddOnInfo tempinfo; - fInfoMap->Insert(id, tempinfo); - AddOnInfo *info; - fInfoMap->Get(id, &info); + AddOnInfo info; + fInfoMap.insert(std::make_pair(id, info)); + } catch (std::bad_alloc& exception) { + fFileMap.erase(fileNode); + return; + } - // setup - info->id = id; - info->wants_autostart = false; // temporary default - info->flavor_count = 0; - info->addon = addon; + InfoMap::iterator found = fInfoMap.find(id); + AddOnInfo& info = found->second; + + info.id = id; + info.wants_autostart = false; // temporary default + info.flavor_count = 0; + info.addon = addon; // scan the flavors - ScanAddOnFlavors(addon); + _ScanAddOnFlavors(addon); // need to call BMediaNode::WantsAutoStart() // after the flavors have been scanned - info->wants_autostart = addon->WantsAutoStart(); + info.wants_autostart = addon->WantsAutoStart(); - if (info->wants_autostart) + if (info.wants_autostart) TRACE("add-on %ld WantsAutoStart!\n", id); // During startup, first all add-ons are loaded, then all @@ -447,45 +578,47 @@ MediaAddonServer::AddOnAdded(const char *path, ino_t file_node) // After startup is done, we simply do it for each new // loaded add-on, too. if (!fStartup) { - InstantiatePhysicalInputsAndOutputs(info); - InstantiateAutostartFlavors(info); - PutAddonIfPossible(info); + _InstantiatePhysicalInputsAndOutputs(info); + _InstantiateAutostartFlavors(info); + _PutAddonIfPossible(info); // since something might have changed server_rescan_defaults_command cmd; - SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd)); + SendToServer(SERVER_RESCAN_DEFAULTS, &cmd, sizeof(cmd)); } // we do not call _DormantNodeManager->PutAddon(id) - // since it is done by PutAddonIfPossible() + // since it is done by _PutAddonIfPossible() } void -MediaAddonServer::DestroyInstantiatedFlavors(AddOnInfo *info) +MediaAddonServer::_DestroyInstantiatedFlavors(AddOnInfo& info) { - printf("MediaAddonServer::DestroyInstantiatedFlavors\n"); - media_node *node; - while (info->active_flavors.GetNext(&node)) { - if ((node->kind & B_TIME_SOURCE) != 0 - && (fMediaRoster->StopTimeSource(*node, 0, true) != B_OK)) { - printf("MediaAddonServer::DestroyInstantiatedFlavors couldn't stop " + printf("MediaAddonServer::_DestroyInstantiatedFlavors\n"); + + NodeVector::iterator iterator = info.active_flavors.begin(); + for (; iterator != info.active_flavors.end(); iterator++) { + media_node& node = *iterator; + if ((node.kind & B_TIME_SOURCE) != 0 + && (fMediaRoster->StopTimeSource(node, 0, true) != B_OK)) { + printf("MediaAddonServer::_DestroyInstantiatedFlavors couldn't stop " "timesource\n"); continue; } - if (fMediaRoster->StopNode(*node, 0, true) != B_OK) { - printf("MediaAddonServer::DestroyInstantiatedFlavors couldn't stop " + if (fMediaRoster->StopNode(node, 0, true) != B_OK) { + printf("MediaAddonServer::_DestroyInstantiatedFlavors couldn't stop " "node\n"); continue; } - if (node->kind & B_BUFFER_CONSUMER) { + if ((node.kind & B_BUFFER_CONSUMER) != 0) { media_input inputs[16]; int32 count = 0; - if (fMediaRoster->GetConnectedInputsFor(*node, inputs, 16, &count) + if (fMediaRoster->GetConnectedInputsFor(node, inputs, 16, &count) != B_OK) { - printf("MediaAddonServer::DestroyInstantiatedFlavors couldn't " + printf("MediaAddonServer::_DestroyInstantiatedFlavors couldn't " "get connected inputs\n"); continue; } @@ -494,90 +627,95 @@ MediaAddonServer::DestroyInstantiatedFlavors(AddOnInfo *info) media_node_id sourceNode; if ((sourceNode = fMediaRoster->NodeIDFor( inputs[i].source.port)) < 0) { - printf("MediaAddonServer::DestroyInstantiatedFlavors " + printf("MediaAddonServer::_DestroyInstantiatedFlavors " "couldn't get source node id\n"); continue; } if (fMediaRoster->Disconnect(sourceNode, inputs[i].source, - node->node, inputs[i].destination) != B_OK) { - printf("MediaAddonServer::DestroyInstantiatedFlavors " + node.node, inputs[i].destination) != B_OK) { + printf("MediaAddonServer::_DestroyInstantiatedFlavors " "couldn't disconnect input\n"); continue; } } } - if (node->kind & B_BUFFER_PRODUCER) { + if ((node.kind & B_BUFFER_PRODUCER) != 0) { media_output outputs[16]; int32 count = 0; - if (fMediaRoster->GetConnectedOutputsFor(*node, outputs, 16, + if (fMediaRoster->GetConnectedOutputsFor(node, outputs, 16, &count) != B_OK) { - printf("MediaAddonServer::DestroyInstantiatedFlavors couldn't " + printf("MediaAddonServer::_DestroyInstantiatedFlavors couldn't " "get connected outputs\n"); continue; } - + for (int32 i = 0; i < count; i++) { media_node_id destNode; if ((destNode = fMediaRoster->NodeIDFor( outputs[i].destination.port)) < 0) { - printf("MediaAddonServer::DestroyInstantiatedFlavors " + printf("MediaAddonServer::_DestroyInstantiatedFlavors " "couldn't get destination node id\n"); continue; } - if (fMediaRoster->Disconnect(node->node, outputs[i].source, + if (fMediaRoster->Disconnect(node.node, outputs[i].source, destNode, outputs[i].destination) != B_OK) { - printf("MediaAddonServer::DestroyInstantiatedFlavors " + printf("MediaAddonServer::_DestroyInstantiatedFlavors " "couldn't disconnect output\n"); continue; } } } - - info->active_flavors.RemoveCurrent(); } + + info.active_flavors.clear(); } void -MediaAddonServer::PutAddonIfPossible(AddOnInfo *info) +MediaAddonServer::_PutAddonIfPossible(AddOnInfo& info) { - if (info->addon && info->active_flavors.IsEmpty()) { - _DormantNodeManager->PutAddon(info->id); - info->addon = NULL; + if (info.addon && info.active_flavors.empty()) { + _DormantNodeManager->PutAddon(info.id); + info.addon = NULL; } } void -MediaAddonServer::InstantiatePhysicalInputsAndOutputs(AddOnInfo *info) +MediaAddonServer::_InstantiatePhysicalInputsAndOutputs(AddOnInfo& info) { CALLED(); - int count = info->addon->CountFlavors(); - for (int i = 0; i < count; i++) { - const flavor_info *flavorinfo; - if (info->addon->GetFlavorAt(i, &flavorinfo) != B_OK) { - ERROR("MediaAddonServer::InstantiatePhysialInputsAndOutputs GetFlavorAt failed for index %d!\n", i); + int32 count = info.addon->CountFlavors(); + + for (int32 i = 0; i < count; i++) { + const flavor_info* flavorinfo; + if (info.addon->GetFlavorAt(i, &flavorinfo) != B_OK) { + ERROR("MediaAddonServer::InstantiatePhysialInputsAndOutputs " + "GetFlavorAt failed for index %ld!\n", i); continue; } - if (flavorinfo->kinds & (B_PHYSICAL_INPUT | B_PHYSICAL_OUTPUT)) { + if ((flavorinfo->kinds & (B_PHYSICAL_INPUT | B_PHYSICAL_OUTPUT)) != 0) { media_node node; - status_t rv; - dormant_node_info dni; - dni.addon = info->id; - dni.flavor_id = flavorinfo->internal_id; - strcpy(dni.name, flavorinfo->name); - - printf("MediaAddonServer::InstantiatePhysialInputsAndOutputs: \"%s\" is a physical input/output\n", flavorinfo->name); - rv = fMediaRoster->InstantiateDormantNode(dni, &node); - if (rv != B_OK) { - ERROR("MediaAddonServer::InstantiatePhysialInputsAndOutputs Couldn't instantiate node flavor, internal_id %ld, name %s\n", flavorinfo->internal_id, flavorinfo->name); + dormant_node_info dormantNodeInfo; + dormantNodeInfo.addon = info.id; + dormantNodeInfo.flavor_id = flavorinfo->internal_id; + strcpy(dormantNodeInfo.name, flavorinfo->name); + + PRINT("MediaAddonServer::InstantiatePhysialInputsAndOutputs: " + "\"%s\" is a physical input/output\n", flavorinfo->name); + status_t status = fMediaRoster->InstantiateDormantNode( + dormantNodeInfo, &node); + if (status != B_OK) { + ERROR("MediaAddonServer::InstantiatePhysialInputsAndOutputs " + "Couldn't instantiate node flavor, internal_id %ld, " + "name %s\n", flavorinfo->internal_id, flavorinfo->name); } else { - printf("Node created!\n"); - info->active_flavors.Insert(node); + PRINT("Node created!\n"); + info.active_flavors.push_back(node); } } } @@ -585,35 +723,36 @@ MediaAddonServer::InstantiatePhysicalInputsAndOutputs(AddOnInfo *info) void -MediaAddonServer::InstantiateAutostartFlavors(AddOnInfo *info) +MediaAddonServer::_InstantiateAutostartFlavors(AddOnInfo& info) { - if (!info->wants_autostart) + if (!info.wants_autostart) return; - - for (int32 index = 0; ;index++) { - BMediaNode *outNode; - int32 outInternalID; - bool outHasMore; - status_t rv; - printf("trying autostart of node %ld, index %ld\n", info->id, index); - rv = info->addon->AutoStart(index, &outNode, &outInternalID, &outHasMore); - if (rv == B_OK) { + + for (int32 index = 0;; index++) { + PRINT("trying autostart of node %ld, index %ld\n", info.id, index); + + BMediaNode* node; + int32 internalID; + bool hasMore; + status_t status = info.addon->AutoStart(index, &node, &internalID, + &hasMore); + if (status == B_OK) { printf("started node %ld\n", index); - // XXX IncrementAddonFlavorInstancesCount + // TODO: IncrementAddonFlavorInstancesCount - rv = MediaRosterEx(fMediaRoster)->RegisterNode(outNode, info->id, - outInternalID); - if (rv != B_OK) { - printf("failed to register node %ld\n",index); - // XXX DecrementAddonFlavorInstancesCount + status = MediaRosterEx(fMediaRoster)->RegisterNode(node, info.id, + internalID); + if (status != B_OK) { + ERROR("failed to register node %ld\n", index); + // TODO: DecrementAddonFlavorInstancesCount } - info->active_flavors.Insert(outNode->Node()); + info.active_flavors.push_back(node->Node()); - if (!outHasMore) + if (!hasMore) return; - } else if (rv == B_MEDIA_ADDON_FAILED && outHasMore) { + } else if (status == B_MEDIA_ADDON_FAILED && hasMore) { continue; } else { break; @@ -623,186 +762,79 @@ MediaAddonServer::InstantiateAutostartFlavors(AddOnInfo *info) void -MediaAddonServer::AddOnRemoved(ino_t file_node) -{ - media_addon_id *tempid; - media_addon_id id; - AddOnInfo *info; - int32 oldflavorcount; - // XXX locking? +MediaAddonServer::_AddOnRemoved(ino_t fileNode) +{ + // TODO: locking? - if (!fFileMap->Get(file_node, &tempid)) { - ERROR("MediaAddonServer::AddOnRemoved: inode %Ld removed, but no media add-on found\n", file_node); + FileMap::iterator foundFile = fFileMap.find(fileNode); + if (foundFile == fFileMap.end()) { + ERROR("MediaAddonServer::_AddOnRemoved: inode %Ld removed, but no " + "media add-on found\n", fileNode); return; } - id = *tempid; // tempid pointer is invalid after Removing() it from the map - fFileMap->Remove(file_node); - if (!fInfoMap->Get(id, &info)) { - ERROR("MediaAddonServer::AddOnRemoved: couldn't get addon info for add-on %ld\n", id); - oldflavorcount = 1000; + media_addon_id id = foundFile->second; + fFileMap.erase(foundFile); + + int32 oldFlavorCount; + InfoMap::iterator foundInfo = fInfoMap.find(id); + + if (foundInfo == fInfoMap.end()) { + ERROR("MediaAddonServer::_AddOnRemoved: couldn't get addon info for " + "add-on %ld\n", id); + oldFlavorCount = 1000; } else { - oldflavorcount = info->flavor_count; //same reason as above + AddOnInfo& info = foundInfo->second; + oldFlavorCount = info.flavor_count; - DestroyInstantiatedFlavors(info); - PutAddonIfPossible(info); + _DestroyInstantiatedFlavors(info); + _PutAddonIfPossible(info); - if (info->addon) { - ERROR("MediaAddonServer::AddOnRemoved: couldn't unload addon %ld since flavors are in use\n", id); + if (info.addon) { + ERROR("MediaAddonServer::_AddOnRemoved: couldn't unload addon " + "%ld since flavors are in use\n", id); } + + fInfoMap.erase(foundInfo); } - fInfoMap->Remove(id); _DormantNodeManager->UnregisterAddon(id); - BPrivate::media::notifications::FlavorsChanged(id, 0, oldflavorcount); + BPrivate::media::notifications::FlavorsChanged(id, 0, oldFlavorCount); } void -MediaAddonServer::WatchDir(BEntry *dir) +MediaAddonServer::_WatchDir(BEntry* dir) { // send fake notices to trigger add-on loading BDirectory directory(dir); - node_ref nref; - entry_ref ref; BEntry entry; while (directory.GetNextEntry(&entry, false) == B_OK) { - if (entry.GetRef(&ref) != B_OK || entry.GetNodeRef(&nref) != B_OK) + node_ref nodeRef; + entry_ref ref; + if (entry.GetRef(&ref) != B_OK || entry.GetNodeRef(&nodeRef) != B_OK) continue; BMessage msg(B_NODE_MONITOR); msg.AddInt32("opcode", B_ENTRY_CREATED); msg.AddInt32("device", ref.device); msg.AddInt64("directory", ref.directory); - msg.AddInt64("node", nref.node); + msg.AddInt64("node", nodeRef.node); msg.AddString("name", ref.name); msg.AddBool("nowait", true); MessageReceived(&msg); } - dir->GetNodeRef(&nref); - watch_node(&nref, B_WATCH_DIRECTORY, be_app_messenger); -} - - -void -MediaAddonServer::MessageReceived(BMessage *msg) -{ - switch (msg->what) { - case MEDIA_ADDON_SERVER_PLAY_MEDIA: - { - const char *name, *type; - if ((msg->FindString(MEDIA_NAME_KEY, &name) != B_OK) - || (msg->FindString(MEDIA_TYPE_KEY, &type) != B_OK)) { - msg->SendReply(B_ERROR); - } - - PlayMediaFile(type, name); - msg->SendReply((uint32)B_OK); - // XXX don't know which reply is expected - return; - } - - case B_NODE_MONITOR: - { - switch (msg->FindInt32("opcode")) { - case B_ENTRY_CREATED: - { - const char *name; - entry_ref ref; - ino_t node; - BEntry e; - BPath p; - msg->FindString("name", &name); - msg->FindInt64("node", &node); - msg->FindInt32("device", &ref.device); - msg->FindInt64("directory", &ref.directory); - ref.set_name(name); - e.SetTo(&ref,false);// build a BEntry for the created file/link/dir - e.GetPath(&p); // get the path to the file/link/dir - e.SetTo(&ref,true); // travese links to see - if (e.IsFile()) { // if it's a link to a file, or a file - if (false == msg->FindBool("nowait")) { - // XXX wait 5 seconds if this is a regular notification - // because the file creation may not be finshed when the - // notification arrives (very ugly, how can we fix this?) - // this will also fail if copying takes longer than 5 seconds - snooze(5000000); - } - AddOnAdded(p.Path(),node); - } - return; - } - case B_ENTRY_REMOVED: - { - ino_t node; - msg->FindInt64("node",&node); - AddOnRemoved(node); - return; - } - case B_ENTRY_MOVED: - { - ino_t from; - ino_t to; - msg->FindInt64("from directory", &from); - msg->FindInt64("to directory", &to); - if (fSystemAddOnsNode == from || fUserAddOnsNode == from) { - msg->ReplaceInt32("opcode",B_ENTRY_REMOVED); - msg->AddInt64("directory",from); - MessageReceived(msg); - } - if (fSystemAddOnsNode == to || fUserAddOnsNode == to) { - msg->ReplaceInt32("opcode",B_ENTRY_CREATED); - msg->AddInt64("directory",to); - msg->AddBool("nowait",true); - MessageReceived(msg); - } - return; - } - } - break; - } - - default: - inherited::MessageReceived(msg); - break; - } - printf("MediaAddonServer: Unhandled message:\n"); - msg->PrintToStream(); + node_ref nodeRef; + if (dir->GetNodeRef(&nodeRef) == B_OK) + watch_node(&nodeRef, B_WATCH_DIRECTORY, be_app_messenger); } // #pragma mark - -void -DumpFlavorInfo(const flavor_info *info) -{ - printf(" name = %s\n",info->name); - printf(" info = %s\n",info->info); - printf(" internal_id = %ld\n",info->internal_id); - printf(" possible_count = %ld\n",info->possible_count); - printf(" flavor_flags = 0x%lx",info->flavor_flags); - if (info->flavor_flags & B_FLAVOR_IS_GLOBAL) printf(" B_FLAVOR_IS_GLOBAL"); - if (info->flavor_flags & B_FLAVOR_IS_LOCAL) printf(" B_FLAVOR_IS_LOCAL"); - printf("\n"); - printf(" kinds = 0x%Lx",info->kinds); - if (info->kinds & B_BUFFER_PRODUCER) printf(" B_BUFFER_PRODUCER"); - if (info->kinds & B_BUFFER_CONSUMER) printf(" B_BUFFER_CONSUMER"); - if (info->kinds & B_TIME_SOURCE) printf(" B_TIME_SOURCE"); - if (info->kinds & B_CONTROLLABLE) printf(" B_CONTROLLABLE"); - if (info->kinds & B_FILE_INTERFACE) printf(" B_FILE_INTERFACE"); - if (info->kinds & B_ENTITY_INTERFACE) printf(" B_ENTITY_INTERFACE"); - if (info->kinds & B_PHYSICAL_INPUT) printf(" B_PHYSICAL_INPUT"); - if (info->kinds & B_PHYSICAL_OUTPUT) printf(" B_PHYSICAL_OUTPUT"); - if (info->kinds & B_SYSTEM_MIXER) printf(" B_SYSTEM_MIXER"); - printf("\n"); - printf(" in_format_count = %ld\n",info->in_format_count); - printf(" out_format_count = %ld\n",info->out_format_count); -} - - int main() {