Replace the Sound View dialog with a wxWidgets-based one.
Replace the Sound View dialog with a wxWidgets-based one.

* Removes the one that was orignally based entirely on the DeSmuME one, while still looking most the same but cleaner.
* To accommodate this, I needed to rework how wxWidgets was initialized so the configuration dialog boxes could also work alongside this.
* Needed to add a custom wxApp to handle the above.
* This also means that the configuration dialog no longer needs the plugin's HINSTANCE passed along.
* Had to not disable wxGauge or wxToogleButton for the Sound View dialog.
* Also remove the now-unneeded enums in the XSFConfig*.cpp files.
* Sound View is still done in a thread so its event loop can run independently from the rest of the plugin.
* XSFConfig_NCSF doesn't need to be the one to start the Sound View dialog now.

--- a/src/in_2sf/XSFConfig_2SF.cpp
+++ b/src/in_2sf/XSFConfig_2SF.cpp
@@ -10,6 +10,7 @@
 #include <string>
 #include <cstddef>
 #include "windowsh_wrapper.h"
+#include "XSFApp.h"
 #include "XSFConfig.h"
 #include "XSFConfig_2SF.h"
 #include "XSFConfigDialog_2SF.h"
@@ -21,15 +22,14 @@
 class XSFConfigDialog;
 class XSFPlayer;
 
-enum
-{
-	idInterpolation = 1000,
-	idMutes
-};
-
 const unsigned XSFConfig::initSampleRate = static_cast<unsigned>(DESMUME_SAMPLE_RATE);
 const std::string XSFConfig::commonName = "2SF Decoder";
 const std::string XSFConfig::versionNumber = "0.9b";
+
+XSFApp *XSFApp::Create()
+{
+	return new XSFApp();
+}
 
 XSFConfig *XSFConfig::Create()
 {

--- a/src/in_gsf/XSFConfig_GSF.cpp
+++ b/src/in_gsf/XSFConfig_GSF.cpp
@@ -10,6 +10,7 @@
 #include <string>
 #include <cstddef>
 #include "windowsh_wrapper.h"
+#include "XSFApp.h"
 #include "XSFConfig.h"
 #include "XSFConfig_GSF.h"
 #include "XSFConfigDialog_GSF.h"
@@ -20,15 +21,14 @@
 class XSFConfigDialog;
 class XSFPlayer;
 
-enum
-{
-	idLowPassFiltering = 1000,
-	idMutes
-};
-
 const unsigned XSFConfig::initSampleRate = 44100;
 const std::string XSFConfig::commonName = "GSF Decoder";
 const std::string XSFConfig::versionNumber = "0.9b";
+
+XSFApp *XSFApp::Create()
+{
+	return new XSFApp();
+}
 
 XSFConfig *XSFConfig::Create()
 {

--- a/src/in_ncsf/CMakeLists.txt
+++ b/src/in_ncsf/CMakeLists.txt
@@ -14,12 +14,11 @@
 	SSEQPlayer/SWAV.h
 	SSEQPlayer/SYMBSection.h
 	SSEQPlayer/Track.h
-	resource.h
+	SoundView.h
+	XSFApp_NCSF.h
 	XSFConfig_NCSF.h
 	XSFConfigDialog_NCSF.h
 	XSFPlayer_NCSF.h)
-set(RESOURCES
-	in_ncsf.rc)
 set(SOURCES
 	SSEQPlayer/Channel.cpp
 	SSEQPlayer/FATSection.cpp
@@ -34,14 +33,15 @@
 	SSEQPlayer/SWAV.cpp
 	SSEQPlayer/SYMBSection.cpp
 	SSEQPlayer/Track.cpp
+	SoundView.cpp
+	XSFApp_NCSF.cpp
 	XSFConfig_NCSF.cpp
 	XSFConfigDialog_NCSF.cpp
 	XSFPlayer_NCSF.cpp)
 
-add_library(in_ncsf SHARED ${HEADERS} ${RESOURCES} ${SOURCES})
+add_library(in_ncsf SHARED ${HEADERS} ${SOURCES})
 set_target_properties(in_ncsf PROPERTIES PREFIX "")
 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Header Files" FILES ${HEADERS})
-source_group("Resource Files" FILES ${RESOURCES})
 source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCES})
 target_compile_options(in_ncsf PUBLIC
 	$<$<CXX_COMPILER_ID:MSVC>:/wd6011 /wd6385 /wd26819>)

