/* * 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 #include #include #include #include #include #include const char *kMediaFilesManagerSettingsDirectory = "Media"; const char *kMediaFilesManagerSettingsFile = "MMediaFilesManager"; MMediaFilesManager::MMediaFilesManager() : fLocker(new BLocker("media files manager locker")), fRegistryMap(new Map >), 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 *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 *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 *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 *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 *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 *map; if (!fRegistryMap->Get(typeString, &map)) { map = new Map; 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 *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 *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); } }