diff options
| author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-03-27 23:33:40 +0900 | 
|---|---|---|
| committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-03-27 23:33:40 +0900 | 
| commit | 30c59a00956142aafda87c0bdc71c46d1a2218ff (patch) | |
| tree | 0bf1c81767dc8edb86ade2a4e224392e2ac5280b /win32 | |
| parent | 0073f2b8befc6163f2970cb7a01e75fffc95994e (diff) | |
add oscilloscope view
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/oscilloview.c | 139 | ||||
| -rw-r--r-- | win32/oscilloview.h | 19 | 
2 files changed, 158 insertions, 0 deletions
| diff --git a/win32/oscilloview.c b/win32/oscilloview.c new file mode 100644 index 0000000..9759cc1 --- /dev/null +++ b/win32/oscilloview.c @@ -0,0 +1,139 @@ +#include "oscilloview.h" +#include <mmsystem.h> +#include <shellapi.h> +#include <windowsx.h> + +enum { +  TIMER_UPDATE = 1 +}; + +struct oscilloview oscilloview_g = { +  .flag = ATOMIC_FLAG_INIT +}; + +enum { +  VIEW_SAMPLES = 1024, +  VIEW_SKIP = 2, +}; + +static struct { +  HINSTANCE hinst; +  HWND parent; +  HWND oscilloview; +  ATOM oscilloview_class; +  struct oscillodata oscillodata[LIBOPNA_OSCILLO_TRACK_COUNT]; +  UINT mmtimer; +} g; + +static void on_destroy(HWND hwnd) { +  g.oscilloview = 0; +  timeKillEvent(g.mmtimer); +} + +static void CALLBACK mmtimer_cb(UINT timerid, UINT msg, +                                DWORD_PTR userptr, +                                DWORD_PTR dw1, DWORD_PTR dw2) { +  PostMessage(g.oscilloview, WM_USER, 0, 0); +} + +static bool on_create(HWND hwnd, const CREATESTRUCT *cs) { +  ShowWindow(hwnd, SW_SHOW); +  //SetTimer(hwnd, TIMER_UPDATE, 16, 0); +  g.mmtimer = timeSetEvent(16, 16, mmtimer_cb, 0, TIME_PERIODIC); +  DragAcceptFiles(hwnd, TRUE); +  return true; +} + +static void draw_track(HDC dc, +                       int x, int y, int w, int h, +                       const struct oscillodata *data) { +  int start = OSCILLO_SAMPLE_COUNT - VIEW_SAMPLES; +  start -= (data->offset >> OSCILLO_OFFSET_SHIFT); +  if (start < 0) start = 0; +  MoveToEx(dc, x, y + h/2.0 - (data->buf[start] / 16384.0) * h/2, 0); +  for (int i = 0; i < (VIEW_SAMPLES / VIEW_SKIP); i++) { +    LineTo(dc, (double)x + ((i)*w)/(VIEW_SAMPLES / VIEW_SKIP), y + h/2.0 - (data->buf[start + i*VIEW_SKIP] / 16384.0) * h/2); +  } +} + +static void on_paint(HWND hwnd) { +  RECT cr; +  GetClientRect(hwnd, &cr); +  PAINTSTRUCT ps; +  HDC dc = BeginPaint(hwnd, &ps); +  HDC mdc = CreateCompatibleDC(dc); +  HBITMAP bitmap = CreateCompatibleBitmap(dc, cr.right, cr.bottom); +  SelectObject(mdc, bitmap); + +  FillRect(mdc, &cr, GetStockObject(BLACK_BRUSH)); +  SelectObject(mdc, GetStockObject(WHITE_PEN)); +  int width = cr.right / 3; +  int height = cr.bottom / 3; +  for (int x = 0; x < 3; x++) { +    for (int y = 0; y < 3; y++) { +      draw_track(mdc, x*width, y*height, width, height, &g.oscillodata[x*3+y]); +    } +  } + +  BitBlt(dc, 0, 0, cr.right, cr.bottom, mdc, 0, 0, SRCCOPY); +  SelectObject(mdc, 0); +  DeleteObject(bitmap); +  DeleteDC(mdc); +  EndPaint(hwnd, &ps); +} + +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_TIMER, on_timer); +  HANDLE_MSG(hwnd, WM_PAINT, on_paint); +  case WM_ERASEBKGND: +    return 1; +  case WM_USER: +    if (!atomic_flag_test_and_set_explicit( +      &oscilloview_g.flag, memory_order_acquire)) { +      memcpy(g.oscillodata, +             oscilloview_g.oscillodata, +             sizeof(oscilloview_g.oscillodata)); +      atomic_flag_clear_explicit(&oscilloview_g.flag, memory_order_release); +    } +    InvalidateRect(hwnd, 0, FALSE); +    return 0; +  case WM_DROPFILES: +    return SendMessage(g.parent, msg, wParam, lParam); +  } +  return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void show_oscilloview(HINSTANCE hinst, HWND parent) { +  g.hinst = hinst; +  g.parent = parent; +  if (!g.oscilloview) { +    if (!g.oscilloview_class) { +      WNDCLASS wc = {0}; +      wc.style = 0; +      wc.lpfnWndProc = wndproc; +      wc.hInstance = g.hinst; +      wc.hIcon = LoadIcon(g.hinst, MAKEINTRESOURCE(1)); +      wc.hCursor = LoadCursor(NULL, IDC_ARROW); +      wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); +      wc.lpszClassName = L"myon_fmplayer_ym2608_oscilloviewer"; +      g.oscilloview_class = RegisterClass(&wc); +    } +    if (!g.oscilloview_class) { +      MessageBox(parent, L"Cannot register oscilloviewer class", L"Error", MB_ICONSTOP); +      return; +    } +    g.oscilloview = CreateWindowEx(0, +                                     MAKEINTATOM(g.oscilloview_class), +                                     L"FMPlayer Oscilloview", +                                     WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN | WS_SIZEBOX | WS_MAXIMIZEBOX, +                                     CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, +                                     parent, 0, g.hinst, 0); +  } else { +    SetForegroundWindow(g.oscilloview); +  } +} diff --git a/win32/oscilloview.h b/win32/oscilloview.h new file mode 100644 index 0000000..8849830 --- /dev/null +++ b/win32/oscilloview.h @@ -0,0 +1,19 @@ +#ifndef MYON_FMPLAYER_WIN32_OSCILLOVIEW_H_INCLUDED +#define MYON_FMPLAYER_WIN32_OSCILLOVIEW_H_INCLUDED + +#include "libopna/opna.h" +#include "oscillo/oscillo.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <stdatomic.h> + +extern struct oscilloview { +  atomic_flag flag; +  struct oscillodata oscillodata[LIBOPNA_OSCILLO_TRACK_COUNT]; +} oscilloview_g; + +void show_oscilloview(HINSTANCE hinst, HWND parent); + +#endif // MYON_FMPLAYER_WIN32_OSCILLOVIEW_H_INCLUDED + | 
