Browse code

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.

Naram Qashat authored on 2021/04/04 12:46:14
Showing 27 changed files
... ...
@@ -63,7 +63,9 @@ set(HEADERS
63 63
 	spu/adpcmdecoder.h
64 64
 	spu/interpolator.h
65 65
 	spu/samplecache.h
66
-	spu/sampledata.h)
66
+	spu/sampledata.h
67
+	XSFConfig_2SF.h
68
+	XSFConfigDialog_2SF.h)
67 69
 set(SOURCES
68 70
 	desmume/addons/slot1_retail.cpp
69 71
 	desmume/arm_instructions.cpp
... ...
@@ -112,12 +114,13 @@ set(SOURCES
112 114
 	spu/samplecache.cpp
113 115
 	spu/sampledata.cpp
114 116
 	XSFConfig_2SF.cpp
117
+	XSFConfigDialog_2SF.cpp
115 118
 	XSFPlayer_2SF.cpp)
116 119
 
117 120
 add_library(in_2sf SHARED ${HEADERS} ${SOURCES})
118 121
 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Header Files" FILES ${HEADERS})
119 122
 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCES})
120 123
 target_compile_options(in_2sf PUBLIC
121
-	$<$<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>)
124
+	$<$<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>)
122 125
 target_link_libraries(in_2sf
123 126
 	in_xsf_framework)
