MediaFiles support added

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5324 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2003-11-12 10:24:42 +00:00
parent adcc5beaca
commit 4691dc7ff8
6 changed files with 680 additions and 15 deletions

View File

@ -1,34 +1,73 @@
/***********************************************************************
* AUTHOR: Marcus Overhagen
* AUTHOR: Marcus Overhagen, Jérôme Duval
* FILE: MediaFiles.cpp
* DESCR:
***********************************************************************/
#include <MediaFiles.h>
#include "DataExchange.h"
#include "debug.h"
/*************************************************************
* public BMediaFiles
*************************************************************/
const char BMediaFiles::B_SOUNDS[] = "XXX fixme"; /* for "types" */
const char BMediaFiles::B_SOUNDS[] = "Sounds"; /* for "types" */
BMediaFiles::BMediaFiles()
: m_type_index(-1),
m_cur_type(""),
m_item_index(-1)
{
UNIMPLEMENTED();
}
/* virtual */
BMediaFiles::~BMediaFiles()
{
UNIMPLEMENTED();
}
/* virtual */ status_t
BMediaFiles::RewindTypes()
{
UNIMPLEMENTED();
CALLED();
status_t rv;
server_rewindtypes_request request;
server_rewindtypes_reply reply;
for(int32 i = 0; i < m_types.CountItems(); i++)
delete m_types.ItemAt(i);
m_types.MakeEmpty();
TRACE("BMediaFiles::RewindTypes: sending SERVER_REWINDTYPES\n");
rv = QueryServer(SERVER_REWINDTYPES, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK) {
ERROR("BMediaFiles::RewindTypes: failed to rewindtypes (error %#lx)\n", rv);
return rv;
}
char *types;
area_id clone;
clone = clone_area("rewind types clone", reinterpret_cast<void **>(&types), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area);
if (clone < B_OK) {
ERROR("BMediaFiles::RewindTypes failed to clone area, %#lx\n", clone);
delete_area(reply.area);
return B_ERROR;
}
for (int32 i = 0; i < reply.count; i++) {
m_types.AddItem(new BString(types + i * B_MEDIA_NAME_LENGTH));
}
delete_area(clone);
delete_area(reply.area);
m_type_index = 0;
return B_OK;
}
@ -37,16 +76,62 @@ BMediaFiles::RewindTypes()
/* virtual */ status_t
BMediaFiles::GetNextType(BString *out_type)
{
UNIMPLEMENTED();
CALLED();
if(m_type_index < 0 || m_type_index >= m_types.CountItems()) {
m_type_index = -1;
return B_BAD_INDEX;
}
*out_type = *(BString*)m_types.ItemAt(m_type_index);
m_type_index++;
return B_ERROR;
return B_OK;
}
/* virtual */ status_t
BMediaFiles::RewindRefs(const char *type)
{
UNIMPLEMENTED();
CALLED();
status_t rv;
server_rewindrefs_request request;
server_rewindrefs_reply reply;
for(int32 i = 0; i < m_items.CountItems(); i++)
delete m_items.ItemAt(i);
m_items.MakeEmpty();
TRACE("BMediaFiles::RewindRefs: sending SERVER_REWINDREFS for type %s\n", type);
strncpy(request.type, type, B_MEDIA_NAME_LENGTH);
rv = QueryServer(SERVER_REWINDREFS, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK) {
ERROR("BMediaFiles::RewindRefs: failed to rewindrefs (error %#lx)\n", rv);
return rv;
}
if(reply.count>0) {
char *items;
area_id clone;
clone = clone_area("rewind refs clone", reinterpret_cast<void **>(&items), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, reply.area);
if (clone < B_OK) {
ERROR("BMediaFiles::RewindRefs failed to clone area, %#lx\n", clone);
delete_area(reply.area);
return B_ERROR;
}
for (int32 i = 0; i < reply.count; i++) {
m_items.AddItem(new BString(items + i * B_MEDIA_NAME_LENGTH));
}
delete_area(clone);
delete_area(reply.area);
}
m_cur_type = BString(type);
m_item_index = 0;
return B_OK;
}
@ -56,9 +141,18 @@ BMediaFiles::RewindRefs(const char *type)
BMediaFiles::GetNextRef(BString *out_type,
entry_ref *out_ref)
{
UNIMPLEMENTED();
CALLED();
if(m_item_index < 0 || m_item_index >= m_items.CountItems()) {
m_item_index = -1;
return B_BAD_INDEX;
}
*out_type = *(BString*)m_items.ItemAt(m_item_index);
m_item_index++;
GetRefFor(m_cur_type.String(), out_type->String(), out_ref);
return B_ERROR;
return B_OK;
}
@ -67,9 +161,25 @@ BMediaFiles::GetRefFor(const char *type,
const char *item,
entry_ref *out_ref)
{
UNIMPLEMENTED();
CALLED();
status_t rv;
server_getreffor_request request;
server_getreffor_reply reply;
strncpy(request.type, type, B_MEDIA_NAME_LENGTH);
strncpy(request.item, item, B_MEDIA_NAME_LENGTH);
TRACE("BMediaFiles::GetRefFor: sending SERVER_GETREFFOR\n");
rv = QueryServer(SERVER_GETREFFOR, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK) {
ERROR("BMediaFiles::GetRefFor: failed to getreffor (error %#lx)\n", rv);
return rv;
}
return B_ERROR;
*out_ref = reply.ref;
return B_OK;
}
@ -78,7 +188,22 @@ BMediaFiles::SetRefFor(const char *type,
const char *item,
const entry_ref &ref)
{
UNIMPLEMENTED();
CALLED();
status_t rv;
server_setreffor_request request;
server_setreffor_reply reply;
strncpy(request.type, type, B_MEDIA_NAME_LENGTH);
strncpy(request.item, item, B_MEDIA_NAME_LENGTH);
request.ref = ref;
TRACE("BMediaFiles::SetRefFor: sending SERVER_SETREFFOR\n");
rv = QueryServer(SERVER_SETREFFOR, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK) {
ERROR("BMediaFiles::SetRefFor: failed to setreffor (error %#lx)\n", rv);
return rv;
}
return B_OK;
}
@ -89,7 +214,21 @@ BMediaFiles::RemoveRefFor(const char *type,
const char *item,
const entry_ref &ref)
{
UNIMPLEMENTED();
status_t rv;
server_removereffor_request request;
server_removereffor_reply reply;
strncpy(request.type, type, B_MEDIA_NAME_LENGTH);
strncpy(request.item, item, B_MEDIA_NAME_LENGTH);
request.ref = ref;
TRACE("BMediaFiles::RemoveRefFor: sending SERVER_REMOVEREFFOR\n");
rv = QueryServer(SERVER_REMOVEREFFOR, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK) {
ERROR("BMediaFiles::RemoveRefFor: failed to removereffor (error %#lx)\n", rv);
return rv;
}
return B_OK;
}
@ -99,7 +238,20 @@ BMediaFiles::RemoveRefFor(const char *type,
BMediaFiles::RemoveItem(const char *type,
const char *item)
{
UNIMPLEMENTED();
status_t rv;
server_removeitem_request request;
server_removeitem_reply reply;
strncpy(request.type, type, B_MEDIA_NAME_LENGTH);
strncpy(request.item, item, B_MEDIA_NAME_LENGTH);
TRACE("BMediaFiles::RemoveItem: sending SERVER_REMOVEITEM\n");
rv = QueryServer(SERVER_REMOVEITEM, &request, sizeof(request), &reply, sizeof(reply));
if (rv != B_OK) {
ERROR("BMediaFiles::RemoveItem: failed to removeitem (error %#lx)\n", rv);
return rv;
}
return B_OK;
}

View File

@ -9,6 +9,7 @@ Server media_server :
AppManager.cpp
BufferManager.cpp
DefaultManager.cpp
MMediaFilesManager.cpp
NodeManager.cpp
NotificationManager.cpp
Queue.cpp

View File

@ -0,0 +1,336 @@
/*
* Copyright 2003, Jérôme Duval. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <Autolock.h>
#include <string.h>
#include <storage/FindDirectory.h>
#include <storage/Path.h>
#include "MMediaFilesManager.h"
#include "debug.h"
MMediaFilesManager::MMediaFilesManager()
: fLocker(new BLocker("media files manager locker")),
fRegistryMap(new Map<BString, Map<BString, entry_ref> >)
{
CALLED();
LoadState();
#if DEBUG >=3
Dump();
#endif
}
MMediaFilesManager::~MMediaFilesManager()
{
CALLED();
SaveState();
delete fRegistryMap;
delete fLocker;
}
int32
MMediaFilesManager::ReadPascalString(BFile &file, char **str)
{
uint32 len;
*str=NULL;
if (file.Read(&len, 4) < 4)
return -1;
if (len == 0)
return 0;
*str = (char *)malloc(len);
if (file.Read(*str, len) < (int32)len) {
free(*str);
*str = NULL;
return -1;
}
return (int32)len;
}
int32
MMediaFilesManager::WritePascalString(BFile &file, const char *str)
{
if(str == NULL)
return -1;
uint32 len = strlen(str) + 1;
if (file.Write(&len, 4) < 4)
return -1;
if (len == 0)
return 0;
if (file.Write(str, len) < (int32)len) {
return -1;
}
return (int32)len;
}
// this is called by the media_server *before* any add-ons have been loaded
status_t
MMediaFilesManager::LoadState()
{
CALLED();
status_t err = B_OK;
BPath path;
if((err = find_directory(B_USER_SETTINGS_DIRECTORY, &path))!=B_OK)
return err;
path.Append("Media/MMediaFilesManager");
BFile file(path.Path(), B_READ_ONLY);
uint32 category_count;
if (file.Read(header, sizeof(uint32)*3) < (int32)sizeof(uint32)*3)
return B_ERROR;
TRACE("0x%08lx %ld\n", header[0], header[0]);
TRACE("0x%08lx %ld\n", header[1], header[1]);
TRACE("0x%08lx %ld\n", header[2], header[2]);
if (file.Read(&category_count, sizeof(uint32)) < (int32)sizeof(uint32))
return B_ERROR;
while (category_count--) {
char *str;
char *key, *val;
int32 len;
len = ReadPascalString(file, &str);
if (len < 0)
return B_ERROR;
if (len == 0)
break;
TRACE("%s {\n", str);
do {
int32 vol = 0;
len = ReadPascalString(file, &key);
if (len < 0)
return B_ERROR;
if (len == 0)
break;
len = ReadPascalString(file, &val);
if (len == 1) {
free(val);
val = strdup("(null)");
}
/*if (file.Read(&vol, sizeof(uint32)) < (int32)sizeof(uint32))
return B_ERROR;*/
TRACE(" %s: %s, volume: %f\n", key, val, *(float *)&vol);
entry_ref ref;
if(len>1) {
BEntry entry(val);
entry.GetRef(&ref);
}
SetRefFor(str, key, ref);
free(key);
free(val);
} while (true);
TRACE("}\n");
free(str);
}
return B_OK;
}
status_t
MMediaFilesManager::SaveState()
{
status_t err = B_OK;
BPath path;
if((err = find_directory(B_USER_SETTINGS_DIRECTORY, &path))!=B_OK)
return err;
path.Append("Media/MMediaFilesManager");
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE);
uint32 zero = 0;
if (file.Write(header, sizeof(uint32)*3) < (int32)sizeof(uint32)*3)
return B_ERROR;
uint32 category_count = fRegistryMap->CountItems();
if (file.Write(&category_count, sizeof(uint32)) < (int32)sizeof(uint32))
return B_ERROR;
BString *type;
Map<BString, entry_ref> *map;
BString *item;
entry_ref *ref;
for (fRegistryMap->Rewind(); fRegistryMap->GetNext(&map); ) {
fRegistryMap->GetCurrentKey(&type);
WritePascalString(file, type->String());
for (map->Rewind(); map->GetNext(&ref);) {
map->GetCurrentKey(&item);
BPath path(ref);
WritePascalString(file, item->String());
WritePascalString(file, path.Path() ? path.Path() : "");
}
file.Write(&zero, sizeof(uint32));
}
file.Write(&zero, sizeof(uint32));
return B_OK;
}
void
MMediaFilesManager::Dump()
{
BAutolock lock(fLocker);
printf("\n");
/* for each type, the registry map contains a map of item/entry_ref
*/
printf("MMediaFilesManager: registry map follows\n");
BString *type;
Map<BString, entry_ref> *map;
BString *item;
entry_ref *ref;
for (fRegistryMap->Rewind(); fRegistryMap->GetNext(&map); ) {
fRegistryMap->GetCurrentKey(&type);
for (map->Rewind(); map->GetNext(&ref);) {
map->GetCurrentKey(&item);
BPath path(ref);
printf(" type \"%s\", item \"%s\", path \"%s\"\n",
type->String(), item->String(), (path.InitCheck() == B_OK) ? path.Path() : "INVALID");
}
}
printf("MMediaFilesManager: list end\n");
printf("\n");
}
status_t
MMediaFilesManager::RewindTypes(BString ***types, int32 *count)
{
CALLED();
if(types==NULL || count == NULL)
return B_BAD_VALUE;
Map<BString, entry_ref> *map;
BString *type;
*count = fRegistryMap->CountItems();
*types = new (BString*)[*count];
int32 i=0;
for (fRegistryMap->Rewind(); i<*count && fRegistryMap->GetNext(&map); i++) {
fRegistryMap->GetCurrentKey(&type);
(*types)[i] = type;
}
return B_OK;
}
status_t
MMediaFilesManager::RewindRefs(const char* type, BString ***items, int32 *count)
{
CALLED();
if(type == NULL || items==NULL || count == NULL)
return B_BAD_VALUE;
Map<BString, entry_ref> *map;
entry_ref *ref;
BString *item;
fRegistryMap->Get(BString(type), &map);
*count = map->CountItems();
*items = new (BString*)[*count];
int32 i=0;
for (map->Rewind(); i<*count && map->GetNext(&ref); i++) {
map->GetCurrentKey(&item);
(*items)[i] = item;
}
return B_OK;
}
status_t
MMediaFilesManager::GetRefFor(const char *type,
const char *item,
entry_ref **out_ref)
{
CALLED();
Map <BString, entry_ref> *map;
if(!fRegistryMap->Get(BString(type), &map))
return B_ENTRY_NOT_FOUND;
if(!map->Get(BString(item), out_ref))
return B_ENTRY_NOT_FOUND;
return B_OK;
}
status_t
MMediaFilesManager::SetRefFor(const char *type,
const char *item,
const entry_ref &ref)
{
CALLED();
TRACE("MMediaFilesManager::SetRefFor %s %s\n", type, item);
BString itemString(item);
itemString.Truncate(B_MEDIA_NAME_LENGTH);
BString typeString(type);
Map <BString, entry_ref> *map;
if(!fRegistryMap->Get(typeString, &map)) {
map = new Map<BString, entry_ref>;
fRegistryMap->Insert(typeString, *map);
fRegistryMap->Get(typeString, &map);
}
if(map->Has(itemString))
map->Remove(itemString);
map->Insert(itemString, ref);
return B_OK;
}
status_t
MMediaFilesManager::RemoveRefFor(const char *type,
const char *item,
const entry_ref &ref)
{
CALLED();
BString itemString(item);
BString typeString(type);
Map <BString, entry_ref> *map;
if(!fRegistryMap->Get(typeString, &map))
return B_OK;
map->Remove(itemString);
map->Insert(itemString, *(new entry_ref));
return B_OK;
}
status_t
MMediaFilesManager::RemoveItem(const char *type,
const char *item)
{
CALLED();
BString itemString(item);
BString typeString(type);
Map <BString, entry_ref> *map;
if(!fRegistryMap->Get(typeString, &map))
return B_OK;
map->Remove(itemString);
return B_OK;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright 2003, Jérôme Duval. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <Entry.h>
#include <File.h>
#include <Locker.h>
#include <String.h>
#include "TMap.h"
#include "DataExchange.h"
class MMediaFilesManager
{
public:
MMediaFilesManager();
~MMediaFilesManager();
status_t LoadState();
status_t SaveState();
void Dump();
status_t RewindTypes(
BString ***types,
int32 *count);
status_t RewindRefs(
const char * type,
BString ***items,
int32 *count);
status_t GetRefFor(
const char * type,
const char * item,
entry_ref ** out_ref);
status_t SetRefFor(
const char * type,
const char * item,
const entry_ref & ref);
status_t RemoveRefFor( // This might better be called "ClearRefFor"
const char * type, // but it's too late now...
const char * item,
const entry_ref & ref);
status_t RemoveItem( // new in 4.1, removes the whole item.
const char * type,
const char * item);
private:
static int32 ReadPascalString(BFile &file, char **str);
static int32 WritePascalString(BFile &file, const char *str);
private:
BLocker *fLocker;
Map<BString, Map<BString, entry_ref> > * fRegistryMap;
uint32 header[3];
};

View File

@ -37,6 +37,7 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 Marcus Ov
#include <MediaFormats.h>
#include <Autolock.h>
#include <string.h>
#include "MMediaFilesManager.h"
#include "NotificationManager.h"
#include "ServerInterface.h"
#include "DataExchange.h"
@ -58,6 +59,7 @@ NotificationManager *gNotificationManager;
BufferManager *gBufferManager;
AppManager *gAppManager;
NodeManager *gNodeManager;
MMediaFilesManager *gMMediaFilesManager;
namespace BPrivate { namespace media {
extern team_id team;
@ -118,6 +120,7 @@ ServerApp::ServerApp()
gBufferManager = new BufferManager;
gAppManager = new AppManager;
gNodeManager = new NodeManager;
gMMediaFilesManager = new MMediaFilesManager;
control_port = create_port(64, MEDIA_SERVER_PORT_NAME);
control_thread = spawn_thread(controlthread, "media_server control", 105, this);
@ -135,6 +138,7 @@ ServerApp::~ServerApp()
delete gBufferManager;
delete gAppManager;
delete gNodeManager;
delete gMMediaFilesManager;
delete fLocker;
delete_port(control_port);
status_t err;
@ -149,6 +153,7 @@ void ServerApp::ArgvReceived(int32 argc, char **argv)
gNodeManager->Dump();
gBufferManager->Dump();
gNotificationManager->Dump();
gMMediaFilesManager->Dump();
}
if (strstr(argv[arg], "buffer")) {
gBufferManager->Dump();
@ -554,7 +559,117 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size)
gBufferManager->UnregisterBuffer(cmd->team, cmd->bufferid);
break;
}
case SERVER_REWINDTYPES:
{
const server_rewindtypes_request *request = reinterpret_cast<const server_rewindtypes_request *>(data);
server_rewindtypes_reply reply;
BString **types = NULL;
rv = gMMediaFilesManager->RewindTypes(
&types, &reply.count);
if(reply.count>0) {
// we create an area here, and pass it to the library, where it will be deleted.
char *start_addr;
size_t size = ((reply.count * B_MEDIA_NAME_LENGTH) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
reply.area = create_area("rewind types", reinterpret_cast<void **>(&start_addr), B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (reply.area < B_OK) {
ERROR("SERVER_REWINDTYPES: failed to create area, error %s\n", strerror(reply.area));
reply.count = 0;
rv = B_ERROR;
} else {
for (int32 index = 0; index < reply.count; index++)
strncpy(start_addr + B_MEDIA_NAME_LENGTH * index, types[index]->String(), B_MEDIA_NAME_LENGTH);
}
}
delete types;
rv = request->SendReply(rv, &reply, sizeof(reply));
if (rv != B_OK)
delete_area(reply.area); // if we couldn't send the message, delete the area
break;
}
case SERVER_REWINDREFS:
{
const server_rewindrefs_request *request = reinterpret_cast<const server_rewindrefs_request *>(data);
server_rewindrefs_reply reply;
BString **items = NULL;
rv = gMMediaFilesManager->RewindRefs(request->type,
&items, &reply.count);
// we create an area here, and pass it to the library, where it will be deleted.
if(reply.count>0) {
char *start_addr;
size_t size = ((reply.count * B_MEDIA_NAME_LENGTH) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
reply.area = create_area("rewind refs", reinterpret_cast<void **>(&start_addr), B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
if (reply.area < B_OK) {
ERROR("SERVER_REWINDREFS: failed to create area, error %s\n", strerror(reply.area));
reply.count = 0;
rv = B_ERROR;
} else {
for (int32 index = 0; index < reply.count; index++)
strncpy(start_addr + B_MEDIA_NAME_LENGTH * index, items[index]->String(), B_MEDIA_NAME_LENGTH);
}
}
delete items;
rv = request->SendReply(rv, &reply, sizeof(reply));
if (rv != B_OK)
delete_area(reply.area); // if we couldn't send the message, delete the area
break;
}
case SERVER_GETREFFOR:
{
const server_getreffor_request *request = reinterpret_cast<const server_getreffor_request *>(data);
server_getreffor_reply reply;
entry_ref *ref;
rv = gMMediaFilesManager->GetRefFor(request->type, request->item, &ref);
if(rv==B_OK) {
reply.ref = *ref;
}
request->SendReply(rv, &reply, sizeof(reply));
break;
}
case SERVER_SETREFFOR:
{
const server_setreffor_request *request = reinterpret_cast<const server_setreffor_request *>(data);
server_setreffor_reply reply;
entry_ref ref = request->ref;
rv = gMMediaFilesManager->SetRefFor(request->type, request->item, ref);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
case SERVER_REMOVEREFFOR:
{
const server_removereffor_request *request = reinterpret_cast<const server_removereffor_request *>(data);
server_removereffor_reply reply;
entry_ref ref = request->ref;
rv = gMMediaFilesManager->RemoveRefFor(request->type, request->item, ref);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
case SERVER_REMOVEITEM:
{
const server_removeitem_request *request = reinterpret_cast<const server_removeitem_request *>(data);
server_removeitem_reply reply;
rv = gMMediaFilesManager->RemoveItem(request->type, request->item);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
default:
printf("media_server: received unknown message code %#08lx\n",code);
}

View File

@ -3,8 +3,10 @@ class AppManager;
class NodeManager;
class BufferManager;
class NotificationManager;
class MMediaFilesManager;
extern AppManager * gAppManager;
extern NodeManager * gNodeManager;
extern BufferManager * gBufferManager;
extern NotificationManager * gNotificationManager;
extern MMediaFilesManager * gMMediaFilesManager;