mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-23 14:53:52 +00:00
546 lines
15 KiB
C++
546 lines
15 KiB
C++
|
|
//============================================================================
|
|
//----------------------------------------------------------------------------
|
|
// Prefs.c
|
|
//----------------------------------------------------------------------------
|
|
//============================================================================
|
|
|
|
#include "PLPasStr.h"
|
|
#include "DialogManager.h"
|
|
#include "Externs.h"
|
|
#include "Environ.h"
|
|
#include "FileManager.h"
|
|
#include "IGpAudioDriver.h"
|
|
#include "IGpDisplayDriver.h"
|
|
#include "IGpInputDriver.h"
|
|
#include "IGpPrefsHandler.h"
|
|
#include "IOStream.h"
|
|
#include "MemoryManager.h"
|
|
#include "HostAudioDriver.h"
|
|
#include "HostDisplayDriver.h"
|
|
#include "HostInputDriver.h"
|
|
|
|
|
|
#define kPrefCreatorType 'ozm5'
|
|
#define kPrefFileType 'gliP'
|
|
#define kPrefFileName PSTR("Glider Prefs v2")
|
|
#define kDefaultPrefFName PSTR("Preferences")
|
|
#define kPrefsStringsID 160
|
|
#define kNewPrefsAlertID 160
|
|
#define kPrefsFNameIndex 1
|
|
|
|
typedef struct modulePrefsListEntry
|
|
{
|
|
THandle<char> m_identifier;
|
|
THandle<uint8_t> m_contents;
|
|
uint32_t m_version;
|
|
} modulePrefsListEntry;
|
|
|
|
Boolean CanUseFindFolder (void);
|
|
Boolean WritePrefs (const prefsInfo *, short versionNow, THandle<modulePrefsListEntry> *theModulePrefs);
|
|
PLError_t ReadPrefs (prefsInfo *thePrefs, short versionNeed, Boolean *isOldVersion, THandle<modulePrefsListEntry> *theModulePrefs);
|
|
Boolean DeletePrefs ();
|
|
void BringUpDeletePrefsAlert (void);
|
|
|
|
|
|
THandle<modulePrefsListEntry> theModulePrefs;
|
|
|
|
|
|
//============================================================== Functions
|
|
//-------------------------------------------------------------- CanUseFindFolder
|
|
|
|
Boolean CanUseFindFolder (void)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------- WritePrefs
|
|
|
|
Boolean WritePrefs (const prefsInfo *thePrefs, short versionNow, THandle<modulePrefsListEntry> modulePrefs)
|
|
{
|
|
PLError_t theErr;
|
|
PortabilityLayer::IOStream *fileStream;
|
|
long byteCount;
|
|
Str255 fileName;
|
|
|
|
PortabilityLayer::FileManager *fm = PortabilityLayer::FileManager::GetInstance();
|
|
|
|
PasStringCopy(kPrefFileName, fileName);
|
|
|
|
VFileSpec theSpecs = MakeVFileSpec(PortabilityLayer::VirtualDirectories::kPrefs, fileName);
|
|
if (!fm->FileExists(PortabilityLayer::VirtualDirectories::kPrefs, fileName))
|
|
{
|
|
theErr = fm->CreateFileAtCurrentTime(theSpecs.m_dir, theSpecs.m_name, kPrefCreatorType, kPrefFileType);
|
|
if (theErr != PLErrors::kNone)
|
|
{
|
|
CheckFileError(theErr, PSTR("Preferences"));
|
|
return(false);
|
|
}
|
|
}
|
|
theErr = fm->OpenFileData(theSpecs.m_dir, theSpecs.m_name, PortabilityLayer::EFilePermission_Write, fileStream);
|
|
if (theErr != PLErrors::kNone)
|
|
{
|
|
CheckFileError(theErr, PSTR("Preferences"));
|
|
return(false);
|
|
}
|
|
|
|
uint32_t version = versionNow;
|
|
if (fileStream->Write(&version, sizeof(version)) != sizeof(version))
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(false);
|
|
}
|
|
|
|
byteCount = sizeof(*thePrefs);
|
|
|
|
if (fileStream->Write(thePrefs, byteCount) != byteCount)
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(false);
|
|
}
|
|
|
|
uint32_t numEntries = 0;
|
|
if (modulePrefs)
|
|
numEntries = modulePrefs.MMBlock()->m_size / sizeof(modulePrefsListEntry);
|
|
|
|
if (fileStream->Write(&numEntries, sizeof(numEntries)) != sizeof(numEntries))
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(false);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < numEntries; i++)
|
|
{
|
|
modulePrefsListEntry *entry = (*modulePrefs) + i;
|
|
|
|
uint32_t version = entry->m_version;
|
|
|
|
if (fileStream->Write(&version, sizeof(version)) != sizeof(version))
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(false);
|
|
}
|
|
|
|
THandle<void> handles[2] = { entry->m_identifier.StaticCast<void>(), entry->m_contents.StaticCast<void>() };
|
|
|
|
for (int hi = 0; hi < 2; hi++)
|
|
{
|
|
uint32_t hSize = handles[hi].MMBlock()->m_size;
|
|
|
|
if (fileStream->Write(&hSize, sizeof(hSize)) != sizeof(hSize))
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(false);
|
|
}
|
|
|
|
if (fileStream->Write(*handles[hi], hSize) != hSize)
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
fileStream->Close();
|
|
|
|
return(true);
|
|
}
|
|
|
|
//-------------------------------------------------------------- SavePrefs
|
|
|
|
Boolean SavePrefs (prefsInfo *thePrefs, THandle<void> *modulePrefs, short versionNow)
|
|
{
|
|
if (!WritePrefs(thePrefs, versionNow, modulePrefs->StaticCast<modulePrefsListEntry>()))
|
|
return(false);
|
|
|
|
return(true);
|
|
}
|
|
|
|
static void DestroyModulePrefs(THandle<modulePrefsListEntry> *theModulePrefs)
|
|
{
|
|
if (!*theModulePrefs)
|
|
return;
|
|
|
|
modulePrefsListEntry *firstOldEntry = **theModulePrefs;
|
|
|
|
if (!firstOldEntry)
|
|
return;
|
|
|
|
size_t numOldPrefs = theModulePrefs->MMBlock()->m_size / sizeof(modulePrefsListEntry);
|
|
|
|
for (size_t i = 0; i < numOldPrefs; i++)
|
|
{
|
|
firstOldEntry[i].m_contents.Dispose();
|
|
firstOldEntry[i].m_identifier.Dispose();
|
|
firstOldEntry[i].~modulePrefsListEntry();
|
|
}
|
|
|
|
theModulePrefs->Dispose();
|
|
}
|
|
|
|
//-------------------------------------------------------------- ReadPrefs
|
|
|
|
PLError_t ReadPrefs (prefsInfo *thePrefs, short versionNeed, Boolean *isOldVersion, THandle<modulePrefsListEntry> *theModulePrefs)
|
|
{
|
|
PLError_t theErr;
|
|
PortabilityLayer::IOStream *fileStream;
|
|
long byteCount;
|
|
VFileSpec theSpecs;
|
|
Str255 fileName;
|
|
|
|
*isOldVersion = false;
|
|
|
|
PortabilityLayer::FileManager *fm = PortabilityLayer::FileManager::GetInstance();
|
|
|
|
PasStringCopy(kPrefFileName, fileName);
|
|
|
|
theSpecs = MakeVFileSpec(PortabilityLayer::VirtualDirectory_t::kPrefs, fileName);
|
|
|
|
if (!PortabilityLayer::FileManager::GetInstance()->FileExists(theSpecs.m_dir, theSpecs.m_name))
|
|
return PLErrors::kFileNotFound;
|
|
|
|
theErr = fm->OpenFileData(theSpecs.m_dir, theSpecs.m_name, PortabilityLayer::EFilePermission_Read, fileStream);
|
|
if (theErr != PLErrors::kNone)
|
|
{
|
|
CheckFileError(theErr, PSTR("Preferences"));
|
|
return(theErr);
|
|
}
|
|
|
|
uint32_t version = 0;
|
|
if (fileStream->Read(&version, sizeof(version)) != sizeof(version))
|
|
{
|
|
CheckFileError(theErr, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
|
|
if (version != versionNeed)
|
|
{
|
|
*isOldVersion = true;
|
|
fileStream->Close();
|
|
return(PLErrors::kNone);
|
|
}
|
|
|
|
byteCount = sizeof(*thePrefs);
|
|
|
|
if (fileStream->Read(thePrefs, byteCount) != byteCount)
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
|
|
uint32_t numModulePrefs = 0;
|
|
if (fileStream->Read(&numModulePrefs, sizeof(numModulePrefs)) != sizeof(numModulePrefs))
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
|
|
DestroyModulePrefs(theModulePrefs);
|
|
|
|
if (numModulePrefs)
|
|
{
|
|
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
|
|
|
*theModulePrefs = THandle<modulePrefsListEntry>(mm->AllocHandle(numModulePrefs * sizeof(modulePrefsListEntry)));
|
|
|
|
if (!*theModulePrefs)
|
|
{
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
|
|
modulePrefsListEntry *firstNewEntry = **theModulePrefs;
|
|
|
|
for (size_t i = 0; i < numModulePrefs; i++)
|
|
new (firstNewEntry + i) modulePrefsListEntry();
|
|
|
|
for (uint32_t i = 0; i < numModulePrefs; i++)
|
|
{
|
|
if (fileStream->Read(&firstNewEntry[i].m_version, sizeof(firstNewEntry[i].m_version)) != sizeof(firstNewEntry[i].m_version))
|
|
{
|
|
DestroyModulePrefs(theModulePrefs);
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
|
|
for (int subHandle = 0; subHandle < 2; subHandle++)
|
|
{
|
|
uint32_t handleSz;
|
|
if (fileStream->Read(&handleSz, sizeof(handleSz)) != sizeof(handleSz))
|
|
{
|
|
DestroyModulePrefs(theModulePrefs);
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
|
|
PortabilityLayer::MMHandleBlock *mmBlock = mm->AllocHandle(handleSz);
|
|
if (!mmBlock)
|
|
{
|
|
DestroyModulePrefs(theModulePrefs);
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
|
|
if (subHandle == 0)
|
|
firstNewEntry[i].m_identifier = THandle<char>(mmBlock);
|
|
else
|
|
firstNewEntry[i].m_contents = THandle<uint8_t>(mmBlock);
|
|
|
|
if (fileStream->Read(mmBlock->m_contents, handleSz) != handleSz)
|
|
{
|
|
DestroyModulePrefs(theModulePrefs);
|
|
CheckFileError(PLErrors::kIOError, PSTR("Preferences"));
|
|
fileStream->Close();
|
|
return(PLErrors::kIOError);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fileStream->Close();
|
|
|
|
return(theErr);
|
|
}
|
|
|
|
//-------------------------------------------------------------- DeletePrefs
|
|
|
|
Boolean DeletePrefs ()
|
|
{
|
|
VFileSpec theSpecs;
|
|
Str255 fileName;
|
|
PLError_t theErr;
|
|
|
|
PasStringCopy(kPrefFileName, fileName);
|
|
|
|
theSpecs = MakeVFileSpec(PortabilityLayer::VirtualDirectories::kPrefs, fileName);
|
|
|
|
return PortabilityLayer::FileManager::GetInstance()->DeleteFile(theSpecs.m_dir, theSpecs.m_name);
|
|
}
|
|
|
|
//-------------------------------------------------------------- RunFunctionOnAllPrefsHandlers
|
|
bool RunFunctionOnAllPrefsHandlers (void *context, bool (*func) (void *context, IGpPrefsHandler *handler))
|
|
{
|
|
IGpPrefsHandler *ddHandler = PortabilityLayer::HostDisplayDriver::GetInstance()->GetPrefsHandler();
|
|
if (ddHandler && !func(context, ddHandler))
|
|
return false;
|
|
|
|
IGpPrefsHandler *adHandler = PortabilityLayer::HostAudioDriver::GetInstance()->GetPrefsHandler();
|
|
if (adHandler && !func(context, adHandler))
|
|
return false;
|
|
|
|
size_t numInputDrivers = PortabilityLayer::HostInputDriver::NumInstances();
|
|
|
|
for (size_t i = 0; i < numInputDrivers; i++)
|
|
{
|
|
IGpPrefsHandler *idHandler = PortabilityLayer::HostInputDriver::GetInstance(i)->GetPrefsHandler();
|
|
if (idHandler && !func(context, idHandler))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------- LoadPrefs
|
|
|
|
Boolean LoadPrefs (prefsInfo *thePrefs, THandle<void> *modulePrefs, short versionNeed)
|
|
{
|
|
PLError_t theErr;
|
|
Boolean noProblems;
|
|
Boolean isOldVersion = 0;
|
|
|
|
THandle<modulePrefsListEntry> mPrefs;
|
|
|
|
theErr = ReadPrefs(thePrefs, versionNeed, &isOldVersion, &mPrefs);
|
|
|
|
if (theErr == PLErrors::kFileNotFound)
|
|
return (false);
|
|
|
|
if (theErr != PLErrors::kNone)
|
|
{
|
|
BringUpDeletePrefsAlert();
|
|
noProblems = DeletePrefs();
|
|
return (false);
|
|
}
|
|
|
|
if (isOldVersion)
|
|
{
|
|
BringUpDeletePrefsAlert();
|
|
noProblems = DeletePrefs();
|
|
return(false);
|
|
}
|
|
|
|
*modulePrefs = mPrefs.StaticCast<void>();
|
|
|
|
return (true);
|
|
}
|
|
|
|
//-------------------------------------------------------------- BringUpDeletePrefsAlert
|
|
|
|
static THandle<void> CloneHandle(THandle<void> hdl)
|
|
{
|
|
if (!hdl)
|
|
return THandle<void>();
|
|
|
|
PortabilityLayer::MMHandleBlock *newHdl = PortabilityLayer::MemoryManager::GetInstance()->AllocHandle(hdl.MMBlock()->m_size);
|
|
if (!newHdl)
|
|
return THandle<void>();
|
|
|
|
memcpy(newHdl->m_contents, hdl.MMBlock()->m_contents, hdl.MMBlock()->m_size);
|
|
|
|
return THandle<void>(newHdl);
|
|
}
|
|
|
|
struct SaveModulePrefsContext
|
|
{
|
|
size_t m_numModulePrefs;
|
|
THandle<modulePrefsListEntry> m_newPrefs;
|
|
};
|
|
|
|
bool SaveModulePrefsWriteFunc(void *vcontext, const void *identifier, size_t identifierSize, const void *contents, size_t contentsSize, uint32_t version)
|
|
{
|
|
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
|
|
|
SaveModulePrefsContext *context = static_cast<SaveModulePrefsContext*>(vcontext);
|
|
modulePrefsListEntry *saveToEntry = nullptr;
|
|
|
|
for (size_t i = 0; i < context->m_numModulePrefs; i++)
|
|
{
|
|
modulePrefsListEntry *checkEntry = (*context->m_newPrefs) + i;
|
|
THandle<char> candidateIdentHdl = checkEntry->m_identifier;
|
|
size_t candidateIdentSize = candidateIdentHdl.MMBlock()->m_size;
|
|
|
|
if (candidateIdentSize == identifierSize && !memcmp(*candidateIdentHdl, identifier, candidateIdentSize))
|
|
{
|
|
saveToEntry = checkEntry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!saveToEntry)
|
|
{
|
|
if (context->m_numModulePrefs == 0)
|
|
context->m_newPrefs = THandle<modulePrefsListEntry>(mm->AllocHandle(sizeof(modulePrefsListEntry)));
|
|
else
|
|
mm->ResizeHandle(context->m_newPrefs.MMBlock(), (context->m_numModulePrefs + 1) * sizeof(modulePrefsListEntry));
|
|
|
|
saveToEntry = (*context->m_newPrefs) + context->m_numModulePrefs;
|
|
new (saveToEntry) modulePrefsListEntry();
|
|
|
|
context->m_numModulePrefs++;
|
|
}
|
|
|
|
if (saveToEntry->m_contents)
|
|
saveToEntry->m_contents.Dispose();
|
|
|
|
if (!saveToEntry->m_identifier)
|
|
{
|
|
saveToEntry->m_identifier = THandle<char>(mm->AllocHandle(identifierSize));
|
|
memcpy(*saveToEntry->m_identifier, identifier, identifierSize);
|
|
}
|
|
|
|
saveToEntry->m_contents = THandle<uint8_t>(mm->AllocHandle(contentsSize));
|
|
memcpy(*saveToEntry->m_contents, contents, contentsSize);
|
|
|
|
saveToEntry->m_version = version;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SaveModulePrefsCallback(void *vcontext, IGpPrefsHandler *handler)
|
|
{
|
|
return handler->SavePrefs(vcontext, SaveModulePrefsWriteFunc);
|
|
}
|
|
|
|
Boolean SaveModulePrefs(THandle<void> currentModulePrefs, THandle<void> *outModulePrefs)
|
|
{
|
|
SaveModulePrefsContext context;
|
|
|
|
size_t numModulePrefs = 0;
|
|
THandle<modulePrefsListEntry> newPrefs;
|
|
|
|
if (currentModulePrefs)
|
|
{
|
|
numModulePrefs = currentModulePrefs.MMBlock()->m_size / sizeof(modulePrefsListEntry);
|
|
newPrefs = CloneHandle(currentModulePrefs).StaticCast<modulePrefsListEntry>();
|
|
|
|
modulePrefsListEntry *entries = *newPrefs;
|
|
for (size_t i = 0; i < numModulePrefs; i++)
|
|
{
|
|
entries[i].m_contents = CloneHandle(entries[i].m_contents.StaticCast<void>()).StaticCast<uint8_t>();
|
|
entries[i].m_identifier = CloneHandle(entries[i].m_identifier.StaticCast<void>()).StaticCast<char>();
|
|
}
|
|
}
|
|
else
|
|
newPrefs = THandle<modulePrefsListEntry>(PortabilityLayer::MemoryManager::GetInstance()->AllocHandle(0));
|
|
|
|
context.m_newPrefs = newPrefs;
|
|
context.m_numModulePrefs = numModulePrefs;
|
|
|
|
bool savedOK = RunFunctionOnAllPrefsHandlers(&context, SaveModulePrefsCallback);
|
|
|
|
if (savedOK)
|
|
{
|
|
outModulePrefs->Dispose();
|
|
*outModulePrefs = context.m_newPrefs.StaticCast<void>();
|
|
}
|
|
|
|
return savedOK;
|
|
}
|
|
|
|
//-------------------------------------------------------------- BringUpDeletePrefsAlert
|
|
|
|
struct ApplyModulePrefsContext
|
|
{
|
|
size_t m_numModulePrefs;
|
|
THandle<modulePrefsListEntry> m_newPrefs;
|
|
};
|
|
|
|
bool ApplyModulePrefsCallback(void *vcontext, IGpPrefsHandler *handler)
|
|
{
|
|
ApplyModulePrefsContext *context = static_cast<ApplyModulePrefsContext*>(vcontext);
|
|
|
|
const modulePrefsListEntry *entries = *(context->m_newPrefs);
|
|
|
|
for (size_t i = 0; i < context->m_numModulePrefs; i++)
|
|
handler->ApplyPrefs(*entries[i].m_identifier, entries[i].m_identifier.MMBlock()->m_size, *entries[i].m_contents, entries[i].m_contents.MMBlock()->m_size, entries[i].m_version);
|
|
|
|
return true;
|
|
}
|
|
|
|
Boolean ApplyModulePrefs (THandle<void> *modulePrefs)
|
|
{
|
|
ApplyModulePrefsContext context;
|
|
|
|
context.m_newPrefs = modulePrefs->StaticCast<modulePrefsListEntry>();
|
|
context.m_numModulePrefs = context.m_newPrefs.MMBlock()->m_size / sizeof(modulePrefsListEntry);
|
|
|
|
return RunFunctionOnAllPrefsHandlers(&context, ApplyModulePrefsCallback);
|
|
}
|
|
|
|
//-------------------------------------------------------------- BringUpDeletePrefsAlert
|
|
|
|
void BringUpDeletePrefsAlert (void)
|
|
{
|
|
short whoCares;
|
|
|
|
InitCursor();
|
|
// CenterAlert(kNewPrefsAlertID);
|
|
whoCares = PortabilityLayer::DialogManager::GetInstance()->DisplayAlert(kNewPrefsAlertID, nullptr);
|
|
}
|
|
|