124 127
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+/*
2
+ * xSF - 2SF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#include <string>
9
+#include <wx/arrstr.h>
10
+#include <wx/choice.h>
11
+#include <wx/gbsizer.h>
12
+#include <wx/listbox.h>
13
+#include <wx/stattext.h>
14
+#include <wx/valgen.h>
15
+#include "XSFConfig.h"
16
+#include "XSFConfigDialog.h"
17
+#include "XSFConfigDialog_2SF.h"
18
+
19
+XSFConfigDialog_2SF::XSFConfigDialog_2SF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
20
+{
21
+	auto interpolationLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Interpolation");
22
+	this->outputSizer->Add(interpolationLabel, { 4, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
23
+	wxArrayString interpolationChoices;
24
+	interpolationChoices.Add("None");
25
+	interpolationChoices.Add("Linear");
26
+	interpolationChoices.Add("Cosine");
27
+	interpolationChoices.Add("Sharp");
28
+	auto interpolationChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, interpolationChoices, 0, wxGenericValidator{ &this->interpolation });
29
+	this->outputSizer->Add(interpolationChoice, { 4, 1 }, { 1, 1 }, wxALL, 5);
30
+
31
+	auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
32
+	this->outputSizer->Add(muteLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
33
+	wxArrayString muteChoices;
34
+	for (int i = 0; i < 16; ++i)
35
+		muteChoices.Add("SPU " + std::to_string(i + 1));
36
+	auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
37
+	this->outputSizer->Add(muteListBox, { 5, 1 }, { 1, 1 }, wxALL, 5);
38
+}
0 39
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+/*
2
+ * xSF - 2SF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#pragma once
9
+
10
+#include <wx/dynarray.h>
11
+#include "XSFConfigDialog.h"
12
+
13
+class wxString;
14
+class wxWindow;
15
+class XSFConfig;
16
+
17
+class XSFConfigDialog_2SF : public XSFConfigDialog
18
+{
19
+public:
20
+	XSFConfigDialog_2SF(XSFConfig &config, wxWindow *parent, const wxString &title);
21
+
22
+	int interpolation;
23
+	wxArrayInt mute;
24
+};
... ...
@@ -11,10 +11,14 @@
11 11
 #include <cstddef>
12 12
 #include "windowsh_wrapper.h"
13 13
 #include "XSFConfig.h"
14
+#include "XSFConfig_2SF.h"
15
+#include "XSFConfigDialog_2SF.h"
14 16
 #include "convert.h"
15 17
 #include "desmume/NDSSystem.h"
16 18
 #include "desmume/version.h"
17 19
 
20
+class wxWindow;
21
+class XSFConfigDialog;
18 22
 class XSFPlayer;
19 23
 
20 24
 enum
... ...
@@ -23,33 +27,9 @@ enum
23 27
 	idMutes
24 28
 };
25 29
 
26
-class XSFConfig_2SF : public XSFConfig
27
-{
28
-protected:
29
-	static unsigned initInterpolation;
30
-	static std::string initMutes;
31
-
32
-	friend class XSFConfig;
33
-	unsigned interpolation;
34
-	std::bitset<16> mutes;
35
-
36
-	XSFConfig_2SF();
37
-	void LoadSpecificConfig() override;
38
-	void SaveSpecificConfig() override;
39
-	void GenerateSpecificDialogs() override;
40
-	INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
41
-	void ResetSpecificConfigDefaults(HWND hwndDlg) override;
42
-	void SaveSpecificConfigDialog(HWND hwndDlg) override;
43
-	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
44
-public:
45
-	void About(HWND parent) override;
46
-};
47
-
48
-unsigned XSFConfig::initSampleRate = static_cast<unsigned>(DESMUME_SAMPLE_RATE);
49
-std::string XSFConfig::commonName = "2SF Decoder";
50
-std::string XSFConfig::versionNumber = "0.9b";
51
-unsigned XSFConfig_2SF::initInterpolation = 2;
52
-std::string XSFConfig_2SF::initMutes = "0000000000000000";
30
+const unsigned XSFConfig::initSampleRate = static_cast<unsigned>(DESMUME_SAMPLE_RATE);
31
+const std::string XSFConfig::commonName = "2SF Decoder";
32
+const std::string XSFConfig::versionNumber = "0.9b";
53 33
 
54 34
 XSFConfig *XSFConfig::Create()
55 35
 {
... ...
@@ -74,54 +54,32 @@ void XSFConfig_2SF::SaveSpecificConfig()
74 54
 	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
75 55
 }
76 56
 
77
-void XSFConfig_2SF::GenerateSpecificDialogs()
78
-{
79
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Interpolation").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
80
-	this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idInterpolation).IsDropDownList().
81
-		WithTabStop());
82
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
83
-	this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).WithBorder().
84
-		WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
85
-}
86
-
87
-INT_PTR CALLBACK XSFConfig_2SF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
57
+void XSFConfig_2SF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
88 58
 {
89
-	switch (uMsg)
90
-	{
91
-		case WM_INITDIALOG:
92
-			// Interpolation
93
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"No Interpolation"));
94
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear Interpolation"));
95
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Cosine Interpolation"));
96
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Sharp Interpolation"));
97
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, this->interpolation, 0);
98
-			// Mutes
99
-			for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
100
-			{
101
-				SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + std::to_wstring(x + 1)).c_str()));
102
-				SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
103
-			}
104
-			break;
105
-		case WM_COMMAND:
106
-			break;
107
-	}
108
-
109
-	return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
59
+	auto twosfDialog = static_cast<XSFConfigDialog_2SF *>(dialog);
60
+	twosfDialog->interpolation = static_cast<int>(this->interpolation);
61
+	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
62
+		if (this->mutes[x])
63
+			twosfDialog->mute.Add(x);
110 64
 }
111 65
 
112
-void XSFConfig_2SF::ResetSpecificConfigDefaults(HWND hwndDlg)
66
+void XSFConfig_2SF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
113 67
 {
114
-	SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, XSFConfig_2SF::initInterpolation, 0);
68
+	auto twosfDialog = static_cast<XSFConfigDialog_2SF *>(dialog);
69
+	twosfDialog->interpolation = XSFConfig_2SF::initInterpolation;
70
+	twosfDialog->mute.Clear();
115 71
 	auto tmpMutes = std::bitset<16>(XSFConfig_2SF::initMutes);
116 72
 	for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
117
-		SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
73
+		if (tmpMutes[x])
74
+			twosfDialog->mute.Add(x);
118 75
 }
119 76
 
120
-void XSFConfig_2SF::SaveSpecificConfigDialog(HWND hwndDlg)
77
+void XSFConfig_2SF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
121 78
 {
122
-	this->interpolation = static_cast<unsigned>(SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_GETCURSEL, 0, 0));
79
+	auto twosfDialog = static_cast<XSFConfigDialog_2SF *>(dialog);
80
+	this->interpolation = twosfDialog->interpolation;
123 81
 	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
124
-		this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
82
+		this->mutes[x] = twosfDialog->mute.Index(x) != wxNOT_FOUND;
125 83
 }
126 84
 
127 85
 void XSFConfig_2SF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
... ...
@@ -139,3 +97,8 @@ void XSFConfig_2SF::About(HWND parent)
139 97
 	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"
140 98
 		"Utilizes modified " + EMU_DESMUME_NAME_AND_VERSION() + " for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
141 99
 }
100
+
101
+XSFConfigDialog *XSFConfig_2SF::CreateDialogBox(wxWindow *window, const std::string &title)
102
+{
103
+	return new XSFConfigDialog_2SF(*this, window, title);
104
+}
142 105
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+/*
2
+ * xSF - 2SF configuration
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#pragma once
9
+
10
+#include <bitset>
11
+#include <string>
12
+#include "windowsh_wrapper.h"
13
+#include "XSFConfig.h"
14
+
15
+class wxWindow;
16
+class XSFConfigDialog;
17
+class XSFPlayer;
18
+
19
+class XSFConfig_2SF : public XSFConfig
20
+{
21
+protected:
22
+	static constexpr unsigned initInterpolation = 2;
23
+	inline static const std::string initMutes = "0000000000000000";
24
+
25
+	friend class XSFConfig;
26
+	unsigned interpolation;
27
+	std::bitset<16> mutes;
28
+
29
+	XSFConfig_2SF();
30
+	void LoadSpecificConfig() override;
31
+	void SaveSpecificConfig() override;
32
+	void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
33
+	void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
34
+	void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
35
+	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
36
+public:
37
+	void About(HWND parent) override;
38
+	XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
39
+};
... ...
@@ -12,7 +12,9 @@ set(HEADERS
12 12
 	vbam/gba/GBAcpu.h
13 13
 	vbam/gba/GBAinline.h
14 14
 	vbam/gba/Globals.h
15
-	vbam/gba/Sound.h)
15
+	vbam/gba/Sound.h
16
+	XSFConfig_GSF.h
17
+	XSFConfigDialog_GSF.h)
16 18
 set(SOURCES
17 19
 	vbam/apu/Blip_Buffer.cpp
18 20
 	vbam/apu/Gb_Apu.cpp
... ...
@@ -25,6 +27,7 @@ set(SOURCES
25 27
 	vbam/gba/Globals.cpp
26 28
 	vbam/gba/Sound.cpp
27 29
 	XSFConfig_GSF.cpp
30
+	XSFConfigDialog_GSF.cpp
28 31
 	XSFPlayer_GSF.cpp)
29 32
 
30 33
 add_library(in_gsf SHARED ${HEADERS} ${SOURCES})
31 34
new file mode 100644
... ...
@@ -0,0 +1,34 @@
1
+/*
2
+ * xSF - GSF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#include <wx/arrstr.h>
9
+#include <wx/checkbox.h>
10
+#include <wx/gbsizer.h>
11
+#include <wx/listbox.h>
12
+#include <wx/stattext.h>
13
+#include <wx/valgen.h>
14
+#include "XSFConfig.h"
15
+#include "XSFConfigDialog.h"
16
+#include "XSFConfigDialog_GSF.h"
17
+
18
+XSFConfigDialog_GSF::XSFConfigDialog_GSF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
19
+{
20
+	auto lowPassFilteringCheckBox = new wxCheckBox(this->outputPanel, wxID_ANY, "Low-Pass Filtering", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->lowPassFiltering });
21
+	this->outputSizer->Add(lowPassFilteringCheckBox, { 4, 0 }, { 1, 2 }, wxALL, 5);
22
+
23
+	auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
24
+	this->outputSizer->Add(muteLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
25
+	wxArrayString muteChoices;
26
+	muteChoices.Add("Square 1");
27
+	muteChoices.Add("Square 2");
28
+	muteChoices.Add("Wave Pattern");
29
+	muteChoices.Add("Noise");
30
+	muteChoices.Add("PCM A");
31
+	muteChoices.Add("PCM B");
32
+	auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
33
+	this->outputSizer->Add(muteListBox, { 5, 1 }, { 1, 1 }, wxALL, 5);
34
+}
0 35
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+/*
2
+ * xSF - GSF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#pragma once
9
+
10
+#include <wx/dynarray.h>
11
+#include "XSFConfigDialog.h"
12
+
13
+class wxString;
14
+class wxWindow;
15
+class XSFConfig;
16
+
17
+class XSFConfigDialog_GSF : public XSFConfigDialog
18
+{
19
+public:
20
+	XSFConfigDialog_GSF(XSFConfig &config, wxWindow *parent, const wxString &title);
21
+
22
+	bool lowPassFiltering;
23
+	wxArrayInt mute;
24
+};
... ...
@@ -8,11 +8,16 @@
8 8
 #include <bitset>
9 9
 #include <sstream>
10 10
 #include <string>
11
+#include <cstddef>
11 12
 #include "windowsh_wrapper.h"
12 13
 #include "XSFConfig.h"
14
+#include "XSFConfig_GSF.h"
15
+#include "XSFConfigDialog_GSF.h"
13 16
 #include "convert.h"
14 17
 #include "vbam/gba/Sound.h"
15 18
 
19
+class wxWindow;
20
+class XSFConfigDialog;
16 21
 class XSFPlayer;
17 22
 
18 23
 enum
... ...
@@ -21,33 +26,9 @@ enum
21 26
 	idMutes
22 27
 };
23 28
 
24
-class XSFConfig_GSF : public XSFConfig
25
-{
26
-protected:
27
-	static bool initLowPassFiltering;
28
-	static std::string initMutes;
29
-
30
-	friend class XSFConfig;
31
-	bool lowPassFiltering;
32
-	std::bitset<6> mutes;
33
-
34
-	XSFConfig_GSF();
35
-	void LoadSpecificConfig() override;
36
-	void SaveSpecificConfig() override;
37
-	void GenerateSpecificDialogs() override;
38
-	INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
39
-	void ResetSpecificConfigDefaults(HWND hwndDlg) override;
40
-	void SaveSpecificConfigDialog(HWND hwndDlg) override;
41
-	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
42
-public:
43
-	void About(HWND parent) override;
44
-};
45
-
46
-unsigned XSFConfig::initSampleRate = 44100;
47
-std::string XSFConfig::commonName = "GSF Decoder";
48
-std::string XSFConfig::versionNumber = "0.9b";
49
-bool XSFConfig_GSF::initLowPassFiltering = true;
50
-std::string XSFConfig_GSF::initMutes = "000000";
29
+const unsigned XSFConfig::initSampleRate = 44100;
30
+const std::string XSFConfig::commonName = "GSF Decoder";
31
+const std::string XSFConfig::versionNumber = "0.9b";
51 32
 
52 33
 XSFConfig *XSFConfig::Create()
53 34
 {
... ...
@@ -82,53 +63,32 @@ void XSFConfig_GSF::SaveSpecificConfig()
82 63
 	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
83 64
 }
84 65
 
85
-void XSFConfig_GSF::GenerateSpecificDialogs()
86
-{
87
-	this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Low-Pass Filtering").WithSize(80, 10).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7), 2).WithTabStop().
88
-		WithID(idLowPassFiltering));
89
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10)).IsLeftJustified());
90
-	this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).WithBorder().
91
-		WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
92
-}
93
-
94
-INT_PTR CALLBACK XSFConfig_GSF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
66
+void XSFConfig_GSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
95 67
 {
96
-	switch (uMsg)
97
-	{
98
-		case WM_INITDIALOG:
99
-			// Low-Pass Filtering
100
-			if (this->lowPassFiltering)
101
-				SendMessageW(GetDlgItem(hwndDlg, idLowPassFiltering), BM_SETCHECK, BST_CHECKED, 0);
102
-			// Mutes
103
-			SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Square 1"));
104
-			SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Square 2"));
105
-			SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Wave Pattern"));
106
-			SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Noise"));
107
-			SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"PCM A"));
108
-			SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"PCM B"));
109
-			for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
110
-				SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
111
-			break;
112
-		case WM_COMMAND:
113
-			break;
114
-	}
115
-
116
-	return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
68
+	auto gsfDialog = static_cast<XSFConfigDialog_GSF *>(dialog);
69
+	gsfDialog->lowPassFiltering = this->lowPassFiltering;
70
+	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
71
+		if (this->mutes[x])
72
+			gsfDialog->mute.Add(x);
117 73
 }
118 74
 
119
-void XSFConfig_GSF::ResetSpecificConfigDefaults(HWND hwndDlg)
75
+void XSFConfig_GSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
120 76
 {
121
-	SendMessageW(GetDlgItem(hwndDlg, idLowPassFiltering), BM_SETCHECK, XSFConfig_GSF::initLowPassFiltering ? BST_CHECKED : BST_UNCHECKED, 0);
77
+	auto gsfDialog = static_cast<XSFConfigDialog_GSF *>(dialog);
78
+	gsfDialog->lowPassFiltering = XSFConfig_GSF::initLowPassFiltering;
79
+	gsfDialog->mute.Clear();
122 80
 	auto tmpMutes = std::bitset<6>(XSFConfig_GSF::initMutes);
123
-	for (int x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
124
-		SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
81
+	for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
82
+		if (tmpMutes[x])
83
+			gsfDialog->mute.Add(x);
125 84
 }
126 85
 
127
-void XSFConfig_GSF::SaveSpecificConfigDialog(HWND hwndDlg)
86
+void XSFConfig_GSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
128 87
 {
129
-	this->lowPassFiltering = SendMessageW(GetDlgItem(hwndDlg, idLowPassFiltering), BM_GETCHECK, 0, 0) == BST_CHECKED;
130
-	for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
131
-		this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
88
+	auto gsfDialog = static_cast<XSFConfigDialog_GSF *>(dialog);
89
+	this->lowPassFiltering = gsfDialog->lowPassFiltering;
90
+	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
91
+		this->mutes[x] = gsfDialog->mute.Index(x) != wxNOT_FOUND;
132 92
 }
133 93
 
134 94
 void XSFConfig_GSF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
... ...
@@ -146,3 +106,8 @@ void XSFConfig_GSF::About(HWND parent)
146 106
 	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"
147 107
 		"Utilizes modified VBA-M, SVN revision 1231, for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
148 108
 }
109
+
110
+XSFConfigDialog *XSFConfig_GSF::CreateDialogBox(wxWindow *window, const std::string &title)
111
+{
112
+	return new XSFConfigDialog_GSF(*this, window, title);
113
+}
149 114
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+/*
2
+ * xSF - GSF configuration
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#pragma once
9
+
10
+#include <bitset>
11
+#include <string>
12
+#include "windowsh_wrapper.h"
13
+#include "XSFConfig.h"
14
+
15
+class wxWindow;
16
+class XSFConfigDialog;
17
+class XSFPlayer;
18
+
19
+class XSFConfig_GSF : public XSFConfig
20
+{
21
+protected:
22
+	static constexpr bool initLowPassFiltering = true;
23
+	inline static const std::string initMutes = "000000";
24
+
25
+	friend class XSFConfig;
26
+	bool lowPassFiltering;
27
+	std::bitset<6> mutes;
28
+
29
+	XSFConfig_GSF();
30
+	void LoadSpecificConfig() override;
31
+	void SaveSpecificConfig() override;
32
+	void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
33
+	void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
34
+	void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
35
+	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
36
+public:
37
+	void About(HWND parent) override;
38
+	XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
39
+};
... ...
@@ -16,6 +16,7 @@ set(HEADERS
16 16
 	SSEQPlayer/Track.h
17 17
 	resource.h
18 18
 	XSFConfig_NCSF.h
19
+	XSFConfigDialog_NCSF.h
19 20
 	XSFPlayer_NCSF.h)
20 21
 set(RESOURCES
21 22
 	in_ncsf.rc)
... ...
@@ -34,6 +35,7 @@ set(SOURCES
34 35
 	SSEQPlayer/SYMBSection.cpp
35 36
 	SSEQPlayer/Track.cpp
36 37
 	XSFConfig_NCSF.cpp
38
+	XSFConfigDialog_NCSF.cpp
37 39
 	XSFPlayer_NCSF.cpp)
38 40
 
39 41
 add_library(in_ncsf SHARED ${HEADERS} ${RESOURCES} ${SOURCES})
40 42
new file mode 100644
... ...
@@ -0,0 +1,45 @@
1
+/*
2
+ * xSF - NCSF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#include <string>
9
+#include <wx/arrstr.h>
10
+#include <wx/checkbox.h>
11
+#include <wx/choice.h>
12
+#include <wx/gbsizer.h>
13
+#include <wx/listbox.h>
14
+#include <wx/stattext.h>
15
+#include <wx/valgen.h>
16
+#include "XSFConfig.h"
17
+#include "XSFConfigDialog.h"
18
+#include "XSFConfigDialog_NCSF.h"
19
+
20
+XSFConfigDialog_NCSF::XSFConfigDialog_NCSF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
21
+{
22
+#ifndef NDEBUG
23
+	auto useSoundViewCheckBox = new wxCheckBox(this->generalPanel, wxID_ANY, "Use Sound View Window", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->useSoundView });
24
+	this->generalSizer->Add(useSoundViewCheckBox, { 5, 0 }, { 1, 2 }, wxALL, 5);
25
+#endif
26
+
27
+	auto interpolationLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Interpolation");
28
+	this->outputSizer->Add(interpolationLabel, { 4, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
29
+	wxArrayString interpolationChoices;
30
+	interpolationChoices.Add("None");
31
+	interpolationChoices.Add("Linear");
32
+	interpolationChoices.Add("4-point, 3rd-order Legrange");
33
+	interpolationChoices.Add("6-point, 5th-order Legrange");
34
+	interpolationChoices.Add("16-point Sinc (Nuttall 3-term Window)");
35
+	auto interpolationChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, interpolationChoices, 0, wxGenericValidator{ &this->interpolation });
36
+	this->outputSizer->Add(interpolationChoice, { 4, 1 }, { 1, 1 }, wxALL, 5);
37
+
38
+	auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
39
+	this->outputSizer->Add(muteLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
40
+	wxArrayString muteChoices;
41
+	for (int i = 0; i < 16; ++i)
42
+		muteChoices.Add("SPU " + std::to_string(i + 1));
43
+	auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
44
+	this->outputSizer->Add(muteListBox, { 5, 1 }, { 1, 1 }, wxALL, 5);
45
+}
0 46
new file mode 100644
... ...
@@ -0,0 +1,27 @@
1
+/*
2
+ * xSF - NCSF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#pragma once
9
+
10
+#include <wx/dynarray.h>
11
+#include "XSFConfigDialog.h"
12
+
13
+class wxString;
14
+class wxWindow;
15
+class XSFConfig;
16
+
17
+class XSFConfigDialog_NCSF : public XSFConfigDialog
18
+{
19
+public:
20
+	XSFConfigDialog_NCSF(XSFConfig &config, wxWindow *parent, const wxString &title);
21
+
22
+#ifndef NDEBUG
23
+	bool useSoundView;
24
+#endif
25
+	int interpolation;
26
+	wxArrayInt mute;
27
+};
... ...
@@ -11,7 +11,9 @@
11 11
 #include <cstddef>
12 12
 #include "windowsh_wrapper.h"
13 13
 #include <windowsx.h>
14
+#include "XSFConfig.h"
14 15
 #include "XSFConfig_NCSF.h"
16
+#include "XSFConfigDialog_NCSF.h"
15 17
 #include "XSFPlayer_NCSF.h"
16 18
 #include "convert.h"
17 19
 #ifndef NDEBUG
... ...
@@ -22,17 +24,19 @@
22 24
 # include <CommCtrl.h>
23 25
 #endif
24 26
 
27
+class wxWindow;
28
+class XSFConfigDialog;
29
+class XSFPlayer;
30
+
25 31
 enum
26 32
 {
27 33
 	idInterpolation = 1000,
28 34
 	idMutes
29 35
 };
30 36
 
31
-unsigned XSFConfig::initSampleRate = 44100;
32
-std::string XSFConfig::commonName = "NCSF Decoder";
33
-std::string XSFConfig::versionNumber = "1.11.1";
34
-unsigned XSFConfig_NCSF::initInterpolation = 4;
35
-std::string XSFConfig_NCSF::initMutes = "0000000000000000";
37
+const unsigned XSFConfig::initSampleRate = 44100;
38
+const std::string XSFConfig::commonName = "NCSF Decoder";
39
+const std::string XSFConfig::versionNumber = "1.11.1";
36 40
 
37 41
 XSFConfig *XSFConfig::Create()
38 42
 {
... ...
@@ -41,7 +45,7 @@ XSFConfig *XSFConfig::Create()
41 45
 
42 46
 XSFConfig_NCSF::XSFConfig_NCSF() : XSFConfig(), interpolation(0), mutes()
43 47
 #ifndef NDEBUG
44
-	, soundViewData()
48
+	, useSoundViewDialog(false), soundViewData()
45 49
 #endif
46 50
 {
47 51
 	this->supportedSampleRates.push_back(8000);
... ...
@@ -59,6 +63,9 @@ XSFConfig_NCSF::XSFConfig_NCSF() : XSFConfig(), interpolation(0), mutes()
59 63
 
60 64
 void XSFConfig_NCSF::LoadSpecificConfig()
61 65
 {
66
+#ifndef NDEBUG
67
+	this->useSoundViewDialog = this->configIO->GetValue("UseSoundViewDialog", XSFConfig_NCSF::initUseSoundViewDialog);
68
+#endif
62 69
 	this->interpolation = this->configIO->GetValue("Interpolation", XSFConfig_NCSF::initInterpolation);
63 70
 	std::stringstream mutesSS(this->configIO->GetValue("Mutes", XSFConfig_NCSF::initMutes));
64 71
 	mutesSS >> this->mutes;
... ...
@@ -66,64 +73,56 @@ void XSFConfig_NCSF::LoadSpecificConfig()
66 73
 
67 74
 void XSFConfig_NCSF::SaveSpecificConfig()
68 75
 {
76
+#ifndef NDEBUG
77
+	this->configIO->SetValue("UseSoundViewDialog", this->useSoundViewDialog);
78
+#endif
69 79
 	this->configIO->SetValue("Interpolation", this->interpolation);
70 80
 	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
71 81
 }
72 82
 
73
-void XSFConfig_NCSF::GenerateSpecificDialogs()
74
-{
75
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Interpolation").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
76
-	this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(110, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idInterpolation).
77
-		IsDropDownList().WithTabStop());
78
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
79
-	this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).
80
-		WithBorder().WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
81
-}
82
-
83
-INT_PTR CALLBACK XSFConfig_NCSF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
83
+void XSFConfig_NCSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
84 84
 {
85
-	switch (uMsg)
86
-	{
87
-		case WM_INITDIALOG:
88
-			// Interpolation
89
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"None"));
90
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear"));
91
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"4-point, 3rd-order Legrange"));
92
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"6-point, 5th-order Legrange"));
93
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"16-point Sinc (Nuttall 3-term Window)"));
94
-			SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, this->interpolation, 0);
95
-			// Mutes
96
-			for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
97
-			{
98
-				SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + std::to_wstring(x + 1)).c_str()));
99
-				SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
100
-			}
101
-			break;
102
-		case WM_COMMAND:
103
-			break;
104
-	}
105
-
106
-	return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
85
+	auto ncsfDialog = static_cast<XSFConfigDialog_NCSF *>(dialog);
86
+#ifndef NDEBUG
87
+	ncsfDialog->useSoundView = this->useSoundViewDialog;
88
+#endif
89
+	ncsfDialog->interpolation = static_cast<int>(this->interpolation);
90
+	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
91
+		if (this->mutes[x])
92
+			ncsfDialog->mute.Add(x);
107 93
 }
108 94
 
109
-void XSFConfig_NCSF::ResetSpecificConfigDefaults(HWND hwndDlg)
95
+void XSFConfig_NCSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
110 96
 {
111
-	SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_SETCURSEL, XSFConfig_NCSF::initInterpolation, 0);
97
+	auto ncsfDialog = static_cast<XSFConfigDialog_NCSF *>(dialog);
98
+#ifndef NDEBUG
99
+	ncsfDialog->useSoundView = XSFConfig_NCSF::initUseSoundViewDialog;
100
+#endif
101
+	ncsfDialog->interpolation = XSFConfig_NCSF::initInterpolation;
102
+	ncsfDialog->mute.Clear();
112 103
 	auto tmpMutes = std::bitset<16>(XSFConfig_NCSF::initMutes);
113 104
 	for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
114
-		SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
105
+		if (tmpMutes[x])
106
+			ncsfDialog->mute.Add(x);
115 107
 }
116 108
 
117
-void XSFConfig_NCSF::SaveSpecificConfigDialog(HWND hwndDlg)
109
+void XSFConfig_NCSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
118 110
 {
119
-	this->interpolation = static_cast<unsigned>(SendMessageW(GetDlgItem(hwndDlg, idInterpolation), CB_GETCURSEL, 0, 0));
111
+	auto ncsfDialog = static_cast<XSFConfigDialog_NCSF *>(dialog);
112
+#ifndef NDEBUG
113
+	this->useSoundViewDialog = ncsfDialog->useSoundView;
114
+#endif
115
+	this->interpolation = ncsfDialog->interpolation;
120 116
 	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
121
-		this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
117
+		this->mutes[x] = ncsfDialog->mute.Index(x) != wxNOT_FOUND;
122 118
 }
123 119
 
124 120
 void XSFConfig_NCSF::CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool)
125 121
 {
126 122
 	auto NCSFPlayer = static_cast<XSFPlayer_NCSF *>(xSFPlayer);
123
+#ifndef NDEBUG
124
+	NCSFPlayer->SetUseSoundViewDialog(this->useSoundViewDialog);
125
+#endif
127 126
 	NCSFPlayer->SetInterpolation(this->interpolation);
128 127
 	NCSFPlayer->SetMutes(this->mutes);
129 128
 }
... ...
@@ -134,6 +133,11 @@ void XSFConfig_NCSF::About(HWND parent)
134 133
 		"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);
135 134
 }
136 135
 
136
+XSFConfigDialog *XSFConfig_NCSF::CreateDialogBox(wxWindow *window, const std::string &title)
137
+{
138
+	return new XSFConfigDialog_NCSF(*this, window, title);
139
+}
140
+
137 141
 #ifndef NDEBUG
138 142
 INT_PTR CALLBACK XSFConfig_NCSF::SoundViewDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
139 143
 {
... ...
@@ -18,8 +18,13 @@
18 18
 #include "windowsh_wrapper.h"
19 19
 #include "XSFConfig.h"
20 20
 
21
+class wxWindow;
21 22
 class XSFConfig_NCSF;
23
+class XSFConfigDialog;
24
+class XSFPlayer;
25
+#ifndef DEBUG
22 26
 class XSFPlayer_NCSF;
27
+#endif
23 28
 
24 29
 #ifndef NDEBUG
25 30
 struct SoundViewData
... ...
@@ -41,21 +46,26 @@ struct SoundViewData
41 46
 class XSFConfig_NCSF : public XSFConfig
42 47
 {
43 48
 protected:
44
-	static unsigned initInterpolation;
45
-	static std::string initMutes;
49
+#ifndef NDEBUG
50
+	static constexpr bool initUseSoundViewDialog = true;
51
+#endif
52
+	static constexpr unsigned initInterpolation = 4;
53
+	inline static const std::string initMutes = "0000000000000000";
46 54
 
47 55
 	friend class XSFConfig;
48 56
 	friend struct SoundViewData;
57
+#ifndef NDEBUG
58
+	bool useSoundViewDialog;
59
+#endif
49 60
 	unsigned interpolation;
50 61
 	std::bitset<16> mutes;
51 62
 
52 63
 	XSFConfig_NCSF();
53 64
 	void LoadSpecificConfig() override;
54 65
 	void SaveSpecificConfig() override;
55
-	void GenerateSpecificDialogs() override;
56
-	INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
57
-	void ResetSpecificConfigDefaults(HWND hwndDlg) override;
58
-	void SaveSpecificConfigDialog(HWND hwndDlg) override;
66
+	void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
67
+	void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
68
+	void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
59 69
 	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
60 70
 
61 71
 #ifndef NDEBUG
... ...
@@ -65,6 +75,7 @@ protected:
65 75
 #endif
66 76
 public:
67 77
 	void About(HWND parent) override;
78
+	XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
68 79
 
69 80
 #ifndef NDEBUG
70 81
 	void CallSoundView(XSFPlayer *xSFPlayer, HINSTANCE hInstance, HWND hwndParent);
... ...
@@ -112,6 +112,9 @@ bool XSFPlayer_NCSF::LoadNCSF()
112 112
 }
113 113
 
114 114
 XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes()
115
+#ifndef NDEBUG
116
+	, useSoundViewDialog(false)
117
+#endif
115 118
 {
116 119
 	this->uses32BitSamplesClampedTo16Bit = true;
117 120
 	this->xSF.reset(new XSFFile(filename, 8, 12));
... ...
@@ -119,6 +122,9 @@ XSFPlayer_NCSF::XSFPlayer_NCSF(const std::string &filename) : XSFPlayer(), sseq(
119 122
 
120 123
 #ifdef _WIN32
121 124
 XSFPlayer_NCSF::XSFPlayer_NCSF(const std::wstring &filename) : XSFPlayer(), sseq(0), sdatData(), sdat(), player(), secondsPerSample(0), secondsIntoPlayback(0), secondsUntilNextClock(0), mutes()
125
+#ifndef NDEBUG
126
+	, useSoundViewDialog(false)
127
+#endif
122 128
 {
123 129
 	this->uses32BitSamplesClampedTo16Bit = true;
124 130
 	this->xSF.reset(new XSFFile(filename, 8, 12));
... ...
@@ -151,14 +157,17 @@ static DWORD WINAPI soundViewThread(void *b)
151 157
 XSFPlayer_NCSF::~XSFPlayer_NCSF()
152 158
 {
153 159
 #ifndef NDEBUG
154
-	killSoundViewThread = true;
155
-	if (WaitForSingleObject(soundViewThreadHandle, 2000) == WAIT_TIMEOUT)
160
+	if (soundViewThreadHandle != INVALID_HANDLE_VALUE)
156 161
 	{
157
-		TerminateThread(soundViewThreadHandle, 0);
158
-		static_cast<XSFConfig_NCSF *>(xSFConfig)->CloseSoundView();
162
+		killSoundViewThread = true;
163
+		if (WaitForSingleObject(soundViewThreadHandle, 2000) == WAIT_TIMEOUT)
164
+		{
165
+			TerminateThread(soundViewThreadHandle, 0);
166
+			static_cast<XSFConfig_NCSF *>(xSFConfig)->CloseSoundView();
167
+		}
168
+		CloseHandle(soundViewThreadHandle);
169
+		soundViewThreadHandle = INVALID_HANDLE_VALUE;
159 170
 	}
160
-	CloseHandle(soundViewThreadHandle);
161
-	soundViewThreadHandle = INVALID_HANDLE_VALUE;
162 171
 #endif
163 172
 }
164 173
 
... ...
@@ -168,8 +177,11 @@ bool XSFPlayer_NCSF::Load()
168 177
 		return false;
169 178
 
170 179
 #ifndef NDEBUG
171
-	killSoundViewThread = false;
172
-	soundViewThreadHandle = CreateThread(nullptr, 0, soundViewThread, this, 0, nullptr);
180
+	if (this->useSoundViewDialog)
181
+	{
182
+		killSoundViewThread = false;
183
+		soundViewThreadHandle = CreateThread(nullptr, 0, soundViewThread, this, 0, nullptr);
184
+	}
173 185
 #endif
174 186
 
175 187
 	PseudoFile file;
... ...
@@ -248,6 +260,13 @@ void XSFPlayer_NCSF::Terminate()
248 260
 	this->player.Stop(true);
249 261
 }
250 262
 
263
+#ifndef NDEBUG
264
+void XSFPlayer_NCSF::SetUseSoundViewDialog(bool newUseSoundViewDialog)
265
+{
266
+	this->useSoundViewDialog = newUseSoundViewDialog;
267
+}
268
+#endif
269
+
251 270
 void XSFPlayer_NCSF::SetInterpolation(unsigned interpolation)
252 271
 {
253 272
 	this->player.interpolation = static_cast<Interpolation>(interpolation);
... ...
@@ -22,6 +22,8 @@
22 22
 #include "SSEQPlayer/SDAT.h"
23 23
 #include "SSEQPlayer/Player.h"
24 24
 
25
+class XSFFile;
26
+
25 27
 class XSFPlayer_NCSF : public XSFPlayer
26 28
 {
27 29
 	std::uint32_t sseq;
... ...
@@ -29,6 +31,9 @@ class XSFPlayer_NCSF : public XSFPlayer
29 31
 	std::unique_ptr<SDAT> sdat;
30 32
 	Player player;
31 33
 	double secondsPerSample, secondsIntoPlayback, secondsUntilNextClock;
34
+#ifndef NDEBUG
35
+	bool useSoundViewDialog;
36
+#endif
32 37
 	std::bitset<16> mutes;
33 38
 
34 39
 	void MapNCSFSection(const std::vector<std::uint8_t> &section);
... ...
@@ -45,6 +50,9 @@ public:
45 50
 	void GenerateSamples(std::vector<std::uint8_t> &buf, unsigned offset, unsigned samples) override;
46 51
 	void Terminate() override;
47 52
 
53
+#ifndef NDEBUG
54
+	void SetUseSoundViewDialog(bool newUseSoundViewDialog);
55
+#endif
48 56
 	void SetInterpolation(unsigned interpolation);
49 57
 	void SetMutes(const std::bitset<16> &newMutes);
50 58
 #ifndef NDEBUG
... ...
@@ -24,7 +24,8 @@ set(HEADERS
24 24
 	snes9x/ppu.h
25 25
 	snes9x/sdd1.h
26 26
 	snes9x/snes9x.h
27
-	XSFConfig_SNSF.h)
27
+	XSFConfig_SNSF.h
28
+	XSFConfigDialog_SNSF.h)
28 29
 set(SOURCES
29 30
 	snes9x/apu/apu.cpp
30 31
 	snes9x/apu/SNES_SPC.cpp
... ...
@@ -39,6 +40,7 @@ set(SOURCES
39 40
 	snes9x/ppu.cpp
40 41
 	snes9x/sdd1.cpp
41 42
 	XSFConfig_SNSF.cpp
43
+	XSFConfigDialog_SNSF.cpp
42 44
 	XSFPlayer_SNSF.cpp)
43 45
 
44 46
 add_library(in_snsf SHARED ${HEADERS} ${SOURCES})
45 47
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+/*
2
+ * xSF - SNSF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#include <string>
9
+#include <wx/arrstr.h>
10
+#include <wx/checkbox.h>
11
+#include <wx/choice.h>
12
+#include <wx/gbsizer.h>
13
+#include <wx/listbox.h>
14
+#include <wx/stattext.h>
15
+#include <wx/valgen.h>
16
+#include "XSFConfig.h"
17
+#include "XSFConfigDialog.h"
18
+#include "XSFConfigDialog_SNSF.h"
19
+
20
+XSFConfigDialog_SNSF::XSFConfigDialog_SNSF(XSFConfig &config, wxWindow *parent, const wxString &title) : XSFConfigDialog(config, parent, title)
21
+{
22
+	auto reverseStereoCheckBox = new wxCheckBox(this->outputPanel, wxID_ANY, "Reverse Stereo", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->reverseStereo });
23
+	this->outputSizer->Add(reverseStereoCheckBox, { 4, 0 }, { 1, 2 }, wxALL, 5);
24
+
25
+	auto resamplerLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Resampler");
26
+	this->outputSizer->Add(resamplerLabel, { 5, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
27
+	wxArrayString resamplerChoices;
28
+	resamplerChoices.Add("Linear Resampler");
29
+	resamplerChoices.Add("Hermite Resampler");
30
+	resamplerChoices.Add("Bspline Resampler");
31
+	resamplerChoices.Add("Osculating Resampler");
32
+	resamplerChoices.Add("Sinc Resampler");
33
+	auto resamplerChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, resamplerChoices, 0, wxGenericValidator{ &this->resampler });
34
+	this->outputSizer->Add(resamplerChoice, { 5, 1 }, { 1, 1 }, wxALL, 5);
35
+
36
+	auto muteLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Mute");
37
+	this->outputSizer->Add(muteLabel, { 6, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
38
+	wxArrayString muteChoices;
39
+	for (int i = 0; i < 16; ++i)
40
+		muteChoices.Add("BRRPCM " + std::to_string(i + 1));
41
+	auto muteListBox = new wxListBox(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, muteChoices, wxLB_MULTIPLE, wxGenericValidator{ &this->mute });
42
+	this->outputSizer->Add(muteListBox, { 6, 1 }, { 1, 1 }, wxALL, 5);
43
+}
0 44
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+/*
2
+ * xSF - SNSF configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#pragma once
9
+
10
+#include <wx/dynarray.h>
11
+#include "XSFConfigDialog.h"
12
+
13
+class wxString;
14
+class wxWindow;
15
+class XSFConfig;
16
+
17
+class XSFConfigDialog_SNSF : public XSFConfigDialog
18
+{
19
+public:
20
+	XSFConfigDialog_SNSF(XSFConfig &config, wxWindow *parent, const wxString &title);
21
+
22
+	bool reverseStereo;
23
+	int resampler;
24
+	wxArrayInt mute;
25
+};
... ...
@@ -12,12 +12,19 @@
12 12
 #include <bitset>
13 13
 #include <sstream>
14 14
 #include <string>
15
+#include <cstddef>
15 16
 #include <cstdint>
16 17
 #include "windowsh_wrapper.h"
18
+#include "XSFConfig.h"
17 19
 #include "XSFConfig_SNSF.h"
20
+#include "XSFConfigDialog_SNSF.h"
18 21
 #include "convert.h"
19 22
 #include "snes9x/apu/apu.h"
20 23
 
24
+class wxWindow;
25
+class XSFConfigDialog;
26
+class XSFPlayer;
27
+
21 28
 enum
22 29
 {
23 30
 	idSixteenBitSound = 1000,
... ...
@@ -26,13 +33,9 @@ enum
26 33
 	idMutes
27 34
 };
28 35
 
29
-unsigned XSFConfig::initSampleRate = 44100;
30
-std::string XSFConfig::commonName = "SNSF Decoder";
31
-std::string XSFConfig::versionNumber = "0.9b";
32
-//bool XSFConfig_SNSF::initSixteenBitSound = true;
33
-bool XSFConfig_SNSF::initReverseStereo = false;
34
-unsigned XSFConfig_SNSF::initResampler = 1;
35
-std::string XSFConfig_SNSF::initMutes = "00000000";
36
+const unsigned XSFConfig::initSampleRate = 44100;
37
+const std::string XSFConfig::commonName = "SNSF Decoder";
38
+const std::string XSFConfig::versionNumber = "0.9b";
36 39
 
37 40
 XSFConfig *XSFConfig::Create()
38 41
 {
... ...
@@ -71,69 +74,35 @@ void XSFConfig_SNSF::SaveSpecificConfig()
71 74
 	this->configIO->SetValue("Mutes", this->mutes.to_string<char>());
72 75
 }
73 76
 
74
-void XSFConfig_SNSF::GenerateSpecificDialogs()
77
+void XSFConfig_SNSF::InitializeSpecificConfigDialog(XSFConfigDialog *dialog)
75 78
 {
76
-	/*this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Sixteen-Bit Sound").WithSize(80, 10).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7), 2).WithTabStop().
77
-		WithID(idSixteenBitSound));*/
78
-	this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Reverse Stereo").WithSize(80, 10).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7), 2).WithTabStop().
79
-		WithID(idReverseStereo));
80
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Resampler").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10)).IsLeftJustified());
81
-	this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithTabStop().IsDropDownList().
82
-		WithID(idResampler));
83
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Mute").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
84
-	this->configDialog.AddListBoxControl(DialogListBoxBuilder().WithSize(78, 45).WithExactHeight().InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idMutes).WithBorder().
85
-		WithVerticalScrollbar().WithMultipleSelect().WithTabStop());
86
-}
87
-
88
-INT_PTR CALLBACK XSFConfig_SNSF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
89
-{
90
-	switch (uMsg)
91
-	{
92
-		case WM_INITDIALOG:
93
-			// Sixteen-Bit Sound
94
-			/*if (this->sixteenBitSound)
95
-				SendMessageW(GetDlgItem(hwndDlg, idSixteenBitSound), BM_SETCHECK, BST_CHECKED, 0);*/
96
-			// Reverse Stereo
97
-			if (this->reverseStereo)
98
-				SendMessageW(GetDlgItem(hwndDlg, idReverseStereo), BM_SETCHECK, BST_CHECKED, 0);
99
-			// Resampler
100
-			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear Resampler"));
101
-			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Hermite Resampler"));
102
-			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Bspline Resampler"));
103
-			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Osculating Resampler"));
104
-			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Sinc Resampler"));
105
-			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_SETCURSEL, this->resampler, 0);
106
-			// Mutes
107
-			for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
108
-			{
109
-				SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"BRRPCM " + std::to_wstring(x + 1)).c_str()));
110
-				SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
111
-			}
112
-			break;
113
-		case WM_COMMAND:
114
-			break;
115
-	}
116
-
117
-	return XSFConfig::ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
79
+	auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
80
+	snsfDialog->reverseStereo = this->reverseStereo;
81
+	snsfDialog->resampler = static_cast<int>(this->resampler);
82
+	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
83
+		if (this->mutes[x])
84
+			snsfDialog->mute.Add(x);
118 85
 }
