978 lines
30 KiB
C++
978 lines
30 KiB
C++
/*
|
|
* TrackerSettings.h
|
|
* -----------------
|
|
* Purpose: Header file for application setting handling.
|
|
* Notes : (currently none)
|
|
* Authors: Olivier Lapicque
|
|
* OpenMPT Devs
|
|
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
|
*/
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "openmpt/all/BuildSettings.hpp"
|
|
|
|
#include "mpt/uuid/uuid.hpp"
|
|
|
|
#include "../common/Logging.h"
|
|
#include "../common/version.h"
|
|
#include "openmpt/soundbase/SampleFormat.hpp"
|
|
#include "../soundlib/MixerSettings.h"
|
|
#include "../soundlib/Resampler.h"
|
|
#include "../sounddsp/EQ.h"
|
|
#include "../sounddsp/DSP.h"
|
|
#include "../sounddsp/Reverb.h"
|
|
#include "openmpt/sounddevice/SoundDevice.hpp"
|
|
#include "StreamEncoderSettings.h"
|
|
#include "Settings.h"
|
|
|
|
#include <array>
|
|
#include <bitset>
|
|
|
|
|
|
OPENMPT_NAMESPACE_BEGIN
|
|
|
|
|
|
namespace SoundDevice {
|
|
class Manager;
|
|
} // namespace SoundDevice
|
|
|
|
|
|
namespace Tuning {
|
|
class CTuningCollection;
|
|
} // namespace Tuning
|
|
using CTuningCollection = Tuning::CTuningCollection;
|
|
|
|
|
|
// User-defined colors
|
|
enum ModColor : uint8
|
|
{
|
|
MODCOLOR_BACKNORMAL = 0,
|
|
MODCOLOR_TEXTNORMAL,
|
|
MODCOLOR_BACKCURROW,
|
|
MODCOLOR_TEXTCURROW,
|
|
MODCOLOR_BACKSELECTED,
|
|
MODCOLOR_TEXTSELECTED,
|
|
MODCOLOR_SAMPLE,
|
|
MODCOLOR_BACKPLAYCURSOR,
|
|
MODCOLOR_TEXTPLAYCURSOR,
|
|
MODCOLOR_BACKHILIGHT,
|
|
MODCOLOR_NOTE,
|
|
MODCOLOR_INSTRUMENT,
|
|
MODCOLOR_VOLUME,
|
|
MODCOLOR_PANNING,
|
|
MODCOLOR_PITCH,
|
|
MODCOLOR_GLOBALS,
|
|
MODCOLOR_ENVELOPES,
|
|
MODCOLOR_VUMETER_LO,
|
|
MODCOLOR_VUMETER_MED,
|
|
MODCOLOR_VUMETER_HI,
|
|
MODCOLOR_SEPSHADOW,
|
|
MODCOLOR_SEPFACE,
|
|
MODCOLOR_SEPHILITE,
|
|
MODCOLOR_BLENDCOLOR,
|
|
MODCOLOR_DODGY_COMMANDS,
|
|
MODCOLOR_BACKSAMPLE,
|
|
MODCOLOR_SAMPLESELECTED,
|
|
MODCOLOR_BACKENV,
|
|
MODCOLOR_VUMETER_LO_VST,
|
|
MODCOLOR_VUMETER_MED_VST,
|
|
MODCOLOR_VUMETER_HI_VST,
|
|
MODCOLOR_ENVELOPE_RELEASE,
|
|
MODCOLOR_SAMPLE_LOOPMARKER,
|
|
MODCOLOR_SAMPLE_SUSTAINMARKER,
|
|
MODCOLOR_SAMPLE_CUEPOINT,
|
|
MAX_MODCOLORS,
|
|
// Internal color codes (not saved to color preset files)
|
|
MODCOLOR_2NDHIGHLIGHT,
|
|
MODCOLOR_DEFAULTVOLUME,
|
|
MODCOLOR_DUMMYCOMMAND,
|
|
MAX_MODPALETTECOLORS
|
|
};
|
|
|
|
|
|
// Pattern Setup (contains also non-pattern related settings)
|
|
// Feel free to replace the deprecated flags by new flags, but be sure to
|
|
// update TrackerSettings::TrackerSettings() as well.
|
|
#define PATTERN_PLAYNEWNOTE 0x01 // play new notes while recording
|
|
#define PATTERN_SMOOTHSCROLL 0x02 // scroll tick by tick, not row by row
|
|
#define PATTERN_STDHIGHLIGHT 0x04 // enable primary highlight (measures)
|
|
#define PATTERN_NOFOLLOWONCLICK 0x08 // disable song follow when clicking into pattern
|
|
#define PATTERN_CENTERROW 0x10 // always center active row
|
|
#define PATTERN_WRAP 0x20 // wrap around cursor in editor
|
|
#define PATTERN_EFFECTHILIGHT 0x40 // effect syntax highlighting
|
|
#define PATTERN_HEXDISPLAY 0x80 // display row number in hex
|
|
#define PATTERN_FLATBUTTONS 0x100 // flat toolbar buttons
|
|
#define PATTERN_PLAYNAVIGATEROW 0x200 // play whole row when navigating
|
|
#define PATTERN_SINGLEEXPAND 0x400 // single click to expand tree
|
|
#define PATTERN_PLAYEDITROW 0x800 // play all notes on the current row while entering notes
|
|
#define PATTERN_NOEXTRALOUD 0x1000 // no loud samples in sample editor
|
|
#define PATTERN_DRAGNDROPEDIT 0x2000 // enable drag and drop editing
|
|
#define PATTERN_2NDHIGHLIGHT 0x4000 // activate secondary highlight (beats)
|
|
#define PATTERN_MUTECHNMODE 0x8000 // ignore muted channels
|
|
#define PATTERN_SHOWPREVIOUS 0x10000 // show prev/next patterns
|
|
#define PATTERN_CONTSCROLL 0x20000 // continous pattern scrolling
|
|
#define PATTERN_KBDNOTEOFF 0x40000 // Record note-off events
|
|
#define PATTERN_FOLLOWSONGOFF 0x80000 // follow song off by default
|
|
#define PATTERN_PLAYTRANSPOSE 0x100000 // Preview note transposition
|
|
#define PATTERN_NOCLOSEDIALOG 0x200000 // Don't use OpenMPT's custom close dialog with a list of saved files when closing the main window
|
|
#define PATTERN_DBLCLICKSELECT 0x400000 // Double-clicking pattern selects whole channel
|
|
#define PATTERN_OLDCTXMENUSTYLE 0x800000 // Hide pattern context menu entries instead of greying them out.
|
|
#define PATTERN_SYNCMUTE 0x1000000 // maintain sample sync on mute
|
|
#define PATTERN_AUTODELAY 0x2000000 // automatically insert delay commands in pattern when entering notes
|
|
#define PATTERN_NOTEFADE 0x4000000 // alt. note fade behaviour when entering notes
|
|
#define PATTERN_OVERFLOWPASTE 0x8000000 // continue paste in the next pattern instead of cutting off
|
|
#define PATTERN_SHOWDEFAULTVOLUME 0x10000000 // if there is no volume command next to note+instr, display the sample's default volume.
|
|
#define PATTERN_RESETCHANNELS 0x20000000 // reset channels when looping
|
|
#define PATTERN_LIVEUPDATETREE 0x40000000 // update active sample / instr icons in treeview
|
|
#define PATTERN_SYNCSAMPLEPOS 0x80000000 // sync sample positions when seeking
|
|
|
|
#define PATTERNFONT_SMALL UL_("@1")
|
|
#define PATTERNFONT_LARGE UL_("@2")
|
|
|
|
// MIDI Setup
|
|
#define MIDISETUP_RECORDVELOCITY 0x01 // Record MIDI velocity
|
|
#define MIDISETUP_TRANSPOSEKEYBOARD 0x02 // Apply transpose value to MIDI Notes
|
|
#define MIDISETUP_MIDITOPLUG 0x04 // Pass MIDI messages to plugins
|
|
#define MIDISETUP_MIDIVOL_TO_NOTEVOL 0x08 // Combine MIDI volume to note velocity
|
|
#define MIDISETUP_RECORDNOTEOFF 0x10 // Record MIDI Note Off to pattern
|
|
#define MIDISETUP_RESPONDTOPLAYCONTROLMSGS 0x20 // Respond to Restart/Continue/Stop MIDI commands
|
|
#define MIDISETUP_MIDIMACROCONTROL 0x80 // Record MIDI controller changes a MIDI macro changes in pattern
|
|
#define MIDISETUP_PLAYPATTERNONMIDIIN 0x100 // Play pattern if MIDI Note is received and playback is paused
|
|
#define MIDISETUP_ENABLE_RECORD_DEFAULT 0x200 // Enable MIDI recording by default
|
|
#define MIDISETUP_MIDIMACROPITCHBEND 0x400 // Record MIDI pitch bend messages a MIDI macro changes in pattern
|
|
|
|
|
|
#ifndef NO_EQ
|
|
|
|
// EQ
|
|
|
|
struct EQPresetPacked
|
|
{
|
|
char szName[12]; // locale encoding
|
|
uint32le Gains[MAX_EQ_BANDS];
|
|
uint32le Freqs[MAX_EQ_BANDS];
|
|
};
|
|
MPT_BINARY_STRUCT(EQPresetPacked, 60)
|
|
|
|
struct EQPreset
|
|
{
|
|
char szName[12]; // locale encoding
|
|
uint32 Gains[MAX_EQ_BANDS];
|
|
uint32 Freqs[MAX_EQ_BANDS];
|
|
};
|
|
|
|
|
|
template<> inline SettingValue ToSettingValue(const EQPreset &val)
|
|
{
|
|
EQPresetPacked valpacked;
|
|
std::memcpy(valpacked.szName, val.szName, std::size(valpacked.szName));
|
|
std::copy(val.Gains, val.Gains + MAX_EQ_BANDS, valpacked.Gains);
|
|
std::copy(val.Freqs, val.Freqs + MAX_EQ_BANDS, valpacked.Freqs);
|
|
return SettingValue(EncodeBinarySetting<EQPresetPacked>(valpacked), "EQPreset");
|
|
}
|
|
template<> inline EQPreset FromSettingValue(const SettingValue &val)
|
|
{
|
|
ASSERT(val.GetTypeTag() == "EQPreset");
|
|
EQPresetPacked valpacked = DecodeBinarySetting<EQPresetPacked>(val.as<std::vector<std::byte> >());
|
|
EQPreset valresult;
|
|
std::memcpy(valresult.szName, valpacked.szName, std::size(valresult.szName));
|
|
std::copy(valpacked.Gains, valpacked.Gains + MAX_EQ_BANDS, valresult.Gains);
|
|
std::copy(valpacked.Freqs, valpacked.Freqs + MAX_EQ_BANDS, valresult.Freqs);
|
|
return valresult;
|
|
}
|
|
|
|
#endif // !NO_EQ
|
|
|
|
|
|
template<> inline SettingValue ToSettingValue(const mpt::UUID &val) { return SettingValue(val.ToUString()); }
|
|
template<> inline mpt::UUID FromSettingValue(const SettingValue &val) { return mpt::UUID::FromString(val.as<mpt::ustring>()); }
|
|
|
|
|
|
|
|
// Chords
|
|
struct MPTChord
|
|
{
|
|
enum
|
|
{
|
|
notesPerChord = 4,
|
|
relativeMode = 0x3F,
|
|
noNote = int8_min,
|
|
};
|
|
using NoteType = int8;
|
|
|
|
uint8 key; // Base note
|
|
std::array<NoteType, notesPerChord - 1> notes; // Additional chord notes
|
|
};
|
|
|
|
using MPTChords = std::array<MPTChord, 3 * 12>; // 3 octaves
|
|
|
|
// MIDI recording
|
|
enum RecordAftertouchOptions
|
|
{
|
|
atDoNotRecord = 0,
|
|
atRecordAsVolume,
|
|
atRecordAsMacro,
|
|
};
|
|
|
|
// New file action
|
|
enum NewFileAction
|
|
{
|
|
nfDefaultFormat = 0,
|
|
nfSameAsCurrent,
|
|
nfDefaultTemplate
|
|
};
|
|
|
|
// Sample editor preview behaviour
|
|
enum SampleEditorKeyBehaviour
|
|
{
|
|
seNoteOffOnNewKey = 0,
|
|
seNoteOffOnKeyUp,
|
|
seNoteOffOnKeyRestrike,
|
|
};
|
|
|
|
enum SampleEditorDefaultFormat
|
|
{
|
|
dfFLAC,
|
|
dfWAV,
|
|
dfRAW,
|
|
dfS3I,
|
|
};
|
|
|
|
enum class TimelineFormat
|
|
{
|
|
Seconds = 0,
|
|
Samples,
|
|
SamplesPow2,
|
|
};
|
|
|
|
enum class DefaultChannelColors
|
|
{
|
|
NoColors = 0,
|
|
Rainbow,
|
|
Random,
|
|
};
|
|
|
|
|
|
class SampleUndoBufferSize
|
|
{
|
|
protected:
|
|
size_t sizeByte;
|
|
int32 sizePercent;
|
|
|
|
void CalculateSize();
|
|
|
|
public:
|
|
enum
|
|
{
|
|
defaultSize = 10, // In percent
|
|
};
|
|
|
|
SampleUndoBufferSize(int32 percent = defaultSize) : sizePercent(percent) { CalculateSize(); }
|
|
void Set(int32 percent) { sizePercent = percent; CalculateSize(); }
|
|
|
|
int32 GetSizeInPercent() const { return sizePercent; }
|
|
size_t GetSizeInBytes() const { return sizeByte; }
|
|
};
|
|
|
|
template<> inline SettingValue ToSettingValue(const SampleUndoBufferSize &val) { return SettingValue(val.GetSizeInPercent()); }
|
|
template<> inline SampleUndoBufferSize FromSettingValue(const SettingValue &val) { return SampleUndoBufferSize(val.as<int32>()); }
|
|
|
|
|
|
mpt::ustring IgnoredCCsToString(const std::bitset<128> &midiIgnoreCCs);
|
|
std::bitset<128> StringToIgnoredCCs(const mpt::ustring &in);
|
|
|
|
mpt::ustring SettingsModTypeToString(MODTYPE modtype);
|
|
MODTYPE SettingsStringToModType(const mpt::ustring &str);
|
|
|
|
|
|
template<> inline SettingValue ToSettingValue(const RecordAftertouchOptions &val) { return SettingValue(int32(val)); }
|
|
template<> inline RecordAftertouchOptions FromSettingValue(const SettingValue &val) { return RecordAftertouchOptions(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const SampleEditorKeyBehaviour &val) { return SettingValue(int32(val)); }
|
|
template<> inline SampleEditorKeyBehaviour FromSettingValue(const SettingValue &val) { return SampleEditorKeyBehaviour(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const TimelineFormat &val) { return SettingValue(int32(val)); }
|
|
template<> inline TimelineFormat FromSettingValue(const SettingValue &val) { return TimelineFormat(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const DefaultChannelColors & val) { return SettingValue(int32(val)); }
|
|
template<> inline DefaultChannelColors FromSettingValue(const SettingValue& val) { return DefaultChannelColors(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const MODTYPE &val) { return SettingValue(SettingsModTypeToString(val), "MODTYPE"); }
|
|
template<> inline MODTYPE FromSettingValue(const SettingValue &val) { ASSERT(val.GetTypeTag() == "MODTYPE"); return SettingsStringToModType(val.as<mpt::ustring>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const PlugVolumeHandling &val)
|
|
{
|
|
return SettingValue(int32(val), "PlugVolumeHandling");
|
|
}
|
|
template<> inline PlugVolumeHandling FromSettingValue(const SettingValue &val)
|
|
{
|
|
ASSERT(val.GetTypeTag() == "PlugVolumeHandling");
|
|
if((uint32)val.as<int32>() > PLUGIN_VOLUMEHANDLING_MAX)
|
|
{
|
|
return PLUGIN_VOLUMEHANDLING_IGNORE;
|
|
}
|
|
return static_cast<PlugVolumeHandling>(val.as<int32>());
|
|
}
|
|
|
|
template<> inline SettingValue ToSettingValue(const std::vector<uint32> &val) { return mpt::String::Combine(val, U_(",")); }
|
|
template<> inline std::vector<uint32> FromSettingValue(const SettingValue &val) { return mpt::String::Split<uint32>(val, U_(",")); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const std::vector<mpt::ustring> &val) { return mpt::String::Combine(val, U_(";")); }
|
|
template<> inline std::vector<mpt::ustring> FromSettingValue(const SettingValue &val) { return mpt::String::Split<mpt::ustring>(val, U_(";")); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const SampleFormat &val) { return SettingValue(val.AsInt()); }
|
|
template<> inline SampleFormat FromSettingValue(const SettingValue &val) { return SampleFormat::FromInt(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const SoundDevice::ChannelMapping &val) { return SettingValue(val.ToUString(), "ChannelMapping"); }
|
|
template<> inline SoundDevice::ChannelMapping FromSettingValue(const SettingValue &val) { ASSERT(val.GetTypeTag() == "ChannelMapping"); return SoundDevice::ChannelMapping::FromString(val.as<mpt::ustring>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const ResamplingMode &val) { return SettingValue(int32(val)); }
|
|
template<> inline ResamplingMode FromSettingValue(const SettingValue &val) { return ResamplingMode(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const Resampling::AmigaFilter &val) { return SettingValue(int32(val)); }
|
|
template<> inline Resampling::AmigaFilter FromSettingValue(const SettingValue &val) { return static_cast<Resampling::AmigaFilter>(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const NewFileAction &val) { return SettingValue(int32(val)); }
|
|
template<> inline NewFileAction FromSettingValue(const SettingValue &val) { return NewFileAction(val.as<int32>()); }
|
|
|
|
template<> inline SettingValue ToSettingValue(const std::bitset<128> &val)
|
|
{
|
|
return SettingValue(IgnoredCCsToString(val), "IgnoredCCs");
|
|
}
|
|
template<> inline std::bitset<128> FromSettingValue(const SettingValue &val)
|
|
{
|
|
ASSERT(val.GetTypeTag() == "IgnoredCCs");
|
|
return StringToIgnoredCCs(val.as<mpt::ustring>());
|
|
}
|
|
|
|
template<> inline SettingValue ToSettingValue(const SampleEditorDefaultFormat &val)
|
|
{
|
|
mpt::ustring format;
|
|
switch(val)
|
|
{
|
|
case dfWAV:
|
|
format = U_("wav");
|
|
break;
|
|
case dfFLAC:
|
|
default:
|
|
format = U_("flac");
|
|
break;
|
|
case dfRAW:
|
|
format = U_("raw");
|
|
break;
|
|
case dfS3I:
|
|
format = U_("s3i");
|
|
break;
|
|
}
|
|
return SettingValue(format);
|
|
}
|
|
template<> inline SampleEditorDefaultFormat FromSettingValue(const SettingValue &val)
|
|
{
|
|
mpt::ustring format = mpt::ToLowerCase(val.as<mpt::ustring>());
|
|
if(format == U_("wav"))
|
|
return dfWAV;
|
|
if(format == U_("raw"))
|
|
return dfRAW;
|
|
if(format == U_("s3i"))
|
|
return dfS3I;
|
|
else // if(format == U_("flac"))
|
|
return dfFLAC;
|
|
}
|
|
|
|
enum SoundDeviceStopMode
|
|
{
|
|
SoundDeviceStopModeClosed = 0,
|
|
SoundDeviceStopModeStopped = 1,
|
|
SoundDeviceStopModePlaying = 2,
|
|
};
|
|
|
|
template<> inline SettingValue ToSettingValue(const SoundDeviceStopMode &val)
|
|
{
|
|
return SettingValue(static_cast<int32>(val));
|
|
}
|
|
template<> inline SoundDeviceStopMode FromSettingValue(const SettingValue &val)
|
|
{
|
|
return static_cast<SoundDeviceStopMode>(static_cast<int32>(val));
|
|
}
|
|
|
|
|
|
enum ProcessPriorityClass
|
|
{
|
|
ProcessPriorityClassIDLE = IDLE_PRIORITY_CLASS,
|
|
ProcessPriorityClassBELOW = BELOW_NORMAL_PRIORITY_CLASS,
|
|
ProcessPriorityClassNORMAL = NORMAL_PRIORITY_CLASS,
|
|
ProcessPriorityClassABOVE = ABOVE_NORMAL_PRIORITY_CLASS,
|
|
ProcessPriorityClassHIGH = HIGH_PRIORITY_CLASS,
|
|
ProcessPriorityClassREALTIME = REALTIME_PRIORITY_CLASS
|
|
};
|
|
template<> inline SettingValue ToSettingValue(const ProcessPriorityClass &val)
|
|
{
|
|
mpt::ustring s;
|
|
switch(val)
|
|
{
|
|
case ProcessPriorityClassIDLE:
|
|
s = U_("idle");
|
|
break;
|
|
case ProcessPriorityClassBELOW:
|
|
s = U_("below");
|
|
break;
|
|
case ProcessPriorityClassNORMAL:
|
|
s = U_("normal");
|
|
break;
|
|
case ProcessPriorityClassABOVE:
|
|
s = U_("above");
|
|
break;
|
|
case ProcessPriorityClassHIGH:
|
|
s = U_("high");
|
|
break;
|
|
case ProcessPriorityClassREALTIME:
|
|
s = U_("realtime");
|
|
break;
|
|
default:
|
|
s = U_("normal");
|
|
break;
|
|
}
|
|
return SettingValue(s);
|
|
}
|
|
template<> inline ProcessPriorityClass FromSettingValue(const SettingValue &val)
|
|
{
|
|
ProcessPriorityClass result = ProcessPriorityClassNORMAL;
|
|
mpt::ustring s = val.as<mpt::ustring>();
|
|
if(s.empty())
|
|
{
|
|
result = ProcessPriorityClassNORMAL;
|
|
} else if(s == U_("idle"))
|
|
{
|
|
result = ProcessPriorityClassIDLE;
|
|
} else if(s == U_("below"))
|
|
{
|
|
result = ProcessPriorityClassBELOW;
|
|
} else if(s == U_("normal"))
|
|
{
|
|
result = ProcessPriorityClassNORMAL;
|
|
} else if(s == U_("above"))
|
|
{
|
|
result = ProcessPriorityClassABOVE;
|
|
} else if(s == U_("high"))
|
|
{
|
|
result = ProcessPriorityClassHIGH;
|
|
} else if(s == U_("realtime"))
|
|
{
|
|
result = ProcessPriorityClassREALTIME;
|
|
} else
|
|
{
|
|
result = ProcessPriorityClassNORMAL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
template<> inline SettingValue ToSettingValue(const mpt::Date::Unix &val)
|
|
{
|
|
time_t t = val;
|
|
const tm* lastUpdate = gmtime(&t);
|
|
CString outDate;
|
|
if(lastUpdate)
|
|
{
|
|
outDate.Format(_T("%04d-%02d-%02d %02d:%02d"), lastUpdate->tm_year + 1900, lastUpdate->tm_mon + 1, lastUpdate->tm_mday, lastUpdate->tm_hour, lastUpdate->tm_min);
|
|
}
|
|
return SettingValue(mpt::ToUnicode(outDate), "UTC");
|
|
}
|
|
template<> inline mpt::Date::Unix FromSettingValue(const SettingValue &val)
|
|
{
|
|
MPT_ASSERT(val.GetTypeTag() == "UTC");
|
|
std::string s = mpt::ToCharset(mpt::Charset::Locale, val.as<mpt::ustring>());
|
|
tm lastUpdate;
|
|
MemsetZero(lastUpdate);
|
|
if(sscanf(s.c_str(), "%04d-%02d-%02d %02d:%02d", &lastUpdate.tm_year, &lastUpdate.tm_mon, &lastUpdate.tm_mday, &lastUpdate.tm_hour, &lastUpdate.tm_min) == 5)
|
|
{
|
|
lastUpdate.tm_year -= 1900;
|
|
lastUpdate.tm_mon--;
|
|
}
|
|
time_t outTime = mpt::Date::Unix::FromUTC(lastUpdate);
|
|
if(outTime < 0)
|
|
{
|
|
outTime = 0;
|
|
}
|
|
return mpt::Date::Unix(outTime);
|
|
}
|
|
|
|
struct FontSetting
|
|
{
|
|
enum FontFlags
|
|
{
|
|
None = 0,
|
|
Bold = 1,
|
|
Italic = 2,
|
|
};
|
|
|
|
mpt::ustring name;
|
|
int32 size;
|
|
FlagSet<FontFlags> flags;
|
|
|
|
FontSetting(const mpt::ustring &name = U_(""), int32 size = 120, FontFlags flags = None) : name(name), size(size), flags(flags) { }
|
|
|
|
bool operator== (const FontSetting &other) const
|
|
{
|
|
return name == other.name && size == other.size && flags == other.flags;
|
|
}
|
|
|
|
bool operator!= (const FontSetting &other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
};
|
|
|
|
MPT_DECLARE_ENUM(FontSetting::FontFlags)
|
|
|
|
template<> inline SettingValue ToSettingValue(const FontSetting &val)
|
|
{
|
|
return SettingValue(mpt::ToUnicode(val.name) + U_(",") + mpt::ufmt::val(val.size) + U_("|") + mpt::ufmt::val(val.flags.GetRaw()));
|
|
}
|
|
template<> inline FontSetting FromSettingValue(const SettingValue &val)
|
|
{
|
|
FontSetting setting(val.as<mpt::ustring>());
|
|
std::size_t sizeStart = setting.name.rfind(UC_(','));
|
|
if(sizeStart != std::string::npos)
|
|
{
|
|
const std::vector<mpt::ustring> fields = mpt::String::Split<mpt::ustring>(setting.name.substr(sizeStart + 1), U_("|"));
|
|
if(fields.size() >= 1)
|
|
{
|
|
setting.size = ConvertStrTo<int32>(fields[0]);
|
|
}
|
|
if(fields.size() >= 2)
|
|
{
|
|
setting.flags = static_cast<FontSetting::FontFlags>(ConvertStrTo<int32>(fields[1]));
|
|
}
|
|
setting.name.resize(sizeStart);
|
|
}
|
|
return setting;
|
|
}
|
|
|
|
|
|
class DefaultAndWorkingDirectory
|
|
{
|
|
protected:
|
|
mpt::PathString m_Default;
|
|
mpt::PathString m_Working;
|
|
public:
|
|
DefaultAndWorkingDirectory();
|
|
DefaultAndWorkingDirectory(const mpt::PathString &def);
|
|
~DefaultAndWorkingDirectory();
|
|
public:
|
|
void SetDefaultDir(const mpt::PathString &filenameFrom, bool stripFilename = false);
|
|
void SetWorkingDir(const mpt::PathString &filenameFrom, bool stripFilename = false);
|
|
mpt::PathString GetDefaultDir() const;
|
|
mpt::PathString GetWorkingDir() const;
|
|
private:
|
|
bool InternalSet(mpt::PathString &dest, const mpt::PathString &filenameFrom, bool stripFilename);
|
|
};
|
|
|
|
class ConfigurableDirectory
|
|
: public DefaultAndWorkingDirectory
|
|
{
|
|
protected:
|
|
SettingsContainer &conf;
|
|
Setting<mpt::PathString> m_Setting;
|
|
public:
|
|
ConfigurableDirectory(SettingsContainer &conf, const AnyStringLocale §ion, const AnyStringLocale &key, const mpt::PathString &def);
|
|
~ConfigurableDirectory();
|
|
};
|
|
|
|
|
|
class DebugSettings
|
|
{
|
|
|
|
private:
|
|
|
|
SettingsContainer &conf;
|
|
|
|
private:
|
|
|
|
// Debug
|
|
|
|
#if !defined(MPT_LOG_IS_DISABLED)
|
|
Setting<int> DebugLogLevel;
|
|
Setting<std::string> DebugLogFacilitySolo;
|
|
Setting<std::string> DebugLogFacilityBlocked;
|
|
Setting<bool> DebugLogFileEnable;
|
|
Setting<bool> DebugLogDebuggerEnable;
|
|
Setting<bool> DebugLogConsoleEnable;
|
|
#endif
|
|
|
|
Setting<bool> DebugTraceEnable;
|
|
Setting<uint32> DebugTraceSize;
|
|
Setting<bool> DebugTraceAlwaysDump;
|
|
|
|
Setting<bool> DebugStopSoundDeviceOnCrash;
|
|
Setting<bool> DebugStopSoundDeviceBeforeDump;
|
|
|
|
Setting<bool> DebugDelegateToWindowsHandler;
|
|
|
|
public:
|
|
|
|
DebugSettings(SettingsContainer &conf);
|
|
|
|
~DebugSettings();
|
|
|
|
};
|
|
|
|
|
|
namespace SoundDevice
|
|
{
|
|
namespace Legacy
|
|
{
|
|
typedef uint16 ID;
|
|
inline constexpr SoundDevice::Legacy::ID MaskType = 0xff00;
|
|
inline constexpr SoundDevice::Legacy::ID MaskIndex = 0x00ff;
|
|
inline constexpr int ShiftType = 8;
|
|
inline constexpr int ShiftIndex = 0;
|
|
inline constexpr SoundDevice::Legacy::ID TypeWAVEOUT = 0;
|
|
inline constexpr SoundDevice::Legacy::ID TypeDSOUND = 1;
|
|
inline constexpr SoundDevice::Legacy::ID TypeASIO = 2;
|
|
inline constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WASAPI = 3;
|
|
inline constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WDMKS = 4;
|
|
inline constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WMME = 5;
|
|
inline constexpr SoundDevice::Legacy::ID TypePORTAUDIO_DS = 6;
|
|
} // namespace Legacy
|
|
} // namespace SoundDevice
|
|
|
|
|
|
class TrackerSettings
|
|
{
|
|
|
|
private:
|
|
SettingsContainer &conf;
|
|
|
|
public:
|
|
|
|
// Version
|
|
|
|
Setting<mpt::ustring> IniVersion;
|
|
const bool FirstRun;
|
|
const Version PreviousSettingsVersion;
|
|
Setting<mpt::UUID> VersionInstallGUID;
|
|
|
|
// Display
|
|
|
|
Setting<bool> m_ShowSplashScreen;
|
|
Setting<bool> gbMdiMaximize;
|
|
Setting<bool> highResUI;
|
|
Setting<LONG> glTreeSplitRatio;
|
|
Setting<LONG> glTreeWindowWidth;
|
|
Setting<LONG> glGeneralWindowHeight;
|
|
Setting<LONG> glPatternWindowHeight;
|
|
Setting<LONG> glSampleWindowHeight;
|
|
Setting<LONG> glInstrumentWindowHeight;
|
|
Setting<LONG> glCommentsWindowHeight;
|
|
Setting<LONG> glGraphWindowHeight;
|
|
|
|
Setting<int32> gnPlugWindowX;
|
|
Setting<int32> gnPlugWindowY;
|
|
Setting<int32> gnPlugWindowWidth;
|
|
Setting<int32> gnPlugWindowHeight;
|
|
Setting<int32> gnPlugWindowLast; // Last selected plugin ID
|
|
|
|
Setting<uint32> gnMsgBoxVisiblityFlags;
|
|
Setting<uint32> GUIUpdateInterval;
|
|
CachedSetting<uint32> FSUpdateInterval;
|
|
CachedSetting<uint32> VuMeterUpdateInterval;
|
|
CachedSetting<float> VuMeterDecaySpeedDecibelPerSecond;
|
|
|
|
CachedSetting<bool> accidentalFlats;
|
|
Setting<bool> rememberSongWindows;
|
|
Setting<bool> showDirsInSampleBrowser;
|
|
Setting<DefaultChannelColors> defaultRainbowChannelColors;
|
|
|
|
Setting<FontSetting> commentsFont;
|
|
|
|
// Misc
|
|
|
|
Setting<MODTYPE> defaultModType;
|
|
Setting<NewFileAction> defaultNewFileAction;
|
|
Setting<PlugVolumeHandling> DefaultPlugVolumeHandling;
|
|
Setting<bool> autoApplySmoothFT2Ramping;
|
|
CachedSetting<uint32> MiscITCompressionStereo; // Mask: bit0: IT, bit1: Compat IT, bit2: MPTM
|
|
CachedSetting<uint32> MiscITCompressionMono; // Mask: bit0: IT, bit1: Compat IT, bit2: MPTM
|
|
CachedSetting<bool> MiscSaveChannelMuteStatus;
|
|
CachedSetting<bool> MiscAllowMultipleCommandsPerKey;
|
|
CachedSetting<bool> MiscDistinguishModifiers;
|
|
Setting<ProcessPriorityClass> MiscProcessPriorityClass;
|
|
CachedSetting<bool> MiscFlushFileBuffersOnSave;
|
|
CachedSetting<bool> MiscCacheCompleteFileBeforeLoading;
|
|
Setting<bool> MiscUseSingleInstance;
|
|
|
|
// Sound Settings
|
|
|
|
bool m_SoundShowRecordingSettings;
|
|
Setting<bool> m_SoundShowDeprecatedDevices;
|
|
Setting<bool> m_SoundDeprecatedDeviceWarningShown;
|
|
Setting<std::vector<uint32> > m_SoundSampleRates;
|
|
Setting<bool> m_SoundSettingsOpenDeviceAtStartup;
|
|
Setting<SoundDeviceStopMode> m_SoundSettingsStopMode;
|
|
|
|
bool m_SoundDeviceSettingsUseOldDefaults;
|
|
SoundDevice::Legacy::ID m_SoundDeviceID_DEPRECATED;
|
|
SoundDevice::Settings m_SoundDeviceSettingsDefaults;
|
|
SoundDevice::Settings GetSoundDeviceSettingsDefaults() const;
|
|
#if defined(MPT_WITH_DIRECTSOUND)
|
|
bool m_SoundDeviceDirectSoundOldDefaultIdentifier;
|
|
#endif // MPT_WITH_DIRECTSOUND
|
|
|
|
Setting<SoundDevice::Identifier> m_SoundDeviceIdentifier;
|
|
SoundDevice::Identifier GetSoundDeviceIdentifier() const;
|
|
void SetSoundDeviceIdentifier(const SoundDevice::Identifier &identifier);
|
|
SoundDevice::Settings GetSoundDeviceSettings(const SoundDevice::Identifier &device) const;
|
|
void SetSoundDeviceSettings(const SoundDevice::Identifier &device, const SoundDevice::Settings &settings);
|
|
|
|
Setting<uint32> MixerMaxChannels;
|
|
Setting<uint32> MixerDSPMask;
|
|
Setting<uint32> MixerFlags;
|
|
Setting<uint32> MixerSamplerate;
|
|
Setting<uint32> MixerOutputChannels;
|
|
Setting<uint32> MixerPreAmp;
|
|
Setting<uint32> MixerStereoSeparation;
|
|
Setting<uint32> MixerVolumeRampUpMicroseconds;
|
|
Setting<uint32> MixerVolumeRampDownMicroseconds;
|
|
Setting<uint32> MixerNumInputChannels;
|
|
MixerSettings GetMixerSettings() const;
|
|
void SetMixerSettings(const MixerSettings &settings);
|
|
|
|
Setting<ResamplingMode> ResamplerMode;
|
|
Setting<uint8> ResamplerSubMode;
|
|
Setting<int32> ResamplerCutoffPercent;
|
|
Setting<Resampling::AmigaFilter> ResamplerEmulateAmiga;
|
|
CResamplerSettings GetResamplerSettings() const;
|
|
void SetResamplerSettings(const CResamplerSettings &settings);
|
|
|
|
Setting<int> SoundBoostedThreadPriority;
|
|
Setting<mpt::ustring> SoundBoostedThreadMMCSSClass;
|
|
Setting<bool> SoundBoostedThreadRealtimePosix;
|
|
Setting<int> SoundBoostedThreadNicenessPosix;
|
|
Setting<int> SoundBoostedThreadRtprioPosix;
|
|
Setting<bool> SoundMaskDriverCrashes;
|
|
Setting<bool> SoundAllowDeferredProcessing;
|
|
|
|
// MIDI Settings
|
|
|
|
Setting<UINT> m_nMidiDevice;
|
|
Setting<CString> midiDeviceName;
|
|
// FIXME: MIDI recording is currently done in its own callback/thread and
|
|
// accesses settings framework from in there. Work-around the ASSERTs for
|
|
// now by using cached settings.
|
|
CachedSetting<uint32> m_dwMidiSetup;
|
|
CachedSetting<RecordAftertouchOptions> aftertouchBehaviour;
|
|
CachedSetting<uint16> midiVelocityAmp;
|
|
CachedSetting<std::bitset<128> > midiIgnoreCCs;
|
|
|
|
Setting<uint32> midiImportPatternLen;
|
|
Setting<uint32> midiImportQuantize;
|
|
Setting<uint8> midiImportTicks;
|
|
|
|
// Pattern Editor
|
|
|
|
CachedSetting<bool> gbLoopSong;
|
|
CachedSetting<UINT> gnPatternSpacing;
|
|
CachedSetting<bool> gbPatternVUMeters;
|
|
CachedSetting<bool> gbPatternPluginNames;
|
|
CachedSetting<bool> gbPatternRecord;
|
|
CachedSetting<bool> patternNoEditPopup;
|
|
CachedSetting<bool> patternStepCommands;
|
|
CachedSetting<uint32> m_dwPatternSetup;
|
|
CachedSetting<uint32> m_nRowHighlightMeasures; // primary (measures) and secondary (beats) highlight
|
|
CachedSetting<uint32> m_nRowHighlightBeats; // primary (measures) and secondary (beats) highlight
|
|
CachedSetting<ROWINDEX> recordQuantizeRows;
|
|
CachedSetting<UINT> gnAutoChordWaitTime;
|
|
CachedSetting<int32> orderlistMargins;
|
|
CachedSetting<int32> rowDisplayOffset;
|
|
Setting<FontSetting> patternFont;
|
|
Setting<mpt::ustring> patternFontDot;
|
|
Setting<int32> effectVisWidth;
|
|
Setting<int32> effectVisHeight;
|
|
Setting<int32> effectVisX;
|
|
Setting<int32> effectVisY;
|
|
Setting<CString> patternAccessibilityFormat;
|
|
CachedSetting<bool> patternAlwaysDrawWholePatternOnScrollSlow;
|
|
CachedSetting<bool> orderListOldDropBehaviour;
|
|
|
|
// Sample Editor
|
|
|
|
Setting<SampleUndoBufferSize> m_SampleUndoBufferSize;
|
|
Setting<SampleEditorKeyBehaviour> sampleEditorKeyBehaviour;
|
|
Setting<SampleEditorDefaultFormat> m_defaultSampleFormat;
|
|
Setting<TimelineFormat> sampleEditorTimelineFormat;
|
|
Setting<ResamplingMode> sampleEditorDefaultResampler;
|
|
Setting<int32> m_nFinetuneStep; // Increment finetune by x cents when using spin control.
|
|
Setting<int32> m_FLACCompressionLevel; // FLAC compression level for saving (0...8)
|
|
Setting<bool> compressITI;
|
|
Setting<bool> m_MayNormalizeSamplesOnLoad;
|
|
Setting<bool> previewInFileDialogs;
|
|
CachedSetting<bool> cursorPositionInHex;
|
|
|
|
// Export
|
|
|
|
Setting<bool> ExportDefaultToSoundcardSamplerate;
|
|
StreamEncoderSettingsConf ExportStreamEncoderSettings;
|
|
|
|
// Components
|
|
|
|
Setting<bool> ComponentsLoadOnStartup;
|
|
Setting<bool> ComponentsKeepLoaded;
|
|
bool IsComponentBlocked(const std::string &name);
|
|
|
|
// Effects
|
|
|
|
#ifndef NO_REVERB
|
|
CReverbSettings m_ReverbSettings;
|
|
#endif
|
|
#ifndef NO_DSP
|
|
CSurroundSettings m_SurroundSettings;
|
|
#endif
|
|
#ifndef NO_DSP
|
|
CMegaBassSettings m_MegaBassSettings;
|
|
#endif
|
|
#ifndef NO_EQ
|
|
EQPreset m_EqSettings;
|
|
EQPreset m_EqUserPresets[4];
|
|
#endif
|
|
#ifndef NO_DSP
|
|
BitCrushSettings m_BitCrushSettings;
|
|
#endif
|
|
|
|
// Display (Colors)
|
|
|
|
std::array<COLORREF, MAX_MODCOLORS> rgbCustomColors;
|
|
|
|
// AutoSave
|
|
CachedSetting<bool> CreateBackupFiles;
|
|
CachedSetting<bool> AutosaveEnabled;
|
|
CachedSetting<uint32> AutosaveIntervalMinutes;
|
|
CachedSetting<uint32> AutosaveHistoryDepth;
|
|
CachedSetting<bool> AutosaveUseOriginalPath;
|
|
ConfigurableDirectory AutosavePath;
|
|
|
|
// Paths
|
|
|
|
ConfigurableDirectory PathSongs;
|
|
ConfigurableDirectory PathSamples;
|
|
ConfigurableDirectory PathInstruments;
|
|
ConfigurableDirectory PathPlugins;
|
|
ConfigurableDirectory PathPluginPresets;
|
|
ConfigurableDirectory PathExport;
|
|
DefaultAndWorkingDirectory PathTunings;
|
|
DefaultAndWorkingDirectory PathUserTemplates;
|
|
mpt::PathString m_szKbdFile;
|
|
|
|
// Default template
|
|
|
|
Setting<mpt::PathString> defaultTemplateFile;
|
|
Setting<mpt::ustring> defaultArtist;
|
|
|
|
Setting<uint32> mruListLength;
|
|
std::vector<mpt::PathString> mruFiles;
|
|
|
|
// Chords
|
|
|
|
MPTChords Chords;
|
|
|
|
// Tunings
|
|
|
|
std::unique_ptr<CTuningCollection> oldLocalTunings;
|
|
|
|
// Plugins
|
|
|
|
Setting<bool> bridgeAllPlugins;
|
|
Setting<bool> enableAutoSuspend;
|
|
CachedSetting<bool> midiMappingInPluginEditor;
|
|
Setting<mpt::ustring> pluginProjectPath;
|
|
CachedSetting<mpt::lstring> vstHostProductString;
|
|
CachedSetting<mpt::lstring> vstHostVendorString;
|
|
CachedSetting<int32> vstHostVendorVersion;
|
|
|
|
// Broken Plugins Workarounds
|
|
|
|
Setting<bool> BrokenPluginsWorkaroundVSTMaskAllCrashes;
|
|
Setting<bool> BrokenPluginsWorkaroundVSTNeverUnloadAnyPlugin;
|
|
|
|
#if defined(MPT_ENABLE_UPDATE)
|
|
|
|
// Update
|
|
|
|
Setting<bool> UpdateEnabled;
|
|
Setting<bool> UpdateInstallAutomatically;
|
|
Setting<mpt::Date::Unix> UpdateLastUpdateCheck;
|
|
Setting<int32> UpdateUpdateCheckPeriod_DEPRECATED;
|
|
Setting<int32> UpdateIntervalDays;
|
|
Setting<uint32> UpdateChannel;
|
|
Setting<mpt::ustring> UpdateUpdateURL_DEPRECATED;
|
|
Setting<mpt::ustring> UpdateAPIURL;
|
|
Setting<bool> UpdateStatisticsConsentAsked;
|
|
Setting<bool> UpdateStatistics;
|
|
Setting<bool> UpdateSendGUID_DEPRECATED;
|
|
Setting<bool> UpdateShowUpdateHint;
|
|
Setting<CString> UpdateIgnoreVersion;
|
|
Setting<bool> UpdateSkipSignatureVerificationUNSECURE;
|
|
Setting<std::vector<mpt::ustring>> UpdateSigningKeysRootAnchors;
|
|
|
|
#endif // MPT_ENABLE_UPDATE
|
|
|
|
// Wine support
|
|
|
|
Setting<bool> WineSupportEnabled;
|
|
Setting<bool> WineSupportAlwaysRecompile;
|
|
Setting<bool> WineSupportAskCompile;
|
|
Setting<int32> WineSupportCompileVerbosity;
|
|
Setting<bool> WineSupportForeignOpenMPT;
|
|
Setting<bool> WineSupportAllowUnknownHost;
|
|
Setting<int32> WineSupportEnablePulseAudio; // 0==off 1==auto 2==on
|
|
Setting<int32> WineSupportEnablePortAudio; // 0==off 1==auto 2==on
|
|
Setting<int32> WineSupportEnableRtAudio; // 0==off 1==auto 2==on
|
|
|
|
public:
|
|
|
|
TrackerSettings(SettingsContainer &conf);
|
|
|
|
~TrackerSettings();
|
|
|
|
void MigrateOldSoundDeviceSettings(SoundDevice::Manager &manager);
|
|
|
|
private:
|
|
void MigrateTunings(const Version storedVersion);
|
|
std::unique_ptr<CTuningCollection> LoadLocalTunings();
|
|
public:
|
|
|
|
void SaveSettings();
|
|
|
|
static void GetDefaultColourScheme(std::array<COLORREF, MAX_MODCOLORS> &colours);
|
|
|
|
std::vector<uint32> GetSampleRates() const;
|
|
|
|
static MPTChords &GetChords() { return Instance().Chords; }
|
|
|
|
// Get settings object singleton
|
|
static TrackerSettings &Instance();
|
|
|
|
void SetMIDIDevice(UINT id);
|
|
UINT GetCurrentMIDIDevice();
|
|
|
|
protected:
|
|
|
|
static std::vector<uint32> GetDefaultSampleRates();
|
|
|
|
#ifndef NO_EQ
|
|
|
|
void FixupEQ(EQPreset &eqSettings);
|
|
|
|
#endif // !NO_EQ
|
|
|
|
void LoadChords(MPTChords &chords);
|
|
void SaveChords(MPTChords &chords);
|
|
|
|
};
|
|
|
|
|
|
|
|
OPENMPT_NAMESPACE_END
|