Skip to content

Commit

Permalink
FEAT(client): profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
Hartmnt committed Jan 3, 2025
1 parent e64f334 commit 68990c1
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 4 deletions.
15 changes: 15 additions & 0 deletions src/mumble/JSONSerialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,21 @@ void from_json(const nlohmann::json &j, OverlaySettings &settings) {
}


void to_json(nlohmann::json &j, const Profiles &settings) {
#define PROCESS(category, key, variable) save(j, SettingsKeys::key, settings.variable);

PROCESS_ALL_PROFILE_SETTINGS

#undef PROCESS
}

void from_json(const nlohmann::json &j, Profiles &settings) {
#define PROCESS(category, key, variable) load(j, SettingsKeys::key, settings.variable, settings.variable, true);

PROCESS_ALL_PROFILE_SETTINGS

#undef PROCESS
}

void to_json(nlohmann::json &j, const QString &string) {
j = string.toStdString();
Expand Down
2 changes: 2 additions & 0 deletions src/mumble/JSONSerialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ void to_json(nlohmann::json &j, const Settings &settings);
void from_json(const nlohmann::json &j, Settings &settings);
void to_json(nlohmann::json &j, const OverlaySettings &settings);
void from_json(const nlohmann::json &j, OverlaySettings &settings);
void to_json(nlohmann::json &j, const Profiles &settings);
void from_json(const nlohmann::json &j, Profiles &settings);

void to_json(nlohmann::json &j, const QString &string);
void from_json(const nlohmann::json &j, QString &string);
Expand Down
49 changes: 45 additions & 4 deletions src/mumble/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,14 @@ void Settings::save(const QString &path) const {
throw std::runtime_error("Expected settings file to have \".json\" extension");
}

nlohmann::json settingsJSON = *this;
nlohmann::json settingsJSON = profiles;
nlohmann::json &profilesJSON = settingsJSON.at(SettingsKeys::PROFILES);
nlohmann::json activeProfileJSON = *this;

qInfo("Saving settings profile '%s'", qUtf8Printable(profiles.activeProfileName));

profilesJSON.erase(profiles.activeProfileName.toStdString());
profilesJSON.push_back({ profiles.activeProfileName, activeProfileJSON });

QFile tmpFile(QString::fromLatin1("%1/mumble_settings.json.tmp")
.arg(QStandardPaths::writableLocation(QStandardPaths::TempLocation)));
Expand Down Expand Up @@ -226,11 +233,36 @@ void Settings::load(const QString &path) {

std::ifstream stream(Mumble::QtUtils::qstring_to_path(path));

nlohmann::json settingsJSON;
try {
stream >> settingsJSON;
nlohmann::json profilesJSON;
stream >> profilesJSON;

if (profilesJSON.contains(SettingsKeys::ACTIVE_PROFILE)) {
Profiles loadedProfiles;
profilesJSON.get_to(loadedProfiles);

if (loadedProfiles.allProfiles.contains(loadedProfiles.activeProfileName)) {
qInfo("Loading settings profile '%s'", qUtf8Printable(loadedProfiles.activeProfileName));
*this = loadedProfiles.allProfiles[loadedProfiles.activeProfileName];
} else if (loadedProfiles.allProfiles.contains(Profiles::s_default_profile_name)) {
qWarning("Failed to load settings profile '%s'. Falling back to 'default'...",
qUtf8Printable(loadedProfiles.activeProfileName));
loadedProfiles.activeProfileName = Profiles::s_default_profile_name;
*this = loadedProfiles.allProfiles[Profiles::s_default_profile_name];
} else {
qWarning("Failed to load profile 'default'. Trying to load raw settings file...");
profilesJSON.get_to(*this);
}

settingsJSON.get_to(*this);
// Assign the profile information loaded from file to this settings object for later use when saving.
profiles = loadedProfiles;
} else {
// The file does not contain the key "SettingsKeys::ACTIVE_PROFILE"
// We assume the JSON file does not contain any profiles, because it is
// old. We load the file raw instead and convert it to the s_default_profile_name profile.
qWarning("Migrating settings file to 'default' profile");
profilesJSON.get_to(*this);
}

if (!mumbleQuitNormally) {
// These settings were saved without Mumble quitting normally afterwards. In order to prevent loading
Expand Down Expand Up @@ -401,6 +433,8 @@ std::size_t qHash(const ChannelTarget &target) {
return qHash(target.channelID);
}

const QString Profiles::s_default_profile_name = QLatin1String("default");

const QString Settings::cqsDefaultPushClickOn = QLatin1String(":/on.ogg");
const QString Settings::cqsDefaultPushClickOff = QLatin1String(":/off.ogg");

Expand Down Expand Up @@ -1222,6 +1256,7 @@ void Settings::verifySettingsKeys() const {
#define INTERMEDIATE_OPERATION categoryNames.push_back(currentCategoryName);
PROCESS_ALL_SETTINGS_WITH_INTERMEDIATE_OPERATION
PROCESS_ALL_OVERLAY_SETTINGS_WITH_INTERMEDIATE_OPERATION
PROCESS_ALL_PROFILE_SETTINGS_WITH_INTERMEDIATE_OPERATION

// Assert that all entries in categoryNames are unique
std::sort(categoryNames.begin(), categoryNames.end());
Expand All @@ -1241,6 +1276,7 @@ void Settings::verifySettingsKeys() const {
keyNames.clear();
PROCESS_ALL_SETTINGS_WITH_INTERMEDIATE_OPERATION
PROCESS_ALL_OVERLAY_SETTINGS_WITH_INTERMEDIATE_OPERATION
PROCESS_ALL_PROFILE_SETTINGS_WITH_INTERMEDIATE_OPERATION
#undef PROCESS
#undef INTERMEDIATE_OPERATION

Expand All @@ -1255,6 +1291,11 @@ void Settings::verifySettingsKeys() const {
PROCESS_ALL_OVERLAY_SETTINGS
std::sort(variableNames.begin(), variableNames.end());
assert(std::unique(variableNames.begin(), variableNames.end()) == variableNames.end());
variableNames.clear();

PROCESS_ALL_PROFILE_SETTINGS
std::sort(variableNames.begin(), variableNames.end());
assert(std::unique(variableNames.begin(), variableNames.end()) == variableNames.end());
#undef PROCESS
}

Expand Down
10 changes: 10 additions & 0 deletions src/mumble/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

class QSettings;
struct MigratedPath;
struct Settings;

// Global helper classes to spread variables around across threads
// especially helpful to initialize things like the stored
Expand Down Expand Up @@ -184,6 +185,13 @@ struct OverlaySettings {
friend bool operator!=(const OverlaySettings &lhs, const OverlaySettings &rhs);
};

struct Profiles {
static const QString s_default_profile_name;

QString activeProfileName = s_default_profile_name;
QMap< QString, Settings > allProfiles = {};
};

struct Settings {
enum AudioTransmit { Continuous, VAD, PushToTalk };
enum VADSource { Amplitude, SignalToNoise };
Expand Down Expand Up @@ -558,6 +566,8 @@ struct Settings {
/// A flag used in order to determine whether or not to offer loading the setting's backup file instead
bool mumbleQuitNormally = false;

Profiles profiles;

bool doEcho() const;
bool doPositionalAudio() const;

Expand Down
4 changes: 4 additions & 0 deletions src/mumble/SettingsKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ namespace SettingsKeys {
* loading settings.
*/

// Meta
const SettingsKey ACTIVE_PROFILE = { "active_profile" };
const SettingsKey PROFILES = { "profiles" };

// Audio settings
const SettingsKey UNMUTE_ON_UNDEAF_KEY = { "unmute_on_undeaf" };
const SettingsKey MUTE_KEY = { "mute" };
Expand Down
9 changes: 9 additions & 0 deletions src/mumble/SettingsMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

// Mappings between SettingsKey objects and the corresponding fields in the Settings struct

#define PROFILE_SETTINGS \
PROCESS(profiles, ACTIVE_PROFILE, activeProfileName) \
PROCESS(profiles, PROFILES, allProfiles)

#define MISC_SETTINGS \
PROCESS(misc, DATABASE_LOCATION_KEY, qsDatabaseLocation) \
PROCESS(misc, IMAGE_DIRECTORY_KEY, qsImagePath) \
Expand Down Expand Up @@ -342,6 +346,7 @@

#define PROCESS_ALL_OVERLAY_SETTINGS OVERLAY_SETTINGS

#define PROCESS_ALL_PROFILE_SETTINGS PROFILE_SETTINGS

#define PROCESS_ALL_SETTINGS_WITH_INTERMEDIATE_OPERATION \
MISC_SETTINGS \
Expand Down Expand Up @@ -391,5 +396,9 @@
OVERLAY_SETTINGS \
INTERMEDIATE_OPERATION

#define PROCESS_ALL_PROFILE_SETTINGS_WITH_INTERMEDIATE_OPERATION \
PROFILE_SETTINGS \
INTERMEDIATE_OPERATION


#endif // MUMBLE_MUMBLE_SETTINGS_MACROS_H_

0 comments on commit 68990c1

Please sign in to comment.