119 86
 
120
-void XSFConfig_SNSF::ResetSpecificConfigDefaults(HWND hwndDlg)
87
+void XSFConfig_SNSF::ResetSpecificConfigDefaults(XSFConfigDialog *dialog)
121 88
 {
122
-	//SendMessageW(GetDlgItem(hwndDlg, idSixteenBitSound), BM_SETCHECK, XSFConfig_SNSF::initSixteenBitSound ? BST_CHECKED : BST_UNCHECKED, 0);
123
-	SendMessageW(GetDlgItem(hwndDlg, idReverseStereo), BM_SETCHECK, XSFConfig_SNSF::initReverseStereo ? BST_CHECKED : BST_UNCHECKED, 0);
124
-	SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_SETCURSEL, XSFConfig_SNSF::initResampler, 0);
89
+	auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
90
+	snsfDialog->reverseStereo = XSFConfig_SNSF::initReverseStereo;
91
+	snsfDialog->resampler = XSFConfig_SNSF::initResampler;
92
+	snsfDialog->mute.Clear();
125 93
 	auto tmpMutes = std::bitset<8>(XSFConfig_SNSF::initMutes);
126
-	for (int x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
127
-		SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, tmpMutes[x], x);
94
+	for (std::size_t x = 0, numMutes = tmpMutes.size(); x < numMutes; ++x)
95
+		if (tmpMutes[x])
96
+			snsfDialog->mute.Add(x);
128 97
 }
