Add wxWidgets-based configuration dialog boxes.
* Removes the configuration dialog boxes that used my DialogBuilder.
* Move default configuration values to be inlined within the headers.
* Moved 2SF's and GSF's XSFConfig classes to their own headers to accommodate the new wxWidgets dialog boxes.
* Make it so NCSF's SoundView dialog can be toggled on or off from the configuration dialog box.
--- a/src/in_2sf/CMakeLists.txt
+++ b/src/in_2sf/CMakeLists.txt
@@ -63,7 +63,9 @@
spu/adpcmdecoder.h
spu/interpolator.h
spu/samplecache.h
- spu/sampledata.h)
+ spu/sampledata.h
+ XSFConfig_2SF.h
+ XSFConfigDialog_2SF.h)
set(SOURCES
desmume/addons/slot1_retail.cpp
desmume/arm_instructions.cpp
@@ -112,13 +114,14 @@
spu/samplecache.cpp
spu/sampledata.cpp
XSFConfig_2SF.cpp
+ XSFConfigDialog_2SF.cpp
XSFPlayer_2SF.cpp)
add_library(in_2sf SHARED ${HEADERS} ${SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Header Files" FILES ${HEADERS})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCES})
target_compile_options(in_2sf PUBLIC
- $<$<CXX_COMPILER_ID:MSVC>:/wd4018 /wd4100 /wd4146 /wd4127 /wd4189 /wd4201 /wd4245 /wd4456 /wd4459 /wd4701 /wd4703 /wd4706 /wd4996 /wd6001 /wd6011 /wd6297 /wd6308 /wd6385 /wd6386 /wd26454 /wd26495 /wd26812 /wd26819 /wd28112>)
+ $<$<CXX_COMPILER_ID:MSVC>:/wd4018 /wd4100 /wd4146 /wd4127 /wd4189 /wd4201 /wd4245 /wd4456 /wd4459 /wd4505 /wd4701 /wd4703 /wd4706 /wd4996 /wd6001 /wd6011 /wd6297 /wd6308 /wd6385 /wd6386 /wd26454 /wd26495 /wd26812 /wd26819 /wd28112>)
target_link_libraries(in_2sf
in_xsf_framework)
--- /dev/null
+++ b/src/in_2sf/XSFConfigDialog_2SF.cpp
@@ -1,1 +1,39 @@
+/*
+ * xSF - 2SF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#include <string>
+#include <wx/arrstr.h>
+#include <wx/choice.h>
+#include <wx/gbsizer.h>
+#include <wx/listbox.h>
+#include <wx/stattext.h>
+#include <wx/valgen.h>
+#include "XSFConfig.h"
+#include "XSFConfigDialog.h"
+#include "XSFConfigDialog_2SF.h"
+
+XSFConfigDialog_2SF::XSFConfigDialog_2SF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
+{
+ auto interpolationLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Interpolation");
+ this->outputSizer->Add(interpolationLabel, { 4, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString interpolationChoices;
+ interpolationChoices.Add("None");
+ interpolationChoices.Add("Linear");
+ interpolationChoices.Add("Cosine");
+ interpolationChoices.Add("Sharp");
+ auto interpolationChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, interpolationChoices, 0, wxGenericValidator{ &this->interpolation });
+ this->outputSizer->Add(interpolationChoice, { 4, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
+ this->outputSizer->Add(muteLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString muteChoices;
+ for (int i = 0; i < 16; ++i)
+ muteChoices.Add("SPU " + std::to_string(i + 1));
+ auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
+ this->outputSizer->Add(muteListBox, { 5, 1 }, { 1, 1 }, wxALL, 5);
+}
+
--- /dev/null
+++ b/src/in_2sf/XSFConfigDialog_2SF.h
@@ -1,1 +1,25 @@
+/*
+ * xSF - 2SF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#pragma once
+
+#include <wx/dynarray.h>
+#include "XSFConfigDialog.h"
+
+class wxString;
+class wxWindow;
+class XSFConfig;
+
+class XSFConfigDialog_2SF : public XSFConfigDialog
+{
+public:
+ XSFConfigDialog_2SF(XSFConfig &config, wxWindow *parent, const wxString &title);
+
+ int interpolation;
+ wxArrayInt mute;
+};
+
--- a/src/in_2sf/XSFConfig_2SF.cpp
+++ b/src/in_2sf/XSFConfig_2SF.cpp
@@ -11,10 +11,14 @@
#include <cstddef>
#include "windowsh_wrapper.h"
#include "XSFConfig.h"
+#include "XSFConfig_2SF.h"
+#include "XSFConfigDialog_2SF.h"
#include "convert.h"
#include "desmume/NDSSystem.h"
#include "desmume/version.h"
+class wxWindow;
+class XSFConfigDialog;
class XSFPlayer;
enum
@@ -23,33 +27,9 @@
idMutes
};
-class XSFConfig_2SF : public XSFConfig
-{
-protected:
- static unsigned initInterpolation;
- static std::string initMutes;
-
- friend class XSFConfig;
- unsigned interpolation;
- std::bitset<16> mutes;
-
- XSFConfig_2SF();
- void LoadSpecificConfig() override;
- void SaveSpecificConfig() override;
- void GenerateSpecificDialogs() override;
- INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
- void ResetSpecificConfigDefaults(HWND hwndDlg) override;
- void SaveSpecificConfigDialog(HWND hwndDlg) override;
- void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
-public:
- void About(HWND parent) override;
-};
-
-unsigned XSFConfig::initSampleRate = static_cast<unsigned>(DESMUME_SAMPLE_RATE);
-std::string XSFConfig::commonName = "2SF Decoder";
-std::string XSFConfig::versionNumber = "0.9b";
-unsigned XSFConfig_2SF::initInterpolation = 2;
-std::string XSFConfig_2SF::initMutes = "0000000000000000";
+const unsigned XSFConfig::initSampleRate = static_cast<unsigned>(DESMUME_SAMPLE_RATE);
+const std::string XSFConfig::commonName = "2SF Decoder";
+const std::string XSFConfig::versionNumber = "0.9b";
XSFConfig *XSFConfig::Create()
{
@@ -74,54 +54,32 @@
this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
}
-void XSFConfig_2SF::GenerateSpecificDialogs()
+void XSFConfig_2SF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
{
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Interpolation").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idInterpolation).IsDropDownList().
- WithTabStop());
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).WithBorder().
- WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
+ auto twosfDialog = static_cast<XSFConfigDialog_2SF *>(dialog);
+ twosfDialog->interpolation = static_cast<int>(this->interpolation);
+ for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
+ if (this->mutes[x])
+ twosfDialog->mute.Add(x);
}
-INT_PTR CALLBACK XSFConfig_2SF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+void XSFConfig_2SF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- // Interpolation
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"No Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Cosine Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Sharp Interpolation"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, this->interpolation, 0);
- // Mutes
- for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- {
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + std::to_wstring(x + 1)).c_str()));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
- }
- break;
- case WM_COMMAND:
- break;
- }
-
- return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
+ auto twosfDialog = static_cast<XSFConfigDialog_2SF *>(dialog);
+ twosfDialog->interpolation = XSFConfig_2SF::initInterpolation;
+ twosfDialog->mute.Clear();
+ auto tmpMutes = std::bitset<16>(XSFConfig_2SF::initMutes);
+ for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
+ if (tmpMutes[x])
+ twosfDialog->mute.Add(x);
}
-void XSFConfig_2SF::ResetSpecificConfigDefaults(HWND hwndDlg)
+void XSFConfig_2SF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
{
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, XSFConfig_2SF::initInterpolation, 0);
- auto tmpMutes = std::bitset<16>(XSFConfig_2SF::initMutes);
- for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
-}
-
-void XSFConfig_2SF::SaveSpecificConfigDialog(HWND hwndDlg)
-{
- this->interpolation = static_cast<unsigned>(SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_GETCURSEL, 0, 0));
+ auto twosfDialog = static_cast<XSFConfigDialog_2SF *>(dialog);
+ this->interpolation = twosfDialog->interpolation;
for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
+ this->mutes[x] = twosfDialog->mute.Index(x) != wxNOT_FOUND;
}
void XSFConfig_2SF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
@@ -140,3 +98,8 @@
"Utilizes modified " + EMU_DESMUME_NAME_AND_VERSION() + " for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
}
+XSFConfigDialog *XSFConfig_2SF::CreateDialogBox(wxWindow *window, const std::string &title)
+{
+ return new XSFConfigDialog_2SF(*this, window, title);
+}
+
--- /dev/null
+++ b/src/in_2sf/XSFConfig_2SF.h
@@ -1,1 +1,40 @@
+/*
+ * xSF - 2SF configuration
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#pragma once
+
+#include <bitset>
+#include <string>
+#include "windowsh_wrapper.h"
+#include "XSFConfig.h"
+
+class wxWindow;
+class XSFConfigDialog;
+class XSFPlayer;
+
+class XSFConfig_2SF : public XSFConfig
+{
+protected:
+ static constexpr unsigned initInterpolation = 2;
+ inline static const std::string initMutes = "0000000000000000";
+
+ friend class XSFConfig;
+ unsigned interpolation;
+ std::bitset<16> mutes;
+
+ XSFConfig_2SF();
+ void LoadSpecificConfig() override;
+ void SaveSpecificConfig() override;
+ void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
+ void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
+ void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
+ void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
+public:
+ void About(HWND parent) override;
+ XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
+};
+
--- a/src/in_gsf/CMakeLists.txt
+++ b/src/in_gsf/CMakeLists.txt
@@ -12,7 +12,9 @@
vbam/gba/GBAcpu.h
vbam/gba/GBAinline.h
vbam/gba/Globals.h
- vbam/gba/Sound.h)
+ vbam/gba/Sound.h
+ XSFConfig_GSF.h
+ XSFConfigDialog_GSF.h)
set(SOURCES
vbam/apu/Blip_Buffer.cpp
vbam/apu/Gb_Apu.cpp
@@ -25,6 +27,7 @@
vbam/gba/Globals.cpp
vbam/gba/Sound.cpp
XSFConfig_GSF.cpp
+ XSFConfigDialog_GSF.cpp
XSFPlayer_GSF.cpp)
add_library(in_gsf SHARED ${HEADERS} ${SOURCES})
--- /dev/null
+++ b/src/in_gsf/XSFConfigDialog_GSF.cpp
@@ -1,1 +1,35 @@
+/*
+ * xSF - GSF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#include <wx/arrstr.h>
+#include <wx/checkbox.h>
+#include <wx/gbsizer.h>
+#include <wx/listbox.h>
+#include <wx/stattext.h>
+#include <wx/valgen.h>
+#include "XSFConfig.h"
+#include "XSFConfigDialog.h"
+#include "XSFConfigDialog_GSF.h"
+
+XSFConfigDialog_GSF::XSFConfigDialog_GSF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
+{
+ auto lowPassFilteringCheckBox = new wxCheckBox(this->outputPanel, wxID_ANY, "Low-Pass Filtering", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->lowPassFiltering });
+ this->outputSizer->Add(lowPassFilteringCheckBox, { 4, 0 }, { 1, 2 }, wxALL, 5);
+
+ auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
+ this->outputSizer->Add(muteLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString muteChoices;
+ muteChoices.Add("Square 1");
+ muteChoices.Add("Square 2");
+ muteChoices.Add("Wave Pattern");
+ muteChoices.Add("Noise");
+ muteChoices.Add("PCM A");
+ muteChoices.Add("PCM B");
+ auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
+ this->outputSizer->Add(muteListBox, { 5, 1 }, { 1, 1 }, wxALL, 5);
+}
+
--- /dev/null
+++ b/src/in_gsf/XSFConfigDialog_GSF.h
@@ -1,1 +1,25 @@
+/*
+ * xSF - GSF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#pragma once
+
+#include <wx/dynarray.h>
+#include "XSFConfigDialog.h"
+
+class wxString;
+class wxWindow;
+class XSFConfig;
+
+class XSFConfigDialog_GSF : public XSFConfigDialog
+{
+public:
+ XSFConfigDialog_GSF(XSFConfig &config, wxWindow *parent, const wxString &title);
+
+ bool lowPassFiltering;
+ wxArrayInt mute;
+};
+
--- a/src/in_gsf/XSFConfig_GSF.cpp
+++ b/src/in_gsf/XSFConfig_GSF.cpp
@@ -8,11 +8,16 @@
#include <bitset>
#include <sstream>
#include <string>
+#include <cstddef>
#include "windowsh_wrapper.h"
#include "XSFConfig.h"
+#include "XSFConfig_GSF.h"
+#include "XSFConfigDialog_GSF.h"
#include "convert.h"
#include "vbam/gba/Sound.h"
+class wxWindow;
+class XSFConfigDialog;
class XSFPlayer;
enum
@@ -21,33 +26,9 @@
idMutes
};
-class XSFConfig_GSF : public XSFConfig
-{
-protected:
- static bool initLowPassFiltering;
- static std::string initMutes;
-
- friend class XSFConfig;
- bool lowPassFiltering;
- std::bitset<6> mutes;
-
- XSFConfig_GSF();
- void LoadSpecificConfig() override;
- void SaveSpecificConfig() override;
- void GenerateSpecificDialogs() override;
- INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
- void ResetSpecificConfigDefaults(HWND hwndDlg) override;
- void SaveSpecificConfigDialog(HWND hwndDlg) override;
- void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
-public:
- void About(HWND parent) override;
-};
-
-unsigned XSFConfig::initSampleRate = 44100;
-std::string XSFConfig::commonName = "GSF Decoder";
-std::string XSFConfig::versionNumber = "0.9b";
-bool XSFConfig_GSF::initLowPassFiltering = true;
-std::string XSFConfig_GSF::initMutes = "000000";
+const unsigned XSFConfig::initSampleRate = 44100;
+const std::string XSFConfig::commonName = "GSF Decoder";
+const std::string XSFConfig::versionNumber = "0.9b";
XSFConfig *XSFConfig::Create()
{
@@ -82,53 +63,32 @@
this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
}
-void XSFConfig_GSF::GenerateSpecificDialogs()
+void XSFConfig_GSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
{
- this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Low-Pass Filtering").WithSize(80, 10).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7), 2).WithTabStop().
- WithID(idLowPassFiltering));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10)).IsLeftJustified());
- this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).WithBorder().
- WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
+ auto gsfDialog = static_cast<XSFConfigDialog_GSF *>(dialog);
+ gsfDialog->lowPassFiltering = this->lowPassFiltering;
+ for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
+ if (this->mutes[x])
+ gsfDialog->mute.Add(x);
}
-INT_PTR CALLBACK XSFConfig_GSF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+void XSFConfig_GSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- // Low-Pass Filtering
- if (this->lowPassFiltering)
- SendMessageW(GetDlgItem(hwndDlg, idLowPassFiltering), BM_SETCHECK, BST_CHECKED, 0);
- // Mutes
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Square 1"));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Square 2"));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Wave Pattern"));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Noise"));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"PCM A"));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"PCM B"));
- for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
- break;
- case WM_COMMAND:
- break;
- }
-
- return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
+ auto gsfDialog = static_cast<XSFConfigDialog_GSF *>(dialog);
+ gsfDialog->lowPassFiltering = XSFConfig_GSF::initLowPassFiltering;
+ gsfDialog->mute.Clear();
+ auto tmpMutes = std::bitset<6>(XSFConfig_GSF::initMutes);
+ for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
+ if (tmpMutes[x])
+ gsfDialog->mute.Add(x);
}
-void XSFConfig_GSF::ResetSpecificConfigDefaults(HWND hwndDlg)
+void XSFConfig_GSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
{
- SendMessageW(GetDlgItem(hwndDlg, idLowPassFiltering), BM_SETCHECK, XSFConfig_GSF::initLowPassFiltering ? BST_CHECKED : BST_UNCHECKED, 0);
- auto tmpMutes = std::bitset<6>(XSFConfig_GSF::initMutes);
- for (int x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
-}
-
-void XSFConfig_GSF::SaveSpecificConfigDialog(HWND hwndDlg)
-{
- this->lowPassFiltering = SendMessageW(GetDlgItem(hwndDlg, idLowPassFiltering), BM_GETCHECK, 0, 0) == BST_CHECKED;
- for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
+ auto gsfDialog = static_cast<XSFConfigDialog_GSF *>(dialog);
+ this->lowPassFiltering = gsfDialog->lowPassFiltering;
+ for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
+ this->mutes[x] = gsfDialog->mute.Index(x) != wxNOT_FOUND;
}
void XSFConfig_GSF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
@@ -147,3 +107,8 @@
"Utilizes modified VBA-M, SVN revision 1231, for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
}
+XSFConfigDialog *XSFConfig_GSF::CreateDialogBox(wxWindow *window, const std::string &title)
+{
+ return new XSFConfigDialog_GSF(*this, window, title);
+}
+
--- /dev/null
+++ b/src/in_gsf/XSFConfig_GSF.h
@@ -1,1 +1,40 @@
+/*
+ * xSF - GSF configuration
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#pragma once
+
+#include <bitset>
+#include <string>
+#include "windowsh_wrapper.h"
+#include "XSFConfig.h"
+
+class wxWindow;
+class XSFConfigDialog;
+class XSFPlayer;
+
+class XSFConfig_GSF : public XSFConfig
+{
+protected:
+ static constexpr bool initLowPassFiltering = true;
+ inline static const std::string initMutes = "000000";
+
+ friend class XSFConfig;
+ bool lowPassFiltering;
+ std::bitset<6> mutes;
+
+ XSFConfig_GSF();
+ void LoadSpecificConfig() override;
+ void SaveSpecificConfig() override;
+ void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
+ void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
+ void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
+ void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
+public:
+ void About(HWND parent) override;
+ XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
+};
+
--- a/src/in_ncsf/CMakeLists.txt
+++ b/src/in_ncsf/CMakeLists.txt
@@ -16,6 +16,7 @@
SSEQPlayer/Track.h
resource.h
XSFConfig_NCSF.h
+ XSFConfigDialog_NCSF.h
XSFPlayer_NCSF.h)
set(RESOURCES
in_ncsf.rc)
@@ -34,6 +35,7 @@
SSEQPlayer/SYMBSection.cpp
SSEQPlayer/Track.cpp
XSFConfig_NCSF.cpp
+ XSFConfigDialog_NCSF.cpp
XSFPlayer_NCSF.cpp)
add_library(in_ncsf SHARED ${HEADERS} ${RESOURCES} ${SOURCES})
--- /dev/null
+++ b/src/in_ncsf/XSFConfigDialog_NCSF.cpp
@@ -1,1 +1,46 @@
+/*
+ * xSF - NCSF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#include <string>
+#include <wx/arrstr.h>
+#include <wx/checkbox.h>
+#include <wx/choice.h>
+#include <wx/gbsizer.h>
+#include <wx/listbox.h>
+#include <wx/stattext.h>
+#include <wx/valgen.h>
+#include "XSFConfig.h"
+#include "XSFConfigDialog.h"
+#include "XSFConfigDialog_NCSF.h"
+
+XSFConfigDialog_NCSF::XSFConfigDialog_NCSF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
+{
+#ifndef NDEBUG
+ auto useSoundViewCheckBox = new wxCheckBox(this->generalPanel, wxID_ANY, "Use Sound View Window", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->useSoundView });
+ this->generalSizer->Add(useSoundViewCheckBox, { 5, 0 }, { 1, 2 }, wxALL, 5);
+#endif
+
+ auto interpolationLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Interpolation");
+ this->outputSizer->Add(interpolationLabel, { 4, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString interpolationChoices;
+ interpolationChoices.Add("None");
+ interpolationChoices.Add("Linear");
+ interpolationChoices.Add("4-point, 3rd-order Legrange");
+ interpolationChoices.Add("6-point, 5th-order Legrange");
+ interpolationChoices.Add("16-point Sinc (Nuttall 3-term Window)");
+ auto interpolationChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, interpolationChoices, 0, wxGenericValidator{ &this->interpolation });
+ this->outputSizer->Add(interpolationChoice, { 4, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
+ this->outputSizer->Add(muteLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString muteChoices;
+ for (int i = 0; i < 16; ++i)
+ muteChoices.Add("SPU " + std::to_string(i + 1));
+ auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
+ this->outputSizer->Add(muteListBox, { 5, 1 }, { 1, 1 }, wxALL, 5);
+}
+
--- /dev/null
+++ b/src/in_ncsf/XSFConfigDialog_NCSF.h
@@ -1,1 +1,28 @@
+/*
+ * xSF - NCSF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#pragma once
+
+#include <wx/dynarray.h>
+#include "XSFConfigDialog.h"
+
+class wxString;
+class wxWindow;
+class XSFConfig;
+
+class XSFConfigDialog_NCSF : public XSFConfigDialog
+{
+public:
+ XSFConfigDialog_NCSF(XSFConfig &config, wxWindow *parent, const wxString &title);
+
+#ifndef NDEBUG
+ bool useSoundView;
+#endif
+ int interpolation;
+ wxArrayInt mute;
+};
+
--- a/src/in_ncsf/XSFConfig_NCSF.cpp
+++ b/src/in_ncsf/XSFConfig_NCSF.cpp
@@ -11,7 +11,9 @@
#include <cstddef>
#include "windowsh_wrapper.h"
#include <windowsx.h>
+#include "XSFConfig.h"
#include "XSFConfig_NCSF.h"
+#include "XSFConfigDialog_NCSF.h"
#include "XSFPlayer_NCSF.h"
#include "convert.h"
#ifndef NDEBUG
@@ -22,17 +24,19 @@
# include <CommCtrl.h>
#endif
+class wxWindow;
+class XSFConfigDialog;
+class XSFPlayer;
+
enum
{
idInterpolation = 1000,
idMutes
};
-unsigned XSFConfig::initSampleRate = 44100;
-std::string XSFConfig::commonName = "NCSF Decoder";
-std::string XSFConfig::versionNumber = "1.11.1";
-unsigned XSFConfig_NCSF::initInterpolation = 4;
-std::string XSFConfig_NCSF::initMutes = "0000000000000000";
+const unsigned XSFConfig::initSampleRate = 44100;
+const std::string XSFConfig::commonName = "NCSF Decoder";
+const std::string XSFConfig::versionNumber = "1.11.1";
XSFConfig *XSFConfig::Create()
{
@@ -41,7 +45,7 @@
XSFConfig_NCSF::XSFConfig_NCSF() : XSFConfig(), interpolation(0), mutes()
#ifndef NDEBUG
- , soundViewData()
+ , useSoundViewDialog(false), soundViewData()
#endif
{
this->supportedSampleRates.push_back(8000);
@@ -59,6 +63,9 @@
void XSFConfig_NCSF::LoadSpecificConfig()
{
+#ifndef NDEBUG
+ this->useSoundViewDialog = this->configIO->GetValue("UseSoundViewDialog", XSFConfig_NCSF::initUseSoundViewDialog);
+#endif
this->interpolation = this->configIO->GetValue("Interpolation", XSFConfig_NCSF::initInterpolation);
std::stringstream mutesSS(this->configIO->GetValue("Mutes", XSFConfig_NCSF::initMutes));
mutesSS >> this->mutes;
@@ -66,64 +73,56 @@
void XSFConfig_NCSF::SaveSpecificConfig()
{
+#ifndef NDEBUG
+ this->configIO->SetValue("UseSoundViewDialog", this->useSoundViewDialog);
+#endif
this->configIO->SetValue("Interpolation", this->interpolation);
this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
}
-void XSFConfig_NCSF::GenerateSpecificDialogs()
-{
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Interpolation").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(110, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idInterpolation).
- IsDropDownList().WithTabStop());
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).
- WithBorder().WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
-}
-
-INT_PTR CALLBACK XSFConfig_NCSF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- // Interpolation
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"None"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"4-point, 3rd-order Legrange"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order Legrange"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"16-point Sinc (Nuttall 3-term Window)"));
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, this->interpolation, 0);
- // Mutes
- for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- {
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + std::to_wstring(x + 1)).c_str()));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
- }
- break;
- case WM_COMMAND:
- break;
- }
-
- return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
-}
-
-void XSFConfig_NCSF::ResetSpecificConfigDefaults(HWND hwndDlg)
-{
- SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, XSFConfig_NCSF::initInterpolation, 0);
+void XSFConfig_NCSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
+{
+ auto ncsfDialog = static_cast<XSFConfigDialog_NCSF *>(dialog);
+#ifndef NDEBUG
+ ncsfDialog->useSoundView = this->useSoundViewDialog;
+#endif
+ ncsfDialog->interpolation = static_cast<int>(this->interpolation);
+ for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
+ if (this->mutes[x])
+ ncsfDialog->mute.Add(x);
+}
+
+void XSFConfig_NCSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
+{
+ auto ncsfDialog = static_cast<XSFConfigDialog_NCSF *>(dialog);
+#ifndef NDEBUG
+ ncsfDialog->useSoundView = XSFConfig_NCSF::initUseSoundViewDialog;
+#endif
+ ncsfDialog->interpolation = XSFConfig_NCSF::initInterpolation;
+ ncsfDialog->mute.Clear();
auto tmpMutes = std::bitset<16>(XSFConfig_NCSF::initMutes);
for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
-}
-
-void XSFConfig_NCSF::SaveSpecificConfigDialog(HWND hwndDlg)
-{
- this->interpolation = static_cast<unsigned>(SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_GETCURSEL, 0, 0));
+ if (tmpMutes[x])
+ ncsfDialog->mute.Add(x);
+}
+
+void XSFConfig_NCSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
+{
+ auto ncsfDialog = static_cast<XSFConfigDialog_NCSF *>(dialog);
+#ifndef NDEBUG
+ this->useSoundViewDialog = ncsfDialog->useSoundView;
+#endif
+ this->interpolation = ncsfDialog->interpolation;
for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
+ this->mutes[x] = ncsfDialog->mute.Index(x) != wxNOT_FOUND;
}
void XSFConfig_NCSF::CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool)
{
auto NCSFPlayer = static_cast<XSFPlayer_NCSF *>(xSFPlayer);
+#ifndef NDEBUG
+ NCSFPlayer->SetUseSoundViewDialog(this->useSoundViewDialog);
+#endif
NCSFPlayer->SetInterpolation(this->interpolation);
NCSFPlayer->SetMutes(this->mutes);
}
@@ -132,6 +131,11 @@
{
MessageBoxW(parent, ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber + ", using xSF Winamp plugin framework (based on the vio*sf plugins) by Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]\n\n"
"Utilizes code adapted from the FeOS Sound System library by fincs, git revision 5204c55 on GitHub, for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
+}
+
+XSFConfigDialog *XSFConfig_NCSF::CreateDialogBox(wxWindow *window, const std::string &title)
+{
+ return new XSFConfigDialog_NCSF(*this, window, title);
}
#ifndef NDEBUG
--- a/src/in_ncsf/XSFConfig_NCSF.h
+++ b/src/in_ncsf/XSFConfig_NCSF.h
@@ -18,8 +18,13 @@
#include "windowsh_wrapper.h"
#include "XSFConfig.h"
+class wxWindow;
class XSFConfig_NCSF;
+class XSFConfigDialog;
+class XSFPlayer;
+#ifndef DEBUG
class XSFPlayer_NCSF;
+#endif
#ifndef NDEBUG
struct SoundViewData
@@ -41,21 +46,26 @@
class XSFConfig_NCSF : public XSFConfig
{
protected:
- static unsigned initInterpolation;
- static std::string initMutes;
+#ifndef NDEBUG
+ static constexpr bool initUseSoundViewDialog = true;
+#endif
+ static constexpr unsigned initInterpolation = 4;
+ inline static const std::string initMutes = "0000000000000000";
friend class XSFConfig;
friend struct SoundViewData;
+#ifndef NDEBUG
+ bool useSoundViewDialog;
+#endif
unsigned interpolation;
std::bitset<16> mutes;
XSFConfig_NCSF();
void LoadSpecificConfig() override;
void SaveSpecificConfig() override;
- void GenerateSpecificDialogs() override;
- INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
- void ResetSpecificConfigDefaults(HWND hwndDlg) override;
- void SaveSpecificConfigDialog(HWND hwndDlg) override;
+ void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
+ void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
+ void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
#ifndef NDEBUG
@@ -65,6 +75,7 @@
#endif
public:
void About(HWND parent) override;
+ XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
#ifndef NDEBUG
void CallSoundView(XSFPlayer *xSFPlayer, HINSTANCE hInstance, HWND hwndParent);
--- a/src/in_ncsf/XSFPlayer_NCSF.cpp
+++ b/src/in_ncsf/XSFPlayer_NCSF.cpp
@@ -112,6 +112,9 @@
}
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes()
+#ifndef NDEBUG
+ , useSoundViewDialog(false)
+#endif
{
this->uses32BitSamplesClampedTo16Bit = true;
this->xSF.reset(new XSFFile(filename, 8, 12));
@@ -119,6 +122,9 @@
#ifdef _WIN32
XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes()
+#ifndef NDEBUG
+ , useSoundViewDialog(false)
+#endif
{
this->uses32BitSamplesClampedTo16Bit = true;
this->xSF.reset(new XSFFile(filename, 8, 12));
@@ -151,14 +157,17 @@
XSFPlayer_NCSF::~XSFPlayer_NCSF()
{
#ifndef NDEBUG
- killSoundViewThread = true;
- if (WaitForSingleObject(soundViewThreadHandle, 2000) == WAIT_TIMEOUT)
- {
- TerminateThread(soundViewThreadHandle, 0);
- static_cast<XSFConfig_NCSF *>(xSFConfig)->CloseSoundView();
- }
- CloseHandle(soundViewThreadHandle);
- soundViewThreadHandle = INVALID_HANDLE_VALUE;
+ if (soundViewThreadHandle != INVALID_HANDLE_VALUE)
+ {
+ killSoundViewThread = true;
+ if (WaitForSingleObject(soundViewThreadHandle, 2000) == WAIT_TIMEOUT)
+ {
+ TerminateThread(soundViewThreadHandle, 0);
+ static_cast<XSFConfig_NCSF *>(xSFConfig)->CloseSoundView();
+ }
+ CloseHandle(soundViewThreadHandle);
+ soundViewThreadHandle = INVALID_HANDLE_VALUE;
+ }
#endif
}
@@ -168,8 +177,11 @@
return false;
#ifndef NDEBUG
- killSoundViewThread = false;
- soundViewThreadHandle = CreateThread(nullptr, 0, soundViewThread, this, 0, nullptr);
+ if (this->useSoundViewDialog)
+ {
+ killSoundViewThread = false;
+ soundViewThreadHandle = CreateThread(nullptr, 0, soundViewThread, this, 0, nullptr);
+ }
#endif
PseudoFile file;
@@ -248,6 +260,13 @@
this->player.Stop(true);
}
+#ifndef NDEBUG
+void XSFPlayer_NCSF::SetUseSoundViewDialog(bool newUseSoundViewDialog)
+{
+ this->useSoundViewDialog = newUseSoundViewDialog;
+}
+#endif
+
void XSFPlayer_NCSF::SetInterpolation(unsigned interpolation)
{
this->player.interpolation = static_cast<Interpolation>(interpolation);
--- a/src/in_ncsf/XSFPlayer_NCSF.h
+++ b/src/in_ncsf/XSFPlayer_NCSF.h
@@ -22,6 +22,8 @@
#include "SSEQPlayer/SDAT.h"
#include "SSEQPlayer/Player.h"
+class XSFFile;
+
class XSFPlayer_NCSF : public XSFPlayer
{
std::uint32_t sseq;
@@ -29,6 +31,9 @@
std::unique_ptr<SDAT> sdat;
Player player;
double secondsPerSample, secondsIntoPlayback, secondsUntilNextClock;
+#ifndef NDEBUG
+ bool useSoundViewDialog;
+#endif
std::bitset<16> mutes;
void MapNCSFSection(const std::vector<std::uint8_t> §ion);
@@ -45,6 +50,9 @@
void GenerateSamples(std::vector<std::uint8_t> &buf, unsigned offset, unsigned samples) override;
void Terminate() override;
+#ifndef NDEBUG
+ void SetUseSoundViewDialog(bool newUseSoundViewDialog);
+#endif
void SetInterpolation(unsigned interpolation);
void SetMutes(const std::bitset<16> &newMutes);
#ifndef NDEBUG
--- a/src/in_snsf/CMakeLists.txt
+++ b/src/in_snsf/CMakeLists.txt
@@ -24,7 +24,8 @@
snes9x/ppu.h
snes9x/sdd1.h
snes9x/snes9x.h
- XSFConfig_SNSF.h)
+ XSFConfig_SNSF.h
+ XSFConfigDialog_SNSF.h)
set(SOURCES
snes9x/apu/apu.cpp
snes9x/apu/SNES_SPC.cpp
@@ -39,6 +40,7 @@
snes9x/ppu.cpp
snes9x/sdd1.cpp
XSFConfig_SNSF.cpp
+ XSFConfigDialog_SNSF.cpp
XSFPlayer_SNSF.cpp)
add_library(in_snsf SHARED ${HEADERS} ${SOURCES})
--- /dev/null
+++ b/src/in_snsf/XSFConfigDialog_SNSF.cpp
@@ -1,1 +1,44 @@
+/*
+ * xSF - SNSF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#include <string>
+#include <wx/arrstr.h>
+#include <wx/checkbox.h>
+#include <wx/choice.h>
+#include <wx/gbsizer.h>
+#include <wx/listbox.h>
+#include <wx/stattext.h>
+#include <wx/valgen.h>
+#include "XSFConfig.h"
+#include "XSFConfigDialog.h"
+#include "XSFConfigDialog_SNSF.h"
+
+XSFConfigDialog_SNSF::XSFConfigDialog_SNSF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
+{
+ auto reverseStereoCheckBox = new wxCheckBox(this->outputPanel, wxID_ANY, "Reverse Stereo", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->reverseStereo });
+ this->outputSizer->Add(reverseStereoCheckBox, { 4, 0 }, { 1, 2 }, wxALL, 5);
+
+ auto resamplerLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Resampler");
+ this->outputSizer->Add(resamplerLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString resamplerChoices;
+ resamplerChoices.Add("Linear Resampler");
+ resamplerChoices.Add("Hermite Resampler");
+ resamplerChoices.Add("Bspline Resampler");
+ resamplerChoices.Add("Osculating Resampler");
+ resamplerChoices.Add("Sinc Resampler");
+ auto resamplerChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, resamplerChoices, 0, wxGenericValidator{ &this->resampler });
+ this->outputSizer->Add(resamplerChoice, { 5, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
+ this->outputSizer->Add(muteLabel, { 6, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString muteChoices;
+ for (int i = 0; i < 16; ++i)
+ muteChoices.Add("BRRPCM " + std::to_string(i + 1));
+ auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
+ this->outputSizer->Add(muteListBox, { 6, 1 }, { 1, 1 }, wxALL, 5);
+}
+
--- /dev/null
+++ b/src/in_snsf/XSFConfigDialog_SNSF.h
@@ -1,1 +1,26 @@
+/*
+ * xSF - SNSF configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#pragma once
+
+#include <wx/dynarray.h>
+#include "XSFConfigDialog.h"
+
+class wxString;
+class wxWindow;
+class XSFConfig;
+
+class XSFConfigDialog_SNSF : public XSFConfigDialog
+{
+public:
+ XSFConfigDialog_SNSF(XSFConfig &config, wxWindow *parent, const wxString &title);
+
+ bool reverseStereo;
+ int resampler;
+ wxArrayInt mute;
+};
+
--- a/src/in_snsf/XSFConfig_SNSF.cpp
+++ b/src/in_snsf/XSFConfig_SNSF.cpp
@@ -12,11 +12,18 @@
#include <bitset>
#include <sstream>
#include <string>
+#include <cstddef>
#include <cstdint>
#include "windowsh_wrapper.h"
+#include "XSFConfig.h"
#include "XSFConfig_SNSF.h"
+#include "XSFConfigDialog_SNSF.h"
#include "convert.h"
#include "snes9x/apu/apu.h"
+
+class wxWindow;
+class XSFConfigDialog;
+class XSFPlayer;
enum
{
@@ -26,13 +33,9 @@
idMutes
};
-unsigned XSFConfig::initSampleRate = 44100;
-std::string XSFConfig::commonName = "SNSF Decoder";
-std::string XSFConfig::versionNumber = "0.9b";
-//bool XSFConfig_SNSF::initSixteenBitSound = true;
-bool XSFConfig_SNSF::initReverseStereo = false;
-unsigned XSFConfig_SNSF::initResampler = 1;
-std::string XSFConfig_SNSF::initMutes = "00000000";
+const unsigned XSFConfig::initSampleRate = 44100;
+const std::string XSFConfig::commonName = "SNSF Decoder";
+const std::string XSFConfig::versionNumber = "0.9b";
XSFConfig *XSFConfig::Create()
{
@@ -71,69 +74,35 @@
this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
}
-void XSFConfig_SNSF::GenerateSpecificDialogs()
+void XSFConfig_SNSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
{
- /*this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Sixteen-Bit Sound").WithSize(80, 10).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7), 2).WithTabStop().
- WithID(idSixteenBitSound));*/
- this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Reverse Stereo").WithSize(80, 10).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7), 2).WithTabStop().
- WithID(idReverseStereo));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Resampler").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10)).IsLeftJustified());
- this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithTabStop().IsDropDownList().
- WithID(idResampler));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).WithBorder().
- WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
+ auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
+ snsfDialog->reverseStereo = this->reverseStereo;
+ snsfDialog->resampler = static_cast<int>(this->resampler);
+ for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
+ if (this->mutes[x])
+ snsfDialog->mute.Add(x);
}
-INT_PTR CALLBACK XSFConfig_SNSF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+void XSFConfig_SNSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
{
- switch (uMsg)
- {
- case WM_INITDIALOG:
- // Sixteen-Bit Sound
- /*if (this->sixteenBitSound)
- SendMessageW(GetDlgItem(hwndDlg, idSixteenBitSound), BM_SETCHECK, BST_CHECKED, 0);*/
- // Reverse Stereo
- if (this->reverseStereo)
- SendMessageW(GetDlgItem(hwndDlg, idReverseStereo), BM_SETCHECK, BST_CHECKED, 0);
- // Resampler
- SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear Resampler"));
- SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Hermite Resampler"));
- SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Bspline Resampler"));
- SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Osculating Resampler"));
- SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Sinc Resampler"));
- SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_SETCURSEL, this->resampler, 0);
- // Mutes
- for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- {
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"BRRPCM " + std::to_wstring(x + 1)).c_str()));
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
- }
- break;
- case WM_COMMAND:
- break;
- }
-
- return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
+ auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
+ snsfDialog->reverseStereo = XSFConfig_SNSF::initReverseStereo;
+ snsfDialog->resampler = XSFConfig_SNSF::initResampler;
+ snsfDialog->mute.Clear();
+ auto tmpMutes = std::bitset<8>(XSFConfig_SNSF::initMutes);
+ for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
+ if (tmpMutes[x])
+ snsfDialog->mute.Add(x);
}
-void XSFConfig_SNSF::ResetSpecificConfigDefaults(HWND hwndDlg)
+void XSFConfig_SNSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
{
- //SendMessageW(GetDlgItem(hwndDlg, idSixteenBitSound), BM_SETCHECK, XSFConfig_SNSF::initSixteenBitSound ? BST_CHECKED : BST_UNCHECKED, 0);
- SendMessageW(GetDlgItem(hwndDlg, idReverseStereo), BM_SETCHECK, XSFConfig_SNSF::initReverseStereo ? BST_CHECKED : BST_UNCHECKED, 0);
- SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_SETCURSEL, XSFConfig_SNSF::initResampler, 0);
- auto tmpMutes = std::bitset<8>(XSFConfig_SNSF::initMutes);
- for (int x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
-}
-
-void XSFConfig_SNSF::SaveSpecificConfigDialog(HWND hwndDlg)
-{
- //this->sixteenBitSound = SendMessageW(GetDlgItem(hwndDlg, idSixteenBitSound), BM_GETCHECK, 0, 0) == BST_CHECKED;
- this->reverseStereo = SendMessageW(GetDlgItem(hwndDlg, idReverseStereo), BM_GETCHECK, 0, 0) == BST_CHECKED;
- this->resampler = static_cast<unsigned>(SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_GETCURSEL, 0, 0));
- for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
- this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
+ auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
+ this->reverseStereo = snsfDialog->reverseStereo;
+ this->resampler = snsfDialog->resampler;
+ for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
+ this->mutes[x] = snsfDialog->mute.Index(x) != wxNOT_FOUND;
}
void XSFConfig_SNSF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
@@ -154,3 +123,8 @@
"Utilizes modified snes9x v1.53 for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
}
+XSFConfigDialog *XSFConfig_SNSF::CreateDialogBox(wxWindow *window, const std::string &title)
+{
+ return new XSFConfigDialog_SNSF(*this, window, title);
+}
+
--- a/src/in_snsf/XSFConfig_SNSF.h
+++ b/src/in_snsf/XSFConfig_SNSF.h
@@ -16,14 +16,16 @@
#include "windowsh_wrapper.h"
#include "XSFConfig.h"
+class wxWindow;
+class XSFConfigDialog;
class XSFPlayer;
class XSFConfig_SNSF : public XSFConfig
{
protected:
- static bool /*initSixteenBitSound, */initReverseStereo;
- static unsigned initResampler;
- static std::string initMutes;
+ static constexpr bool /*initSixteenBitSound = true, */initReverseStereo = false;
+ static constexpr unsigned initResampler = 1;
+ inline static const std::string initMutes = "00000000";
friend class XSFConfig;
bool /*sixteenBitSound, */reverseStereo;
@@ -32,14 +34,14 @@
XSFConfig_SNSF();
void LoadSpecificConfig() override;
void SaveSpecificConfig() override;
- void GenerateSpecificDialogs() override;
- INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
- void ResetSpecificConfigDefaults(HWND hwndDlg) override;
- void SaveSpecificConfigDialog(HWND hwndDlg) override;
+ void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
+ void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
+ void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
public:
unsigned resampler;
void About(HWND parent) override;
+ XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
};
--- a/src/in_xsf_framework/CMakeLists.txt
+++ b/src/in_xsf_framework/CMakeLists.txt
@@ -198,6 +198,7 @@
set(wxUSE_ZIPSTREAM OFF CACHE BOOL " " FORCE)
set(wxUSE_ZLIB OFF CACHE STRING " " FORCE)
+add_compile_definitions($<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Debug>>:_ITERATOR_DEBUG_LEVEL=0>)
add_subdirectory(wxWidgets)
# in_xsf_framework
@@ -216,6 +217,7 @@
windowsh_wrapper.h
XSFCommon.h
XSFConfig.h
+ XSFConfigDialog.h
XSFFile.h
XSFPlayer.h)
set(SOURCES
@@ -225,6 +227,7 @@
TagList.cpp
XSFConfig.cpp
XSFConfig_Winamp.cpp
+ XSFConfigDialog.cpp
XSFFile.cpp
XSFPlayer.cpp)
--- a/src/in_xsf_framework/XSFConfig.cpp
+++ b/src/in_xsf_framework/XSFConfig.cpp
@@ -7,10 +7,14 @@
#include <algorithm>
#include <string>
+#include <type_traits>
#include <vector>
+#include <wx/app.h>
+#include <wx/nativewin.h>
#include "windowsh_wrapper.h"
#include <windowsx.h>
#include "XSFConfig.h"
+#include "XSFConfigDialog.h"
#include "XSFFile.h"
#include "XSFPlayer.h"
#include "convert.h"
@@ -37,18 +41,8 @@
idInfoComment
};
-bool XSFConfig::initPlayInfinitely = false;
-std::string XSFConfig::initSkipSilenceOnStartSec = "5";
-std::string XSFConfig::initDetectSilenceSec = "5";
-std::string XSFConfig::initDefaultLength = "1:55";
-std::string XSFConfig::initDefaultFade = "5";
-std::string XSFConfig::initTitleFormat = "%game%[ - [%disc%.]%track%] - %title%";
-double XSFConfig::initVolume = 1.0;
-VolumeType XSFConfig::initVolumeType = VolumeType::ReplayGainAlbum;
-PeakType XSFConfig::initPeakType = PeakType::ReplayGainTrack;
-
XSFConfig::XSFConfig() : playInfinitely(false), skipSilenceOnStartSec(0), detectSilenceSec(0), defaultLength(0), defaultFade(0), volume(0.0), volumeType(VolumeType::None), peakType(PeakType::None),
- sampleRate(0), titleFormat(""), configDialog(), configDialogProperty(), infoDialog(), supportedSampleRates(), configIO(XSFConfigIO::Create())
+ sampleRate(0), titleFormat(""), infoDialog(), supportedSampleRates(), configIO(XSFConfigIO::Create())
{
}
@@ -98,8 +92,44 @@
this->SaveSpecificConfig();
}
+class XSFConfigApp : public wxApp
+{
+ HWND parent;
+ XSFConfig *config;
+public:
+ XSFConfigApp() : parent(nullptr), config(nullptr)
+ {
+ }
+
+ XSFConfigApp(HWND parent, XSFConfig *config) : parent(parent), config(config)
+ {
+ }
+
+ bool OnInit() override
+ {
+ // NOTE: This is only good enough to make it so the dialog box isn't shown on the taskbar, it is not good enough to make the dialog modal to Winamp's preferences screen... it'll actually crash if someone changes to another section of preferences...
+
+ auto window = new wxNativeContainerWindow(this->parent);
+ auto dialog = this->config->CreateDialogBox(window, XSFConfig::commonName + " v" + XSFConfig::versionNumber);
+ dialog->Finalize();
+ this->config->InitializeConfigDialog(dialog);
+ if (dialog->ShowModal() == wxID_OK)
+ {
+ this->config->SaveConfigDialog(dialog);
+ this->config->SaveConfig();
+ }
+ dialog->Destroy();
+ window->Destroy();
+ return true;
+ }
+};
+
+wxIMPLEMENT_APP_NO_MAIN(XSFConfigApp);
+
void XSFConfig::GenerateDialogs()
{
+ // NOTE: Eventually this will be done away with when I decide to make an actual info dialog box using wxWidgets.
+
this->infoDialog = DialogBuilder().IsPopup().WithBorder().WithDialogFrame().WithDialogModalFrame().WithSystemMenu().WithFont(L"MS Shell Dlg", 8);
this->infoDialog.AddLabelControl(DialogLabelBuilder(L"Title:").WithSize(50, 8).WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(7, 10)).IsRightJustified());
this->infoDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(200, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().WithAutoHScroll().WithBorder().
@@ -123,82 +153,9 @@
this->infoDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(200, 54).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().WithAutoVScroll().WithBorder().
WithTabStop().WithID(idInfoComment).WithVerticalScrollbar().WithWantReturn().IsMultiline());
- this->configDialog = DialogBuilder().WithTitle(ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber)).IsPopup().WithBorder().WithDialogFrame().WithDialogModalFrame().WithSystemMenu().WithFont(L"MS Shell Dlg", 8);
- this->configDialog.AddGroupControl(DialogGroupBuilder(L"General").WithRelativePositionToParent(RelativePositionToParent::PositionType::FromTopLeft, Point<short>(7, 7)));
- this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Play infinitely").WithSize(60, 10).InGroup(L"General").WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(6, 11)).WithTabStop().
- WithID(idPlayInfinitely));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Default play length (m:s)").WithSize(85, 8).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7)).
- IsLeftJustified());
- this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
- WithAutoHScroll().WithBorder().WithTabStop().WithID(idDefaultLength));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Default fadeout length (m:s)").WithSize(85, 8).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).
- IsLeftJustified());
- this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
- WithAutoHScroll().WithBorder().WithTabStop().WithID(idDefaultFade));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Skip silence on start (sec)").WithSize(85, 8).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).
- IsLeftJustified());
- this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
- WithAutoHScroll().WithBorder().WithTabStop().WithID(idSkipSilenceOnStartSec));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Detect silence (sec)").WithSize(85, 8).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).
- IsLeftJustified());
- this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
- WithAutoHScroll().WithBorder().WithTabStop().WithID(idDetectSilenceSec));
- this->configDialog.AddGroupControl(DialogGroupBuilder(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7)));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Volume").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(6, 14)).IsLeftJustified());
- this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
- WithAutoHScroll().WithBorder().WithTabStop().WithID(idVolume));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"ReplayGain").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idReplayGain).
- IsDropDownList().WithTabStop());
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Clip Protect").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idClipProtect).
- IsDropDownList().WithTabStop());
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Sample Rate").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
- this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(50, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idSampleRate).
- IsDropDownList().WithTabStop());
- this->configDialog.AddGroupControl(DialogGroupBuilder(L"Title Format").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7)));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"NOTE: This is only used if Advanced Title Formatting is disabled in Winamp.").WithSize(150, 16).InGroup(L"Title Format").
- WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(6, 11)).IsLeftJustified());
- this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(150, 14).InGroup(L"Title Format").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 4)).IsLeftJustified().
- WithAutoHScroll().WithBorder().WithTabStop().WithID(idTitleFormat));
- this->configDialog.AddLabelControl(DialogLabelBuilder(L"Names between percent symbols (e.g. %game%, %title%) will be replaced with the respective value from the file's tags. Using square brackets around any "
- L"items will cause them to only be displayed if there was a replacement done (e.g. [%disc%.] will display 01. if disc was in the tags as 01, but will display nothing if disc was not in the tags). Square "
- L"bracket blocks can be nested.").WithSize(150, 72).InGroup(L"Title Format").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 4)).IsLeftJustified());
-
- this->GenerateSpecificDialogs();
-
this->infoDialog.AddButtonControl(DialogButtonBuilder(L"OK").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomRight, Point<short>(-104, 7)).WithID(IDOK).IsDefault().WithTabStop());
this->infoDialog.AddButtonControl(DialogButtonBuilder(L"Cancel").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(4, 0)).WithID(IDCANCEL).WithTabStop());
this->infoDialog.AutoSize();
-
- this->configDialogProperty = this->configDialog;
- this->configDialogProperty = DialogBuilder().IsChild().IsControlWindow().WithFont(L"MS Shell Dlg", 8);
- this->configDialogProperty.AutoSize();
-
- this->configDialog.AddButtonControl(DialogButtonBuilder(L"Reset Defaults").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomRight, Point<short>(-50, 7)).WithID(idResetDefaults).
- WithTabStop());
- this->configDialog.AddButtonControl(DialogButtonBuilder(L"OK").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomRight, Point<short>(-104, 7)).WithID(IDOK).IsDefault().WithTabStop());
- this->configDialog.AddButtonControl(DialogButtonBuilder(L"Cancel").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(4, 0)).WithID(IDCANCEL).WithTabStop());
- this->configDialog.AutoSize();
-}
-
-INT_PTR CALLBACK XSFConfig::ConfigDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- XSFConfig *thisPtr = nullptr;
-
- if (uMsg == WM_INITDIALOG)
- {
- thisPtr = reinterpret_cast<XSFConfig *>(lParam);
-
- SetWindowLongPtr(hwndDlg, DWLP_USER, reinterpret_cast<LONG_PTR>(thisPtr));
- }
- else
- thisPtr = reinterpret_cast<XSFConfig *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
-
- if (thisPtr)
- return thisPtr->ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
- else
- return false;
}
INT_PTR CALLBACK XSFConfig::InfoDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -218,63 +175,6 @@
return thisPtr->InfoDialogProc(hwndDlg, uMsg, wParam, lParam);
else
return false;
-}
-
-INT_PTR CALLBACK XSFConfig::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM)
-{
- switch (uMsg)
- {
- case WM_CLOSE:
- EndDialog(hwndDlg, IDCANCEL);
- break;
- case WM_INITDIALOG:
- if (this->playInfinitely)
- SendMessageW(GetDlgItem(hwndDlg, idPlayInfinitely), BM_SETCHECK, BST_CHECKED, 0);
- SetWindowTextW(GetDlgItem(hwndDlg, idDefaultLength), ConvertFuncs::MSToWString(this->defaultLength).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), ConvertFuncs::MSToWString(this->defaultFade).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), ConvertFuncs::MSToWString(this->skipSilenceOnStartSec).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), ConvertFuncs::MSToWString(this->detectSilenceSec).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idVolume), ConvertFuncs::TrimDoubleString(std::to_wstring(this->volume)).c_str());
- SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Disabled"));
- SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Use Volume Tag"));
- SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Track"));
- SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Album"));
- SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_SETCURSEL, static_cast<WPARAM>(this->volumeType), 0);
- SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Disabled"));
- SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Track"));
- SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Album"));
- SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_SETCURSEL, static_cast<WPARAM>(this->peakType), 0);
- for (unsigned x = 0, rates = this->supportedSampleRates.size(); x < rates; ++x)
- {
- unsigned rate = this->supportedSampleRates[x];
- SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(std::to_wstring(rate).c_str()));
- if (this->sampleRate == rate)
- SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_SETCURSEL, x, 0);
- }
- SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), ConvertFuncs::StringToWString(this->titleFormat).c_str());
- break;
- case WM_COMMAND:
- switch (GET_WM_COMMAND_ID(wParam, lParam))
- {
- case IDOK:
- this->SaveConfigDialog(hwndDlg);
- this->SaveConfig();
- EndDialog(hwndDlg, IDOK);
- break;
- case IDCANCEL:
- EndDialog(hwndDlg, IDCANCEL);
- break;
- case idResetDefaults:
- this->ResetConfigDefaults(hwndDlg);
- break;
- default:
- return false;
- }
- break;
- default:
- return false;
- }
- return true;
}
extern XSFFile *xSFFileInInfo;
@@ -326,7 +226,11 @@
void XSFConfig::CallConfigDialog(HINSTANCE hInstance, HWND hwndParent)
{
- DialogBoxIndirectParamW(hInstance, this->configDialog.GenerateTemplate(), hwndParent, XSFConfig::ConfigDialogProcStatic, reinterpret_cast<LPARAM>(this));
+ auto app = new XSFConfigApp(hwndParent, this);
+ wxApp::SetInstance(app);
+ wxEntryStart(hInstance);
+ app->OnInit();
+ wxEntryCleanup();
}
void XSFConfig::CallInfoDialog(HINSTANCE hInstance, HWND hwndParent)
@@ -334,37 +238,54 @@
DialogBoxIndirectParamW(hInstance, this->infoDialog.GenerateTemplate(), hwndParent, XSFConfig::InfoDialogProcStatic, reinterpret_cast<LPARAM>(this));
}
-void XSFConfig::ResetConfigDefaults(HWND hwndDlg)
-{
- SendMessageW(GetDlgItem(hwndDlg, idPlayInfinitely), BM_SETCHECK, XSFConfig::initPlayInfinitely ? BST_CHECKED : BST_UNCHECKED, 0);
- SetWindowTextW(GetDlgItem(hwndDlg, idDefaultLength), ConvertFuncs::StringToWString(XSFConfig::initDefaultLength).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), ConvertFuncs::StringToWString(XSFConfig::initDefaultFade).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), ConvertFuncs::StringToWString(XSFConfig::initSkipSilenceOnStartSec).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), ConvertFuncs::StringToWString(XSFConfig::initDetectSilenceSec).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idVolume), ConvertFuncs::TrimDoubleString(std::to_wstring(XSFConfig::initVolume)).c_str());
- SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_SETCURSEL, static_cast<WPARAM>(XSFConfig::initVolumeType), 0);
- SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_SETCURSEL, static_cast<WPARAM>(XSFConfig::initPeakType), 0);
+void XSFConfig::InitializeConfigDialog(XSFConfigDialog *dialog)
+{
+ dialog->playInfinitely = this->playInfinitely;
+ dialog->defaultPlayLength = ConvertFuncs::MSToString(this->defaultLength);
+ dialog->defaultFadeoutLength = ConvertFuncs::MSToString(this->defaultFade);
+ dialog->skipSilenceOnStart = ConvertFuncs::MSToString(this->skipSilenceOnStartSec);
+ dialog->detectSilence = ConvertFuncs::MSToString(this->detectSilenceSec);
+ dialog->volume = this->volume;
+ dialog->replayGain = static_cast<std::underlying_type_t<VolumeType>>(this->volumeType);
+ dialog->clipProtect = static_cast<std::underlying_type_t<PeakType>>(this->peakType);
+ auto found = std::find(this->supportedSampleRates.begin(), this->supportedSampleRates.end(), this->sampleRate);
+ dialog->sampleRate = found == this->supportedSampleRates.end() ? 0 : found - this->supportedSampleRates.begin();
+ dialog->titleFormat = this->titleFormat;
+
+ this->InitializeSpecificConfigDialog(dialog);
+}
+
+void XSFConfig::ResetConfigDefaults(XSFConfigDialog *dialog)
+{
+ dialog->playInfinitely = XSFConfig::initPlayInfinitely;
+ dialog->defaultPlayLength = XSFConfig::initDefaultLength;
+ dialog->defaultFadeoutLength = XSFConfig::initDefaultFade;
+ dialog->skipSilenceOnStart = XSFConfig::initSkipSilenceOnStartSec;
+ dialog->detectSilence = XSFConfig::initDetectSilenceSec;
+ dialog->volume = XSFConfig::initVolume;
+ dialog->replayGain = static_cast<std::underlying_type_t<VolumeType>>(XSFConfig::initVolumeType);
+ dialog->clipProtect = static_cast<std::underlying_type_t<PeakType>>(XSFConfig::initPeakType);
auto found = std::find(this->supportedSampleRates.begin(), this->supportedSampleRates.end(), XSFConfig::initSampleRate);
- SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_SETCURSEL, found - this->supportedSampleRates.begin(), 0);
- SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), ConvertFuncs::StringToWString(XSFConfig::initTitleFormat).c_str());
-
- this->ResetSpecificConfigDefaults(hwndDlg);
-}
-
-void XSFConfig::SaveConfigDialog(HWND hwndDlg)
-{
- this->playInfinitely = SendMessageW(GetDlgItem(hwndDlg, idPlayInfinitely), BM_GETCHECK, 0, 0) == BST_CHECKED;
- this->defaultLength = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDefaultLength)));
- this->defaultFade = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDefaultFade)));
- this->skipSilenceOnStartSec = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec)));
- this->detectSilenceSec = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDetectSilenceSec)));
- this->volume = convertTo<double>(this->GetTextFromWindow(GetDlgItem(hwndDlg, idVolume)));
- this->volumeType = static_cast<VolumeType>(SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_GETCURSEL, 0, 0));
- this->peakType = static_cast<PeakType>(SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_GETCURSEL, 0, 0));
- this->sampleRate = XSFConfig::supportedSampleRates[SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_GETCURSEL, 0, 0)];
- this->titleFormat = ConvertFuncs::WStringToString(this->GetTextFromWindow(GetDlgItem(hwndDlg, idTitleFormat)));
-
- this->SaveSpecificConfigDialog(hwndDlg);
+ dialog->sampleRate = found == this->supportedSampleRates.end() ? 0 : found - this->supportedSampleRates.begin();
+ dialog->titleFormat = XSFConfig::initTitleFormat;
+
+ this->ResetSpecificConfigDefaults(dialog);
+}
+
+void XSFConfig::SaveConfigDialog(XSFConfigDialog *dialog)
+{
+ this->playInfinitely = dialog->playInfinitely;
+ this->defaultLength = ConvertFuncs::StringToMS(dialog->defaultPlayLength);
+ this->defaultFade = ConvertFuncs::StringToMS(dialog->defaultFadeoutLength);
+ this->skipSilenceOnStartSec = ConvertFuncs::StringToMS(dialog->skipSilenceOnStart);
+ this->detectSilenceSec = ConvertFuncs::StringToMS(dialog->detectSilence);
+ this->volume = dialog->volume;
+ this->volumeType = static_cast<VolumeType>(dialog->replayGain);
+ this->peakType = static_cast<PeakType>(dialog->clipProtect);
+ this->sampleRate = this->supportedSampleRates[dialog->sampleRate];
+ this->titleFormat = dialog->titleFormat.ToStdString();
+
+ this->SaveSpecificConfigDialog(dialog);
}
void XSFConfig::CopyConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad)
@@ -385,6 +306,11 @@
return this->configIO->GetHInstance();
}
+const std::vector<unsigned> &XSFConfig::GetSupportedSampleRates() const
+{
+ return this->supportedSampleRates;
+}
+
bool XSFConfig::GetPlayInfinitely() const
{
return this->playInfinitely;
--- a/src/in_xsf_framework/XSFConfig.h
+++ b/src/in_xsf_framework/XSFConfig.h
@@ -12,11 +12,12 @@
#include <type_traits>
#include <vector>
#include "DialogBuilder.h"
+#include "XSFFile.h"
#include "convert.h"
#include "windowsh_wrapper.h"
-enum class PeakType;
-enum class VolumeType;
+class wxWindow;
+class XSFConfigDialog;
class XSFPlayer;
class XSFConfigIO
@@ -68,30 +69,29 @@
PeakType peakType;
unsigned sampleRate;
std::string titleFormat;
- DialogTemplate configDialog, configDialogProperty, infoDialog;
+ DialogTemplate infoDialog;
std::vector<unsigned> supportedSampleRates;
std::unique_ptr<XSFConfigIO> configIO;
XSFConfig();
std::wstring GetTextFromWindow(HWND hwnd);
virtual void LoadSpecificConfig() = 0;
- virtual void GenerateSpecificDialogs() = 0;
virtual void SaveSpecificConfig() = 0;
- virtual INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual INT_PTR CALLBACK InfoDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
- virtual void ResetSpecificConfigDefaults(HWND hwndDlg) = 0;
- virtual void SaveSpecificConfigDialog(HWND hwndDlg) = 0;
+ virtual void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) = 0;
+ virtual void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) = 0;
+ virtual void SaveSpecificConfigDialog(XSFConfigDialog *dialog) = 0;
virtual void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) = 0;
public:
- static bool initPlayInfinitely;
- static std::string initSkipSilenceOnStartSec, initDetectSilenceSec, initDefaultLength, initDefaultFade, initTitleFormat;
- static double initVolume;
- static VolumeType initVolumeType;
- static PeakType initPeakType;
+ static constexpr bool initPlayInfinitely = false;
+ inline static const std::string initSkipSilenceOnStartSec = "5", initDetectSilenceSec = "5", initDefaultLength = "1:55", initDefaultFade = "5", initTitleFormat = "%game%[ - [%disc%.]%track%] - %title%";
+ static constexpr double initVolume = 1.0;
+ static constexpr VolumeType initVolumeType = VolumeType::ReplayGainAlbum;
+ static constexpr PeakType initPeakType = PeakType::ReplayGainTrack;
// These are not defined in XSFConfig.cpp, they should be defined in your own config's source.
- static unsigned initSampleRate;
- static std::string commonName;
- static std::string versionNumber;
+ static const unsigned initSampleRate;
+ static const std::string commonName;
+ static const std::string versionNumber;
// The Create function is not defined in XSFConfig.cpp, it should be defined in your own config's source and return a pointer to your config's class.
static XSFConfig *Create();
static const std::string &CommonNameWithVersion();
@@ -100,17 +100,20 @@
void LoadConfig();
void SaveConfig();
void GenerateDialogs();
- static INT_PTR CALLBACK ConfigDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK InfoDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CallConfigDialog(HINSTANCE hInstance, HWND hwndParent);
void CallInfoDialog(HINSTANCE hInstance, HWND hwndParent);
- void ResetConfigDefaults(HWND hwndDlg);
- void SaveConfigDialog(HWND hwndDlg);
+ void InitializeConfigDialog(XSFConfigDialog *dialog);
+ void ResetConfigDefaults(XSFConfigDialog *dialog);
+ void SaveConfigDialog(XSFConfigDialog *dialog);
void CopyConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad);
void SetHInstance(HINSTANCE hInstance);
HINSTANCE GetHInstance() const;
virtual void About(HWND parent) = 0;
+ virtual XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) = 0;
+
+ const std::vector<unsigned> &GetSupportedSampleRates() const;
bool GetPlayInfinitely() const;
unsigned long GetSkipSilenceOnStartSec() const;
--- /dev/null
+++ b/src/in_xsf_framework/XSFConfigDialog.cpp
@@ -1,1 +1,157 @@
+/*
+ * xSF - Core configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#include <string>
+#include <wx/button.h>
+#include <wx/checkbox.h>
+#include <wx/choice.h>
+#include <wx/dialog.h>
+#include <wx/gbsizer.h>
+#include <wx/notebook.h>
+#include <wx/sizer.h>
+#include <wx/stattext.h>
+#include <wx/string.h>
+#include <wx/textctrl.h>
+#include <wx/valgen.h>
+#include <wx/valnum.h>
+#include <wx/window.h>
+#include "RegExValidator.h"
+#include "XSFConfig.h"
+#include "XSFConfigDialog.h"
+
+enum
+{
+ idResetDefaults = 1
+};
+
+// This just sets up the base dialog box's controls, it does not do the auto-sizing at this stage.
+XSFConfigDialog::XSFConfigDialog(XSFConfig &config, wxWindow *parent, const wxString &title) : wxDialog(parent, wxID_ANY, title), config(config)
+{
+ this->mainSizer = new wxGridBagSizer;
+
+ auto notebook = new wxNotebook(this, wxID_ANY);
+
+ this->generalPanel = new wxPanel(notebook, wxID_ANY);
+ this->generalSizer = new wxGridBagSizer;
+
+ auto playInfinitelyCheckBox = new wxCheckBox(this->generalPanel, wxID_ANY, "Play Infinitely", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->playInfinitely });
+ this->generalSizer->Add(playInfinitelyCheckBox, { 0, 0 }, { 1, 2 }, wxALL, 5);
+
+ auto defaultPlayLengthLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Default play length (m:s)");
+ this->generalSizer->Add(defaultPlayLengthLabel, { 1, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ auto defaultPlayLengthTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->defaultPlayLength, wxRE_ADVANCED });
+ this->generalSizer->Add(defaultPlayLengthTextCtrl, { 1, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto defaultFadeoutLengthLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Default fadeout length (m:s)");
+ this->generalSizer->Add(defaultFadeoutLengthLabel, { 2, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ auto defaultFadeoutLengthTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->defaultFadeoutLength, wxRE_ADVANCED });
+ this->generalSizer->Add(defaultFadeoutLengthTextCtrl, { 2, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto skipSilenceOnStartLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Skip silence on start (s)");
+ this->generalSizer->Add(skipSilenceOnStartLabel, { 3, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ auto skipSilenceOnStartTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->skipSilenceOnStart, wxRE_ADVANCED });
+ this->generalSizer->Add(skipSilenceOnStartTextCtrl, { 3, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto detectSilenceLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Detect silence (s)");
+ this->generalSizer->Add(detectSilenceLabel, { 4, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ auto detectSilenceTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->detectSilence, wxRE_ADVANCED });
+ this->generalSizer->Add(detectSilenceTextCtrl, { 4, 1 }, { 1, 1 }, wxALL, 5);
+
+ notebook->AddPage(this->generalPanel, "General");
+
+ this->outputPanel = new wxPanel(notebook, wxID_ANY);
+ this->outputSizer = new wxGridBagSizer;
+
+ auto volumeLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Volume");
+ this->outputSizer->Add(volumeLabel, { 0, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ auto volumeTextCtrl = new wxTextCtrl(this->outputPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, wxFloatingPointValidator<double>{ &this->volume, wxNUM_VAL_NO_TRAILING_ZEROES });
+ this->outputSizer->Add(volumeTextCtrl, { 0, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto replayGainLabel = new wxStaticText(this->outputPanel, wxID_ANY, "ReplayGain");
+ this->outputSizer->Add(replayGainLabel, { 1, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString replayGainChoices;
+ replayGainChoices.Add("Disabled");
+ replayGainChoices.Add("Use Volume Tag");
+ replayGainChoices.Add("Track");
+ replayGainChoices.Add("Album");
+ auto replayGainChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, replayGainChoices, 0, wxGenericValidator{ &this->replayGain });
+ this->outputSizer->Add(replayGainChoice, { 1, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto clipProtectLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Clip Protect");
+ this->outputSizer->Add(clipProtectLabel, { 2, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString clipProtectChoices;
+ clipProtectChoices.Add("Disabled");
+ clipProtectChoices.Add("Track");
+ clipProtectChoices.Add("Album");
+ auto clipProtectChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, clipProtectChoices, 0, wxGenericValidator{ &this->clipProtect });
+ this->outputSizer->Add(clipProtectChoice, { 2, 1 }, { 1, 1 }, wxALL, 5);
+
+ auto sampleRateLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Sample Rate");
+ this->outputSizer->Add(sampleRateLabel, { 3, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+ wxArrayString sampleRateChoices;
+ for (auto supportedSampleRate : this->config.GetSupportedSampleRates())
+ sampleRateChoices.Add(std::to_string(supportedSampleRate));
+ auto sampleRateChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, sampleRateChoices, 0, wxGenericValidator{ &this->sampleRate });
+ this->outputSizer->Add(sampleRateChoice, { 3, 1 }, { 1, 1 }, wxALL, 5);
+
+ notebook->AddPage(this->outputPanel, "Output");
+
+ auto titleFormatPanel = new wxPanel(notebook, wxID_ANY);
+ auto titleFormatSizer = new wxBoxSizer(wxVERTICAL);
+
+ auto titleFormatPreText = new wxStaticText(titleFormatPanel, wxID_ANY, "NOTE: This is only used if Advanced Title Formatting is disabled in Winamp.");
+ titleFormatPreText->Wrap(300);
+ titleFormatSizer->Add(titleFormatPreText, 0, wxALL, 5);
+
+ auto titleFormatTextCtrl = new wxTextCtrl(titleFormatPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 225, -1 }, 0, wxGenericValidator{ &this->titleFormat });
+ titleFormatSizer->Add(titleFormatTextCtrl, 0, wxALL, 5);
+
+ auto titleFormatPostText = new wxStaticText(titleFormatPanel, wxID_ANY, "Names between percent symbols (e.g. %game%, %title%) will be replaced with the respective value from the file's tags. "
+ "Using square brackets around any items will cause them to only be displayed if there was a replacement done (e.g. [%disc%.] will display 01. if disc was in the tags as 01, but will "
+ "display nothing if disc was not in the tags). Square bracket blocks can be nested.");
+ titleFormatPostText->Wrap(300);
+ titleFormatSizer->Add(titleFormatPostText, 0, wxALL, 5);
+
+ titleFormatPanel->SetSizer(titleFormatSizer);
+ titleFormatPanel->Layout();
+ titleFormatSizer->Fit(titleFormatPanel);
+ notebook->AddPage(titleFormatPanel, "Title Format");
+
+ this->mainSizer->Add(notebook, { 0, 0 }, { 1, 2 }, wxALL | wxEXPAND, 5);
+
+ auto resetDefaults = new wxButton(this, idResetDefaults, "Reset Defaults");
+ this->mainSizer->Add(resetDefaults, { 1, 1 }, { 1, 1 }, wxALIGN_RIGHT | wxALL, 5);
+ this->Bind(wxEVT_BUTTON, [&](wxCommandEvent &)
+ {
+ this->config.ResetConfigDefaults(this);
+ this->TransferDataToWindow();
+ }, idResetDefaults);
+
+ auto standardButtons = new wxStdDialogButtonSizer;
+ auto standardButtonOK = new wxButton(this, wxID_OK);
+ standardButtons->AddButton(standardButtonOK);
+ auto standardButtonCancel = new wxButton(this, wxID_CANCEL);
+ standardButtons->AddButton(standardButtonCancel);
+ standardButtons->Realize();
+ this->mainSizer->Add(standardButtons, { 2, 0 }, { 1, 2 }, wxBOTTOM | wxEXPAND | wxTOP, 5);
+}
+
+void XSFConfigDialog::Finalize()
+{
+ this->generalPanel->SetSizer(this->generalSizer);
+ this->generalPanel->Layout();
+ this->generalSizer->Fit(this->generalPanel);
+
+ this->outputPanel->SetSizer(this->outputSizer);
+ this->outputPanel->Layout();
+ this->outputSizer->Fit(this->outputPanel);
+
+ this->SetSizer(this->mainSizer);
+ this->Layout();
+ this->mainSizer->Fit(this);
+}
+
--- /dev/null
+++ b/src/in_xsf_framework/XSFConfigDialog.h
@@ -1,1 +1,46 @@
+/*
+ * xSF - Core configuration dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
+#pragma once
+
+#include <wx/msw/winundef.h>
+#include <wx/dialog.h>
+#include <wx/string.h>
+
+class wxGridBagSizer;
+class wxPanel;
+class wxWindow;
+class XSFConfig;
+
+class XSFConfigDialog : public wxDialog
+{
+ inline static const std::string timeRegex = R"(^\d+(:[0-5]\d){0,2}([.,]\d+)?$)";
+
+ wxGridBagSizer *mainSizer;
+ XSFConfig &config;
+public:
+ XSFConfigDialog(XSFConfig &config, wxWindow *parent, const wxString &title);
+ void Finalize();
+
+ wxPanel *generalPanel;
+ wxGridBagSizer *generalSizer;
+
+ wxPanel *outputPanel;
+ wxGridBagSizer *outputSizer;
+
+ bool playInfinitely = false;
+ wxString defaultPlayLength;
+ wxString defaultFadeoutLength;
+ wxString skipSilenceOnStart;
+ wxString detectSilence;
+ double volume = 1;
+ int replayGain;
+ int clipProtect;
+ int sampleRate;
+ wxString titleFormat;
+};
+