From 4a55b8d74132daa7b9c2b09c337532e5b0683cbf Mon Sep 17 00:00:00 2001 From: Takamichi Horikawa Date: Mon, 3 Apr 2017 22:26:21 +0900 Subject: win32: add about dialog --- win32/about.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++ win32/about.h | 14 ++++ win32/fmplayer.mak | 1 + win32/main.c | 148 +++++++++++++++++++++++++++++++-------- win32/oscilloview.c | 14 +++- win32/oscilloview.h | 3 +- 6 files changed, 347 insertions(+), 30 deletions(-) create mode 100644 win32/about.c create mode 100644 win32/about.h diff --git a/win32/about.c b/win32/about.c new file mode 100644 index 0000000..f18c067 --- /dev/null +++ b/win32/about.c @@ -0,0 +1,197 @@ +#include "about.h" +#include +#include +#include +#include +#include "version.h" + +enum { + ID_OK = 0x10 +}; + +extern HWND g_currentdlg; + +static struct { + HINSTANCE hinst; + void (*closecb)(void *ptr); + void *cbptr; + HWND about; + ATOM about_class; + HFONT font, font_large; + HWND static_main, static_icon, static_help, static_info, button_ok; + wchar_t *soundapiname; + bool adpcm_rom, font_rom; +} g; + +static void on_destroy(HWND hwnd) { + DestroyWindow(g.static_main); + DestroyWindow(g.static_info); + DestroyWindow(g.static_help); + DestroyWindow(g.static_icon); + DestroyWindow(g.button_ok); + if (g.closecb) { + g.closecb(g.cbptr); + } + g.about = 0; +} + +static void update_status(void) { + static wchar_t buf[1024]; + swprintf(buf, sizeof(buf)/sizeof(buf[0]), + L"Audio API: %ls\r\n" + "ym2608_adpcm_rom.bin: %lsavailable\r\n" + "font.rom: %ls\r\n" + "SSE2 (for SIMD SSG resampling): %lsavailable\r\n" + "SSSE3 (for SIMD FMDSP palette lookup): %lsavailable", + g.soundapiname ? g.soundapiname : L"", + g.adpcm_rom ? L"" : L"un", + g.font_rom ? L"available" : L"unavailable, using MS Gothic", + __builtin_cpu_supports("sse2") ? L"" : L"un", + __builtin_cpu_supports("ssse3") ? L"" : L"un"); + SetWindowText(g.static_info, buf); +} + +static bool on_create(HWND hwnd, const CREATESTRUCT *cs) { + RECT wr = { + .left = 0, + .top = 0, + .right = 480, + .bottom = 300 + }; + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + DWORD exstyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE); + AdjustWindowRectEx(&wr, style, 0, exstyle); + SetWindowPos(hwnd, HWND_TOP, 0, 0, wr.right-wr.left, wr.bottom-wr.top, + SWP_NOZORDER | SWP_NOMOVE); + if (!g.font) { + NONCLIENTMETRICS ncm; + ncm.cbSize = sizeof(ncm); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); + LONG height = ncm.lfMessageFont.lfHeight; + ncm.lfMessageFont.lfHeight = height * 1.2; + ncm.lfMessageFont.lfWidth = 0; + g.font = CreateFontIndirect(&ncm.lfMessageFont); + ncm.lfMessageFont.lfHeight = height * 1.5; + ncm.lfMessageFont.lfWidth = 0; + g.font_large = CreateFontIndirect(&ncm.lfMessageFont); + } + g.static_icon = CreateWindowEx(0, L"static", + MAKEINTRESOURCE(1), + WS_CHILD | WS_VISIBLE | SS_ICON, + 100, 10, 32, 32, + hwnd, 0, g.hinst, 0); +#ifdef _WIN64 +#define ABOUT_ARCH "(amd64)" +#else +#define ABOUT_ARCH "(i586)" +#endif + g.static_info = CreateWindowEx(0, L"static", + L"", + WS_CHILD | WS_VISIBLE, + 75, 50, 400, 90, + hwnd, 0, g.hinst, 0); + SetWindowFont(g.static_info, g.font, TRUE); + update_status(); + g.static_help = CreateWindowEx(0, L"static", + L"F11: toggle track display page\r\n" + "F12: display FMDSP at 2x\r\n" + "Ctrl+F1-F10: FMDSP color palette\r\n\r\n" + "1-9,0,-: toggle track mask (Ctrl: PPZ8)\r\n" + "Shift+1-9,0,-: track solo\r\n" + "=: invert all mask\r\n" + "\\: all tracks on", + WS_CHILD | WS_VISIBLE, + 75, 140, 400, 400, + hwnd, 0, g.hinst, 0); + SetWindowFont(g.static_help, g.font, TRUE); + g.static_main = CreateWindowEx(0, L"static", + L"FMPlayer/Win32 " ABOUT_ARCH " v" FMPLAYER_VERSION_STR, + WS_CHILD | WS_VISIBLE, + 150, 10, 400, 40, + hwnd, 0, g.hinst, 0); + SetWindowFont(g.static_main, g.font_large, TRUE); + g.button_ok = CreateWindowEx(0, L"button", + L"&OK", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, + 200, 270, 80, 25, + hwnd, (HMENU)ID_OK, g.hinst, 0); + SetWindowFont(g.button_ok, g.font, TRUE); + ShowWindow(hwnd, SW_SHOW); + return true; +} + +static void on_activate(HWND hwnd, bool activate, HWND targetwnd, WINBOOL state) { + if (activate) g_currentdlg = hwnd; + else g_currentdlg = 0; +} + +static void on_command(HWND hwnd, int id, HWND hwnd_c, UINT code) { + if (code == BN_CLICKED && (id == ID_OK)) { + DestroyWindow(hwnd); + } +} + +static LRESULT CALLBACK wndproc( + HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam +) { + switch (msg) { + HANDLE_MSG(hwnd, WM_DESTROY, on_destroy); + HANDLE_MSG(hwnd, WM_CREATE, on_create); + HANDLE_MSG(hwnd, WM_ACTIVATE, on_activate); + HANDLE_MSG(hwnd, WM_COMMAND, on_command); + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void about_open(HINSTANCE hinst, HWND parent, void (*closecb)(void *ptr), void *cbptr) { + g.closecb = closecb; + g.cbptr = cbptr; + g.hinst = hinst; + if (!g.about) { + if (!g.about_class) { + WNDCLASS wc = {0}; + wc.lpfnWndProc = wndproc; + wc.hInstance = g.hinst; + wc.hIcon = LoadIcon(g.hinst, MAKEINTRESOURCE(1)); + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); + wc.lpszClassName = L"myon_fmplayer_ym2608_about"; + g.about_class = RegisterClass(&wc); + } + if (!g.about_class) { + MessageBox(parent, L"Cannot register class", L"Error", MB_ICONSTOP); + return; + } + g.about = CreateWindowEx(0, + MAKEINTATOM(g.about_class), + L"About", + WS_CAPTION | WS_SYSMENU, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + parent, 0, g.hinst, 0); + } else { + SetForegroundWindow(g.about); + } +} + +void about_setsoundapiname(const wchar_t *apiname) { + free(g.soundapiname); + g.soundapiname = wcsdup(apiname); + if (g.about) update_status(); +} + +void about_set_fontrom_loaded(bool loaded) { + g.font_rom = loaded; + if (g.about) update_status(); +} + +void about_set_adpcmrom_loaded(bool loaded) { + g.adpcm_rom = loaded; + if (g.about) update_status(); +} + +void about_close(void) { + if (g.about) { + g.closecb = 0; + DestroyWindow(g.about); + } +} diff --git a/win32/about.h b/win32/about.h new file mode 100644 index 0000000..2356e26 --- /dev/null +++ b/win32/about.h @@ -0,0 +1,14 @@ +#ifndef MYON_FMPLAYER_WIN32_ABOUT_H_INCLUDED +#define MYON_FMPLAYER_WIN32_ABOUT_H_INCLUDED + +#define WIN32_LEAN_AND_MEAN +#include +#include + +void about_open(HINSTANCE hinst, HWND parent, void (*closecb)(void *ptr), void *cbptr); +void about_close(void); +void about_setsoundapiname(const wchar_t *apiname); +void about_set_fontrom_loaded(bool loaded); +void about_set_adpcmrom_loaded(bool loaded); + +#endif // MYON_FMPLAYER_WIN32_ABOUT_H_INCLUDED diff --git a/win32/fmplayer.mak b/win32/fmplayer.mak index 180de1c..14e3246 100644 --- a/win32/fmplayer.mak +++ b/win32/fmplayer.mak @@ -35,6 +35,7 @@ OBJBASE=main \ guid \ fmplayer_file \ fmplayer_file_win \ + about \ $(FMDRIVER_OBJS) \ $(LIBOPNA_OBJS) \ $(TONEDATA_OBJS) \ diff --git a/win32/main.c b/win32/main.c index 8dc6bb8..76cd883 100644 --- a/win32/main.c +++ b/win32/main.c @@ -19,6 +19,7 @@ #include "toneview.h" #include "oscillo/oscillo.h" #include "oscilloview.h" +#include "about.h" enum { ID_OPENFILE = 0x10, @@ -26,6 +27,7 @@ enum { ID_2X, ID_TONEVIEW, ID_OSCILLOVIEW, + ID_ABOUT, }; #define FMPLAYER_CLASSNAME L"myon_fmplayer_ym2608_win32" @@ -62,7 +64,8 @@ static struct { HWND mainwnd; WNDPROC btn_defproc; HWND driverinfo; - HWND button_2x; + HWND button_2x, button_toneview, button_oscilloview, button_about; + bool toneview_on, oscilloview_on, about_on; const wchar_t *lastopenpath; bool fmdsp_2x; struct oscillodata oscillodata_audiothread[LIBOPNA_OSCILLO_TRACK_COUNT]; @@ -140,6 +143,7 @@ static bool loadfontrom(void) { CloseHandle(file); fmdsp_font_from_font_rom(&g.font, g.fontrom); g.font_loaded = true; + about_set_fontrom_loaded(true); return true; err_file: CloseHandle(file); @@ -178,6 +182,7 @@ static void loadrom(void) { || readbytes != OPNA_ROM_SIZE) goto err_buf; CloseHandle(file); g.drum_rom = buf; + about_set_adpcmrom_loaded(true); return; err_buf: HeapFree(g.heap, 0, buf); @@ -229,6 +234,7 @@ static void openfile(HWND hwnd, const wchar_t *path) { g.sound = sound_init(hwnd, SRATE, SECTLEN, sound_cb, &g.opna_timer); SetWindowText(g.driverinfo, g.sound->apiname); + about_setsoundapiname(g.sound->apiname); } fmdsp_vram_init(&g.fmdsp, &g.work, g.vram); if (!g.sound) goto err; @@ -327,11 +333,38 @@ static void on_dropfiles(HWND hwnd, HDROP hdrop) { } #endif // ENABLE_WM_DROPFILES -static void mask_set(unsigned mask, bool shift) { - if (shift) { - opna_set_mask(&g.opna, ~mask); +static void mask_set(int p, bool shift, bool control) { + if (!control) { + if (p >= 11) return; + static const unsigned masktbl[11] = { + LIBOPNA_CHAN_FM_1, + LIBOPNA_CHAN_FM_2, + LIBOPNA_CHAN_FM_3, + LIBOPNA_CHAN_FM_4, + LIBOPNA_CHAN_FM_5, + LIBOPNA_CHAN_FM_6, + LIBOPNA_CHAN_SSG_1, + LIBOPNA_CHAN_SSG_2, + LIBOPNA_CHAN_SSG_3, + LIBOPNA_CHAN_DRUM_ALL, + LIBOPNA_CHAN_ADPCM, + }; + unsigned mask = masktbl[p]; + if (shift) { + opna_set_mask(&g.opna, ~mask); + ppz8_set_mask(&g.ppz8, -1); + } else { + opna_set_mask(&g.opna, opna_get_mask(&g.opna) ^ mask); + } } else { - opna_set_mask(&g.opna, opna_get_mask(&g.opna) ^ mask); + if (p >= 8) return; + unsigned mask = 1u<