--- /dev/null
+++ b/src/in_ncsf/SoundView.cpp
@@ -1,1 +1,279 @@
-
+/*
+ * xSF - Sound View Dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ *
+ * Based on the Sound View dialog box from DeSmuME
+ * http://desmume.org/
+ */
+
+#include <string>
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wold-style-cast"
+#endif
+#include <wx/button.h>
+#include <wx/checkbox.h>
+#include <wx/dialog.h>
+#include <wx/event.h>
+#include <wx/gauge.h>
+#include <wx/gbsizer.h>
+#include <wx/sizer.h>
+#include <wx/stattext.h>
+#include <wx/tglbtn.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+#include "convert.h"
+#include "SoundView.h"
+#include "SSEQPlayer/common.h"
+#include "SSEQPlayer/consts.h"
+#include "XSFCommon.h"
+#include "XSFConfig_NCSF.h"
+#include "XSFPlayer_NCSF.h"
+
+class wxWindow;
+
+enum
+{
+	idVolumeMode = 1,
+	idUnmuteAll,
+	idChannel00Mute
+};
+
+// Idea comes from https://derekwill.com/2014/06/24/combating-the-lag-of-the-winforms-progressbar/
+void SoundView::GaugeSetValueImmediate(wxGauge *gauge, int value)
+{
+	// This whole thing is to get around the progressive animation of progress bars since Windows Vista
+	if (value == gauge->GetRange())
+	{
+		// When the value equals the maximum, we have to temporarily increase the maximum before setting the value
+		gauge->SetRange(value + 1);
+		gauge->SetValue(value);
+		gauge->SetRange(value);
+	}
+	else
+		gauge->SetValue(value + 1);
+	gauge->SetValue(value);
+}
+
+SoundView::SoundView(wxWindow *parent, XSFConfig_NCSF *ncsfConfig, XSFPlayer_NCSF *ncsfPlayer) : wxDialog(parent, wxID_ANY, "Sound View"), config(ncsfConfig), player(ncsfPlayer), channelData(), volumeModeAlternative(false)
+{
+	auto outerSizer = new wxBoxSizer(wxVERTICAL);
+
+	auto mainSizer = new wxGridBagSizer;
+
+	auto volumeModeButton = new wxToggleButton(this, idVolumeMode, "Vol. Mode");
+	mainSizer->Add(volumeModeButton, { 0 ,0 }, { 1, 2 }, wxALIGN_LEFT | wxBOTTOM | wxLEFT, 5);
+	this->Bind(wxEVT_TOGGLEBUTTON, [&](wxCommandEvent &)
+	{
+		this->volumeModeAlternative = !this->volumeModeAlternative;
+	}, idVolumeMode);
+
+	auto unmuteAllButton = new wxButton(this, idUnmuteAll, "Unmute All");
+	mainSizer->Add(unmuteAllButton, { 0, 5 }, { 1, 1 }, wxALIGN_RIGHT | wxBOTTOM | wxRIGHT, 5);
+	this->Bind(wxEVT_BUTTON, [&](wxCommandEvent &)
+	{
+		for (int i = 0; i < 16; ++i)
+			this->channelData[i].muteCheckBox->SetValue(false);
+		this->config->mutes.reset();
+		this->config->SaveConfig();
+		this->player->SetMutes(this->config->mutes);
+	}, idUnmuteAll);
+
+	outerSizer->Add(mainSizer, 1, wxALL | wxEXPAND, 10);
+
+	for (int i = 0; i < 2; ++i)
+	{
+		auto volumeLabel = new wxStaticText(this, wxID_ANY, "Volume", wxDefaultPosition, { 150, -1 }, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(volumeLabel, { 1, 7 * i + 1 }, { 1, 2 }, wxALL, 1);
+
+		auto repeatModeLabel = new wxStaticText(this, wxID_ANY, "Repeat Mode", wxDefaultPosition, { 108, -1 }, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(repeatModeLabel, { 1, 7 * i + 3 }, { 1, 1 }, wxALL, 1);
+
+		auto stateLabel = new wxStaticText(this, wxID_ANY, "State", wxDefaultPosition, { 90, -1 }, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(stateLabel, { 1, 7 * i + 4 }, { 1, 1 }, wxALL, 1);
+
+		auto timerValueLabel = new wxStaticText(this, wxID_ANY, "Timer Value", wxDefaultPosition, { 132, -1 }, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(timerValueLabel, { 1, 7 * i + 5 }, { 1, 1 }, wxALL, 1);
+
+		auto panLabel = new wxStaticText(this, wxID_ANY, "Pan", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(panLabel, { 2, 7 * i + 1 }, { 1, 2 }, wxALL | wxEXPAND, 1);
+
+		auto formatLabel = new wxStaticText(this, wxID_ANY, "Format", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(formatLabel, { 2, 7 * i + 3 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+		auto loopStartLabel = new wxStaticText(this, wxID_ANY, "Loop Start", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(loopStartLabel, { 2, 7 * i + 4 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+		auto soundPosLenLabel = new wxStaticText(this, wxID_ANY, "Sound Pos / Len", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC);
+		mainSizer->Add(soundPosLenLabel, { 2, 7 * i + 5 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+	}
+
+	for (int i = 0; i < 8; ++i)
+		for (int j = 0; j < 2; ++j)
+		{
+			int channelNum = 8 * j + i;
+			auto channelLabel = new wxStaticText(this, wxID_ANY, std::string("#") + (channelNum < 10 ? "0" : "") + std::to_string(channelNum));
+			mainSizer->Add(channelLabel, { 2 * i + 3, 7 * j }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 1);
+
+			auto &currentChannelData = this->channelData[channelNum];
+
+			currentChannelData.volumeGauge = new wxGauge(this, wxID_ANY, 128, wxDefaultPosition, { 102, 18 }, wxGA_SMOOTH);
+			mainSizer->Add(currentChannelData.volumeGauge, { 2 * i + 3, 7 * j + 1 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 1);
+
+			currentChannelData.volumeLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.volumeLabel, { 2 * i + 3, 7 * j + 2 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+			currentChannelData.repeatModeLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.repeatModeLabel, { 2 * i + 3, 7 * j + 3 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+			currentChannelData.stateLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.stateLabel, { 2 * i + 3, 7 * j + 4 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+			currentChannelData.timerValueLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.timerValueLabel, { 2 * i + 3, 7 * j + 5 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+			currentChannelData.muteCheckBox = new wxCheckBox(this, idChannel00Mute + channelNum, wxEmptyString);
+			mainSizer->Add(currentChannelData.muteCheckBox, { 2 * i + 4, 7 * j }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 1);
+			this->Bind(wxEVT_CHECKBOX, [this, currentChannelData, channelNum](wxCommandEvent &)
+			{
+				this->config->mutes[channelNum] = currentChannelData.muteCheckBox->GetValue();
+				this->config->SaveConfig();
+				this->player->SetMutes(this->config->mutes);
+			}, idChannel00Mute + channelNum);
+
+			currentChannelData.panGauge = new wxGauge(this, wxID_ANY, 128, wxDefaultPosition, { 102, 18 }, wxGA_SMOOTH);
+			mainSizer->Add(currentChannelData.panGauge, { 2 * i + 4, 7 * j + 1 }, { 1, 1 }, wxALIGN_CENTER_VERTICAL | wxALL, 1);
+
+			currentChannelData.panLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.panLabel, { 2 * i + 4, 7 * j + 2 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+			currentChannelData.formatLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.formatLabel, { 2 * i + 4, 7 * j + 3 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+			currentChannelData.loopStartLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.loopStartLabel, { 2 * i + 4, 7 * j + 4 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+
+			currentChannelData.soundPosLenLabel = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL | wxBORDER_STATIC | wxST_NO_AUTORESIZE);
+			mainSizer->Add(currentChannelData.soundPosLenLabel, { 2 * i + 4, 7 * j + 5 }, { 1, 1 }, wxALL | wxEXPAND, 1);
+		}
+
+	this->SetSizer(outerSizer);
+	this->Layout();
+	outerSizer->Fit(this);
+
+	this->Center();
+
+	this->SyncToConfig();
+	this->Bind(wxEVT_IDLE, &SoundView::OnIdle, this);
+}
+
+void SoundView::OnIdle(wxIdleEvent &evt)
+{
+	this->Refresh();
+	evt.RequestMore();
+}
+
+void SoundView::Refresh()
+{
+	auto ncsfPlayer = this->player;
+	std::string buf;
+	for (std::size_t chanId = 0; chanId < 16; ++chanId)
+	{
+		const auto &chn = ncsfPlayer->GetChannel(chanId);
+		auto &chnData = this->channelData[chanId];
+
+		if (chn.state > ChannelState::Start)
+		{
+			this->GaugeSetValueImmediate(chnData.panGauge, muldiv7(128, chn.reg.panning));
+			std::uint8_t datashift = chn.reg.volumeDiv;
+			if (datashift == 3)
+				datashift = 4;
+			std::int32_t vol = muldiv7(128, chn.reg.volumeMul) >> datashift;
+			this->GaugeSetValueImmediate(chnData.volumeGauge, vol);
+
+			if (this->volumeModeAlternative)
+				buf = std::to_string(chn.reg.volumeMul) + "/" + std::to_string(1 << datashift);
+			else
+				buf = std::to_string(vol);
+			chnData.volumeLabel->SetLabel(buf);
+
+			if (!chn.reg.panning)
+				buf = "L";
+			else if (chn.reg.panning == 64)
+				buf = "C";
+			else if (chn.reg.panning == 127)
+				buf = "R";
+			else if (chn.reg.panning < 64)
+				buf = "L" + std::to_string(64 - chn.reg.panning);
+			else //if (chn.reg.panning > 64)
+				buf = "R" + std::to_string(chn.reg.panning - 64);
+			chnData.panLabel->SetLabel(buf);
+
+			static const std::string modes[] = { "Manual", "Loop Infinite", "One-Shot", "Prohibited" };
+			chnData.repeatModeLabel->SetLabel(std::to_string(chn.reg.repeatMode) + " (" + modes[chn.reg.repeatMode] + ")");
+
+			if (chn.reg.format != 3)
+			{
+				static const std::string formats[] = { "PCM8", "PCM16", "IMA-ADPCM" };
+				chnData.formatLabel->SetLabel(std::to_string(chn.reg.format) + " (" + formats[chn.reg.format] + ")");
+			}
+			else
+			{
+				buf = "3 (";
+				if (chanId < 8)
+					buf += "PSG/Noise?";
+				else if (chanId < 14)
+					buf += ConvertFuncs::TrimDoubleString(std::to_string(chn.reg.waveDuty == 7 ? 0 : 12.5 * (chn.reg.waveDuty + 1))) + "% Square";
+				else
+					buf += "Noise";
+				buf += ")";
+				chnData.formatLabel->SetLabel(buf);
+			}
+
+			static const std::string states[] = { "NONE", "START", "ATTACK", "DECAY", "SUSTAIN", "RELEASE" };
+			chnData.stateLabel->SetLabel(states[ConvertFuncs::ToIntegral(chn.state)]);
+
+			chnData.loopStartLabel->SetLabel("samp #" + std::to_string(chn.reg.loopStart));
+
+			std::string tmpBuf = NumToHexString(chn.reg.timer).substr(2);
+			buf = "$" + tmpBuf + " (";
+			tmpBuf = ConvertFuncs::TrimDoubleString(std::to_string((ARM7_CLOCK / 2) / static_cast<double>(0x10000 - chn.reg.timer) / 8));
+			if (tmpBuf.find('.') != std::string::npos)
+				tmpBuf = tmpBuf.substr(0, tmpBuf.find('.') + 2);
+			buf += tmpBuf + " Hz)";
+			chnData.timerValueLabel->SetLabel(buf);
+
+			chnData.soundPosLenLabel->SetLabel("samp #" + std::to_string(static_cast<std::uint32_t>(chn.reg.samplePosition)) + " / " + std::to_string(chn.reg.totalLength));
+		}
+		else if (chnData.lastState != ChannelState::None)
+		{
+			chnData.panGauge->SetValue(0);
+			chnData.volumeGauge->SetValue(0);
+			chnData.volumeLabel->SetLabel("---");
+			chnData.panLabel->SetLabel("---");
+			chnData.repeatModeLabel->SetLabel("---");
+			chnData.formatLabel->SetLabel("---");
+			chnData.stateLabel->SetLabel("NONE");
+			chnData.loopStartLabel->SetLabel("---");
+			chnData.timerValueLabel->SetLabel("---");
+			chnData.soundPosLenLabel->SetLabel("---");
+		}
+
+		chnData.lastState = chn.state;
+	}
+}
+
+void SoundView::SyncToConfig()
+{
+	for (int i = 0; i < 16; ++i)
+		this->channelData[i].muteCheckBox->SetValue(this->config->mutes[i]);
+}
+

--- /dev/null
+++ b/src/in_ncsf/SoundView.h
@@ -1,1 +1,66 @@
+/*
+ * xSF - Sound View Dialog
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ *
+ * Based on the Sound View dialog box from DeSmuME
+ * http://desmume.org/
+ */
 
+#pragma once
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wold-style-cast"
+#endif
+#include <wx/dialog.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+#include "SSEQPlayer/consts.h"
+
+class wxCheckBox;
+class wxGauge;
+class wxIdleEvent;
+class wxStaticText;
+class wxWindow;
+class XSFConfig_NCSF;
+class XSFPlayer_NCSF;
+
+struct SoundViewData
+{
+	wxGauge *volumeGauge = nullptr;
+	wxStaticText *volumeLabel = nullptr;
+	wxStaticText *repeatModeLabel = nullptr;
+	wxStaticText *stateLabel = nullptr;
+	wxStaticText *timerValueLabel = nullptr;
+	wxCheckBox *muteCheckBox = nullptr;
+	wxGauge *panGauge = nullptr;
+	wxStaticText *panLabel = nullptr;
+	wxStaticText *formatLabel = nullptr;
+	wxStaticText *loopStartLabel = nullptr;
+	wxStaticText *soundPosLenLabel = nullptr;
+	ChannelState lastState = ChannelState::Start;
+};
+
+class SoundView : public wxDialog
+{
+	void GaugeSetValueImmediate(wxGauge *gauge, int value);
+public:
+	SoundView(wxWindow *parent, XSFConfig_NCSF *ncsfConfig, XSFPlayer_NCSF *ncsfPlayer);
+	void OnIdle(wxIdleEvent &evt);
+	void Refresh();
+	void SyncToConfig();
+
+	XSFConfig_NCSF *config;
+	XSFPlayer_NCSF *player;
+	SoundViewData channelData[16];
+	bool volumeModeAlternative;
+};
+

--- /dev/null
+++ b/src/in_ncsf/XSFApp_NCSF.cpp
@@ -1,1 +1,31 @@
+/*
+ * xSF - NCSF wxWidgets App
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
 
+#include "SoundView.h"
+#include "XSFApp_NCSF.h"
+
+class XSFConfig_NCSF;
+class XSFPlayer_NCSF;
+
+void XSFApp_NCSF::CreateSoundView(XSFConfig_NCSF *config, XSFPlayer_NCSF *player)
+{
+	this->dialog = new SoundView(nullptr, config, player);
+	this->dialog->ShowModal();
+}
+
+void XSFApp_NCSF::SyncSoundViewToConfig()
+{
+	if (this->dialog)
+		this->dialog->SyncToConfig();
+}
+
+void XSFApp_NCSF::DestroySoundView()
+{
+	this->dialog->Destroy();
+	this->dialog = nullptr;
+}
+

--- /dev/null
+++ b/src/in_ncsf/XSFApp_NCSF.h
@@ -1,1 +1,24 @@
+/*
+ * xSF - NCSF wxWidgets App
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
 
+#pragma once
+
+#include "XSFApp.h"
+
+class SoundView;
+class XSFConfig_NCSF;
+class XSFPlayer_NCSF;
+
+class XSFApp_NCSF : public XSFApp
+{
+	SoundView *dialog;
+public:
+	void CreateSoundView(XSFConfig_NCSF *config, XSFPlayer_NCSF *player);
+	void SyncSoundViewToConfig();
+	void DestroySoundView();
+};
+

--- a/src/in_ncsf/XSFConfig_NCSF.cpp
+++ b/src/in_ncsf/XSFConfig_NCSF.cpp
@@ -11,37 +11,33 @@
 #include <cstddef>
 #include <cstdint>
 #include "windowsh_wrapper.h"
-#include <windowsx.h>
-#include <CommCtrl.h>
-#include "SSEQPlayer/common.h"
-#include "SSEQPlayer/consts.h"
+#include "XSFApp.h"
+#include "XSFApp_NCSF.h"
 #include "XSFConfig.h"
 #include "XSFConfig_NCSF.h"
 #include "XSFConfigDialog_NCSF.h"
 #include "XSFPlayer_NCSF.h"
 #include "convert.h"
-#include "resource.h"
 
 class wxWindow;
 class XSFConfigDialog;
 class XSFPlayer;
 
-enum
-{
-	idInterpolation = 1000,
-	idMutes
-};
-
 const unsigned XSFConfig::initSampleRate = 44100;
 const std::string XSFConfig::commonName = "NCSF Decoder";
 const std::string XSFConfig::versionNumber = "1.11.1";
+
+XSFApp *XSFApp::Create()
+{
+	return new XSFApp_NCSF();
+}
 
 XSFConfig *XSFConfig::Create()
 {
 	return new XSFConfig_NCSF();
 }
 
-XSFConfig_NCSF::XSFConfig_NCSF() : XSFConfig(), interpolation(0), mutes(), useSoundViewDialog(false), soundViewData()
+XSFConfig_NCSF::XSFConfig_NCSF() : XSFConfig(), interpolation(0), mutes(), useSoundViewDialog(false)
 {
 	this->supportedSampleRates.push_back(8000);
 	this->supportedSampleRates.push_back(11025);
@@ -93,6 +89,8 @@
 			ncsfDialog->mute.Add(x);
 }
 
+extern std::unique_ptr<XSFApp> xSFApp;
+
 void XSFConfig_NCSF::SaveSpecificConfigDialog(XSFConfigDialog *dialog)
 {
 	auto ncsfDialog = static_cast<XSFConfigDialog_NCSF *>(dialog);
@@ -100,6 +98,7 @@
 	this->interpolation = ncsfDialog->interpolation;
 	for (std::size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
 		this->mutes[x] = ncsfDialog->mute.Index(x) != wxNOT_FOUND;
+	static_cast<XSFApp_NCSF *>(xSFApp.get())->SyncSoundViewToConfig();
 }
 
 void XSFConfig_NCSF::CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool)
@@ -121,212 +120,3 @@
 	return new XSFConfigDialog_NCSF(*this, window, title);
 }
 
-INT_PTR CALLBACK XSFConfig_NCSF::SoundViewDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
-	auto data = reinterpret_cast<SoundViewData *>(GetWindowLongW(hwndDlg, DWLP_USER));
-	if (!data && uMsg != WM_INITDIALOG)
-		return false;
-
-	switch (uMsg)
-	{
-		case WM_INITDIALOG:
-			if (!data)
-			{
-				data = reinterpret_cast<SoundViewData *>(lParam);
-				SetWindowLongW(hwndDlg, DWLP_USER, reinterpret_cast<LONG>(data));
-			}
-			data->hDlg = hwndDlg;
-			for (int chanId = 0; chanId < 16; ++chanId)
-			{
-				SendDlgItemMessageW(hwndDlg, IDC_SOUND0VOLBAR + chanId, PBM_SETRANGE, 0, MAKELPARAM(0, 128));
-				SendDlgItemMessageW(hwndDlg, IDC_SOUND0PANBAR + chanId, PBM_SETRANGE, 0, MAKELPARAM(0, 128));
-				SendDlgItemMessageW(hwndDlg, IDC_SOUND0MUTE + chanId, BM_SETCHECK, data->config->mutes[chanId], 0);
-			}
-			break;
-		case WM_CLOSE:
-		case WM_DESTROY:
-			data->config->CloseSoundView();
-			break;
-		case WM_COMMAND:
-			{
-				auto id = GET_WM_COMMAND_ID(wParam, lParam);
-				switch (id)
-				{
-					case IDC_BUTTON_VOLMODE:
-						data->volModeAlternative = !!IsDlgButtonChecked(hwndDlg, IDC_BUTTON_VOLMODE);
-						break;
-					case IDC_SOUND0MUTE:
-					case IDC_SOUND1MUTE:
-					case IDC_SOUND2MUTE:
-					case IDC_SOUND3MUTE:
-					case IDC_SOUND4MUTE:
-					case IDC_SOUND5MUTE:
-					case IDC_SOUND6MUTE:
-					case IDC_SOUND7MUTE:
-					case IDC_SOUND8MUTE:
-					case IDC_SOUND9MUTE:
-					case IDC_SOUND10MUTE:
-					case IDC_SOUND11MUTE:
-					case IDC_SOUND12MUTE:
-					case IDC_SOUND13MUTE:
-					case IDC_SOUND14MUTE:
-					case IDC_SOUND15MUTE:
-						data->config->mutes[id - IDC_SOUND0MUTE] = !!IsDlgButtonChecked(hwndDlg, id);
-						data->config->SaveConfig();
-						data->player->SetMutes(data->config->mutes);
-						break;
-					case IDC_SOUND_UNMUTE_ALL:
-						for (int chanId = 0; chanId < 16; ++chanId)
-							SendDlgItemMessageW(hwndDlg, IDC_SOUND0MUTE + chanId, BM_SETCHECK, false, 0);
-						data->config->mutes.reset();
-						data->config->SaveConfig();
-						data->player->SetMutes(data->config->mutes);
-						break;
-					default:
-						return false;
-				}
-			}
-			break;
-		default:
-			return false;
-	}
-
-	return true;
-}
-
-void XSFConfig_NCSF::CallSoundView(XSFPlayer *xSFPlayer, HINSTANCE hInstance, HWND hwndParent)
-{
-	this->soundViewData.reset(new SoundViewData);
-	this->soundViewData->config = this;
-	this->soundViewData->player = static_cast<XSFPlayer_NCSF *>(xSFPlayer);
-
-	auto hDlg = CreateDialogParamW(hInstance, MAKEINTRESOURCEW(IDD_SOUND_VIEW), hwndParent, XSFConfig_NCSF::SoundViewDialogProc, reinterpret_cast<LPARAM>(this->soundViewData.get()));
-	if (!hDlg)
-	{
-		this->soundViewData.reset();
-		return;
-	}
-
-	ShowWindow(hDlg, SW_SHOW);
-	UpdateWindow(hDlg);
-}
-
-static inline void ProgressSetPosImmediate(HWND hDlg, int nIDDlgItem, int nPos)
-{
-	int nMin = SendDlgItemMessageW(hDlg, nIDDlgItem, PBM_GETRANGE, true, reinterpret_cast<LPARAM>(nullptr));
-	int nMax = SendDlgItemMessageW(hDlg, nIDDlgItem, PBM_GETRANGE, false, reinterpret_cast<LPARAM>(nullptr));
-
-	// get rid of fancy progress animation since Windows Vista
-	// http://stackoverflow.com/questions/1061715/how-do-i-make-tprogressbar-stop-lagging
-	if (nPos < nMax)
-	{
-		SendDlgItemMessageW(hDlg, nIDDlgItem, PBM_SETPOS, nPos + 1, 0);
-		SendDlgItemMessageW(hDlg, nIDDlgItem, PBM_SETPOS, nPos, 0); // This will set Progress backwards and give an instant update
-	}
-	else
-	{
-		SendDlgItemMessageW(hDlg, nIDDlgItem, PBM_SETRANGE32, nMin, nPos + 1);
-		SendDlgItemMessageW(hDlg, nIDDlgItem, PBM_SETPOS, nPos + 1, 0);
-		SendDlgItemMessageW(hDlg, nIDDlgItem, PBM_SETRANGE32, nMin, nPos); // This will also set Progress backwards also so instant update
-	}
-}
-
-void XSFConfig_NCSF::RefreshSoundView()
-{
-	auto player = this->soundViewData->player;
-	auto hDlg = this->soundViewData->hDlg;
-	std::wstring buf;
-	for (std::size_t chanId = 0; chanId < 16; ++chanId)
-	{
-		const auto &chn = player->GetChannel(chanId);
-
-		if (chn.state > ChannelState::Start)
-		{
-			ProgressSetPosImmediate(hDlg, IDC_SOUND0PANBAR + chanId, muldiv7(128, chn.reg.panning));
-			std::uint8_t datashift = chn.reg.volumeDiv;
-			if (datashift == 3)
-				datashift = 4;
-			std::int32_t vol = muldiv7(128, chn.reg.volumeMul) >> datashift;
-			ProgressSetPosImmediate(hDlg, IDC_SOUND0VOLBAR + chanId, vol);
-
-			if (this->soundViewData->volModeAlternative)
-				buf = std::to_wstring(chn.reg.volumeMul) + L"/" + std::to_wstring(1 << datashift);
-			else
-				buf = std::to_wstring(vol);
-			SetDlgItemTextW(hDlg, IDC_SOUND0VOL + chanId, buf.c_str());
-
-			if (!chn.reg.panning)
-				buf = L"L";
-			else if (chn.reg.panning == 64)
-				buf = L"C";
-			else if (chn.reg.panning == 127)
-				buf = L"R";
-			else if (chn.reg.panning < 64)
-				buf = L"L" + std::to_wstring(64 - chn.reg.panning);
-			else //if (chn.reg.panning > 64)
-				buf = L"R" + std::to_wstring(chn.reg.panning - 64);
-			SetDlgItemTextW(hDlg, IDC_SOUND0PAN + chanId, buf.c_str());
-
-			static const std::wstring modes[] = { L"Manual", L"Loop Infinite", L"One-Shot", L"Prohibited" };
-			SetDlgItemTextW(hDlg, IDC_SOUND0REPEATMODE + chanId, (std::to_wstring(chn.reg.repeatMode) + L" (" + modes[chn.reg.repeatMode] + L")").c_str());
-
-			if (chn.reg.format != 3)
-			{
-				static const std::wstring formats[] = { L"PCM8", L"PCM16", L"IMA-ADPCM" };
-				SetDlgItemTextW(hDlg, IDC_SOUND0FORMAT + chanId, (std::to_wstring(chn.reg.format) + L" (" + formats[chn.reg.format] + L")").c_str());
-			}
-			else
-			{
-				buf = L"3 (";
-				if (chanId < 8)
-					buf += L"PSG/Noise?";
-				else if (chanId < 14)
-					buf += ConvertFuncs::TrimDoubleString(std::to_wstring(chn.reg.waveDuty == 7 ? 0 : 12.5 * (chn.reg.waveDuty + 1))) + L"% Square";
-				else
-					buf += L"Noise";
-				buf += L")";
-				SetDlgItemTextW(hDlg, IDC_SOUND0FORMAT + chanId, buf.c_str());
-			}
-
-			static const std::wstring states[] = { L"NONE", L"START", L"ATTACK", L"DECAY", L"SUSTAIN", L"RELEASE" };
-			SetDlgItemTextW(hDlg, IDC_SOUND0STATE + chanId, states[ConvertFuncs::ToIntegral(chn.state)].c_str());
-
-			SetDlgItemTextW(hDlg, IDC_SOUND0PNT + chanId, (L"samp #" + std::to_wstring(chn.reg.loopStart)).c_str());
-
-			std::wstring tmpBuf = ConvertFuncs::StringToWString(NumToHexString(chn.reg.timer)).substr(2);
-			buf = L"$" + tmpBuf + L" (";
-			tmpBuf = ConvertFuncs::TrimDoubleString(std::to_wstring((ARM7_CLOCK / 2) / static_cast<double>(0x10000 - chn.reg.timer) / 8));
-			if (tmpBuf.find('.') != std::wstring::npos)
-				tmpBuf = tmpBuf.substr(0, tmpBuf.find('.') + 2);
-			buf += tmpBuf + L" Hz)";
-			SetDlgItemTextW(hDlg, IDC_SOUND0TMR + chanId, buf.c_str());
-
-			SetDlgItemTextW(hDlg, IDC_SOUND0POSLEN + chanId, (L"samp #" + std::to_wstring(static_cast<std::uint32_t>(chn.reg.samplePosition)) + L" / " + std::to_wstring(chn.reg.totalLength)).c_str());
-		}
-		else if (this->soundViewData->channelLastStates[chanId] != ChannelState::None)
-		{
-			ProgressSetPosImmediate(hDlg, IDC_SOUND0PANBAR + chanId, 0);
-			ProgressSetPosImmediate(hDlg, IDC_SOUND0VOLBAR + chanId, 0);
-			SetDlgItemTextW(hDlg, IDC_SOUND0VOL + chanId, L"---");
-			SetDlgItemTextW(hDlg, IDC_SOUND0PAN + chanId, L"---");
-			SetDlgItemTextW(hDlg, IDC_SOUND0REPEATMODE + chanId, L"---");
-			SetDlgItemTextW(hDlg, IDC_SOUND0FORMAT + chanId, L"---");
-			SetDlgItemTextW(hDlg, IDC_SOUND0STATE + chanId, L"NONE");
-			SetDlgItemTextW(hDlg, IDC_SOUND0PNT + chanId, L"---");
-			SetDlgItemTextW(hDlg, IDC_SOUND0TMR + chanId, L"---");
-			SetDlgItemTextW(hDlg, IDC_SOUND0POSLEN + chanId, L"---");
-		}
-
-		this->soundViewData->channelLastStates[chanId] = chn.state;
-	}
-}
-
-void XSFConfig_NCSF::CloseSoundView()
-{
-	if (this->soundViewData)
-	{
-		DestroyWindow(this->soundViewData->hDlg);
-		this->soundViewData.reset();
-	}
-}
-

--- a/src/in_ncsf/XSFConfig_NCSF.h
+++ b/src/in_ncsf/XSFConfig_NCSF.h
@@ -16,26 +16,11 @@
 #include "SSEQPlayer/consts.h"
 #include "XSFConfig.h"
 
+class SoundView;
 class wxWindow;
 class XSFConfig_NCSF;
 class XSFConfigDialog;
 class XSFPlayer;
-class XSFPlayer_NCSF;
-
-struct SoundViewData
-{
-	XSFConfig_NCSF *config;
-	XSFPlayer_NCSF *player;
-	ChannelState channelLastStates[16];
-	HWND hDlg;
-
-	bool volModeAlternative;
-
-	SoundViewData() : config(nullptr), player(nullptr), hDlg(nullptr), volModeAlternative(false)
-	{
-		std::fill_n(&this->channelLastStates[0], sizeof(this->channelLastStates), ChannelState::Start);
-	}
-};
 
 class XSFConfig_NCSF : public XSFConfig
 {
@@ -51,9 +36,11 @@
 	inline static const std::string initMutes = "0000000000000000";
 
 	friend class XSFConfig;
-	friend struct SoundViewData;
+	friend struct SoundViewDataOLD;
+	friend class SoundView;
 	unsigned interpolation;
 	std::bitset<16> mutes;
+	bool useSoundViewDialog;
 
 	XSFConfig_NCSF();
 	void LoadSpecificConfig() override;
@@ -62,17 +49,8 @@
 	void ResetSpecificConfigDefaults(XSFConfigDialog *dialog) override;
 	void SaveSpecificConfigDialog(XSFConfigDialog *dialog) override;
 	void CopySpecificConfigToMemory(XSFPlayer *xSFPlayer, bool preLoad) override;
-
-	bool useSoundViewDialog;
-	std::unique_ptr<SoundViewData> soundViewData;
-
-	static INT_PTR CALLBACK SoundViewDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 public:
 	void About(HWND parent) override;
 	XSFConfigDialog *CreateDialogBox(wxWindow *window, const std::string &title) override;
-
-	void CallSoundView(XSFPlayer *xSFPlayer, HINSTANCE hInstance, HWND hwndParent);
-	void RefreshSoundView();
-	void CloseSoundView();
 };
 

--- a/src/in_ncsf/XSFPlayer_NCSF.cpp
+++ b/src/in_ncsf/XSFPlayer_NCSF.cpp
@@ -18,19 +18,35 @@
 #include <vector>
 #include <cstddef>
 #include <cstdint>
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wold-style-cast"
+#endif
+#include <wx/app.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
 #include <zlib.h>
+#include "SSEQPlayer/common.h"
+#include "SSEQPlayer/consts.h"
+#include "SSEQPlayer/Player.h"
+#include "SSEQPlayer/SDAT.h"
+#include "XSFApp.h"
+#include "XSFApp_NCSF.h"
 #include "XSFCommon.h"
 #include "XSFConfig_NCSF.h"
 #include "XSFPlayer_NCSF.h"
-#include "SSEQPlayer/SDAT.h"
-#include "SSEQPlayer/Player.h"
-#include "SSEQPlayer/common.h"
-#include "SSEQPlayer/consts.h"
 
 const char *XSFPlayer::WinampDescription = "NCSF Decoder";
 const char *XSFPlayer::WinampExts = "ncsf;minincsf\0DS Nitro Composer Sound Format files (*.ncsf;*.minincsf)\0";
 
 extern std::unique_ptr<XSFConfig> xSFConfig;
+extern std::unique_ptr<XSFApp> xSFApp;
 
 XSFPlayer *XSFPlayer::Create(const std::filesystem::path &path)
 {
@@ -105,23 +121,10 @@
 }
 
 static std::unique_ptr<std::thread> soundViewThreadHandle;
-static std::atomic_bool killSoundViewThread;
 
 static void soundViewThread(XSFPlayer_NCSF *player)
 {
-	auto xSFConfig_NCSF = static_cast<XSFConfig_NCSF *>(xSFConfig.get());
-	xSFConfig_NCSF->CallSoundView(player, xSFConfig->GetHInstance(), nullptr);
-	MSG msg;
-	while (!killSoundViewThread)
-	{
-		xSFConfig_NCSF->RefreshSoundView();
-		if (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
-		{
-			TranslateMessage(&msg);
-			DispatchMessageW(&msg);
-		}
-	}
-	xSFConfig_NCSF->CloseSoundView();
+	static_cast<XSFApp_NCSF *>(xSFApp.get())->CreateSoundView(static_cast<XSFConfig_NCSF *>(xSFConfig.get()), player);
 }
 
 XSFPlayer_NCSF::~XSFPlayer_NCSF()
@@ -135,10 +138,7 @@
 		return false;
 
 	if (this->useSoundViewDialog)
-	{
-		killSoundViewThread = false;
 		soundViewThreadHandle.reset(new std::thread(soundViewThread, this));
-	}
 
 	PseudoFile file;
 	file.data = &this->sdatData;
@@ -210,9 +210,12 @@
 {
 	this->player.Stop(true);
 
-	killSoundViewThread = true;
-	soundViewThreadHandle->join();
-	soundViewThreadHandle.reset();
+	if (soundViewThreadHandle)
+	{
+		static_cast<XSFApp_NCSF *>(xSFApp.get())->DestroySoundView();
+		soundViewThreadHandle->join();
+		soundViewThreadHandle.reset();
+	}
 }
 
 void XSFPlayer_NCSF::SetUseSoundViewDialog(bool newUseSoundViewDialog)

--- a/src/in_ncsf/XSFPlayer_NCSF.h
+++ b/src/in_ncsf/XSFPlayer_NCSF.h
@@ -17,9 +17,9 @@
 #include <vector>
 #include <cstddef>
 #include <cstdint>
+#include "SSEQPlayer/Player.h"
+#include "SSEQPlayer/SDAT.h"
 #include "XSFPlayer.h"
-#include "SSEQPlayer/SDAT.h"
-#include "SSEQPlayer/Player.h"
 
 class XSFFile;
 

file:a/src/in_ncsf/in_ncsf.rc (deleted)
--- a/src/in_ncsf/in_ncsf.rc
+++ /dev/null
@@ -1,302 +1,1 @@
-// Microsoft Visual C++ generated resource script.

-//

-#include "resource.h"

-

-#define APSTUDIO_READONLY_SYMBOLS

-/////////////////////////////////////////////////////////////////////////////

-//

-// Generated from the TEXTINCLUDE 2 resource.

-//

-#include "afxres.h"

-

-/////////////////////////////////////////////////////////////////////////////

-#undef APSTUDIO_READONLY_SYMBOLS

-

-/////////////////////////////////////////////////////////////////////////////

-// English (United States) resources

-

-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

-

-#ifdef APSTUDIO_INVOKED

-/////////////////////////////////////////////////////////////////////////////

-//

-// TEXTINCLUDE

-//

-

-1 TEXTINCLUDE

-BEGIN

-    "resource.h\0"

-END

-

-2 TEXTINCLUDE

-BEGIN

-    "#include ""afxres.h""\r\n"

-    "\0"

-END

-

-3 TEXTINCLUDE

-BEGIN

-    "\r\n"

-    "\0"

-END

-

-#endif    // APSTUDIO_INVOKED

-

-

-/////////////////////////////////////////////////////////////////////////////

-//

-// Dialog

-//

-

-IDD_SOUND_VIEW DIALOGEX 0, 0, 718, 269

-STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU

-CAPTION "Sound View"

-FONT 8, "Ms Shell Dlg 2", 0, 0, 0x0

-BEGIN

-    CTEXT           "Volume",IDC_STATIC,30,22,100,11,0,WS_EX_STATICEDGE

-    CTEXT           "Pan",IDC_STATIC,30,34,100,11,0,WS_EX_STATICEDGE

-    CTEXT           "Repeat Mode",IDC_STATIC,131,22,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "Format",IDC_STATIC,131,34,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "State",IDC_STATIC,204,22,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "Loop Start",IDC_STATIC,204,34,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "Timer Value",IDC_STATIC,265,22,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "Sound Pos / Len",IDC_STATIC,265,34,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "Volume",IDC_STATIC,381,22,100,11,0,WS_EX_STATICEDGE

-    CTEXT           "Pan",IDC_STATIC,381,34,100,11,0,WS_EX_STATICEDGE

-    CTEXT           "Repeat Mode",IDC_STATIC,482,22,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "Format",IDC_STATIC,482,34,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "State",IDC_STATIC,555,22,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "Loop Start",IDC_STATIC,555,34,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "Timer Value",IDC_STATIC,616,22,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "Sound Pos / Len",IDC_STATIC,616,34,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#00",IDC_STATIC,4,50,23,10

-    CONTROL         "",IDC_SOUND0VOLBAR,"msctls_progress32",PBS_SMOOTH,30,49,68,11

-    CTEXT           "",IDC_SOUND0VOL,100,49,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND0PANBAR,"msctls_progress32",PBS_SMOOTH,30,62,68,10

-    CTEXT           "",IDC_SOUND0PAN,100,61,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND0REPEATMODE,131,49,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND0FORMAT,131,61,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND0STATE,204,49,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND0PNT,204,61,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND0TMR,265,49,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND0POSLEN,265,61,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#01",IDC_STATIC,4,75,23,10

-    CONTROL         "",IDC_SOUND1VOLBAR,"msctls_progress32",PBS_SMOOTH,30,74,68,11

-    CTEXT           "",IDC_SOUND1VOL,100,74,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND1PANBAR,"msctls_progress32",PBS_SMOOTH,30,87,68,11

-    CTEXT           "",IDC_SOUND1PAN,100,87,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND1REPEATMODE,131,74,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND1FORMAT,131,87,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND1STATE,204,74,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND1PNT,204,87,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND1TMR,265,74,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND1POSLEN,265,87,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#02",IDC_STATIC,4,101,23,10

-    CONTROL         "",IDC_SOUND2VOLBAR,"msctls_progress32",PBS_SMOOTH,30,100,68,11

-    CTEXT           "",IDC_SOUND2VOL,100,100,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND2PANBAR,"msctls_progress32",PBS_SMOOTH,30,113,68,11

-    CTEXT           "",IDC_SOUND2PAN,100,113,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND2REPEATMODE,131,100,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND2FORMAT,131,113,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND2STATE,204,100,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND2PNT,204,113,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND2TMR,265,100,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND2POSLEN,265,113,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#03",IDC_STATIC,4,127,23,10

-    CONTROL         "",IDC_SOUND3VOLBAR,"msctls_progress32",PBS_SMOOTH,30,126,68,11

-    CTEXT           "",IDC_SOUND3VOL,100,126,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND3PANBAR,"msctls_progress32",PBS_SMOOTH,30,139,68,11

-    CTEXT           "",IDC_SOUND3PAN,100,139,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND3REPEATMODE,131,126,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND3FORMAT,131,139,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND3STATE,204,126,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND3PNT,204,139,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND3TMR,265,126,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND3POSLEN,265,139,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#04",IDC_STATIC,4,153,23,10

-    CONTROL         "",IDC_SOUND4VOLBAR,"msctls_progress32",PBS_SMOOTH,30,152,68,11

-    CTEXT           "",IDC_SOUND4VOL,100,152,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND4PANBAR,"msctls_progress32",PBS_SMOOTH,30,165,68,11

-    CTEXT           "",IDC_SOUND4PAN,100,165,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND4REPEATMODE,131,152,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND4FORMAT,131,165,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND4STATE,204,152,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND4PNT,204,165,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND4TMR,265,152,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND4POSLEN,265,165,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#05",IDC_STATIC,4,179,23,10

-    CONTROL         "",IDC_SOUND5VOLBAR,"msctls_progress32",PBS_SMOOTH,30,178,68,11

-    CTEXT           "",IDC_SOUND5VOL,100,178,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND5PANBAR,"msctls_progress32",PBS_SMOOTH,30,191,68,11

-    CTEXT           "",IDC_SOUND5PAN,100,191,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND5REPEATMODE,131,178,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND5FORMAT,131,191,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND5STATE,204,178,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND5PNT,204,191,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND5TMR,265,178,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND5POSLEN,265,191,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#06",IDC_STATIC,4,205,23,10

-    CONTROL         "",IDC_SOUND6VOLBAR,"msctls_progress32",PBS_SMOOTH,30,204,68,11

-    CTEXT           "",IDC_SOUND6VOL,100,204,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND6PANBAR,"msctls_progress32",PBS_SMOOTH,30,217,68,11

-    CTEXT           "",IDC_SOUND6PAN,100,217,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND6REPEATMODE,131,204,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND6FORMAT,131,217,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND6STATE,204,204,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND6PNT,204,217,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND6TMR,265,204,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND6POSLEN,265,217,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#07",IDC_STATIC,4,231,23,10

-    CONTROL         "",IDC_SOUND7VOLBAR,"msctls_progress32",PBS_SMOOTH,30,230,68,11

-    CTEXT           "",IDC_SOUND7VOL,100,230,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND7PANBAR,"msctls_progress32",PBS_SMOOTH,30,244,68,11

-    CTEXT           "",IDC_SOUND7PAN,100,244,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND7REPEATMODE,131,230,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND7FORMAT,131,244,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND7STATE,204,230,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND7PNT,204,244,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND7TMR,265,230,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND7POSLEN,265,244,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#08",IDC_STATIC,355,50,23,10

-    CONTROL         "",IDC_SOUND8VOLBAR,"msctls_progress32",PBS_SMOOTH,381,49,68,11

-    CTEXT           "",IDC_SOUND8VOL,451,49,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND8PANBAR,"msctls_progress32",PBS_SMOOTH,381,62,68,10

-    CTEXT           "",IDC_SOUND8PAN,451,61,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND8REPEATMODE,482,49,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND8FORMAT,482,61,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND8STATE,555,49,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND8PNT,555,61,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND8TMR,616,49,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND8POSLEN,616,61,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#09",IDC_STATIC,355,75,23,10

-    CONTROL         "",IDC_SOUND9VOLBAR,"msctls_progress32",PBS_SMOOTH,381,74,68,11

-    CTEXT           "",IDC_SOUND9VOL,451,74,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND9PANBAR,"msctls_progress32",PBS_SMOOTH,381,87,68,11

-    CTEXT           "",IDC_SOUND9PAN,451,87,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND9REPEATMODE,482,74,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND9FORMAT,482,87,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND9STATE,555,74,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND9PNT,555,87,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND9TMR,616,74,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND9POSLEN,616,87,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#10",IDC_STATIC,355,101,23,10

-    CONTROL         "",IDC_SOUND10VOLBAR,"msctls_progress32",PBS_SMOOTH,381,100,68,11

-    CTEXT           "",IDC_SOUND10VOL,451,100,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND10PANBAR,"msctls_progress32",PBS_SMOOTH,381,113,68,11

-    CTEXT           "",IDC_SOUND10PAN,451,113,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND10REPEATMODE,482,100,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND10FORMAT,482,113,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND10STATE,555,100,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND10PNT,555,113,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND10TMR,616,100,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND10POSLEN,616,113,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#11",IDC_STATIC,355,127,23,10

-    CONTROL         "",IDC_SOUND11VOLBAR,"msctls_progress32",PBS_SMOOTH,381,126,68,11

-    CTEXT           "",IDC_SOUND11VOL,451,126,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND11PANBAR,"msctls_progress32",PBS_SMOOTH,381,139,68,11

-    CTEXT           "",IDC_SOUND11PAN,451,139,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND11REPEATMODE,482,126,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND11FORMAT,482,139,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND11STATE,555,126,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND11PNT,555,139,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND11TMR,616,126,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND11POSLEN,616,139,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#12",IDC_STATIC,355,153,23,10

-    CONTROL         "",IDC_SOUND12VOLBAR,"msctls_progress32",PBS_SMOOTH,381,152,68,11

-    CTEXT           "",IDC_SOUND12VOL,451,152,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND12PANBAR,"msctls_progress32",PBS_SMOOTH,381,165,68,11

-    CTEXT           "",IDC_SOUND12PAN,451,165,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND12REPEATMODE,482,152,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND12FORMAT,482,165,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND12STATE,555,152,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND12PNT,555,165,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND12TMR,616,152,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND12POSLEN,616,165,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#13",IDC_STATIC,355,179,23,10

-    CONTROL         "",IDC_SOUND13VOLBAR,"msctls_progress32",PBS_SMOOTH,381,178,68,11

-    CTEXT           "",IDC_SOUND13VOL,451,178,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND13PANBAR,"msctls_progress32",PBS_SMOOTH,381,191,68,11

-    CTEXT           "",IDC_SOUND13PAN,451,191,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND13REPEATMODE,482,178,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND13FORMAT,482,191,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND13STATE,555,178,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND13PNT,555,191,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND13TMR,616,178,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND13POSLEN,616,191,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#14",IDC_STATIC,355,205,23,10

-    CONTROL         "",IDC_SOUND14VOLBAR,"msctls_progress32",PBS_SMOOTH,381,204,68,11

-    CTEXT           "",IDC_SOUND14VOL,451,204,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND14PANBAR,"msctls_progress32",PBS_SMOOTH,381,217,68,11

-    CTEXT           "",IDC_SOUND14PAN,451,217,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND14REPEATMODE,482,204,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND14FORMAT,482,217,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND14STATE,555,204,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND14PNT,555,217,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND14TMR,616,204,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND14POSLEN,616,217,88,11,0,WS_EX_STATICEDGE

-    RTEXT           "#15",IDC_STATIC,355,231,23,10

-    CONTROL         "",IDC_SOUND15VOLBAR,"msctls_progress32",PBS_SMOOTH,381,230,68,11

-    CTEXT           "",IDC_SOUND15VOL,451,230,30,11,0,WS_EX_STATICEDGE

-    CONTROL         "",IDC_SOUND15PANBAR,"msctls_progress32",PBS_SMOOTH,381,244,68,11

-    CTEXT           "",IDC_SOUND15PAN,451,244,30,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND15REPEATMODE,482,230,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND15FORMAT,482,244,72,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND15STATE,555,230,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND15PNT,555,244,60,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND15TMR,616,230,88,11,0,WS_EX_STATICEDGE

-    CTEXT           "",IDC_SOUND15POSLEN,616,244,88,11,0,WS_EX_STATICEDGE

-    CONTROL         "Vol.Mode",IDC_BUTTON_VOLMODE,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,13,7,45,10

-    CONTROL         "Check1",IDC_SOUND0MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,62,10,10

-    CONTROL         "Check1",IDC_SOUND1MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,87,10,10

-    CONTROL         "Check1",IDC_SOUND2MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,114,10,10

-    CONTROL         "Check1",IDC_SOUND3MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,140,10,10

-    CONTROL         "Check1",IDC_SOUND4MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,164,10,10

-    CONTROL         "Check1",IDC_SOUND5MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,192,10,10

-    CONTROL         "Check1",IDC_SOUND6MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,217,10,10

-    CONTROL         "Check1",IDC_SOUND7MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,243,10,10

-    CONTROL         "Check1",IDC_SOUND8MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,62,10,10

-    CONTROL         "Check1",IDC_SOUND9MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,87,10,10

-    CONTROL         "Check1",IDC_SOUND10MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,114,10,10

-    CONTROL         "Check1",IDC_SOUND11MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,140,10,10

-    CONTROL         "Check1",IDC_SOUND12MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,164,10,10

-    CONTROL         "Check1",IDC_SOUND13MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,192,10,10

-    CONTROL         "Check1",IDC_SOUND14MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,217,10,10

-    CONTROL         "Check1",IDC_SOUND15MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,369,243,10,10

-    PUSHBUTTON      "Unmute All",IDC_SOUND_UNMUTE_ALL,302,3,50,14

-END

-

-

-/////////////////////////////////////////////////////////////////////////////

-//

-// DESIGNINFO

-//

-

-#ifdef APSTUDIO_INVOKED

-GUIDELINES DESIGNINFO

-BEGIN

-    IDD_SOUND_VIEW, DIALOG

-    BEGIN

-        LEFTMARGIN, 4

-        RIGHTMARGIN, 718

-        BOTTOMMARGIN, 255

-    END

-END

-#endif    // APSTUDIO_INVOKED

-

-#endif    // English (United States) resources

-/////////////////////////////////////////////////////////////////////////////

-

-

-

-#ifndef APSTUDIO_INVOKED

-/////////////////////////////////////////////////////////////////////////////

-//

-// Generated from the TEXTINCLUDE 3 resource.

-//

-

-

-/////////////////////////////////////////////////////////////////////////////

-#endif    // not APSTUDIO_INVOKED

-

 

file:a/src/in_ncsf/resource.h (deleted)
--- a/src/in_ncsf/resource.h
+++ /dev/null
@@ -1,195 +1,1 @@
-//{{NO_DEPENDENCIES}}

-// Microsoft Visual C++ generated include file.

-// Used by in_ncsf.rc

-//

-#define IDD_SOUND_VIEW                  1000

-#define IDC_BUTTON_VOLMODE              1001

-#define IDC_SOUND_UNMUTE_ALL            1002

-#define IDC_SOUND0VOL                   1350

-#define IDC_SOUND1VOL                   1351

-#define IDC_SOUND2VOL                   1352

-#define IDC_SOUND3VOL                   1353

-#define IDC_SOUND4VOL                   1354

-#define IDC_SOUND5VOL                   1355

-#define IDC_SOUND6VOL                   1356

-#define IDC_SOUND7VOL                   1357

-#define IDC_SOUND8VOL                   1358

-#define IDC_SOUND9VOL                   1359

-#define IDC_SOUND10VOL                  1360

-#define IDC_SOUND11VOL                  1361

-#define IDC_SOUND12VOL                  1362

-#define IDC_SOUND13VOL                  1363

-#define IDC_SOUND14VOL                  1364

-#define IDC_SOUND15VOL                  1365

-#define IDC_SOUND0VOLBAR                1370

-#define IDC_SOUND1VOLBAR                1371

-#define IDC_SOUND2VOLBAR                1372

-#define IDC_SOUND3VOLBAR                1373

-#define IDC_SOUND4VOLBAR                1374

-#define IDC_SOUND5VOLBAR                1375

-#define IDC_SOUND6VOLBAR                1376

-#define IDC_SOUND7VOLBAR                1377

-#define IDC_SOUND8VOLBAR                1378

-#define IDC_SOUND9VOLBAR                1379

-#define IDC_SOUND10VOLBAR               1380

-#define IDC_SOUND11VOLBAR               1381

-#define IDC_SOUND12VOLBAR               1382

-#define IDC_SOUND13VOLBAR               1383

-#define IDC_SOUND14VOLBAR               1384

-#define IDC_SOUND15VOLBAR               1385

-#define IDC_SOUND0PAN                   1390

-#define IDC_SOUND1PAN                   1391

-#define IDC_SOUND2PAN                   1392

-#define IDC_SOUND3PAN                   1393

-#define IDC_SOUND4PAN                   1394

-#define IDC_SOUND5PAN                   1395

-#define IDC_SOUND6PAN                   1396

-#define IDC_SOUND7PAN                   1397

-#define IDC_SOUND8PAN                   1398

-#define IDC_SOUND9PAN                   1399

-#define IDC_SOUND10PAN                  1400

-#define IDC_SOUND11PAN                  1401

-#define IDC_SOUND12PAN                  1402

-#define IDC_SOUND13PAN                  1403

-#define IDC_SOUND14PAN                  1404

-#define IDC_SOUND15PAN                  1405

-#define IDC_SOUND0PANBAR                1410

-#define IDC_SOUND1PANBAR                1411

-#define IDC_SOUND2PANBAR                1412

-#define IDC_SOUND3PANBAR                1413

-#define IDC_SOUND4PANBAR                1414

-#define IDC_SOUND5PANBAR                1415

-#define IDC_SOUND6PANBAR                1416

-#define IDC_SOUND7PANBAR                1417

-#define IDC_SOUND8PANBAR                1418

-#define IDC_SOUND9PANBAR                1419

-#define IDC_SOUND10PANBAR               1420

-#define IDC_SOUND11PANBAR               1421

-#define IDC_SOUND12PANBAR               1422

-#define IDC_SOUND13PANBAR               1423

-#define IDC_SOUND14PANBAR               1424

-#define IDC_SOUND15PANBAR               1425

-#define IDC_SOUND0REPEATMODE            1470

-#define IDC_SOUND1REPEATMODE            1471

-#define IDC_SOUND2REPEATMODE            1472

-#define IDC_SOUND3REPEATMODE            1473

-#define IDC_SOUND4REPEATMODE            1474

-#define IDC_SOUND5REPEATMODE            1475

-#define IDC_SOUND6REPEATMODE            1476

-#define IDC_SOUND7REPEATMODE            1477

-#define IDC_SOUND8REPEATMODE            1478

-#define IDC_SOUND9REPEATMODE            1479

-#define IDC_SOUND10REPEATMODE           1480

-#define IDC_SOUND11REPEATMODE           1481

-#define IDC_SOUND12REPEATMODE           1482

-#define IDC_SOUND13REPEATMODE           1483

-#define IDC_SOUND14REPEATMODE           1484

-#define IDC_SOUND15REPEATMODE           1485

-#define IDC_SOUND0FORMAT                1490

-#define IDC_SOUND1FORMAT                1491

-#define IDC_SOUND2FORMAT                1492

-#define IDC_SOUND3FORMAT                1493

-#define IDC_SOUND4FORMAT                1494

-#define IDC_SOUND5FORMAT                1495

-#define IDC_SOUND6FORMAT                1496

-#define IDC_SOUND7FORMAT                1497

-#define IDC_SOUND8FORMAT                1498

-#define IDC_SOUND9FORMAT                1499

-#define IDC_SOUND10FORMAT               1500

-#define IDC_SOUND11FORMAT               1501

-#define IDC_SOUND12FORMAT               1502

-#define IDC_SOUND13FORMAT               1503

-#define IDC_SOUND14FORMAT               1504

-#define IDC_SOUND15FORMAT               1505

-#define IDC_SOUND0STATE                 1510

-#define IDC_SOUND1STATE                 1511

-#define IDC_SOUND2STATE                 1512

-#define IDC_SOUND3STATE                 1513

-#define IDC_SOUND4STATE                 1514

-#define IDC_SOUND5STATE                 1515

-#define IDC_SOUND6STATE                 1516

-#define IDC_SOUND7STATE                 1517

-#define IDC_SOUND8STATE                 1518

-#define IDC_SOUND9STATE                 1519

-#define IDC_SOUND10STATE                1520

-#define IDC_SOUND11STATE                1521

-#define IDC_SOUND12STATE                1522

-#define IDC_SOUND13STATE                1523

-#define IDC_SOUND14STATE                1524

-#define IDC_SOUND15STATE                1525

-#define IDC_SOUND0PNT                   1530

-#define IDC_SOUND1PNT                   1531

-#define IDC_SOUND2PNT                   1532

-#define IDC_SOUND3PNT                   1533

-#define IDC_SOUND4PNT                   1534

-#define IDC_SOUND5PNT                   1535

-#define IDC_SOUND6PNT                   1536

-#define IDC_SOUND7PNT                   1537

-#define IDC_SOUND8PNT                   1538

-#define IDC_SOUND9PNT                   1539

-#define IDC_SOUND10PNT                  1540

-#define IDC_SOUND11PNT                  1541

-#define IDC_SOUND12PNT                  1542

-#define IDC_SOUND13PNT                  1543

-#define IDC_SOUND14PNT                  1544

-#define IDC_SOUND15PNT                  1545

-#define IDC_SOUND0TMR                   1550

-#define IDC_SOUND1TMR                   1551

-#define IDC_SOUND2TMR                   1552

-#define IDC_SOUND3TMR                   1553

-#define IDC_SOUND4TMR                   1554

-#define IDC_SOUND5TMR                   1555

-#define IDC_SOUND6TMR                   1556

-#define IDC_SOUND7TMR                   1557

-#define IDC_SOUND8TMR                   1558

-#define IDC_SOUND9TMR                   1559

-#define IDC_SOUND10TMR                  1560

-#define IDC_SOUND11TMR                  1561

-#define IDC_SOUND12TMR                  1562

-#define IDC_SOUND13TMR                  1563

-#define IDC_SOUND14TMR                  1564

-#define IDC_SOUND15TMR                  1565

-#define IDC_SOUND0POSLEN                1570

-#define IDC_SOUND1POSLEN                1571

-#define IDC_SOUND2POSLEN                1572

-#define IDC_SOUND3POSLEN                1573

-#define IDC_SOUND4POSLEN                1574

-#define IDC_SOUND5POSLEN                1575

-#define IDC_SOUND6POSLEN                1576

-#define IDC_SOUND7POSLEN                1577

-#define IDC_SOUND8POSLEN                1578

-#define IDC_SOUND9POSLEN                1579

-#define IDC_SOUND10POSLEN               1580

-#define IDC_SOUND11POSLEN               1581

-#define IDC_SOUND12POSLEN               1582

-#define IDC_SOUND13POSLEN               1583

-#define IDC_SOUND14POSLEN               1584

-#define IDC_SOUND15POSLEN               1585

-#define IDC_SOUND0MUTE                  2000

-#define IDC_SOUND1MUTE                  2001

-#define IDC_SOUND2MUTE                  2002

-#define IDC_SOUND3MUTE                  2003

-#define IDC_SOUND4MUTE                  2004

-#define IDC_SOUND5MUTE                  2005

-#define IDC_SOUND6MUTE                  2006

-#define IDC_SOUND7MUTE                  2007

-#define IDC_SOUND8MUTE                  2008

-#define IDC_SOUND9MUTE                  2009

-#define IDC_SOUND10MUTE                 2010

-#define IDC_SOUND11MUTE                 2011

-#define IDC_SOUND12MUTE                 2012

-#define IDC_SOUND13MUTE                 2013

-#define IDC_SOUND14MUTE                 2014

-#define IDC_SOUND15MUTE                 2015

-

-// Next default values for new objects

-//

-#ifdef APSTUDIO_INVOKED

-#ifndef APSTUDIO_READONLY_SYMBOLS

-#define _APS_NEXT_RESOURCE_VALUE        102

-#define _APS_NEXT_COMMAND_VALUE         40001

-#define _APS_NEXT_CONTROL_VALUE         1001

-#define _APS_NEXT_SYMED_VALUE           101

-#endif

-#endif

 

--- a/src/in_snsf/XSFConfig_SNSF.cpp
+++ b/src/in_snsf/XSFConfig_SNSF.cpp
@@ -15,6 +15,7 @@
 #include <cstddef>
 #include <cstdint>
 #include "windowsh_wrapper.h"
+#include "XSFApp.h"
 #include "XSFConfig.h"
 #include "XSFConfig_SNSF.h"
 #include "XSFConfigDialog_SNSF.h"
@@ -25,17 +26,14 @@
 class XSFConfigDialog;
 class XSFPlayer;
 
-enum
-{
-	idSixteenBitSound = 1000,
-	idReverseStereo,
-	idResampler,
-	idMutes
-};
-
 const unsigned XSFConfig::initSampleRate = 44100;
 const std::string XSFConfig::commonName = "SNSF Decoder";
 const std::string XSFConfig::versionNumber = "0.9b";
+
+XSFApp *XSFApp::Create()
+{
+	return new XSFApp();
+}
 
 XSFConfig *XSFConfig::Create()
 {

--- a/src/in_xsf_framework/CMakeLists.txt
+++ b/src/in_xsf_framework/CMakeLists.txt
@@ -73,7 +73,6 @@
 set(wxUSE_FS_ZIP OFF CACHE BOOL " " FORCE)
 set(wxUSE_FSVOLUME OFF CACHE BOOL " " FORCE)
 set(wxUSE_FSWATCHER OFF CACHE BOOL " " FORCE)
-set(wxUSE_GAUGE OFF CACHE BOOL " " FORCE)
 set(wxUSE_GEOMETRY OFF CACHE BOOL " " FORCE)
 set(wxUSE_GIF OFF CACHE BOOL " " FORCE)
 set(wxUSE_GRAPHICS_CONTEXT OFF CACHE BOOL " " FORCE)
@@ -174,7 +173,6 @@
 set(wxUSE_TIMEPICKCTRL OFF CACHE BOOL " " FORCE)
 set(wxUSE_TIMER OFF CACHE BOOL " " FORCE)
 set(wxUSE_TIPWINDOW OFF CACHE BOOL " " FORCE)
-set(wxUSE_TOGGLEBTN OFF CACHE BOOL " " FORCE)
 set(wxUSE_TOOLBAR OFF CACHE BOOL " " FORCE)
 set(wxUSE_TOOLBAR_NATIVE OFF CACHE BOOL " " FORCE)
 set(wxUSE_TOOLBOOK OFF CACHE BOOL " " FORCE)
@@ -215,6 +213,7 @@
 	RegExValidator.h
 	TagList.h
 	windowsh_wrapper.h
+	XSFApp.h
 	XSFCommon.h
 	XSFConfig.h
 	XSFConfigDialog.h
@@ -225,6 +224,7 @@
 	in_xsf.cpp
 	RegExValidator.cpp
 	TagList.cpp
+	XSFApp.cpp
 	XSFConfig.cpp
 	XSFConfig_Winamp.cpp
 	XSFConfigDialog.cpp

--- /dev/null
+++ b/src/in_xsf_framework/XSFApp.cpp
@@ -1,1 +1,42 @@
+/*
+ * xSF - Core wxWidgets App
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
 
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wold-style-cast"
+#endif
+#include <wx/nativewin.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+#include "windowsh_wrapper.h"
+#include "XSFApp.h"
+#include "XSFConfig.h"
+#include "XSFConfigDialog.h"
+
+void XSFApp::ConfigDialog(HWND parent, XSFConfig *config)
+{
+	// 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 = wxNativeContainerWindow(parent);
+	auto dialog = config->CreateDialogBox(&window, XSFConfig::commonName + " v" + XSFConfig::versionNumber);
+	dialog->Finalize();
+	config->InitializeConfigDialog(dialog);
+	if (dialog->ShowModal() == wxID_OK)
+	{
+		config->SaveConfigDialog(dialog);
+		config->SaveConfig();
+	}
+	dialog->Destroy();
+	window.Destroy();
+}
+

--- /dev/null
+++ b/src/in_xsf_framework/XSFApp.h
@@ -1,1 +1,35 @@
+/*
+ * xSF - Core wxWidgets App
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
+ *
+ * Partially based on the vio*sf framework
+ */
 
+#pragma once
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wold-style-cast"
+#endif
+#include <wx/app.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+#include "windowsh_wrapper.h"
+
+class XSFConfig;
+
+class XSFApp : public wxApp
+{
+public:
+	// Even though most of the plugins are just going to create an instance of XSFApp, I am using this to allow the NCSF plugin to make a derived instance instead.
+	static XSFApp *Create();
+
+	void ConfigDialog(HWND parent, XSFConfig *config);
+};
+

--- a/src/in_xsf_framework/XSFConfig.cpp
+++ b/src/in_xsf_framework/XSFConfig.cpp
@@ -9,22 +9,9 @@
 #include <string>
 #include <type_traits>
 #include <vector>
-#ifdef __GNUC__
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wold-style-cast"
-#elif defined(__clang__)
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wold-style-cast"
-#endif
-#include <wx/app.h>
-#include <wx/nativewin.h>
-#ifdef __GNUC__
-# pragma GCC diagnostic pop
-#elif defined(__clang__)
-# pragma clang diagnostic pop
-#endif
 #include "windowsh_wrapper.h"
 #include <windowsx.h>
+#include "XSFApp.h"
 #include "XSFConfig.h"
 #include "XSFConfigDialog.h"
 #include "XSFFile.h"
@@ -103,52 +90,6 @@
 
 	this->SaveSpecificConfig();
 }
-
-class XSFConfigApp : public wxApp
-{
-	HWND parent;
-	XSFConfig *config;
-public:
-	XSFConfigApp() : parent(nullptr), config(nullptr)
-	{
-	}
-
-	XSFConfigApp(HWND newParent, XSFConfig *newConfig) : parent(newParent), config(newConfig)
-	{
-	}
-
-	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;
-	}
-};
-
-#ifdef __GNUC__
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wold-style-cast"
-#elif defined(__clang__)
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wold-style-cast"
-#endif
-wxIMPLEMENT_APP_NO_MAIN(XSFConfigApp);
-#ifdef __GNUC__
-# pragma GCC diagnostic pop
-#elif defined(__clang__)
-# pragma clang diagnostic pop
-#endif
 
 void XSFConfig::GenerateDialogs()
 {
@@ -248,13 +189,11 @@
 	return true;
 }
 
-void XSFConfig::CallConfigDialog(HINSTANCE hInstance, HWND hwndParent)
-{
-	auto app = new XSFConfigApp(hwndParent, this);
-	wxApp::SetInstance(app);
-	wxEntryStart(hInstance);
-	app->OnInit();
-	wxEntryCleanup();
+extern std::unique_ptr<XSFApp> xSFApp;
+
+void XSFConfig::CallConfigDialog(HWND hwndParent)
+{
+	xSFApp->ConfigDialog(hwndParent, this);
 }
 
 void XSFConfig::CallInfoDialog(HINSTANCE hInstance, HWND hwndParent)

--- a/src/in_xsf_framework/XSFConfig.h
+++ b/src/in_xsf_framework/XSFConfig.h
@@ -101,7 +101,7 @@
 	void SaveConfig();
 	void GenerateDialogs();
 	static INT_PTR CALLBACK InfoDialogProcStatic(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-	void CallConfigDialog(HINSTANCE hInstance, HWND hwndParent);
+	void CallConfigDialog(HWND hwndParent);
 	void CallInfoDialog(HINSTANCE hInstance, HWND hwndParent);
 	void InitializeConfigDialog(XSFConfigDialog *dialog);
 	void ResetConfigDefaults(XSFConfigDialog *dialog);

--- a/src/in_xsf_framework/in_xsf.cpp
+++ b/src/in_xsf_framework/in_xsf.cpp
@@ -15,7 +15,21 @@
 #include <vector>
 #include <cstddef>
 #include <cstdint>
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#elif defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wold-style-cast"
+#endif
+#include <wx/app.h>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#elif defined(__clang__)
+# pragma clang diagnostic pop
+#endif
 #include "windowsh_wrapper.h"
+#include "XSFApp.h"
 #include "XSFCommon.h"
 #include "XSFConfig.h"
 #include "XSFFile.h"
@@ -28,6 +42,7 @@
 static const XSFFile *xSFFile = nullptr;
 XSFFile *xSFFileInInfo = nullptr;
 static std::unique_ptr<XSFPlayer> xSFPlayer;
+std::unique_ptr<XSFApp> xSFApp;
 std::unique_ptr<XSFConfig> xSFConfig;
 static bool paused;
 static std::atomic_int seek_needed;
@@ -83,7 +98,7 @@
 
 void config(HWND hwndParent)
 {
-	xSFConfig->CallConfigDialog(inMod.hDllInstance, hwndParent);
+	xSFConfig->CallConfigDialog(hwndParent);
 	if (xSFPlayer)
 		xSFConfig->CopyConfigToMemory(xSFPlayer.get(), false);
 }
@@ -95,6 +110,9 @@
 
 void init()
 {
+	wxEntryStart(inMod.hDllInstance);
+	xSFApp.reset(XSFApp::Create());
+	wxApp::SetInstance(xSFApp.get());
 	xSFConfig.reset(XSFConfig::Create());
 	xSFConfig->LoadConfig();
 	xSFConfig->GenerateDialogs();
@@ -105,6 +123,8 @@
 {
 	xSFPlayer.reset();
 	xSFConfig.reset();
+	xSFApp.reset();
+	wxEntryCleanup();
 }
 
 void getFileInfo(const in_char *file, in_char *title, int *length_in_ms)