129 98
 
130
-void XSFConfig_SNSF::SaveSpecificConfigDialog(HWND hwndDlg)
99
+void XSFConfig_SNSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
131 100
 {
132
-	//this->sixteenBitSound = SendMessageW(GetDlgItem(hwndDlg, idSixteenBitSound), BM_GETCHECK, 0, 0) == BST_CHECKED;
133
-	this->reverseStereo = SendMessageW(GetDlgItem(hwndDlg, idReverseStereo), BM_GETCHECK, 0, 0) == BST_CHECKED;
134
-	this->resampler = static_cast<unsigned>(SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_GETCURSEL, 0, 0));
135
-	for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
136
-		this->mutes[x] = !!SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_GETSEL, x, 0);
101
+	auto snsfDialog = static_cast<XSFConfigDialog_SNSF *>(dialog);
102
+	this->reverseStereo = snsfDialog->reverseStereo;
103
+	this->resampler = snsfDialog->resampler;
104
+	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
105
+		this->mutes[x] = snsfDialog->mute.Index(x) != wxNOT_FOUND;
137 106
 }
138 107
 
139 108
 void XSFConfig_SNSF::CopySpecificConfigToMemory(XSFPlayer *, bool preLoad)
... ...
@@ -153,3 +122,8 @@ void XSFConfig_SNSF::About(HWND parent)
153 122
 	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"
