aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Tay <nick@windblume.net>2022-05-07 23:26:27 +1000
committerNicholas Tay <nick@windblume.net>2022-05-07 23:47:37 +1000
commit047544a5af9100ec269e9222213385bc7794f619 (patch)
tree6a632da957c05fb790fdd63745e99b867c945274
parentecb4cff6f34783fd345419c0069c685793521e80 (diff)
downloadclak-047544a5af9100ec269e9222213385bc7794f619.tar.gz
clak-047544a5af9100ec269e9222213385bc7794f619.tar.bz2
clak-047544a5af9100ec269e9222213385bc7794f619.zip
Split out platform-specific code for Windows
Not sure if I'm really doing it in the best way possible. Feels a bit weird that some place assumes the existence of other functions.
-rw-r--r--Makefile15
-rw-r--r--clak.c86
-rw-r--r--platform/platform.h10
-rw-r--r--platform/win32.c80
4 files changed, 116 insertions, 75 deletions
diff --git a/Makefile b/Makefile
index c2a94a6..bd016b7 100644
--- a/Makefile
+++ b/Makefile
@@ -5,14 +5,23 @@ BOARDS = mxblue quack
CC = gcc
CFLAGS += -std=c99 -Wall -Wextra -Wshadow -Werror -pedantic
-LDLIBS = -lWinmm
BOARD_FILES = $(addsuffix /board.h,$(addprefix board/,$(BOARDS)))
+ifeq ($(OS),Windows_NT)
+ LDLIBS = -lWinmm
+ PLATFORM = win32
+else
+ UNAME_S := $(shell uname)
+ ifeq ($(UNAME_S),Linux)
+ PLATFORM = linux
+ endif
+endif
+
default: $(NAME)
-$(NAME): $(NAME).c $(BOARD_FILES) board/boards.h
- $(CC) $(CFLAGS) $(NAME).c $(LDLIBS) -o $(NAME)
+$(NAME): $(NAME).c platform/$(PLATFORM).c $(BOARD_FILES) board/boards.h
+ $(CC) $(CFLAGS) $(NAME).c platform/$(PLATFORM).c $(LDLIBS) -o $(NAME)
board/boards.h:
printf "#ifndef BOARD_DEFAULTS_H\n#define BOARD_DEFAULTS_H\n\n" > board/boards.h
diff --git a/clak.c b/clak.c
index 99b1482..eace40d 100644
--- a/clak.c
+++ b/clak.c
@@ -1,15 +1,16 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
-#include <signal.h>
-
-#include <windows.h>
+#include <stdbool.h>
+#include <stdlib.h>
#define VOLUME 0.15
#include "board/boards.h"
#define BOARD(str, buf) { .name = str, .wav = buf },
+#include "platform/platform.h"
+
typedef struct {
char *name;
unsigned char* wav;
@@ -20,16 +21,7 @@ Board boards[] = {
};
int const boards_n = sizeof(boards) / sizeof(boards[0]);
-void sound_init(void)
-{
- DWORD channel_volume = VOLUME * 0xFFFF;
- waveOutSetVolume(NULL, (channel_volume << 16) | channel_volume);
-}
-
-void sound_play(unsigned char *buffer)
-{
- PlaySound((const char *) buffer, NULL, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
-}
+Board *board = NULL;
Board *get_board(char *board_name)
{
@@ -40,15 +32,6 @@ 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();
@@ -57,8 +40,6 @@ void do_exit(int code)
}
void on_clean_exit(void) { do_exit(0); }
-Board *board = NULL;
-
void keyboard_on_down(void)
{
if (board == NULL)
@@ -72,43 +53,6 @@ void keyboard_on_up(void)
// 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)
{
if (argc < 2 || (board = get_board(argv[1])) == NULL) {
@@ -120,20 +64,18 @@ int main(int argc, char **argv)
return 1;
}
- sound_init();
- keyboard_hook();
+ if (!sound_init(VOLUME)) {
+ printf("ERROR: Could not initialise sound system.\n");
+ return 1;
+ }
+ if (!keyboard_hook()) {
+ printf("ERROR: Could not set up keyboard hooks.\n");
+ return 1;
+ }
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);
- }
- }
+ enter_idle();
return 0;
} \ No newline at end of file
diff --git a/platform/platform.h b/platform/platform.h
new file mode 100644
index 0000000..da1efa6
--- /dev/null
+++ b/platform/platform.h
@@ -0,0 +1,10 @@
+#ifndef CLAK_PLATFORM_H_
+#define CLAK_PLATFORM_H_
+
+bool sound_init(float volume);
+void sound_play(unsigned char *buffer);
+void keyboard_unhook(void);
+bool keyboard_hook(void);
+void enter_idle(void);
+
+#endif /* CLAK_PLATFORM_H_ */ \ No newline at end of file
diff --git a/platform/win32.c b/platform/win32.c
new file mode 100644
index 0000000..90cd37c
--- /dev/null
+++ b/platform/win32.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <windows.h>
+
+/* Required callbacks */
+extern void keyboard_on_down(void);
+extern void keyboard_on_up(void);
+
+static HHOOK keyboard_hook_windows;
+
+bool sound_init(float volume)
+{
+ DWORD channel_volume = volume * 0xFFFF;
+ if (waveOutSetVolume(NULL, (channel_volume << 16) | channel_volume) != MMSYSERR_NOERROR)
+ return false;
+ return true;
+}
+
+void sound_play(unsigned char *buffer)
+{
+ PlaySound((const char *) buffer, NULL, SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
+}
+
+/* https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v=vs.85) */
+static 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);
+}
+
+bool 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) {
+ return false;
+ }
+ return true;
+}
+
+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 enter_idle(void)
+{
+ MSG msg;
+ BOOL status;
+ while ((status = GetMessage(&msg, NULL, 0, 0))) {
+ if (status == -1) {
+ // error case
+ printf("ERROR: Windows error, code %lu\n", GetLastError());
+ keyboard_unhook();
+ exit(1);
+ }
+ }
+} \ No newline at end of file