Преглед изворни кода

Merge pull request #3241 from Hyrtwol/sys-windows

Gathered what I made for sys/windows
gingerBill пре 1 година
родитељ
комит
0e168dd292

+ 45 - 0
core/sys/windows/gdi32.odin

@@ -1,6 +1,8 @@
 // +build windows
 package sys_windows
 
+import "core:math/fixed"
+
 foreign import gdi32 "system:Gdi32.lib"
 
 @(default_calling_convention="system")
@@ -11,6 +13,7 @@ foreign gdi32 {
 	SetBkColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF ---
 
 	CreateCompatibleDC :: proc(hdc: HDC) -> HDC ---
+	DeleteDC :: proc(hdc: HDC) -> BOOL ---
 
 	CreateDIBPatternBrush :: proc(h: HGLOBAL, iUsage: UINT) -> HBRUSH ---
 
@@ -93,3 +96,45 @@ foreign gdi32 {
 RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF {
 	return transmute(COLORREF)[4]u8{r, g, b, 0}
 }
+
+FXPT2DOT30 :: distinct fixed.Fixed(i32, 30)
+
+CIEXYZ :: struct {
+	ciexyzX: FXPT2DOT30,
+	ciexyzY: FXPT2DOT30,
+	ciexyzZ: FXPT2DOT30,
+}
+
+CIEXYZTRIPLE :: struct {
+	ciexyzRed:   CIEXYZ,
+	ciexyzGreen: CIEXYZ,
+	ciexyzBlue:  CIEXYZ,
+}
+
+// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header
+BITMAPV5HEADER :: struct {
+	bV5Size:          DWORD,
+	bV5Width:         LONG,
+	bV5Height:        LONG,
+	bV5Planes:        WORD,
+	bV5BitCount:      WORD,
+	bV5Compression:   DWORD,
+	bV5SizeImage:     DWORD,
+	bV5XPelsPerMeter: LONG,
+	bV5YPelsPerMeter: LONG,
+	bV5ClrUsed:       DWORD,
+	bV5ClrImportant:  DWORD,
+	bV5RedMask:       DWORD,
+	bV5GreenMask:     DWORD,
+	bV5BlueMask:      DWORD,
+	bV5AlphaMask:     DWORD,
+	bV5CSType:        DWORD,
+	bV5Endpoints:     CIEXYZTRIPLE,
+	bV5GammaRed:      DWORD,
+	bV5GammaGreen:    DWORD,
+	bV5GammaBlue:     DWORD,
+	bV5Intent:        DWORD,
+	bV5ProfileData:   DWORD,
+	bV5ProfileSize:   DWORD,
+	bV5Reserved:      DWORD,
+}

+ 19 - 0
core/sys/windows/kernel32.odin

@@ -1200,3 +1200,22 @@ SYSTEM_LOGICAL_PROCESSOR_INFORMATION :: struct {
 	Relationship: LOGICAL_PROCESSOR_RELATIONSHIP,
 	DummyUnion: DUMMYUNIONNAME_u,
 }
+
+/* Global Memory Flags */
+GMEM_FIXED          :: 0x0000
+GMEM_MOVEABLE       :: 0x0002
+GMEM_NOCOMPACT      :: 0x0010
+GMEM_NODISCARD      :: 0x0020
+GMEM_ZEROINIT       :: 0x0040
+GMEM_MODIFY         :: 0x0080
+GMEM_DISCARDABLE    :: 0x0100
+GMEM_NOT_BANKED     :: 0x1000
+GMEM_SHARE          :: 0x2000
+GMEM_DDESHARE       :: 0x2000
+GMEM_NOTIFY         :: 0x4000
+GMEM_LOWER          :: GMEM_NOT_BANKED
+GMEM_VALID_FLAGS    :: 0x7F72
+GMEM_INVALID_HANDLE :: 0x8000
+
+GHND                :: (GMEM_MOVEABLE | GMEM_ZEROINIT)
+GPTR                :: (GMEM_FIXED | GMEM_ZEROINIT)

+ 51 - 0
core/sys/windows/shell32.odin

@@ -25,6 +25,7 @@ foreign shell32 {
 	SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR ---
 
 	Shell_NotifyIconW :: proc(dwMessage: DWORD, lpData: ^NOTIFYICONDATAW) -> BOOL ---
+	SHChangeNotify :: proc(wEventId: LONG, uFlags: UINT, dwItem1: LPCVOID, dwItem2: LPCVOID) ---
 
 	SHGetKnownFolderIDList :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppidl: rawptr) -> HRESULT ---
 	SHSetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, pszPath: PCWSTR ) -> HRESULT ---
@@ -91,3 +92,53 @@ KNOWN_FOLDER_FLAG :: enum u32 {
 	SIMPLE_IDLIST                    = 0x00000100,
 	ALIAS_ONLY                       = 0x80000000,
 }
+
+SHCNRF_InterruptLevel     :: 0x0001
+SHCNRF_ShellLevel         :: 0x0002
+SHCNRF_RecursiveInterrupt :: 0x1000
+SHCNRF_NewDelivery        :: 0x8000
+
+SHCNE_RENAMEITEM          :: 0x00000001
+SHCNE_CREATE              :: 0x00000002
+SHCNE_DELETE              :: 0x00000004
+SHCNE_MKDIR               :: 0x00000008
+SHCNE_RMDIR               :: 0x00000010
+SHCNE_MEDIAINSERTED       :: 0x00000020
+SHCNE_MEDIAREMOVED        :: 0x00000040
+SHCNE_DRIVEREMOVED        :: 0x00000080
+SHCNE_DRIVEADD            :: 0x00000100
+SHCNE_NETSHARE            :: 0x00000200
+SHCNE_NETUNSHARE          :: 0x00000400
+SHCNE_ATTRIBUTES          :: 0x00000800
+SHCNE_UPDATEDIR           :: 0x00001000
+SHCNE_UPDATEITEM          :: 0x00002000
+SHCNE_SERVERDISCONNECT    :: 0x00004000
+SHCNE_UPDATEIMAGE         :: 0x00008000
+SHCNE_DRIVEADDGUI         :: 0x00010000
+SHCNE_RENAMEFOLDER        :: 0x00020000
+SHCNE_FREESPACE           :: 0x00040000
+
+SHCNE_EXTENDED_EVENT      :: 0x04000000
+
+SHCNE_ASSOCCHANGED        :: 0x08000000
+
+SHCNE_DISKEVENTS          :: 0x0002381F
+SHCNE_GLOBALEVENTS        :: 0x0C0581E0
+SHCNE_ALLEVENTS           :: 0x7FFFFFFF
+SHCNE_INTERRUPT           :: 0x80000000
+
+SHCNEE_ORDERCHANGED       :: 2
+SHCNEE_MSI_CHANGE         :: 4
+SHCNEE_MSI_UNINSTALL      :: 5
+
+SHCNF_IDLIST              :: 0x0000
+SHCNF_PATHA               :: 0x0001
+SHCNF_PRINTERA            :: 0x0002
+SHCNF_DWORD               :: 0x0003
+SHCNF_PATHW               :: 0x0005
+SHCNF_PRINTERW            :: 0x0006
+SHCNF_TYPE                :: 0x00FF
+SHCNF_FLUSH               :: 0x1000
+SHCNF_FLUSHNOWAIT         :: 0x3000
+
+SHCNF_NOTIFYRECURSIVE     :: 0x10000

+ 78 - 2
core/sys/windows/user32.odin

@@ -47,6 +47,7 @@ foreign user32 {
 	UpdateWindow :: proc(hWnd: HWND) -> BOOL ---
 	SetActiveWindow :: proc(hWnd: HWND) -> HWND ---
 	GetActiveWindow :: proc() -> HWND ---
+	RedrawWindow :: proc(hwnd: HWND, lprcUpdate: LPRECT, hrgnUpdate: HRGN, flags: RedrawWindowFlags) -> BOOL ---
 
 	GetMessageW :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> BOOL ---
 
@@ -85,6 +86,14 @@ foreign user32 {
 	LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR ---
 	LoadImageW :: proc(hInst: HINSTANCE, name: LPCWSTR, type: UINT, cx: c_int, cy: c_int, fuLoad: UINT) -> HANDLE ---
 
+	CreateIcon :: proc(hInstance: HINSTANCE, nWidth: c_int, nHeight: c_int, cPlanes: BYTE, cBitsPixel: BYTE, lpbANDbits: PBYTE, lpbXORbits: PBYTE) -> HICON ---
+	CreateIconFromResource :: proc(presbits: PBYTE, dwResSize: DWORD, fIcon: BOOL, dwVer: DWORD) -> HICON ---
+	DestroyIcon :: proc(hIcon: HICON) -> BOOL ---
+	DrawIcon :: proc(hDC: HDC, X: c_int, Y: c_int, hIcon: HICON) -> BOOL ---
+
+	CreateCursor :: proc(hInst: HINSTANCE, xHotSpot: c_int, yHotSpot: c_int, nWidth: c_int, nHeight: c_int, pvANDPlane: PVOID, pvXORPlane: PVOID) -> HCURSOR ---
+	DestroyCursor :: proc(hCursor: HCURSOR) -> BOOL ---
+
 	GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---
 	GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---
 	ClientToScreen :: proc(hWnd: HWND, lpPoint: LPPOINT) -> BOOL ---
@@ -134,7 +143,7 @@ foreign user32 {
 
 	GetKeyState :: proc(nVirtKey: c_int) -> SHORT ---
 	GetAsyncKeyState :: proc(vKey: c_int) -> SHORT ---
-	
+
 	GetKeyboardState :: proc(lpKeyState: PBYTE) -> BOOL ---
 
 	MapVirtualKeyW :: proc(uCode: UINT, uMapType: UINT) -> UINT ---
@@ -166,7 +175,7 @@ foreign user32 {
 	MonitorFromRect   :: proc(lprc: LPRECT, dwFlags: Monitor_From_Flags) -> HMONITOR ---
 	MonitorFromWindow :: proc(hwnd: HWND, dwFlags: Monitor_From_Flags) -> HMONITOR ---
 	EnumDisplayMonitors :: proc(hdc: HDC, lprcClip: LPRECT, lpfnEnum: Monitor_Enum_Proc, dwData: LPARAM) -> BOOL ---
-	
+
 	EnumWindows :: proc(lpEnumFunc: Window_Enum_Proc, lParam: LPARAM) -> BOOL ---
 
 	SetThreadDpiAwarenessContext :: proc(dpiContext: DPI_AWARENESS_CONTEXT) -> DPI_AWARENESS_CONTEXT ---
@@ -239,6 +248,9 @@ foreign user32 {
 
 	GetSystemMenu :: proc(hWnd: HWND, bRevert: BOOL) -> HMENU ---
 	EnableMenuItem :: proc(hMenu: HMENU, uIDEnableItem: UINT, uEnable: UINT) -> BOOL ---
+
+	DrawTextW :: proc(hdc: HDC, lpchText: LPCWSTR, cchText: INT, lprc: LPRECT, format: DrawTextFormat) -> INT ---
+	DrawTextExW :: proc(hdc: HDC, lpchText: LPCWSTR, cchText: INT, lprc: LPRECT, format: DrawTextFormat, lpdtp: PDRAWTEXTPARAMS) -> INT ---
 }
 
 CreateWindowW :: #force_inline proc "system" (
@@ -471,6 +483,19 @@ RI_MOUSE_BUTTON_5_UP :: 0x0200
 RI_MOUSE_WHEEL :: 0x0400
 RI_MOUSE_HWHEEL :: 0x0800
 
+HID_USAGE_PAGE_GENERIC :: 0x01
+HID_USAGE_PAGE_GAME :: 0x05
+HID_USAGE_PAGE_LED :: 0x08
+HID_USAGE_PAGE_BUTTON :: 0x09
+
+HID_USAGE_GENERIC_POINTER :: 0x01
+HID_USAGE_GENERIC_MOUSE :: 0x02
+HID_USAGE_GENERIC_JOYSTICK :: 0x04
+HID_USAGE_GENERIC_GAMEPAD :: 0x05
+HID_USAGE_GENERIC_KEYBOARD :: 0x06
+HID_USAGE_GENERIC_KEYPAD :: 0x07
+HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER :: 0x08
+
 WINDOWPLACEMENT :: struct {
 	length: UINT,
 	flags: UINT,
@@ -493,3 +518,54 @@ WINDOWINFO :: struct {
 	wCreatorVersion: WORD,
 }
 PWINDOWINFO :: ^WINDOWINFO
+
+DRAWTEXTPARAMS :: struct {
+       cbSize         : UINT ,
+       iTabLength: int  ,
+       iLeftMargin: int  ,
+       iRightMargin: int  ,
+       uiLengthDrawn: UINT ,
+}
+PDRAWTEXTPARAMS :: ^DRAWTEXTPARAMS
+
+DrawTextFormat :: enum UINT {
+	DT_TOP                  = 0x00000000,
+	DT_LEFT                 = 0x00000000,
+	DT_CENTER               = 0x00000001,
+	DT_RIGHT                = 0x00000002,
+	DT_VCENTER              = 0x00000004,
+	DT_BOTTOM               = 0x00000008,
+	DT_WORDBREAK            = 0x00000010,
+	DT_SINGLELINE           = 0x00000020,
+	DT_EXPANDTABS           = 0x00000040,
+	DT_TABSTOP              = 0x00000080,
+	DT_NOCLIP               = 0x00000100,
+	DT_EXTERNALLEADING      = 0x00000200,
+	DT_CALCRECT             = 0x00000400,
+	DT_NOPREFIX             = 0x00000800,
+	DT_INTERNAL             = 0x00001000,
+	DT_EDITCONTROL          = 0x00002000,
+	DT_PATH_ELLIPSIS        = 0x00004000,
+	DT_END_ELLIPSIS         = 0x00008000,
+	DT_MODIFYSTRING         = 0x00010000,
+	DT_RTLREADING           = 0x00020000,
+	DT_WORD_ELLIPSIS        = 0x00040000,
+	DT_NOFULLWIDTHCHARBREAK = 0x00080000,
+	DT_HIDEPREFIX           = 0x00100000,
+	DT_PREFIXONLY           = 0x00200000,
+}
+
+RedrawWindowFlags :: enum UINT {
+	RDW_INVALIDATE      = 0x0001,
+	RDW_INTERNALPAINT   = 0x0002,
+	RDW_ERASE           = 0x0004,
+	RDW_VALIDATE        = 0x0008,
+	RDW_NOINTERNALPAINT = 0x0010,
+	RDW_NOERASE         = 0x0020,
+	RDW_NOCHILDREN      = 0x0040,
+	RDW_ALLCHILDREN     = 0x0080,
+	RDW_UPDATENOW       = 0x0100,
+	RDW_ERASENOW        = 0x0200,
+	RDW_FRAME           = 0x0400,
+	RDW_NOFRAME         = 0x0800,
+}

+ 205 - 1
core/sys/windows/winmm.odin

@@ -11,6 +11,32 @@ foreign winmm {
 	timeBeginPeriod :: proc(uPeriod: UINT) -> MMRESULT ---
 	timeEndPeriod   :: proc(uPeriod: UINT) -> MMRESULT ---
 	timeGetTime     :: proc() -> DWORD ---
+
+	waveOutGetNumDevs :: proc() -> UINT ---
+	waveOutGetDevCapsW :: proc(uDeviceID: UINT_PTR, pwoc: LPWAVEOUTCAPSW, cbwoc: UINT) -> MMRESULT ---
+	waveOutGetVolume :: proc(hwo: HWAVEOUT, pdwVolume: LPDWORD) -> MMRESULT ---
+	waveOutSetVolume :: proc(hwo: HWAVEOUT, dwVolume: DWORD) -> MMRESULT ---
+	waveOutGetErrorTextW :: proc(mmrError: MMRESULT, pszText: LPWSTR, cchText: UINT) -> MMRESULT ---
+	waveOutOpen :: proc(phwo: LPHWAVEOUT, uDeviceID: UINT, pwfx: LPCWAVEFORMATEX, dwCallback: DWORD_PTR, dwInstance: DWORD_PTR, fdwOpen: DWORD) -> MMRESULT ---
+	waveOutClose :: proc(hwo: HWAVEOUT) -> MMRESULT ---
+	waveOutPrepareHeader :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT ---
+	waveOutUnprepareHeader :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT ---
+	waveOutWrite :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT ---
+	waveOutPause :: proc(hwo: HWAVEOUT) -> MMRESULT ---
+	waveOutRestart :: proc(hwo: HWAVEOUT) -> MMRESULT ---
+	waveOutReset :: proc(hwo: HWAVEOUT) -> MMRESULT ---
+	waveOutBreakLoop :: proc(hwo: HWAVEOUT) -> MMRESULT ---
+	waveOutGetPosition :: proc(hwo: HWAVEOUT, pmmt: LPMMTIME, cbmmt: UINT) -> MMRESULT ---
+	waveOutGetPitch :: proc(hwo: HWAVEOUT, pdwPitch: LPDWORD) -> MMRESULT ---
+	waveOutSetPitch :: proc(hwo: HWAVEOUT, pdwPitch: DWORD) -> MMRESULT ---
+	waveOutGetPlaybackRate :: proc(hwo: HWAVEOUT, pdwRate: LPDWORD) -> MMRESULT ---
+	waveOutSetPlaybackRate :: proc(hwo: HWAVEOUT, pdwRate: DWORD) -> MMRESULT ---
+	waveOutGetID :: proc(hwo: HWAVEOUT, puDeviceID: LPUINT) -> MMRESULT ---
+
+	waveInGetNumDevs :: proc() -> UINT ---
+	waveInGetDevCapsW :: proc(uDeviceID: UINT_PTR, pwic: LPWAVEINCAPSW, cbwic: UINT) -> MMRESULT ---
+
+	PlaySoundW :: proc(pszSound: LPCWSTR, hmod: HMODULE, fdwSound: DWORD) -> BOOL ---
 }
 
 LPTIMECAPS :: ^TIMECAPS
@@ -169,4 +195,182 @@ MCIERR_NO_IDENTITY              :: MCIERR_BASE + 94
 MIXERR_INVALLINE    :: (MIXERR_BASE + 0)
 MIXERR_INVALCONTROL :: (MIXERR_BASE + 1)
 MIXERR_INVALVALUE   :: (MIXERR_BASE + 2)
-MIXERR_LASTERROR    :: (MIXERR_BASE + 2)
+MIXERR_LASTERROR    :: (MIXERR_BASE + 2)
+
+/* waveform output */
+MM_WOM_OPEN  :: 0x3BB
+MM_WOM_CLOSE :: 0x3BC
+MM_WOM_DONE  :: 0x3BD
+/* waveform input */
+MM_WIM_OPEN  :: 0x3BE
+MM_WIM_CLOSE :: 0x3BF
+MM_WIM_DATA  :: 0x3C0
+
+WOM_OPEN  :: MM_WOM_OPEN
+WOM_CLOSE :: MM_WOM_CLOSE
+WOM_DONE  :: MM_WOM_DONE
+WIM_OPEN  :: MM_WIM_OPEN
+WIM_CLOSE :: MM_WIM_CLOSE
+WIM_DATA  :: MM_WIM_DATA
+
+WAVE_MAPPER : UINT : 0xFFFFFFFF // -1
+
+WAVE_FORMAT_QUERY                        :: 0x0001
+WAVE_ALLOWSYNC                           :: 0x0002
+WAVE_MAPPED                              :: 0x0004
+WAVE_FORMAT_DIRECT                       :: 0x0008
+WAVE_FORMAT_DIRECT_QUERY                 :: (WAVE_FORMAT_QUERY | WAVE_FORMAT_DIRECT)
+WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE :: 0x0010
+
+WHDR_DONE      :: 0x00000001 /* done bit */
+WHDR_PREPARED  :: 0x00000002 /* set if this header has been prepared */
+WHDR_BEGINLOOP :: 0x00000004 /* loop start block */
+WHDR_ENDLOOP   :: 0x00000008 /* loop end block */
+WHDR_INQUEUE   :: 0x00000010 /* reserved for driver */
+
+WAVECAPS_PITCH          :: 0x0001 /* supports pitch control */
+WAVECAPS_PLAYBACKRATE   :: 0x0002 /* supports playback rate control */
+WAVECAPS_VOLUME         :: 0x0004 /* supports volume control */
+WAVECAPS_LRVOLUME       :: 0x0008 /* separate left-right volume control */
+WAVECAPS_SYNC           :: 0x0010
+WAVECAPS_SAMPLEACCURATE :: 0x0020
+
+WAVE_INVALIDFORMAT :: 0x00000000 /* invalid format */
+WAVE_FORMAT_1M08   :: 0x00000001 /* 11.025 kHz, Mono,   8-bit  */
+WAVE_FORMAT_1S08   :: 0x00000002 /* 11.025 kHz, Stereo, 8-bit  */
+WAVE_FORMAT_1M16   :: 0x00000004 /* 11.025 kHz, Mono,   16-bit */
+WAVE_FORMAT_1S16   :: 0x00000008 /* 11.025 kHz, Stereo, 16-bit */
+WAVE_FORMAT_2M08   :: 0x00000010 /* 22.05  kHz, Mono,   8-bit  */
+WAVE_FORMAT_2S08   :: 0x00000020 /* 22.05  kHz, Stereo, 8-bit  */
+WAVE_FORMAT_2M16   :: 0x00000040 /* 22.05  kHz, Mono,   16-bit */
+WAVE_FORMAT_2S16   :: 0x00000080 /* 22.05  kHz, Stereo, 16-bit */
+WAVE_FORMAT_4M08   :: 0x00000100 /* 44.1   kHz, Mono,   8-bit  */
+WAVE_FORMAT_4S08   :: 0x00000200 /* 44.1   kHz, Stereo, 8-bit  */
+WAVE_FORMAT_4M16   :: 0x00000400 /* 44.1   kHz, Mono,   16-bit */
+WAVE_FORMAT_4S16   :: 0x00000800 /* 44.1   kHz, Stereo, 16-bit */
+WAVE_FORMAT_44M08  :: 0x00000100 /* 44.1   kHz, Mono,   8-bit  */
+WAVE_FORMAT_44S08  :: 0x00000200 /* 44.1   kHz, Stereo, 8-bit  */
+WAVE_FORMAT_44M16  :: 0x00000400 /* 44.1   kHz, Mono,   16-bit */
+WAVE_FORMAT_44S16  :: 0x00000800 /* 44.1   kHz, Stereo, 16-bit */
+WAVE_FORMAT_48M08  :: 0x00001000 /* 48     kHz, Mono,   8-bit  */
+WAVE_FORMAT_48S08  :: 0x00002000 /* 48     kHz, Stereo, 8-bit  */
+WAVE_FORMAT_48M16  :: 0x00004000 /* 48     kHz, Mono,   16-bit */
+WAVE_FORMAT_48S16  :: 0x00008000 /* 48     kHz, Stereo, 16-bit */
+WAVE_FORMAT_96M08  :: 0x00010000 /* 96     kHz, Mono,   8-bit  */
+WAVE_FORMAT_96S08  :: 0x00020000 /* 96     kHz, Stereo, 8-bit  */
+WAVE_FORMAT_96M16  :: 0x00040000 /* 96     kHz, Mono,   16-bit */
+WAVE_FORMAT_96S16  :: 0x00080000 /* 96     kHz, Stereo, 16-bit */
+
+HWAVE    :: distinct HANDLE
+HWAVEIN  :: distinct HANDLE
+HWAVEOUT :: distinct HANDLE
+
+LPHWAVEIN :: ^HWAVEIN
+LPHWAVEOUT :: ^HWAVEOUT
+
+// https://learn.microsoft.com/en-us/windows/win32/multimedia/multimedia-timer-structures
+MMTIME :: struct {
+	wType: UINT,
+	u: struct #raw_union {
+		ms: DWORD,
+		sample: DWORD,
+		cb: DWORD,
+		ticks: DWORD,
+		smpte: struct {
+			hour: BYTE,
+			min: BYTE,
+			sec: BYTE,
+			frame: BYTE,
+			fps: BYTE,
+			dummy: BYTE,
+			pad: [2]BYTE,
+		},
+		midi: struct {
+			songptrpos: DWORD,
+		},
+	},
+}
+LPMMTIME :: ^MMTIME
+
+MAXPNAMELEN :: 32
+MAXERRORLENGTH :: 256
+MMVERSION :: UINT
+
+/* flags for wFormatTag field of WAVEFORMAT */
+WAVE_FORMAT_PCM :: 1
+
+WAVEFORMATEX :: struct {
+	wFormatTag:      WORD,
+	nChannels:       WORD,
+	nSamplesPerSec:  DWORD,
+	nAvgBytesPerSec: DWORD,
+	nBlockAlign:     WORD,
+	wBitsPerSample:  WORD,
+	cbSize:          WORD,
+}
+LPCWAVEFORMATEX :: ^WAVEFORMATEX
+
+WAVEHDR :: struct {
+	lpData:          LPSTR, /* pointer to locked data buffer */
+	dwBufferLength:  DWORD, /* length of data buffer */
+	dwBytesRecorded: DWORD, /* used for input only */
+	dwUser:          DWORD_PTR, /* for client's use */
+	dwFlags:         DWORD, /* assorted flags (see defines) */
+	dwLoops:         DWORD, /* loop control counter */
+	lpNext:          LPWAVEHDR, /* reserved for driver */
+	reserved:        DWORD_PTR, /* reserved for driver */
+}
+LPWAVEHDR :: ^WAVEHDR
+
+WAVEINCAPSW :: struct {
+	wMid:           WORD, /* manufacturer ID */
+	wPid:           WORD, /* product ID */
+	vDriverVersion: MMVERSION, /* version of the driver */
+	szPname:        [MAXPNAMELEN]WCHAR, /* product name (NULL terminated string) */
+	dwFormats:      DWORD, /* formats supported */
+	wChannels:      WORD, /* number of channels supported */
+	wReserved1:     WORD, /* structure packing */
+}
+LPWAVEINCAPSW :: ^WAVEINCAPSW
+
+WAVEOUTCAPSW :: struct {
+	wMid:           WORD, /* manufacturer ID */
+	wPid:           WORD, /* product ID */
+	vDriverVersion: MMVERSION, /* version of the driver */
+	szPname:        [MAXPNAMELEN]WCHAR, /* product name (NULL terminated string) */
+	dwFormats:      DWORD, /* formats supported */
+	wChannels:      WORD, /* number of sources supported */
+	wReserved1:     WORD, /* packing */
+	dwSupport:      DWORD, /* functionality supported by driver */
+}
+LPWAVEOUTCAPSW :: ^WAVEOUTCAPSW
+
+// flag values for PlaySound
+SND_SYNC		:: 0x0000  /* play synchronously (default) */
+SND_ASYNC		:: 0x0001  /* play asynchronously */
+SND_NODEFAULT	:: 0x0002  /* silence (!default) if sound not found */
+SND_MEMORY		:: 0x0004  /* pszSound points to a memory file */
+SND_LOOP		:: 0x0008  /* loop the sound until next sndPlaySound */
+SND_NOSTOP		:: 0x0010  /* don't stop any currently playing sound */
+
+SND_NOWAIT		:: 0x00002000 /* don't wait if the driver is busy */
+SND_ALIAS		:: 0x00010000 /* name is a registry alias */
+SND_ALIAS_ID	:: 0x00110000 /* alias is a predefined ID */
+SND_FILENAME	:: 0x00020000 /* name is file name */
+SND_RESOURCE	:: 0x00040004 /* name is resource name or atom */
+
+SND_PURGE		:: 0x0040  /* purge non-static events for task */
+SND_APPLICATION	:: 0x0080  /* look for application specific association */
+
+SND_SENTRY		:: 0x00080000 /* Generate a SoundSentry event with this sound */
+SND_RING		:: 0x00100000 /* Treat this as a "ring" from a communications app - don't duck me */
+SND_SYSTEM		:: 0x00200000 /* Treat this as a system sound */
+
+
+CALLBACK_TYPEMASK :: 0x00070000    /* callback type mask */
+CALLBACK_NULL     :: 0x00000000    /* no callback */
+CALLBACK_WINDOW   :: 0x00010000    /* dwCallback is a HWND */
+CALLBACK_TASK     :: 0x00020000    /* dwCallback is a HTASK */
+CALLBACK_FUNCTION :: 0x00030000    /* dwCallback is a FARPROC */
+CALLBACK_THREAD   :: CALLBACK_TASK /* thread ID replaces 16 bit task */
+CALLBACK_EVENT    :: 0x00050000    /* dwCallback is an EVENT Handle */