154 123
 		"Utilizes modified snes9x v1.53 for audio playback.").c_str(), ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber).c_str(), MB_OK);
155 124
 }
125
+
126
+XSFConfigDialog *XSFConfig_SNSF::CreateDialogBox(wxWindow *window, const std::string &title)
127
+{
128
+	return new XSFConfigDialog_SNSF(*this, window, title);
129
+}
... ...
@@ -16,14 +16,16 @@
16 16
 #include "windowsh_wrapper.h"
17 17
 #include "XSFConfig.h"
18 18
 
19
+class wxWindow;
20
+class XSFConfigDialog;
19 21
 class XSFPlayer;
20 22
 
21 23
 class XSFConfig_SNSF : public XSFConfig
22 24
 {
23 25
 protected:
24
-	static bool /*initSixteenBitSound, */initReverseStereo;
25
-	static unsigned initResampler;
26
-	static std::string initMutes;
26
+	static constexpr bool /*initSixteenBitSound = true, */initReverseStereo = false;
27
+	static constexpr unsigned initResampler = 1;
28
+	inline static const std::string initMutes = "00000000";
27 29
 
28 30
 	friend class XSFConfig;
29 31
 	bool /*sixteenBitSound, */reverseStereo;
... ...
@@ -32,13 +34,13 @@ protected:
32 34
 	XSFConfig_SNSF();
33 35
 	void LoadSpecificConfig() override;
34 36
 	void SaveSpecificConfig() override;
35
-	void GenerateSpecificDialogs() override;
36
-	INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
37
-	void ResetSpecificConfigDefaults(HWND hwndDlg) override;
38
-	void SaveSpecificConfigDialog(HWND hwndDlg) override;
37
+	void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) override;
38
+	void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
39
+	void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
39 40
 	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
40 41
 public:
41 42
 	unsigned resampler;
42 43
 
43 44
 	void About(HWND parent) override;
45
+	XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
44 46
 };
... ...
@@ -198,6 +198,7 @@ set(wxUSE_XRC OFF CACHE BOOL " " FORCE)
198 198
 set(wxUSE_ZIPSTREAM OFF CACHE BOOL " " FORCE)
199 199
 set(wxUSE_ZLIB OFF CACHE STRING " " FORCE)
200 200
 
201
+add_compile_definitions($<$<AND:$<CXX_COMPILER_ID:MSVC>,$<CONFIG:Debug>>:_ITERATOR_DEBUG_LEVEL=0>)
201 202
 add_subdirectory(wxWidgets)
202 203
 
203 204
 # in_xsf_framework
... ...
@@ -216,6 +217,7 @@ set(HEADERS
216 217
 	windowsh_wrapper.h
217 218
 	XSFCommon.h
218 219
 	XSFConfig.h
220
+	XSFConfigDialog.h
219 221
 	XSFFile.h
220 222
 	XSFPlayer.h)
221 223
 set(SOURCES
... ...
@@ -225,6 +227,7 @@ set(SOURCES
225 227
 	TagList.cpp
226 228
 	XSFConfig.cpp
227 229
 	XSFConfig_Winamp.cpp
230
+	XSFConfigDialog.cpp
228 231
 	XSFFile.cpp
229 232
 	XSFPlayer.cpp)
230 233
 
... ...
@@ -7,10 +7,14 @@
7 7
 
8 8
 #include <algorithm>
9 9
 #include <string>
10
+#include <type_traits>
10 11
 #include <vector>
12
+#include <wx/app.h>
13
+#include <wx/nativewin.h>
11 14
 #include "windowsh_wrapper.h"
12 15
 #include <windowsx.h>
13 16
 #include "XSFConfig.h"
17
+#include "XSFConfigDialog.h"
14 18
 #include "XSFFile.h"
15 19
 #include "XSFPlayer.h"
16 20
 #include "convert.h"
... ...
@@ -37,18 +41,8 @@ enum
37 41
 	idInfoComment
38 42
 };
39 43
 
40
-bool XSFConfig::initPlayInfinitely = false;
41
-std::string XSFConfig::initSkipSilenceOnStartSec = "5";
42
-std::string XSFConfig::initDetectSilenceSec = "5";
43
-std::string XSFConfig::initDefaultLength = "1:55";
44
-std::string XSFConfig::initDefaultFade = "5";
45
-std::string XSFConfig::initTitleFormat = "%game%[ - [%disc%.]%track%] - %title%";
46
-double XSFConfig::initVolume = 1.0;
47
-VolumeType XSFConfig::initVolumeType = VolumeType::ReplayGainAlbum;
48
-PeakType XSFConfig::initPeakType = PeakType::ReplayGainTrack;
49
-
50 44
 XSFConfig::XSFConfig() : playInfinitely(false), skipSilenceOnStartSec(0), detectSilenceSec(0), defaultLength(0), defaultFade(0), volume(0.0), volumeType(VolumeType::None), peakType(PeakType::None),
51
-	sampleRate(0), titleFormat(""), configDialog(), configDialogProperty(), infoDialog(), supportedSampleRates(), configIO(XSFConfigIO::Create())
45
+	sampleRate(0), titleFormat(""), infoDialog(), supportedSampleRates(), configIO(XSFConfigIO::Create())
52 46
 {
53 47
 }
54 48
 
... ...
@@ -98,8 +92,44 @@ void XSFConfig::SaveConfig()
98 92
 	this->SaveSpecificConfig();
99 93
 }
100 94
 
95
+class XSFConfigApp : public wxApp
96
+{
97
+	HWND parent;
98
+	XSFConfig *config;
99
+public:
100
+	XSFConfigApp() : parent(nullptr), config(nullptr)
101
+	{
102
+	}
103
+
104
+	XSFConfigApp(HWND parent, XSFConfig *config) : parent(parent), config(config)
105
+	{
106
+	}
107
+
108
+	bool OnInit() override
109
+	{
110
+		// 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...
111
+
112
+		auto window = new wxNativeContainerWindow(this->parent);
113
+		auto dialog = this->config->CreateDialogBox(window, XSFConfig::commonName + " v" + XSFConfig::versionNumber);
114
+		dialog->Finalize();
115
+		this->config->InitializeConfigDialog(dialog);
116
+		if (dialog->ShowModal() == wxID_OK)
117
+		{
118
+			this->config->SaveConfigDialog(dialog);
119
+			this->config->SaveConfig();
120
+		}
121
+		dialog->Destroy();
122
+		window->Destroy();
123
+		return true;
124
+	}
125
+};
126
+
127
+wxIMPLEMENT_APP_NO_MAIN(XSFConfigApp);
128
+
101 129
 void XSFConfig::GenerateDialogs()
