diff options
| author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-04-03 22:26:21 +0900 | 
|---|---|---|
| committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-04-03 22:26:21 +0900 | 
| commit | 4a55b8d74132daa7b9c2b09c337532e5b0683cbf (patch) | |
| tree | f32a8ce12b44ace66d9e889b6f210164e4489b37 /win32 | |
| parent | 813ed6d6c17d4b3c99e3d237872041f1a0047f97 (diff) | |
win32: add about dialog
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/about.c | 197 | ||||
| -rw-r--r-- | win32/about.h | 14 | ||||
| -rw-r--r-- | win32/fmplayer.mak | 1 | ||||
| -rw-r--r-- | win32/main.c | 148 | ||||
| -rw-r--r-- | win32/oscilloview.c | 14 | ||||
| -rw-r--r-- | win32/oscilloview.h | 3 | 
6 files changed, 347 insertions, 30 deletions
| 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 <windowsx.h> +#include <stdbool.h> +#include <wchar.h> +#include <stdlib.h> +#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 <windows.h> +#include <stdbool.h> + +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<<p; +    if (shift) { +      ppz8_set_mask(&g.ppz8, ~mask); +      opna_set_mask(&g.opna, -1); +    } else { +      ppz8_set_mask(&g.ppz8, ppz8_get_mask(&g.ppz8) ^ mask); +    }    }  } @@ -382,45 +415,48 @@ static bool proc_key(UINT vk, bool down, int repeat) {        }      } else {        bool shift = GetKeyState(VK_SHIFT) & 0x8000U; +      bool ctrl = GetKeyState(VK_CONTROL) & 0x8000U;        switch (vk) {        case '1': -        mask_set(LIBOPNA_CHAN_FM_1, shift); +        mask_set(0, shift, ctrl);          return true;        case '2': -        mask_set(LIBOPNA_CHAN_FM_2, shift); +        mask_set(1, shift, ctrl);          return true;        case '3': -        mask_set(LIBOPNA_CHAN_FM_3, shift); +        mask_set(2, shift, ctrl);          return true;        case '4': -        mask_set(LIBOPNA_CHAN_FM_4, shift); +        mask_set(3, shift, ctrl);          return true;        case '5': -        mask_set(LIBOPNA_CHAN_FM_5, shift); +        mask_set(4, shift, ctrl);          return true;        case '6': -        mask_set(LIBOPNA_CHAN_FM_6, shift); +        mask_set(5, shift, ctrl);          return true;        case '7': -        mask_set(LIBOPNA_CHAN_SSG_1, shift); +        mask_set(6, shift, ctrl);          return true;        case '8': -        mask_set(LIBOPNA_CHAN_SSG_2, shift); +        mask_set(7, shift, ctrl);          return true;        case '9': -        mask_set(LIBOPNA_CHAN_SSG_3, shift); +        mask_set(8, shift, ctrl);          return true;        case '0': -        mask_set(LIBOPNA_CHAN_DRUM_ALL, shift); +        mask_set(9, shift, ctrl);          return true;        case VK_OEM_MINUS: -        mask_set(LIBOPNA_CHAN_ADPCM, shift); +        mask_set(10, shift, ctrl);          return true;        case VK_OEM_PLUS:          opna_set_mask(&g.opna, ~opna_get_mask(&g.opna)); +        ppz8_set_mask(&g.ppz8, ~ppz8_get_mask(&g.ppz8));          return true;        case VK_OEM_5:          opna_set_mask(&g.opna, 0); +        ppz8_set_mask(&g.ppz8, 0);          return true;        }      } @@ -498,30 +534,40 @@ static bool on_create(HWND hwnd, CREATESTRUCT *cs) {      30, 25,      hwnd, (HMENU)ID_2X, g.hinst, 0    ); -  HWND button_toneview = CreateWindowEx( +  g.button_toneview = CreateWindowEx(      0,      L"BUTTON",      L"&Tone viewer", -    WS_TABSTOP | WS_VISIBLE | WS_CHILD, +    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_PUSHLIKE,      250, 10,      100, 25,      hwnd, (HMENU)ID_TONEVIEW, g.hinst, 0    ); -  HWND button_oscilloview = CreateWindowEx( +  g.button_oscilloview = CreateWindowEx(      0,      L"BUTTON",      L"Oscillo&view", -    WS_TABSTOP | WS_VISIBLE | WS_CHILD, +    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_PUSHLIKE,      355, 10,      100, 25,      hwnd, (HMENU)ID_OSCILLOVIEW, g.hinst, 0    ); +  g.button_about = CreateWindowEx( +    0, +    L"BUTTON", +    L"&About", +    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_PUSHLIKE, +    580, 10, +    50, 25, +    hwnd, (HMENU)ID_ABOUT, g.hinst, 0 +  );    g.btn_defproc = (WNDPROC)GetWindowLongPtr(button, GWLP_WNDPROC);    SetWindowLongPtr(button, GWLP_WNDPROC, (intptr_t)btn_wndproc);    SetWindowLongPtr(pbutton, GWLP_WNDPROC, (intptr_t)btn_wndproc);    SetWindowLongPtr(g.button_2x, GWLP_WNDPROC, (intptr_t)btn_wndproc); -  SetWindowLongPtr(button_toneview, GWLP_WNDPROC, (intptr_t)btn_wndproc); -  SetWindowLongPtr(button_oscilloview, GWLP_WNDPROC, (intptr_t)btn_wndproc); +  SetWindowLongPtr(g.button_toneview, GWLP_WNDPROC, (intptr_t)btn_wndproc); +  SetWindowLongPtr(g.button_oscilloview, GWLP_WNDPROC, (intptr_t)btn_wndproc); +  SetWindowLongPtr(g.button_about, GWLP_WNDPROC, (intptr_t)btn_wndproc);    NONCLIENTMETRICS ncm;    ncm.cbSize = sizeof(ncm);    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); @@ -530,8 +576,9 @@ static bool on_create(HWND hwnd, CREATESTRUCT *cs) {    SetWindowFont(pbutton, font, TRUE);    SetWindowFont(g.driverinfo, font, TRUE);    SetWindowFont(g.button_2x, font, TRUE); -  SetWindowFont(button_toneview, font, TRUE); -  SetWindowFont(button_oscilloview, font, TRUE); +  SetWindowFont(g.button_toneview, font, TRUE); +  SetWindowFont(g.button_oscilloview, font, TRUE); +  SetWindowFont(g.button_about, font, TRUE);    loadrom();    loadfont();    fmdsp_init(&g.fmdsp, g.font_loaded ? &g.font : 0); @@ -544,6 +591,24 @@ static bool on_create(HWND hwnd, CREATESTRUCT *cs) {    return true;  } +static void toneview_close_cb(void *ptr) { +  (void)ptr; +  g.toneview_on = false; +  Button_SetCheck(g.button_toneview, false); +} + +static void oscilloview_close_cb(void *ptr) { +  (void)ptr; +  g.oscilloview_on = false; +  Button_SetCheck(g.button_oscilloview, false); +} + +static void about_close_cb(void *ptr) { +  (void)ptr; +  g.about_on = false; +  Button_SetCheck(g.button_about, false); +} +  static void on_command(HWND hwnd, int id, HWND hwnd_c, UINT code) {    (void)code;    (void)hwnd_c; @@ -561,10 +626,37 @@ static void on_command(HWND hwnd, int id, HWND hwnd_c, UINT code) {      toggle_2x(hwnd);      break;    case ID_TONEVIEW: -    show_toneview(g.hinst, hwnd); +    if (!g.toneview_on) { +      g.toneview_on = true; +      toneview_open(g.hinst, hwnd, toneview_close_cb, 0); +      Button_SetCheck(g.button_toneview, true); +    } else { +      g.toneview_on = false; +      toneview_close(); +      Button_SetCheck(g.button_toneview, false); +    }      break;    case ID_OSCILLOVIEW: -    show_oscilloview(g.hinst, hwnd); +    if (!g.oscilloview_on) { +      g.oscilloview_on = true; +      oscilloview_open(g.hinst, hwnd, oscilloview_close_cb, 0); +      Button_SetCheck(g.button_oscilloview, true); +    } else { +      g.oscilloview_on = false; +      oscilloview_close(); +      Button_SetCheck(g.button_oscilloview, false); +    } +    break; +  case ID_ABOUT: +    if (!g.about_on) { +      g.about_on = true; +      about_open(g.hinst, hwnd, about_close_cb, 0); +      Button_SetCheck(g.button_about, true); +    } else { +      g.about_on = false; +      about_close(); +      Button_SetCheck(g.button_about, false); +    }      break;    }  } @@ -744,13 +836,13 @@ int CALLBACK wWinMain(HINSTANCE hinst, HINSTANCE hpinst,    wr.bottom = 480;    AdjustWindowRectEx(&wr, style, 0, exStyle);  #ifdef _WIN64 -#define WIN64STR "(amd64)" +#define WIN64STR "(amd64) "  #else  #define WIN64STR ""  #endif    g.mainwnd = CreateWindowEx(      exStyle, -    (wchar_t*)((uintptr_t)wcatom), L"FMPlayer/Win32 " WIN64STR " v" FMPLAYER_VERSION_STR, +    (wchar_t*)((uintptr_t)wcatom), L"FMPlayer/Win32 " WIN64STR "v" FMPLAYER_VERSION_STR,      style,      CW_USEDEFAULT, CW_USEDEFAULT,      wr.right-wr.left, wr.bottom-wr.top, diff --git a/win32/oscilloview.c b/win32/oscilloview.c index 1478614..12851f4 100644 --- a/win32/oscilloview.c +++ b/win32/oscilloview.c @@ -24,12 +24,15 @@ static struct {    struct oscillodata oscillodata[LIBOPNA_OSCILLO_TRACK_COUNT];    UINT mmtimer;    HPEN whitepen; +  void (*closecb)(void *ptr); +  void *cbptr;  } g;  static void on_destroy(HWND hwnd) {    g.oscilloview = 0;    timeKillEvent(g.mmtimer);    DeleteObject(g.whitepen); +  if (g.closecb) g.closecb(g.cbptr);  }  static void CALLBACK mmtimer_cb(UINT timerid, UINT msg, @@ -111,7 +114,9 @@ static LRESULT CALLBACK wndproc(    return DefWindowProc(hwnd, msg, wParam, lParam);  } -void show_oscilloview(HINSTANCE hinst, HWND parent) { +void oscilloview_open(HINSTANCE hinst, HWND parent, void (*closecb)(void *ptr), void *cbptr) { +  g.closecb = closecb; +  g.cbptr = cbptr;    g.hinst = hinst;    g.parent = parent;    if (!g.oscilloview) { @@ -140,3 +145,10 @@ void show_oscilloview(HINSTANCE hinst, HWND parent) {      SetForegroundWindow(g.oscilloview);    }  } + +void oscilloview_close(void) { +  if (g.oscilloview) { +    g.closecb = 0; +    DestroyWindow(g.oscilloview); +  } +} diff --git a/win32/oscilloview.h b/win32/oscilloview.h index 8849830..00d2e60 100644 --- a/win32/oscilloview.h +++ b/win32/oscilloview.h @@ -13,7 +13,8 @@ extern struct oscilloview {    struct oscillodata oscillodata[LIBOPNA_OSCILLO_TRACK_COUNT];  } oscilloview_g; -void show_oscilloview(HINSTANCE hinst, HWND parent); +void oscilloview_open(HINSTANCE hinst, HWND parent, void (*closecb)(void *ptr), void *cbptr); +void oscilloview_close(void);  #endif // MYON_FMPLAYER_WIN32_OSCILLOVIEW_H_INCLUDED | 
