c067ed4ea4
* Add check whether directory to store settings exists. If not, create it. * Use global constant (like in DefaultManager.cpp) for path/file names. * Cleaned up a little bit and made debug output only appear in case debugging is turned on (meaning printf->TRACE). -> Fixes #1531. (I added a few more error checks to the code, maybe there should be even more...) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24089 a95241bf-73f2-0310-859d-f6bbb57e9c96
415 lines
9.0 KiB
C++
415 lines
9.0 KiB
C++
/*
|
|
* Copyright 2003, Jérôme Duval. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
#include "debug.h"
|
|
#include "MMediaFilesManager.h"
|
|
#include "MediaSounds.h"
|
|
|
|
#include <Application.h>
|
|
#include <Autolock.h>
|
|
#include <Directory.h>
|
|
#include <FindDirectory.h>
|
|
#include <MediaFiles.h>
|
|
#include <Path.h>
|
|
#include <string.h>
|
|
|
|
|
|
const char *kMediaFilesManagerSettingsDirectory = "Media";
|
|
const char *kMediaFilesManagerSettingsFile = "MMediaFilesManager";
|
|
|
|
|
|
MMediaFilesManager::MMediaFilesManager()
|
|
: fLocker(new BLocker("media files manager locker")),
|
|
fRegistryMap(new Map<BString, Map<BString, entry_ref> >),
|
|
fRunner(NULL)
|
|
{
|
|
CALLED();
|
|
entry_ref ref;
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_BEEP, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_STARTUP, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_KEY_DOWN, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_KEY_REPEAT, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_KEY_UP, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_MOUSE_DOWN, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_MOUSE_UP, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_WINDOW_ACTIVATED, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_WINDOW_CLOSE, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_WINDOW_MINIMIZED, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_WINDOW_OPEN, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_WINDOW_RESTORED, ref, false);
|
|
SetRefFor(MEDIA_TYPE_SOUNDS, MEDIA_SOUNDS_WINDOW_ZOOMED, ref, false);
|
|
|
|
LoadState();
|
|
#if DEBUG >=3
|
|
Dump();
|
|
#endif
|
|
}
|
|
|
|
|
|
MMediaFilesManager::~MMediaFilesManager()
|
|
{
|
|
CALLED();
|
|
delete fRunner;
|
|
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();
|
|
BPath path;
|
|
status_t err = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
if (err >= B_OK)
|
|
err = path.Append(kMediaFilesManagerSettingsDirectory);
|
|
if (err >= B_OK)
|
|
err = path.Append(kMediaFilesManagerSettingsFile);
|
|
if (err < B_OK)
|
|
return err;
|
|
|
|
BFile file(path.Path(), B_READ_ONLY);
|
|
|
|
uint32 category_count;
|
|
if (file.Read(header, sizeof(uint32)*3) < (int32)sizeof(uint32)*3) {
|
|
header[0] = 0xac00150c;
|
|
header[1] = 0x18723462;
|
|
header[2] = 0x00000001;
|
|
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 {
|
|
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);
|
|
if (entry.Exists())
|
|
entry.GetRef(&ref);
|
|
}
|
|
SetRefFor(str, key, ref, false);
|
|
|
|
free(key);
|
|
free(val);
|
|
} while (true);
|
|
TRACE("}\n");
|
|
free(str);
|
|
}
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
MMediaFilesManager::SaveState()
|
|
{
|
|
CALLED();
|
|
BPath path;
|
|
status_t err = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
if (err >= B_OK)
|
|
err = path.Append(kMediaFilesManagerSettingsDirectory);
|
|
if (err >= B_OK) {
|
|
err = create_directory(path.Path(),
|
|
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
}
|
|
if (err >= B_OK)
|
|
err = path.Append(kMediaFilesManagerSettingsFile);
|
|
if (err < B_OK)
|
|
return err;
|
|
|
|
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 = NULL;
|
|
Map<BString, entry_ref> *map;
|
|
BString *item = NULL;
|
|
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);
|
|
|
|
/* for each type, the registry map contains a map of item/entry_ref
|
|
*/
|
|
TRACE("MMediaFilesManager: registry map follows\n");
|
|
BString *type = NULL;
|
|
Map<BString, entry_ref> *map;
|
|
BString *item = NULL;
|
|
entry_ref *ref;
|
|
for (fRegistryMap->Rewind(); fRegistryMap->GetNext(&map);) {
|
|
fRegistryMap->GetCurrentKey(&type);
|
|
|
|
for (map->Rewind(); map->GetNext(&ref);) {
|
|
map->GetCurrentKey(&item);
|
|
BPath path(ref);
|
|
TRACE(" type \"%s\", item \"%s\", path \"%s\"\n",
|
|
type->String(), item->String(), (path.InitCheck() == B_OK) ? path.Path() : "INVALID");
|
|
}
|
|
}
|
|
TRACE("MMediaFilesManager: list end\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 = NULL;
|
|
|
|
*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 = NULL;
|
|
entry_ref *ref;
|
|
BString *item = NULL;
|
|
|
|
*count = 0;
|
|
*items = NULL;
|
|
|
|
if (!fRegistryMap->Get(BString(type), &map))
|
|
return B_OK;
|
|
|
|
*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 = NULL;
|
|
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, bool save)
|
|
{
|
|
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);
|
|
if (save)
|
|
LaunchTimer();
|
|
|
|
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)) {
|
|
map->Remove(itemString);
|
|
map->Insert(itemString, *(new entry_ref));
|
|
LaunchTimer();
|
|
}
|
|
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)) {
|
|
map->Remove(itemString);
|
|
LaunchTimer();
|
|
}
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
void
|
|
MMediaFilesManager::LaunchTimer()
|
|
{
|
|
if (!fRunner)
|
|
fRunner = new BMessageRunner(be_app,
|
|
new BMessage(MMEDIAFILESMANAGER_SAVE_TIMER), 3 * 1000000LL, 1);
|
|
}
|
|
|
|
|
|
void
|
|
MMediaFilesManager::TimerMessage()
|
|
{
|
|
SaveState();
|
|
delete fRunner;
|
|
fRunner = NULL;
|
|
}
|
|
|
|
|
|
void
|
|
MMediaFilesManager::HandleAddSystemBeepEvent(BMessage *msg)
|
|
{
|
|
uint32 flags;
|
|
const char *name, *type;
|
|
if ((msg->FindString(MEDIA_NAME_KEY, &name) != B_OK)
|
|
|| (msg->FindString(MEDIA_TYPE_KEY, &type) != B_OK)
|
|
|| (msg->FindInt32(MEDIA_FLAGS_KEY, (int32 *) &flags) != B_OK)) {
|
|
msg->SendReply(B_BAD_VALUE);
|
|
return;
|
|
}
|
|
|
|
entry_ref *pRef = NULL;
|
|
if (GetRefFor(type, name, &pRef) == B_ENTRY_NOT_FOUND) {
|
|
entry_ref ref;
|
|
SetRefFor(type, name, ref);
|
|
}
|
|
}
|
|
|