/*
* SACD Decoder plugin
* Copyright (c) 2011-2015 Maxim V.Anisiutkin <maxim.anisiutkin@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef _SACD_SETUP_H_INCLUDED
#define _SACD_SETUP_H_INCLUDED

#include <atldlgs.h>

#define FIR_FILTER _T("Installable FIR (*.txt)\0*.txt\0All Files (*.*)\0*.*\0\0")

static const GUID g_guid_cfg_output_mode = { 0xd3d21b14, 0x68d2, 0x437f, { 0xa9, 0xc6, 0x5b, 0xa7, 0xb1, 0xd6, 0xe, 0x54 } };
static cfg_int g_cfg_output_mode(g_guid_cfg_output_mode, 0);

static const GUID g_guid_cfg_volume = { 0x9c3dce45, 0x67c2, 0x4221, { 0xa9, 0x1, 0x53, 0x60, 0x44, 0x9e, 0xa, 0x24 } };
static cfg_int g_cfg_volume(g_guid_cfg_volume, 0);

static const GUID g_guid_cfg_log_overloads = { 0xfb56f73a, 0x3fbc, 0x420e, { 0xac, 0x28, 0x27, 0xfd, 0xc9, 0x14, 0xc9, 0x1 } };
static cfg_uint g_cfg_log_overloads(g_guid_cfg_log_overloads, BST_UNCHECKED);

static const GUID g_guid_cfg_samplerate = { 0xde915fec, 0x5557, 0x4746, { 0x87, 0xbc, 0x6a, 0x6f, 0x99, 0xfe, 0x67, 0x5 } };
static cfg_int g_cfg_samplerate(g_guid_cfg_samplerate, 0);

static const GUID g_guid_cfg_converter_mode = { 0x745d7ac3, 0x80c1, 0x41c1, { 0xb9, 0x8, 0xbd, 0x6, 0xd6, 0xa2, 0x87, 0x82 } };
static cfg_int g_cfg_converter_mode(g_guid_cfg_converter_mode, 0);

static const GUID g_guid_cfg_user_fir_name = { 0x35f5e4a6, 0x6cb0, 0x4e3e, { 0xb9, 0x6, 0xec, 0x46, 0xfd, 0x61, 0x24, 0x50 } };
static cfg_string g_cfg_user_fir_name(g_guid_cfg_user_fir_name, "");

static const GUID g_guid_cfg_user_fir_coef = { 0x813f1a8c, 0xdd29, 0x4087, { 0x8c, 0x49, 0xcc, 0x5b, 0x3e, 0xc5, 0xd1, 0xc6 } };
static cfg_objList<double> g_cfg_user_fir_coef(g_guid_cfg_user_fir_coef);

static const GUID g_guid_cfg_area = { 0xa93bec29, 0xc34b, 0x4973, { 0xb7, 0x85, 0xea, 0xc8, 0xf8, 0x4e, 0x1d, 0x83 } };
static cfg_int g_cfg_area(g_guid_cfg_area, 0);

static const GUID g_guid_cfg_editable_tags = { 0x480cf6d8, 0x3512, 0x49ae, { 0xb8, 0xef, 0x3f, 0xe1, 0x84, 0x9c, 0xd7, 0x0 } };
static cfg_uint g_cfg_editable_tags(g_guid_cfg_editable_tags, BST_UNCHECKED);

static const GUID g_guid_cfg_store_tags_with_iso = { 0x4e3f3dd0, 0x7407, 0x4115, { 0xbd, 0xe8, 0x2a, 0x48, 0x2e, 0x71, 0x26, 0x7f } };
static cfg_uint g_cfg_store_tags_with_iso(g_guid_cfg_store_tags_with_iso, BST_UNCHECKED);

static const GUID g_guid_cfg_linked_tags = { 0x94053a83, 0x4d15, 0x4d57,{ 0xa1, 0xa8, 0x83, 0x77, 0xe6, 0x61, 0x4f, 0xf3 } };
static cfg_uint g_cfg_linked_tags(g_guid_cfg_linked_tags, BST_UNCHECKED);

static const GUID g_guid_cfg_emaster = { 0xb9fc1273, 0x2c44, 0x4b00, { 0x93, 0xc3, 0x56, 0x79, 0x79, 0x1a, 0x3a, 0x5f } };
static cfg_uint g_cfg_emaster(g_guid_cfg_emaster, BST_UNCHECKED);

class CSACDPreferences : public CDialogImpl<CSACDPreferences>, public preferences_page_instance {
public:
	static bool in_dsd_mode() {
		return g_cfg_output_mode.get_value() > 0 ? true : false;
	}

	static int get_output_mode() {
		return g_cfg_output_mode.get_value();
	}

	static int get_volume() {
		return g_cfg_volume.get_value();
	}

	static bool get_log_overloads() {
		return g_cfg_log_overloads == BST_CHECKED;
	}

	static int get_samplerate() {
		switch (g_cfg_samplerate.get_value()) {
		case 0:
			return 44100;
		case 1:
			return 88200;
		case 2:
			return 176400;
		case 3:
			return 352800;
		}
		return 44100;
	}

	static int get_converter_mode() {
		return g_cfg_converter_mode.get_value();
	}

	static cfg_objList<double>& get_user_fir() {
		return g_cfg_user_fir_coef;
	}

	static int get_area() {
		return g_cfg_area.get_value();
	}

	static bool get_editable_tags() {
		return g_cfg_editable_tags == BST_CHECKED;
	}

	static bool get_store_tags_with_iso() {
		return g_cfg_store_tags_with_iso == BST_CHECKED;
	}

	static bool get_linked_tags() {
		return g_cfg_linked_tags == BST_CHECKED;
	}

	static bool get_emaster() {
		return g_cfg_emaster == BST_CHECKED;
	}

	CSACDPreferences(preferences_page_callback::ptr callback) : m_callback(callback) {
	}

	enum {IDD = IDD_SACD_PREFERENCES};

	t_uint32 get_state() {
		t_uint32 state = preferences_state::resettable;
		if (HasChanged()) {
			state |= preferences_state::changed;
		}
		return state;
	}

	void apply() {
		g_cfg_output_mode = SendDlgItemMessage(IDC_OUTPUT_MODE_COMBO, CB_GETCURSEL, 0, 0);
		g_cfg_volume = SendDlgItemMessage(IDC_VOLUME_COMBO, CB_GETCURSEL, 0, 0);
		g_cfg_log_overloads = SendDlgItemMessage(IDC_LOG_OVERLOADS, BM_GETCHECK, 0, 0);
		g_cfg_samplerate = SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_GETCURSEL, 0, 0);
		g_cfg_converter_mode = SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_GETCURSEL, 0, 0);
		g_cfg_area = SendDlgItemMessage(IDC_AREA_COMBO, CB_GETCURSEL, 0, 0);
		g_cfg_editable_tags = SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_GETCHECK, 0, 0);
		g_cfg_store_tags_with_iso = SendDlgItemMessage(IDC_STORE_TAGS_WITH_ISO, BM_GETCHECK, 0, 0);
		g_cfg_linked_tags = SendDlgItemMessage(IDC_LINKED_TAGS, BM_GETCHECK, 0, 0);
		g_cfg_emaster = SendDlgItemMessage(IDC_EMASTER, BM_GETCHECK, 0, 0);
		OnChanged();
	}

	void reset() {
		g_cfg_output_mode = 0;
		SendDlgItemMessage(IDC_OUTPUT_MODE_COMBO, CB_SETCURSEL, g_cfg_output_mode, 0);
		g_cfg_volume = 6;
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_SETCURSEL, g_cfg_volume, 0);
		g_cfg_log_overloads = BST_UNCHECKED;
		SendDlgItemMessage(IDC_LOG_OVERLOADS, BM_SETCHECK, g_cfg_log_overloads, 0);
		g_cfg_samplerate = 0;
		SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_SETCURSEL, g_cfg_samplerate, 0);
		g_cfg_converter_mode = 0;
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_SETCURSEL, g_cfg_converter_mode, 0);
		g_cfg_user_fir_name.reset();
		g_cfg_user_fir_coef.remove_all();
		GetDlgItem(IDC_LOAD_FIR_BUTTON).EnableWindow(FALSE);
		GetDlgItem(IDC_SAVE_FIR_BUTTON).EnableWindow(FALSE);
		SendDlgItemMessage(IDC_INSTALLABLE_FILTER_TEXT, WM_SETTEXT, 0, (LPARAM)0);
		SetPcmControls();
		g_cfg_area = 0;
		SendDlgItemMessage(IDC_AREA_COMBO, CB_SETCURSEL, g_cfg_area, 0);
		g_cfg_editable_tags = BST_UNCHECKED;
		SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_SETCHECK, g_cfg_editable_tags, 0);
		GetDlgItem(IDC_STORE_TAGS_WITH_ISO).EnableWindow(g_cfg_editable_tags != 0);
		g_cfg_store_tags_with_iso = BST_UNCHECKED;
		SendDlgItemMessage(IDC_STORE_TAGS_WITH_ISO, BM_SETCHECK, g_cfg_store_tags_with_iso, 0);
		g_cfg_linked_tags = BST_UNCHECKED;
		SendDlgItemMessage(IDC_LINKED_TAGS, BM_SETCHECK, g_cfg_linked_tags, 0);
		g_cfg_emaster = BST_UNCHECKED;
		SendDlgItemMessage(IDC_EMASTER, BM_SETCHECK, g_cfg_emaster, 0);
		OnChanged();
	}

	BEGIN_MSG_MAP(CDVDAPreferences)
		MSG_WM_INITDIALOG(OnInitDialog)
		COMMAND_HANDLER_EX(IDC_OUTPUT_MODE_COMBO, CBN_SELCHANGE, OnOutputModeChange)
		COMMAND_HANDLER_EX(IDC_VOLUME_COMBO, CBN_SELCHANGE, OnVolumeChange)
		COMMAND_HANDLER_EX(IDC_LOG_OVERLOADS, BN_CLICKED, OnLogOverloadsClicked)
		COMMAND_HANDLER_EX(IDC_SAMPLERATE_COMBO, CBN_SELCHANGE, OnSamplerateChange)
		COMMAND_HANDLER_EX(IDC_CONVERTER_MODE_COMBO, CBN_SELCHANGE, OnConverterModeChange)
		COMMAND_HANDLER_EX(IDC_LOAD_FIR_BUTTON, BN_CLICKED, OnLoadFirClicked)
		COMMAND_HANDLER_EX(IDC_SAVE_FIR_BUTTON, BN_CLICKED, OnSaveFirClicked)
		COMMAND_HANDLER_EX(IDC_AREA_COMBO, CBN_SELCHANGE, OnAreaChange)
		COMMAND_HANDLER_EX(IDC_EDITABLE_TAGS, BN_CLICKED, OnEditableTagsClicked)
		COMMAND_HANDLER_EX(IDC_STORE_TAGS_WITH_ISO, BN_CLICKED, OnStoreWithIsoClicked)
		COMMAND_HANDLER_EX(IDC_LINKED_TAGS, BN_CLICKED, OnLinkedTagsClicked)
		COMMAND_HANDLER_EX(IDC_EMASTER, BN_CLICKED, OnEMasterClicked)
	END_MSG_MAP()

private:
	BOOL OnInitDialog(CWindow, LPARAM) {
		GetOutputModeList();
		GetVolumeList();
		SendDlgItemMessage(IDC_LOG_OVERLOADS, BM_SETCHECK, g_cfg_log_overloads, 0);
		GetSamplerateList();
		GetConverterModeList();
		SetPcmControls();
		GetAreaList();
		SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_SETCHECK, g_cfg_editable_tags, 0);
		GetDlgItem(IDC_STORE_TAGS_WITH_ISO).EnableWindow(SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_GETCHECK, 0, 0));
		GetDlgItem(IDC_LINKED_TAGS).EnableWindow(SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_GETCHECK, 0, 0));
		SendDlgItemMessage(IDC_STORE_TAGS_WITH_ISO, BM_SETCHECK, g_cfg_store_tags_with_iso, 0);
		SendDlgItemMessage(IDC_LINKED_TAGS, BM_SETCHECK, g_cfg_linked_tags, 0);
		SendDlgItemMessage(IDC_EMASTER, BM_SETCHECK, g_cfg_emaster, 0);
		return FALSE;
	}

	void OnOutputModeChange(UINT, int, CWindow) {
		SetPcmControls();
		OnChanged();
	}

	void OnVolumeChange(UINT, int, CWindow) {
		OnChanged();
	}

	void OnDeClickerClicked(UINT, int, CWindow) {
		OnChanged();
	}

	void OnLogOverloadsClicked(UINT, int, CWindow) {
		OnChanged();
	}

	void OnSamplerateChange(UINT, int, CWindow) {
		OnChanged();
	}

	void OnConverterModeChange(UINT, int, CWindow) {
		SetUserFirState();
		OnChanged();
	}

	void OnLoadFirClicked(UINT, int, CWindow) {
		CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, FIR_FILTER);
		if (dlg.DoModal(dlg) == IDOK) {
			bool fir_name_is_read = false;
			FILE* fir = _tfopen(dlg.m_szFileName, _T("r"));
			if (fir) {
				g_cfg_user_fir_name.reset();
				g_cfg_user_fir_coef.remove_all();
				while (!feof(fir)) {
					double coef;
					TCHAR str[4096];
					if (_fgetts(str, sizeof(str) / sizeof(*str), fir)) {
						if (_tcslen(str) > 0) {
							if (str[0] == _T('#')) {
								if (_tcslen(str) > 1 && !fir_name_is_read) {
									string_utf8_from_wide(su);
									su = &str[1];
									g_cfg_user_fir_name.set_string(su);
									while (g_cfg_user_fir_name.get_length() > 0 && g_cfg_user_fir_name.get_ptr()[0] == ' ') {
										g_cfg_user_fir_name.remove_chars(0, 1);
									}
									fir_name_is_read = true;
								}
							}
							else {
								if (_stscanf(str, _T("%lg"), &coef) == 1) {
									g_cfg_user_fir_coef.add_item(coef);
								}
							}
						}
					}
				}
				fclose(fir);
			}
			string_wide_from_utf8(filter_description);
			if (fir_name_is_read) {
				filter_description = g_cfg_user_fir_name.get_ptr();
			}
			else {
				string_utf8_from_wide(file_path);
				file_path = dlg.m_szFileName;
				string_filename_ext filename_ext(file_path);
				g_cfg_user_fir_name.set_string(filename_ext);
			}
			filter_description = g_cfg_user_fir_name.get_ptr();
			SendDlgItemMessage(IDC_INSTALLABLE_FILTER_TEXT, WM_SETTEXT, 0, (LPARAM)filter_description.get_ptr());
		}
		OnChanged();
	}

	void OnSaveFirClicked(UINT, int, CWindow) {
		CFileDialog dlg(FALSE, _T("txt"), _T("untitledfir"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, FIR_FILTER);
		if (dlg.DoModal(dlg) == IDOK) {
			FILE* fir = _tfopen(dlg.m_szFileName, _T("w"));
			if (fir) {
				double* fir_coefs  = g_cfg_user_fir_coef.get_ptr();
				int     fir_length = g_cfg_user_fir_coef.get_size();
				if (g_cfg_user_fir_name.get_length() > 0) {
					_ftprintf(fir, _T("# %S\n"), g_cfg_user_fir_name.get_ptr());
				}
				for (int i = 0; i < fir_length; i++) {
					_ftprintf(fir, _T("%.16lg\n"), fir_coefs[i]);
				}
				fclose(fir);
			}
		}
		OnChanged();
	}

	void OnAreaChange(UINT, int, CWindow) {
		OnChanged();
	}

	void OnEditableTagsClicked(UINT, int, CWindow) {
		GetDlgItem(IDC_STORE_TAGS_WITH_ISO).EnableWindow(SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_GETCHECK, 0, 0));
		GetDlgItem(IDC_LINKED_TAGS).EnableWindow(SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_GETCHECK, 0, 0));
		OnChanged();
	}

	void OnStoreWithIsoClicked(UINT, int, CWindow) {
		OnChanged();
	}

	void OnLinkedTagsClicked(UINT, int, CWindow) {
		OnChanged();
	}

	void OnEMasterClicked(UINT, int, CWindow) {
		OnChanged();
	}

	bool HasChanged() {
		if (g_cfg_output_mode.get_value() != SendDlgItemMessage(IDC_OUTPUT_MODE_COMBO, CB_GETCURSEL, 0, 0)) {
			return true;
		}
		if (g_cfg_volume.get_value() != SendDlgItemMessage(IDC_VOLUME_COMBO, CB_GETCURSEL, 0, 0)) {
			return true;
		}
		if (g_cfg_log_overloads.get_value() != SendDlgItemMessage(IDC_LOG_OVERLOADS, BM_GETCHECK, 0, 0)) {
			return true;
		}
		if (g_cfg_samplerate.get_value() != SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_GETCURSEL, 0, 0)) {
			return true;
		}
		if (g_cfg_converter_mode.get_value() != SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_GETCURSEL, 0, 0)) {
			return true;
		}
		if (g_cfg_area.get_value() != SendDlgItemMessage(IDC_AREA_COMBO, CB_GETCURSEL, 0, 0)) {
			return true;
		}
		if (g_cfg_editable_tags.get_value() != SendDlgItemMessage(IDC_EDITABLE_TAGS, BM_GETCHECK, 0, 0)) {
			return true;
		}
		if (g_cfg_store_tags_with_iso.get_value() != SendDlgItemMessage(IDC_STORE_TAGS_WITH_ISO, BM_GETCHECK, 0, 0)) {
			return true;
		}
		if (g_cfg_linked_tags.get_value() != SendDlgItemMessage(IDC_LINKED_TAGS, BM_GETCHECK, 0, 0)) {
			return true;
		}
		if (g_cfg_emaster.get_value() != SendDlgItemMessage(IDC_EMASTER, BM_GETCHECK, 0, 0)) {
			return true;
		}
		return false;
	}

	void OnChanged() {
		m_callback->on_state_changed();
	}

	void GetOutputModeList() {
		SendDlgItemMessage(IDC_OUTPUT_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("PCM"));
		SendDlgItemMessage(IDC_OUTPUT_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("DSD"));
		SendDlgItemMessage(IDC_OUTPUT_MODE_COMBO, CB_SETCURSEL, g_cfg_output_mode.get_value(), 0);
	}

	void GetVolumeList() {
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("+0dB"));
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("+1dB"));
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("+2dB"));
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("+3dB"));
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("+4dB"));
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("+5dB"));
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("+6dB"));
		SendDlgItemMessage(IDC_VOLUME_COMBO, CB_SETCURSEL, g_cfg_volume.get_value(), 0);
	}

	void GetSamplerateList() {
		SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("44100"));
		SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("88200"));
		SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("176400"));
		SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("352800"));
		SendDlgItemMessage(IDC_SAMPLERATE_COMBO, CB_SETCURSEL, g_cfg_samplerate.get_value(), 0);
	}

	void GetConverterModeList() {
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Multistage (Floating-Point)"));
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Multistage (Double-Precision)"));
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Direct (Floating-Point, 30kHz LF)"));
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Direct (Double-Precision, 30kHz LF)"));
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Installable FIR (Floating-Point)"));
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Installable FIR (Double-Precision)"));
		SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_SETCURSEL, g_cfg_converter_mode.get_value(), 0);
		SetUserFirState();
	}

	void GetAreaList() {
		SendDlgItemMessage(IDC_AREA_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("None"));
		SendDlgItemMessage(IDC_AREA_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Stereo"));
		SendDlgItemMessage(IDC_AREA_COMBO, CB_ADDSTRING, 0, (LPARAM)_T("Multichannel"));
		SendDlgItemMessage(IDC_AREA_COMBO, CB_SETCURSEL, g_cfg_area.get_value(), 0);
	}

	void SetPcmControls() {
		BOOL enabled = SendDlgItemMessage(IDC_OUTPUT_MODE_COMBO, CB_GETCURSEL, 0, 0) == 0 ? TRUE : FALSE;
		GetDlgItem(IDC_VOLUME_COMBO).EnableWindow(enabled);
		GetDlgItem(IDC_LOG_OVERLOADS).EnableWindow(enabled);
		GetDlgItem(IDC_SAMPLERATE_COMBO).EnableWindow(enabled);
		GetDlgItem(IDC_CONVERTER_MODE_COMBO).EnableWindow(enabled);
		if (enabled) {
			SetUserFirState();
		}
		else {
			GetDlgItem(IDC_LOAD_FIR_BUTTON).EnableWindow(FALSE);
			GetDlgItem(IDC_SAVE_FIR_BUTTON).EnableWindow(FALSE);
		}
	}

	void SetUserFirState() {
		string_wide_from_utf8(sw);
		switch (SendDlgItemMessage(IDC_CONVERTER_MODE_COMBO, CB_GETCURSEL, 0, 0)) {
		case 4:
		case 5:
			GetDlgItem(IDC_LOAD_FIR_BUTTON).EnableWindow(TRUE);
			GetDlgItem(IDC_SAVE_FIR_BUTTON).EnableWindow(TRUE);
			sw = g_cfg_user_fir_name.get_ptr();
			SendDlgItemMessage(IDC_INSTALLABLE_FILTER_TEXT, WM_SETTEXT, 0, (LPARAM)sw.get_ptr());
			break;
		default:
			GetDlgItem(IDC_LOAD_FIR_BUTTON).EnableWindow(FALSE);
			GetDlgItem(IDC_SAVE_FIR_BUTTON).EnableWindow(FALSE);
			SendDlgItemMessage(IDC_INSTALLABLE_FILTER_TEXT, WM_SETTEXT, 0, (LPARAM)0);
			break;
		}
	}

	const preferences_page_callback::ptr m_callback;
};

class preferences_page_sacd_t : public preferences_page_impl<CSACDPreferences> {
public:
	const char* get_name() {
		return "SACD";
	}
	GUID get_guid() {
		static const GUID guid = { 0x532b5e38, 0x267, 0x4a2d, { 0xa7, 0x89, 0xb0, 0x88, 0x99, 0xd2, 0xb1, 0x48 } };
		return guid;
	}
	GUID get_parent_guid() {
		return guid_tools;
	}
};

static preferences_page_factory_t<preferences_page_sacd_t> g_preferences_page_sacd_factory;

#endif