102 130
 {
131
+	// NOTE: Eventually this will be done away with when I decide to make an actual info dialog box using wxWidgets.
132
+
103 133
 	this->infoDialog = DialogBuilder().IsPopup().WithBorder().WithDialogFrame().WithDialogModalFrame().WithSystemMenu().WithFont(L"MS Shell Dlg", 8);
104 134
 	this->infoDialog.AddLabelControl(DialogLabelBuilder(L"Title:").WithSize(50, 8).WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(7, 10)).IsRightJustified());
105 135
 	this->infoDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(200, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().WithAutoHScroll().WithBorder().
... ...
@@ -123,82 +153,9 @@ void XSFConfig::GenerateDialogs()
123 153
 	this->infoDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(200, 54).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().WithAutoVScroll().WithBorder().
124 154
 		WithTabStop().WithID(idInfoComment).WithVerticalScrollbar().WithWantReturn().IsMultiline());
125 155
 
126
-	this->configDialog = DialogBuilder().WithTitle(ConvertFuncs::StringToWString(XSFConfig::commonName + " v" + XSFConfig::versionNumber)).IsPopup().WithBorder().WithDialogFrame().WithDialogModalFrame().WithSystemMenu().WithFont(L"MS Shell Dlg", 8);
127
-	this->configDialog.AddGroupControl(DialogGroupBuilder(L"General").WithRelativePositionToParent(RelativePositionToParent::PositionType::FromTopLeft, Point<short>(7, 7)));
128
-	this->configDialog.AddCheckBoxControl(DialogCheckBoxBuilder(L"Play infinitely").WithSize(60, 10).InGroup(L"General").WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(6, 11)).WithTabStop().
129
-		WithID(idPlayInfinitely));
130
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Default play length (m:s)").WithSize(85, 8).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7)).
131
-		IsLeftJustified());
132
-	this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
133
-		WithAutoHScroll().WithBorder().WithTabStop().WithID(idDefaultLength));
134
-	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).
135
-		IsLeftJustified());
136
-	this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
137
-		WithAutoHScroll().WithBorder().WithTabStop().WithID(idDefaultFade));
138
-	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).
139
-		IsLeftJustified());
140
-	this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
141
-		WithAutoHScroll().WithBorder().WithTabStop().WithID(idSkipSilenceOnStartSec));
142
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Detect silence (sec)").WithSize(85, 8).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).
143
-		IsLeftJustified());
144
-	this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"General").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
145
-		WithAutoHScroll().WithBorder().WithTabStop().WithID(idDetectSilenceSec));
146
-	this->configDialog.AddGroupControl(DialogGroupBuilder(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7)));
147
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Volume").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(6, 14)).IsLeftJustified());
148
-	this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(25, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).IsLeftJustified().
149
-		WithAutoHScroll().WithBorder().WithTabStop().WithID(idVolume));
150
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"ReplayGain").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
151
-	this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idReplayGain).
152
-		IsDropDownList().WithTabStop());
153
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Clip Protect").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
154
-	this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(78, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idClipProtect).
155
-		IsDropDownList().WithTabStop());
156
-	this->configDialog.AddLabelControl(DialogLabelBuilder(L"Sample Rate").WithSize(50, 8).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 10), 2).IsLeftJustified());
157
-	this->configDialog.AddComboBoxControl(DialogComboBoxBuilder().WithSize(50, 14).InGroup(L"Output").WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(5, -3)).WithID(idSampleRate).
158
-		IsDropDownList().WithTabStop());
159
-	this->configDialog.AddGroupControl(DialogGroupBuilder(L"Title Format").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 7)));
160
-	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").
161
-		WithRelativePositionToParent(RelativePosition::PositionType::FromTopLeft, Point<short>(6, 11)).IsLeftJustified());
162
-	this->configDialog.AddEditBoxControl(DialogEditBoxBuilder().WithSize(150, 14).InGroup(L"Title Format").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 4)).IsLeftJustified().
163
-		WithAutoHScroll().WithBorder().WithTabStop().WithID(idTitleFormat));
164
-	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 "
165
-			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 "
166
-			L"bracket blocks can be nested.").WithSize(150, 72).InGroup(L"Title Format").WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomLeft, Point<short>(0, 4)).IsLeftJustified());
167
-
168
-	this->GenerateSpecificDialogs();
169
-
170 156
 	this->infoDialog.AddButtonControl(DialogButtonBuilder(L"OK").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomRight, Point<short>(-104, 7)).WithID(IDOK).IsDefault().WithTabStop());
171 157
 	this->infoDialog.AddButtonControl(DialogButtonBuilder(L"Cancel").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(4, 0)).WithID(IDCANCEL).WithTabStop());
172 158
 	this->infoDialog.AutoSize();
173
-
174
-	this->configDialogProperty = this->configDialog;
175
-	this->configDialogProperty = DialogBuilder().IsChild().IsControlWindow().WithFont(L"MS Shell Dlg", 8);
176
-	this->configDialogProperty.AutoSize();
177
-
178
-	this->configDialog.AddButtonControl(DialogButtonBuilder(L"Reset Defaults").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomRight, Point<short>(-50, 7)).WithID(idResetDefaults).
179
-		WithTabStop());
180
-	this->configDialog.AddButtonControl(DialogButtonBuilder(L"OK").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromBottomRight, Point<short>(-104, 7)).WithID(IDOK).IsDefault().WithTabStop());
181
-	this->configDialog.AddButtonControl(DialogButtonBuilder(L"Cancel").WithSize(50, 14).WithRelativePositionToSibling(RelativePosition::PositionType::FromTopRight, Point<short>(4, 0)).WithID(IDCANCEL).WithTabStop());
182
-	this->configDialog.AutoSize();
183
-}
184
-
185
-INT_PTR CALLBACK XSFConfig::ConfigDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
186
-{
187
-	XSFConfig *thisPtr = nullptr;
188
-
189
-	if (uMsg == WM_INITDIALOG)
190
-	{
191
-		thisPtr = reinterpret_cast<XSFConfig *>(lParam);
192
-
193
-		SetWindowLongPtr(hwndDlg, DWLP_USER, reinterpret_cast<LONG_PTR>(thisPtr));
194
-	}
195
-	else
196
-		thisPtr = reinterpret_cast<XSFConfig *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
197
-
198
-	if (thisPtr)
199
-		return thisPtr->ConfigDialogProc(hwndDlg, uMsg, wParam, lParam);
200
-	else
201
-		return false;
202 159
 }
203 160
 
204 161
 INT_PTR CALLBACK XSFConfig::InfoDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
... ...
@@ -220,63 +177,6 @@ INT_PTR CALLBACK XSFConfig::InfoDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM
220 177
 		return false;
221 178
 }
222 179
 
223
-INT_PTR CALLBACK XSFConfig::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM)
224
-{
225
-	switch (uMsg)
226
-	{
227
-		case WM_CLOSE:
228
-			EndDialog(hwndDlg, IDCANCEL);
229
-			break;
230
-		case WM_INITDIALOG:
231
-			if (this->playInfinitely)
232
-				SendMessageW(GetDlgItem(hwndDlg, idPlayInfinitely), BM_SETCHECK, BST_CHECKED, 0);
233
-			SetWindowTextW(GetDlgItem(hwndDlg, idDefaultLength), ConvertFuncs::MSToWString(this->defaultLength).c_str());
234
-			SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), ConvertFuncs::MSToWString(this->defaultFade).c_str());
235
-			SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), ConvertFuncs::MSToWString(this->skipSilenceOnStartSec).c_str());
236
-			SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), ConvertFuncs::MSToWString(this->detectSilenceSec).c_str());
237
-			SetWindowTextW(GetDlgItem(hwndDlg, idVolume), ConvertFuncs::TrimDoubleString(std::to_wstring(this->volume)).c_str());
238
-			SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Disabled"));
239
-			SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Use Volume Tag"));
240
-			SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Track"));
241
-			SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Album"));
242
-			SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_SETCURSEL, static_cast<WPARAM>(this->volumeType), 0);
243
-			SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Disabled"));
244
-			SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Track"));
245
-			SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Album"));
246
-			SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_SETCURSEL, static_cast<WPARAM>(this->peakType), 0);
247
-			for (unsigned x = 0, rates = this->supportedSampleRates.size(); x < rates; ++x)
248
-			{
249
-				unsigned rate = this->supportedSampleRates[x];
250
-				SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(std::to_wstring(rate).c_str()));
251
-				if (this->sampleRate == rate)
252
-					SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_SETCURSEL, x, 0);
253
-			}
254
-			SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), ConvertFuncs::StringToWString(this->titleFormat).c_str());
255
-			break;
256
-		case WM_COMMAND:
257
-			switch (GET_WM_COMMAND_ID(wParam, lParam))
258
-			{
259
-				case IDOK:
260
-					this->SaveConfigDialog(hwndDlg);
261
-					this->SaveConfig();
262
-					EndDialog(hwndDlg, IDOK);
263
-					break;
264
-				case IDCANCEL:
265
-					EndDialog(hwndDlg, IDCANCEL);
266
-					break;
267
-				case idResetDefaults:
268
-					this->ResetConfigDefaults(hwndDlg);
269
-					break;
270
-				default:
271
-					return false;
272
-			}
273
-			break;
274
-		default:
275
-			return false;
276
-	}
277
-	return true;
278
-}
279
-
280 180
 extern XSFFile *xSFFileInInfo;
281 181
 
282 182
 INT_PTR CALLBACK XSFConfig::InfoDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM)
... ...
@@ -326,7 +226,11 @@ INT_PTR CALLBACK XSFConfig::InfoDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wPara
326 226
 
327 227
 void XSFConfig::CallConfigDialog(HINSTANCE hInstance, HWND hwndParent)
328 228
 {
329
-	DialogBoxIndirectParamW(hInstance, this->configDialog.GenerateTemplate(), hwndParent, XSFConfig::ConfigDialogProcStatic, reinterpret_cast<LPARAM>(this));
229
+	auto app = new XSFConfigApp(hwndParent, this);
230
+	wxApp::SetInstance(app);
231
+	wxEntryStart(hInstance);
232
+	app->OnInit();
233
+	wxEntryCleanup();
330 234
 }
331 235
 
332 236
 void XSFConfig::CallInfoDialog(HINSTANCE hInstance, HWND hwndParent)
... ...
@@ -334,37 +238,54 @@ void XSFConfig::CallInfoDialog(HINSTANCE hInstance, HWND hwndParent)
334 238
 	DialogBoxIndirectParamW(hInstance, this->infoDialog.GenerateTemplate(), hwndParent, XSFConfig::InfoDialogProcStatic, reinterpret_cast<LPARAM>(this));
335 239
 }
336 240
 
