diff options
| author | Nicholas Tay <nick@windblume.net> | 2022-05-07 23:00:13 +1000 | 
|---|---|---|
| committer | Nicholas Tay <nick@windblume.net> | 2022-05-07 23:00:13 +1000 | 
| commit | ecb4cff6f34783fd345419c0069c685793521e80 (patch) | |
| tree | 2c21821cb000f86d72d7c8512ea27bdbe59bb5c3 | |
| parent | 740a0d2203a56033c630da2f11731f8f34df806d (diff) | |
| download | clak-ecb4cff6f34783fd345419c0069c685793521e80.tar.gz clak-ecb4cff6f34783fd345419c0069c685793521e80.tar.bz2 clak-ecb4cff6f34783fd345419c0069c685793521e80.zip | |
Windows low-level hook working
Had to do some stuff with the previous VK tracking, just like what I had
to do in C# with Meccha, since it keeps firing events.
GetMessage part also just blocks to ensure we keep receiving Windows
events, but not sure what to do otherwise.
Diffstat (limited to '')
| -rw-r--r-- | clak.c | 90 | 
1 files changed, 85 insertions, 5 deletions
| @@ -1,6 +1,7 @@  #include <stdio.h>  #include <unistd.h>  #include <string.h> +#include <signal.h>  #include <windows.h> @@ -25,9 +26,9 @@ void sound_init(void)  	waveOutSetVolume(NULL, (channel_volume << 16) | channel_volume);  } -void sound_play(unsigned char* buffer) +void sound_play(unsigned char *buffer)  { -	PlaySound((const char *) buffer, NULL, SND_MEMORY | SND_SYNC | SND_NODEFAULT); +	PlaySound((const char *) buffer, NULL, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);  }  Board *get_board(char *board_name) @@ -39,9 +40,77 @@ Board *get_board(char *board_name)  	return NULL;  } +HHOOK keyboard_hook_windows; + +void keyboard_unhook(void) +{ +	fprintf(stderr, "Cleaning up keyboard hook...\n"); +	if (!UnhookWindowsHookEx(keyboard_hook_windows)) +		printf("WARN: Windows keyboard hook could not be cleaned up! Error code: %lu\n", GetLastError()); +} + +void do_exit(int code) +{ +	keyboard_unhook(); +	fprintf(stderr, "Goodbye.\n"); +	exit(code); +} +void on_clean_exit(void) { do_exit(0); } + +Board *board = NULL; + +void keyboard_on_down(void) +{ +	if (board == NULL) +		return; +	sound_play(board->wav); +} + +void keyboard_on_up(void) +{ +	// if (board == NULL) +	// 	return; +} + +/* https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v=vs.85) */ +LRESULT CALLBACK keyboard_windows_callback(int nCode, WPARAM wParam, LPARAM lParam) +{ +	/* Needed to prevent repeat fires */ +	static DWORD prev_vk = 0; + +	/* Do not handle unless nCode >= 0, pass to next hook right away */ +	if (nCode >= 0) { +		BOOL down = wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN; +		KBDLLHOOKSTRUCT *hook_struct = (KBDLLHOOKSTRUCT *) lParam; +		DWORD vk = hook_struct->vkCode; +		if (down && vk != prev_vk) { +			keyboard_on_down(); +			prev_vk = vk; +		} else { +			keyboard_on_up(); +			/* Seems like repeat strokes are 0x0 or 0x1, and 'real' ones have 0x80 flag?? +			   Not really sure how to handle this one, can't find many docs... +			   Saw this though: https://github.com/pyglet/pyglet/blob/838d004d68fcc5c3ce83b733e3d088fad0643859/pyglet/window/win32/__init__.py#L794= */ +			if (hook_struct->flags & 0x80) +				prev_vk = 0; +		} +	} + +	return CallNextHookEx(NULL, nCode, wParam, lParam); +} + +void keyboard_hook(void) +{ +	fprintf(stderr, "Setting up keyboard hook...\n"); +	keyboard_hook_windows = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_windows_callback, NULL, 0); +	if (keyboard_hook_windows == NULL) { +		printf("ERROR: Could not set up Windows keyboard hook.\n"); +		do_exit(1); +	} +} +  int main(int argc, char **argv)  { -	Board *board;  	if (argc < 2 || (board = get_board(argv[1])) == NULL) {  		printf("Please provide a valid board name.\n");  		printf("Valid boards: "); @@ -52,8 +121,19 @@ int main(int argc, char **argv)  	}  	sound_init(); -	printf("name: %s\n", board->name); -	sound_play(board->wav); +	keyboard_hook(); +	atexit(on_clean_exit); +	fprintf(stderr, "Hooks set up, welcome to Clak!\n"); + +	MSG msg; +	BOOL status; +	while ((status = GetMessage(&msg, NULL, 0, 0))) { +		if (status == -1) { +			// error case +			printf("ERROR: Windows error, code %lu\n", GetLastError()); +			exit(1); +		} +	}  	return 0;  }
\ No newline at end of file | 