337
-void XSFConfig::ResetConfigDefaults(HWND hwndDlg)
241
+void XSFConfig::InitializeConfigDialog(XSFConfigDialog *dialog)
242
+{
243
+	dialog->playInfinitely = this->playInfinitely;
244
+	dialog->defaultPlayLength = ConvertFuncs::MSToString(this->defaultLength);
245
+	dialog->defaultFadeoutLength = ConvertFuncs::MSToString(this->defaultFade);
246
+	dialog->skipSilenceOnStart = ConvertFuncs::MSToString(this->skipSilenceOnStartSec);
247
+	dialog->detectSilence = ConvertFuncs::MSToString(this->detectSilenceSec);
248
+	dialog->volume = this->volume;
249
+	dialog->replayGain = static_cast<std::underlying_type_t<VolumeType>>(this->volumeType);
250
+	dialog->clipProtect = static_cast<std::underlying_type_t<PeakType>>(this->peakType);
251
+	auto found = std::find(this->supportedSampleRates.begin(), this->supportedSampleRates.end(), this->sampleRate);
252
+	dialog->sampleRate = found == this->supportedSampleRates.end() ? 0 : found - this->supportedSampleRates.begin();
253
+	dialog->titleFormat = this->titleFormat;
254
+
255
+	this->InitializeSpecificConfigDialog(dialog);
256
+}
257
+
258
+void XSFConfig::ResetConfigDefaults(XSFConfigDialog *dialog)
338 259
 {
339
-	SendMessageW(GetDlgItem(hwndDlg, idPlayInfinitely), BM_SETCHECK, XSFConfig::initPlayInfinitely ? BST_CHECKED : BST_UNCHECKED, 0);
340
-	SetWindowTextW(GetDlgItem(hwndDlg, idDefaultLength), ConvertFuncs::StringToWString(XSFConfig::initDefaultLength).c_str());
341
-	SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), ConvertFuncs::StringToWString(XSFConfig::initDefaultFade).c_str());
342
-	SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), ConvertFuncs::StringToWString(XSFConfig::initSkipSilenceOnStartSec).c_str());
343
-	SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), ConvertFuncs::StringToWString(XSFConfig::initDetectSilenceSec).c_str());
344
-	SetWindowTextW(GetDlgItem(hwndDlg, idVolume), ConvertFuncs::TrimDoubleString(std::to_wstring(XSFConfig::initVolume)).c_str());
345
-	SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_SETCURSEL, static_cast<WPARAM>(XSFConfig::initVolumeType), 0);
346
-	SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_SETCURSEL, static_cast<WPARAM>(XSFConfig::initPeakType), 0);
260
+	dialog->playInfinitely = XSFConfig::initPlayInfinitely;
261
+	dialog->defaultPlayLength = XSFConfig::initDefaultLength;
262
+	dialog->defaultFadeoutLength = XSFConfig::initDefaultFade;
263
+	dialog->skipSilenceOnStart = XSFConfig::initSkipSilenceOnStartSec;
264
+	dialog->detectSilence = XSFConfig::initDetectSilenceSec;
265
+	dialog->volume = XSFConfig::initVolume;
266
+	dialog->replayGain = static_cast<std::underlying_type_t<VolumeType>>(XSFConfig::initVolumeType);
267
+	dialog->clipProtect = static_cast<std::underlying_type_t<PeakType>>(XSFConfig::initPeakType);
347 268
 	auto found = std::find(this->supportedSampleRates.begin(), this->supportedSampleRates.end(), XSFConfig::initSampleRate);
348
-	SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_SETCURSEL, found - this->supportedSampleRates.begin(), 0);
349
-	SetWindowTextW(GetDlgItem(hwndDlg, idTitleFormat), ConvertFuncs::StringToWString(XSFConfig::initTitleFormat).c_str());
269
+	dialog->sampleRate = found == this->supportedSampleRates.end() ? 0 : found - this->supportedSampleRates.begin();
270
+	dialog->titleFormat = XSFConfig::initTitleFormat;
350 271
 
351
-	this->ResetSpecificConfigDefaults(hwndDlg);
272
+	this->ResetSpecificConfigDefaults(dialog);
352 273
 }
353 274
 
354
-void XSFConfig::SaveConfigDialog(HWND hwndDlg)
275
+void XSFConfig::SaveConfigDialog(XSFConfigDialog *dialog)
355 276
 {
356
-	this->playInfinitely = SendMessageW(GetDlgItem(hwndDlg, idPlayInfinitely), BM_GETCHECK, 0, 0) == BST_CHECKED;
357
-	this->defaultLength = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDefaultLength)));
358
-	this->defaultFade = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDefaultFade)));
359
-	this->skipSilenceOnStartSec = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec)));
360
-	this->detectSilenceSec = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDetectSilenceSec)));
361
-	this->volume = convertTo<double>(this->GetTextFromWindow(GetDlgItem(hwndDlg, idVolume)));
362
-	this->volumeType = static_cast<VolumeType>(SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_GETCURSEL, 0, 0));
363
-	this->peakType = static_cast<PeakType>(SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_GETCURSEL, 0, 0));
364
-	this->sampleRate = XSFConfig::supportedSampleRates[SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_GETCURSEL, 0, 0)];
365
-	this->titleFormat = ConvertFuncs::WStringToString(this->GetTextFromWindow(GetDlgItem(hwndDlg, idTitleFormat)));
366
-
367
-	this->SaveSpecificConfigDialog(hwndDlg);
277
+	this->playInfinitely = dialog->playInfinitely;
278
+	this->defaultLength = ConvertFuncs::StringToMS(dialog->defaultPlayLength);
279
+	this->defaultFade = ConvertFuncs::StringToMS(dialog->defaultFadeoutLength);
280
+	this->skipSilenceOnStartSec = ConvertFuncs::StringToMS(dialog->skipSilenceOnStart);
281
+	this->detectSilenceSec = ConvertFuncs::StringToMS(dialog->detectSilence);
282
+	this->volume = dialog->volume;
283
+	this->volumeType = static_cast<VolumeType>(dialog->replayGain);
284
+	this->peakType = static_cast<PeakType>(dialog->clipProtect);
285
+	this->sampleRate = this->supportedSampleRates[dialog->sampleRate];
286
+	this->titleFormat = dialog->titleFormat.ToStdString();
287
+
288
+	this->SaveSpecificConfigDialog(dialog);
368 289
 }
369 290
 
370 291
 void XSFConfig::CopyConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad)
... ...
@@ -385,6 +306,11 @@ HINSTANCE XSFConfig::GetHInstance() const
385 306
 	return this->configIO->GetHInstance();
386 307
 }
387 308
 
309
+const std::vector<unsigned> &XSFConfig::GetSupportedSampleRates() const
310
+{
311
+	return this->supportedSampleRates;
312
+}
313
+
388 314
 bool XSFConfig::GetPlayInfinitely() const
389 315
 {
390 316
 	return this->playInfinitely;
... ...
@@ -12,11 +12,12 @@
12 12
 #include <type_traits>
13 13
 #include <vector>
14 14
 #include "DialogBuilder.h"
15
+#include "XSFFile.h"
15 16
 #include "convert.h"
16 17
 #include "windowsh_wrapper.h"
17 18
 
18
-enum class PeakType;
19
-enum class VolumeType;
19
+class wxWindow;
20
+class XSFConfigDialog;
20 21
 class XSFPlayer;
21 22
 
22 23
 class XSFConfigIO
... ...
@@ -68,30 +69,29 @@ protected:
68 69
 	PeakType peakType;
69 70
 	unsigned sampleRate;
70 71
 	std::string titleFormat;
71
-	DialogTemplate configDialog, configDialogProperty, infoDialog;
72
+	DialogTemplate infoDialog;
72 73
 	std::vector<unsigned> supportedSampleRates;
73 74
 	std::unique_ptr<XSFConfigIO> configIO;
74 75
 
75 76
 	XSFConfig();
76 77
 	std::wstring GetTextFromWindow(HWND hwnd);
77 78
 	virtual void LoadSpecificConfig() = 0;
78
-	virtual void GenerateSpecificDialogs() = 0;
79 79
 	virtual void SaveSpecificConfig() = 0;
80
-	virtual INT_PTR CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
81 80
 	virtual INT_PTR CALLBACK InfoDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
82
-	virtual void ResetSpecificConfigDefaults(HWND hwndDlg) = 0;
83
-	virtual void SaveSpecificConfigDialog(HWND hwndDlg) = 0;
81
+	virtual void InitializeSpecificConfigDialog(XSFConfigDialog *dialog) = 0;
82
+	virtual void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) = 0;
83
+	virtual void SaveSpecificConfigDialog(XSFConfigDialog *dialog) = 0;
84 84
 	virtual void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) = 0;
85 85
 public:
86
-	static bool initPlayInfinitely;
87
-	static std::string initSkipSilenceOnStartSec, initDetectSilenceSec, initDefaultLength, initDefaultFade, initTitleFormat;
88
-	static double initVolume;
89
-	static VolumeType initVolumeType;
90
-	static PeakType initPeakType;
86
+	static constexpr bool initPlayInfinitely = false;
87
+	inline static const std::string initSkipSilenceOnStartSec = "5", initDetectSilenceSec = "5", initDefaultLength = "1:55", initDefaultFade = "5", initTitleFormat = "%game%[ - [%disc%.]%track%] - %title%";
88
+	static constexpr double initVolume = 1.0;
89
+	static constexpr VolumeType initVolumeType = VolumeType::ReplayGainAlbum;
90
+	static constexpr PeakType initPeakType = PeakType::ReplayGainTrack;
91 91
 	// These are not defined in XSFConfig.cpp, they should be defined in your own config's source.
92
-	static unsigned initSampleRate;
93
-	static std::string commonName;
94
-	static std::string versionNumber;
92
+	static const unsigned initSampleRate;
93
+	static const std::string commonName;
94
+	static const std::string versionNumber;
95 95
 	// 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.
96 96
 	static XSFConfig *Create();
97 97
 	static const std::string &CommonNameWithVersion();
... ...
@@ -100,17 +100,20 @@ public:
100 100
 	void LoadConfig();
101 101
 	void SaveConfig();
102 102
 	void GenerateDialogs();
103
-	static INT_PTR CALLBACK ConfigDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
104 103
 	static INT_PTR CALLBACK InfoDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
105 104
 	void CallConfigDialog(HINSTANCE hInstance, HWND hwndParent);
106 105
 	void CallInfoDialog(HINSTANCE hInstance, HWND hwndParent);
107
-	void ResetConfigDefaults(HWND hwndDlg);
108
-	void SaveConfigDialog(HWND hwndDlg);
106
+	void InitializeConfigDialog(XSFConfigDialog *dialog);
107
+	void ResetConfigDefaults(XSFConfigDialog *dialog);
108
+	void SaveConfigDialog(XSFConfigDialog *dialog);
109 109
 	void CopyConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad);
110 110
 	void SetHInstance(HINSTANCE hInstance);
111 111
 	HINSTANCE GetHInstance() const;
112 112
 
113 113
 	virtual void About(HWND parent) = 0;
114
+	virtual XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) = 0;
115
+
116
+	const std::vector<unsigned> &GetSupportedSampleRates() const;
114 117
 
115 118
 	bool GetPlayInfinitely() const;
116 119
 	unsigned long GetSkipSilenceOnStartSec() const;
117 120
new file mode 100644
... ...
@@ -0,0 +1,156 @@
1
+/*
2
+ * xSF - Core configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#include <string>
9
+#include <wx/button.h>
10
+#include <wx/checkbox.h>
11
+#include <wx/choice.h>
12
+#include <wx/dialog.h>
13
+#include <wx/gbsizer.h>
14
+#include <wx/notebook.h>
15
+#include <wx/sizer.h>
16
+#include <wx/stattext.h>
17
+#include <wx/string.h>
18
+#include <wx/textctrl.h>
19
+#include <wx/valgen.h>
20
+#include <wx/valnum.h>
21
+#include <wx/window.h>
22
+#include "RegExValidator.h"
23
+#include "XSFConfig.h"
24
+#include "XSFConfigDialog.h"
25
+
26
+enum
27
+{
28
+	idResetDefaults = 1
29
+};
30
+
31
+// This just sets up the base dialog box's controls, it does not do the auto-sizing at this stage.
32
+XSFConfigDialog::XSFConfigDialog(XSFConfig &config, wxWindow *parent, const wxString &title) : wxDialog(parent, wxID_ANY, title), config(config)
33
+{
34
+	this->mainSizer = new wxGridBagSizer;
35
+
36
+	auto notebook = new wxNotebook(this, wxID_ANY);
37
+
38
+	this->generalPanel = new wxPanel(notebook, wxID_ANY);
39
+	this->generalSizer = new wxGridBagSizer;
40
+
41
+	auto playInfinitelyCheckBox = new wxCheckBox(this->generalPanel, wxID_ANY, "Play Infinitely", wxDefaultPosition, wxDefaultSize, 0, wxGenericValidator{ &this->playInfinitely });
42
+	this->generalSizer->Add(playInfinitelyCheckBox, { 0, 0 }, { 1, 2 }, wxALL, 5);
43
+
44
+	auto defaultPlayLengthLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Default play length (m:s)");
45
+	this->generalSizer->Add(defaultPlayLengthLabel, { 1, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
46
+	auto defaultPlayLengthTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->defaultPlayLength, wxRE_ADVANCED });
47
+	this->generalSizer->Add(defaultPlayLengthTextCtrl, { 1, 1 }, { 1, 1 }, wxALL, 5);
48
+
49
+	auto defaultFadeoutLengthLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Default fadeout length (m:s)");
50
+	this->generalSizer->Add(defaultFadeoutLengthLabel, { 2, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
51
+	auto defaultFadeoutLengthTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->defaultFadeoutLength, wxRE_ADVANCED });
52
+	this->generalSizer->Add(defaultFadeoutLengthTextCtrl, { 2, 1 }, { 1, 1 }, wxALL, 5);
53
+
54
+	auto skipSilenceOnStartLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Skip silence on start (s)");
55
+	this->generalSizer->Add(skipSilenceOnStartLabel, { 3, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
56
+	auto skipSilenceOnStartTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->skipSilenceOnStart, wxRE_ADVANCED });
57
+	this->generalSizer->Add(skipSilenceOnStartTextCtrl, { 3, 1 }, { 1, 1 }, wxALL, 5);
58
+
59
+	auto detectSilenceLabel = new wxStaticText(this->generalPanel, wxID_ANY, "Detect silence (s)");
60
+	this->generalSizer->Add(detectSilenceLabel, { 4, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
61
+	auto detectSilenceTextCtrl = new wxTextCtrl(this->generalPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, RegExValidator{ XSFConfigDialog::timeRegex, &this->detectSilence, wxRE_ADVANCED });
62
+	this->generalSizer->Add(detectSilenceTextCtrl, { 4, 1 }, { 1, 1 }, wxALL, 5);
63
+
64
+	notebook->AddPage(this->generalPanel, "General");
65
+
66
+	this->outputPanel = new wxPanel(notebook, wxID_ANY);
67
+	this->outputSizer = new wxGridBagSizer;
68
+
69
+	auto volumeLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Volume");
70
+	this->outputSizer->Add(volumeLabel, { 0, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
71
+	auto volumeTextCtrl = new wxTextCtrl(this->outputPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 38, -1 }, 0, wxFloatingPointValidator<double>{ &this->volume, wxNUM_VAL_NO_TRAILING_ZEROES });
72
+	this->outputSizer->Add(volumeTextCtrl, { 0, 1 }, { 1, 1 }, wxALL, 5);
73
+
74
+	auto replayGainLabel = new wxStaticText(this->outputPanel, wxID_ANY, "ReplayGain");
75
+	this->outputSizer->Add(replayGainLabel, { 1, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
76
+	wxArrayString replayGainChoices;
77
+	replayGainChoices.Add("Disabled");
78
+	replayGainChoices.Add("Use Volume Tag");
79
+	replayGainChoices.Add("Track");
80
+	replayGainChoices.Add("Album");
81
+	auto replayGainChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, replayGainChoices, 0, wxGenericValidator{ &this->replayGain });
82
+	this->outputSizer->Add(replayGainChoice, { 1, 1 }, { 1, 1 }, wxALL, 5);
83
+
84
+	auto clipProtectLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Clip Protect");
85
+	this->outputSizer->Add(clipProtectLabel, { 2, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
86
+	wxArrayString clipProtectChoices;
87
+	clipProtectChoices.Add("Disabled");
88
+	clipProtectChoices.Add("Track");
89
+	clipProtectChoices.Add("Album");
90
+	auto clipProtectChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, clipProtectChoices, 0, wxGenericValidator{ &this->clipProtect });
91
+	this->outputSizer->Add(clipProtectChoice, { 2, 1 }, { 1, 1 }, wxALL, 5);
92
+
93
+	auto sampleRateLabel = new wxStaticText(this->outputPanel, wxID_ANY, "Sample Rate");
94
+	this->outputSizer->Add(sampleRateLabel, { 3, 0 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 5);
95
+	wxArrayString sampleRateChoices;
96
+	for (auto supportedSampleRate : this->config.GetSupportedSampleRates())
97
+		sampleRateChoices.Add(std::to_string(supportedSampleRate));
98
+	auto sampleRateChoice = new wxChoice(this->outputPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, sampleRateChoices, 0, wxGenericValidator{ &this->sampleRate });
99
+	this->outputSizer->Add(sampleRateChoice, { 3, 1 }, { 1, 1 }, wxALL, 5);
100
+
101
+	notebook->AddPage(this->outputPanel, "Output");
102
+
103
+	auto titleFormatPanel = new wxPanel(notebook, wxID_ANY);
104
+	auto titleFormatSizer = new wxBoxSizer(wxVERTICAL);
105
+
106
+	auto titleFormatPreText = new wxStaticText(titleFormatPanel, wxID_ANY, "NOTE: This is only used if Advanced Title Formatting is disabled in Winamp.");
107
+	titleFormatPreText->Wrap(300);
108
+	titleFormatSizer->Add(titleFormatPreText, 0, wxALL, 5);
109
+
110
+	auto titleFormatTextCtrl = new wxTextCtrl(titleFormatPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, { 225, -1 }, 0, wxGenericValidator{ &this->titleFormat });
111
+	titleFormatSizer->Add(titleFormatTextCtrl, 0, wxALL, 5);
112
+
113
+	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. "
114
+		"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 "
115
+		"display nothing if disc was not in the tags). Square bracket blocks can be nested.");
116
+	titleFormatPostText->Wrap(300);
117
+	titleFormatSizer->Add(titleFormatPostText, 0, wxALL, 5);
118
+
119
+	titleFormatPanel->SetSizer(titleFormatSizer);
120
+	titleFormatPanel->Layout();
121
+	titleFormatSizer->Fit(titleFormatPanel);
122
+	notebook->AddPage(titleFormatPanel, "Title Format");
123
+
124
+	this->mainSizer->Add(notebook, { 0, 0 }, { 1, 2 }, wxALL | wxEXPAND, 5);
125
+
126
+	auto resetDefaults = new wxButton(this, idResetDefaults, "Reset Defaults");
127
+	this->mainSizer->Add(resetDefaults, { 1, 1 }, { 1, 1 }, wxALIGN_RIGHT | wxALL, 5);
128
+	this->Bind(wxEVT_BUTTON, [&](wxCommandEvent &)
129
+	{
130
+		this->config.ResetConfigDefaults(this);
131
+		this->TransferDataToWindow();
132
+	}, idResetDefaults);
133
+
134
+	auto standardButtons = new wxStdDialogButtonSizer;
135
+	auto standardButtonOK = new wxButton(this, wxID_OK);
136
+	standardButtons->AddButton(standardButtonOK);
137
+	auto standardButtonCancel = new wxButton(this, wxID_CANCEL);
138
+	standardButtons->AddButton(standardButtonCancel);
139
+	standardButtons->Realize();
140
+	this->mainSizer->Add(standardButtons, { 2, 0 }, { 1, 2 }, wxBOTTOM | wxEXPAND | wxTOP, 5);
141
+}
142
+
143
+void XSFConfigDialog::Finalize()
144
+{
145
+	this->generalPanel->SetSizer(this->generalSizer);
146
+	this->generalPanel->Layout();
147
+	this->generalSizer->Fit(this->generalPanel);
148
+
149
+	this->outputPanel->SetSizer(this->outputSizer);
150
+	this->outputPanel->Layout();
151
+	this->outputSizer->Fit(this->outputPanel);
152
+
153
+	this->SetSizer(this->mainSizer);
154
+	this->Layout();
155
+	this->mainSizer->Fit(this);
156
+}
0 157
new file mode 100644
... ...
@@ -0,0 +1,45 @@
1
+/*
2
+ * xSF - Core configuration dialog
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ *
5
+ * Partially based on the vio*sf framework
6
+ */
7
+
8
+#pragma once
9
+
10
+#include <wx/msw/winundef.h>
11
+#include <wx/dialog.h>
12
+#include <wx/string.h>
13
+
14
+class wxGridBagSizer;
15
+class wxPanel;
16
+class wxWindow;
17
+class XSFConfig;
18
+
19
+class XSFConfigDialog : public wxDialog
20
+{
21
+	inline static const std::string timeRegex = R"(^\d+(:[0-5]\d){0,2}([.,]\d+)?$)";
22
+
23
+	wxGridBagSizer *mainSizer;
24
+	XSFConfig &config;
25
+public:
26
+	XSFConfigDialog(XSFConfig &config, wxWindow *parent, const wxString &title);
27
+	void Finalize();
28
+
29
+	wxPanel *generalPanel;
30
+	wxGridBagSizer *generalSizer;
31
+
32
+	wxPanel *outputPanel;
33
+	wxGridBagSizer *outputSizer;
34
+
35
+	bool playInfinitely = false;
36
+	wxString defaultPlayLength;
37
+	wxString defaultFadeoutLength;
38
+	wxString skipSilenceOnStart;
39
+	wxString detectSilence;
40
+	double volume = 1;
41
+	int replayGain;
42
+	int clipProtect;
43
+	int sampleRate;
44
+	wxString titleFormat;
45
+};