changeset 10:42ac054c0231

*: huge refactoring dirtools now uses wchar (wayyy overdue) the timer doesn't have a stupid design anymore we don't use windows.h at all now ...
author Paper <paper@paper.us.eu.org>
date Sun, 11 Feb 2024 19:43:31 -0500
parents 07f0e2f43204
children e6a594f16403
files Makefile src/config.c src/dirtools.c src/include/config.h src/include/dirtools.h src/include/main.h src/include/resource.h src/include/timer.h src/include/utils.h src/main.c src/timer.c src/utils.c
diffstat 12 files changed, 179 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Dec 16 21:55:37 2022 -0500
+++ b/Makefile	Sun Feb 11 19:43:31 2024 -0500
@@ -8,21 +8,22 @@
 else
 	CFLAGS += -I"/c/Program Files (x86)/Winamp SDK"
 endif
-LDFLAGS=-L"discord_game_sdk/lib/x86" -ldiscord_game_sdk -Wl,--enable-stdcall-fixup
+LDFLAGS=-L"discord_game_sdk/lib/x86" -lshlwapi -lole32 -luuid -ldiscord_game_sdk -Wl,--enable-stdcall-fixup
 DEPS=src/include/config.h src/include/dirtools.h src/include/main.h \
-     src/include/timer.h src/include/resource.h src/include/utils.h
-RC=src/include/dialog.rc
-OBJ=src/config.o src/dirtools.o src/main.o src/timer.o src/utils.o
+     src/include/resource.h src/include/timer.h src/include/utils.h \
+	 src/include/json.h
+OBJ=src/config.o src/dirtools.o src/main.o src/timer.o src/utils.o \
+	src/dialog.o
+.SUFFIXES: .rc
 
-gen_DiscordGameSDK.dll: $(OBJ) src/include/dialog.o
-	gcc -o $@ $(CFLAGS) $^ $(LDFLAGS)
+gen_DiscordGameSDK.dll: $(OBJ) $(DEPS)
+	$(CC) -o $@ $(CFLAGS) $(OBJ) $(LDFLAGS)
 
-src/include/dialog.o: src/include/dialog.rc
-	windres -i $< -o $@
+.rc.o:
+	windres -Isrc/include -i $< -o $@
 
-src/%.o: src/%.c $(DEPS)
-	gcc -c $(CFLAGS) $< -o $@
+.c.o:
+	$(CC) -c $(CFLAGS) $< -o $@
 
 clean:
-	find . -type f -name '*.o' -not -path "./discord_game_sdk/*" -delete
-	find . -type f -name '*.dll' -not -path "./discord_game_sdk/*" -delete
+	rm gen_DiscordGameSDK.dll $(OBJ)
--- a/src/config.c	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/config.c	Sun Feb 11 19:43:31 2024 -0500
@@ -11,35 +11,67 @@
  * display_title=1
  * show_elapsed_time=1
 **/
+#include "dirtools.h"
+#include "config.h"
+#include "resource.h"
+#include "utils.h"
+
+#include <shlobj.h>
+#include <shlwapi.h>
+
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "dirtools.h"
-#include "config.h"
-#include "resource.h"
-#include "utils.h"
-#ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <windowsx.h>
-#define MAX_LINE_LENGTH 128
+
+#define MAX_LINE_LENGTH 256
 
 /* from main */
 extern void update_rich_presence_details(void);
 extern struct config config;
 
+/* must be free'd by the caller */
+LPWSTR cfg_get_path() {
+	/* get location of appdata folder */
+	LPWSTR appdata_folder;
+	SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &appdata_folder);
+
+	/* compatibility with WACUP, falls back to Winamp */
+	WCHAR exe_name[MAX_PATH] = {L'\0'};
+	if (GetModuleFileNameW(NULL, (LPWSTR)&exe_name, MAX_PATH)) {
+		PathStripPathW(exe_name);
+		PathRemoveExtensionW(exe_name);
+	} else { // fail
+		memset(exe_name, '\0', MAX_PATH * sizeof(WCHAR));
+		wcscpy(exe_name, L"Winamp");
+	}
+
+	/* concat until we get the final path */
+	LPWSTR path = dirtools_concat_paths(appdata_folder, exe_name);
+	CoTaskMemFree(appdata_folder);
+
+	LPWSTR final = dirtools_concat_paths(path, L"Plugins\\wgsdk");
+	free(path);
+
+	return final;
+}
+
 int cfg_load(struct config* restrict config) {
-	char line[MAX_LINE_LENGTH] = {0},
-	     *path = dirtools_concat_paths(getenv("APPDATA"), "Winamp\\Plugins\\wgsdk\\config.txt");
-	FILE* config_fp = fopen(path, "r");
+	LPWSTR fold_path = cfg_get_path();
+	LPWSTR path = dirtools_concat_paths(fold_path, L"config.txt");
+	free(fold_path);
+
+	/* find some real win32 replacement for this */
+	FILE* config_fp = _wfopen(path, L"r");
 	if (config_fp == NULL) {
 		free(path);
 		return 1;
 	}
+
 	/* parse the config */
+	char line[MAX_LINE_LENGTH] = {0};
 	while (fgets(line, MAX_LINE_LENGTH, config_fp)) {
+		/* strtok is okay here. */
 		switch (crc32b((unsigned char*)strtok(line, "="))) {
 			case 0x2a666380: // display_title
 				config->display_title = !!atoi(strtok(NULL, "="));
@@ -51,46 +83,52 @@
 				break;
 		}
 	}
+
 	free(path);
 	return 0;
 }
 
 int cfg_save(struct config config) {
-	char* path = dirtools_concat_paths(getenv("APPDATA"), "Winamp\\Plugins\\wgsdk");
-	assert(!dirtools_create_directory(path));
-	free(path);
+	LPWSTR fold_path = cfg_get_path();
+	assert(!dirtools_create_directory(fold_path));
+
+	LPWSTR path = dirtools_concat_paths(fold_path, L"config.txt");
+	free(fold_path);
 
-	path = dirtools_concat_paths(getenv("APPDATA"), "Winamp\\Plugins\\wgsdk\\config.txt");
-	FILE* config_fp = fopen(path, "w");
-	if (config_fp == NULL)
+	FILE* config_fp = _wfopen(path, L"w");
+	if (config_fp == NULL) {
+		free(path);
 		return 1;
+	}
+
 	fprintf(config_fp, "----- wgsdk config ----\n");
 	fprintf(config_fp, "display_title=%d\n",     config.display_title);
 	fprintf(config_fp, "show_elapsed_time=%d\n", config.show_elapsed_time);
 	fclose(config_fp);
+	free(path);
 	return 0;
 }
 
 /* --------------------------------- */
 
-#define conf_item_to_dlg(cons, var) \
-	checkboxHwnd = GetDlgItem(hWnd, cons); \
-	Button_SetCheck(checkboxHwnd, var)
-#define dlg_item_to_conf(cons, var) \
-	checkboxHwnd = GetDlgItem(hWnd, cons); \
-	var = Button_GetCheck(checkboxHwnd)
+#define conf_item_to_dlg(hwnd, cons, var) \
+{ \
+	HWND checkboxHwnd = GetDlgItem(hwnd, cons); \
+	SendMessage(checkboxHwnd, BM_SETCHECK, (var) ? BST_CHECKED : BST_UNCHECKED, 0); \
+}
+#define dlg_item_to_conf(hwnd, cons, var) \
+{ \
+	HWND checkboxHwnd = GetDlgItem(hwnd, cons); \
+	(var) = (SendMessage(checkboxHwnd, BM_GETCHECK, 0, 0) == BST_CHECKED); \
+}
 void cfg_get_controls(HWND hWnd) {
-	HWND checkboxHwnd;
-
-	dlg_item_to_conf(TITLE_CHECK,        config.display_title);
-	dlg_item_to_conf(ELAPSED_TIME_CHECK, config.show_elapsed_time);
+	dlg_item_to_conf(hWnd, TITLE_CHECK,        config.display_title);
+	dlg_item_to_conf(hWnd, ELAPSED_TIME_CHECK, config.show_elapsed_time);
 }
 
 void cfg_set_controls(HWND hWnd) {
-	HWND checkboxHwnd;
-
-	conf_item_to_dlg(TITLE_CHECK,        config.display_title);
-	conf_item_to_dlg(ELAPSED_TIME_CHECK, config.show_elapsed_time);
+	conf_item_to_dlg(hWnd, TITLE_CHECK,        config.display_title);
+	conf_item_to_dlg(hWnd, ELAPSED_TIME_CHECK, config.show_elapsed_time);
 }
 #undef conf_item_to_dlg
 #undef dlg_item_to_conf
--- a/src/dirtools.c	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/dirtools.c	Sun Feb 11 19:43:31 2024 -0500
@@ -13,41 +13,54 @@
 #include <windows.h>
 #include "dirtools.h"
 
-int dirtools_directory_exists(char* path) {
-	DWORD attrib = GetFileAttributesA(path);
+/* these are aids and should be converted to wchar */
+
+static int dirtools_directory_exists(LPCWSTR restrict path) {
+	DWORD attrib = GetFileAttributesW(path);
 	return (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY));
 }
 
-int dirtools_create_directory(char* path) {
-	char* alltoks = calloc(strlen(path)+2, sizeof(char)), *tok;
+int dirtools_create_directory(LPCWSTR restrict path) {
+	size_t len = wcslen(path);
+	WCHAR tmp[len + 1];
+	memset(tmp, '\0', (len + 1) * sizeof(WCHAR));
 
-	for (tok = strtok(path, "\\"); tok != NULL; tok = strtok(NULL, "\\")) {
-		strcat(alltoks, tok);
-		strcat(alltoks, "\\");
-		if (dirtools_directory_exists(path)) {
-			if (!CreateDirectoryA(alltoks, NULL)) {
-				if (GetLastError() == ERROR_PATH_NOT_FOUND) {
-					/* ERROR_PATH_NOT_FOUND should NOT happen here */
-					return 1;
-				}
-			}
-		}
+	for (size_t i = 0; i < len; i++) {
+		if (path[i] != L'\\')
+			continue;
+
+		wcsncpy(tmp, path, i);
+		if (dirtools_directory_exists(tmp))
+			continue;
+
+		if (!CreateDirectoryW(tmp, NULL))
+			if (GetLastError() == ERROR_PATH_NOT_FOUND)
+				return 1;
 	}
 
-	free(alltoks);
+	if (!dirtools_directory_exists(path) && !CreateDirectoryW(path, NULL))
+		if (GetLastError() == ERROR_PATH_NOT_FOUND)
+			return 1;
 
 	return 0;
 }
 
-char* dirtools_concat_paths(char* a, char* b) {
-	if (a[0] == '\0' || b[0] == '\0')
+LPWSTR dirtools_concat_paths(LPCWSTR restrict a, LPCWSTR restrict b) {
+	if (a[0] == L'\0' || b[0] == L'\0')
 		return NULL;
-	char* out = calloc((strlen(a) + strlen(b) + 2), sizeof(char));
+
+	const size_t a_len = wcslen(a);
+	const size_t b_len = wcslen(b);
+	const int add_backslash = (a[a_len] != L'\\' && b[0] != L'\\');
+
+	LPWSTR out = calloc(a_len + b_len + 1 + add_backslash, sizeof(WCHAR));
 	if (out == NULL)
 		return out;
-	strcpy(out, a);
-	if (a[strlen(a)] != '\\' && b[0] != '\\')
-		strcat(out, "\\");
-	strcat(out, b);
+
+	wcscpy(out, a);
+	if (add_backslash)
+		wcscat(out, L"\\");
+
+	wcscat(out, b);
 	return out;
 }
--- a/src/include/config.h	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/include/config.h	Sun Feb 11 19:43:31 2024 -0500
@@ -1,9 +1,8 @@
 #ifndef __config_h
 #define __config_h
-#ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
+
+#include <windef.h>
+
 struct config {
 	int display_title;
 	int show_elapsed_time;
@@ -12,4 +11,4 @@
 int cfg_load(struct config* config);
 int cfg_save(struct config config);
 BOOL CALLBACK cfg_win_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-#endif
\ No newline at end of file
+#endif
--- a/src/include/dirtools.h	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/include/dirtools.h	Sun Feb 11 19:43:31 2024 -0500
@@ -1,5 +1,10 @@
 #ifndef __dirtools_h
 #define __dirtools_h
-int dirtools_create_directory(char* path);
-char* dirtools_concat_paths(char* a, char* b);
-#endif
\ No newline at end of file
+
+#include <windef.h>
+#include <winnt.h>
+
+int dirtools_create_directory(LPCWSTR path);
+LPWSTR dirtools_concat_paths(LPCWSTR a, LPCWSTR b);
+
+#endif // __dirtools_h
\ No newline at end of file
--- a/src/include/main.h	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/include/main.h	Sun Feb 11 19:43:31 2024 -0500
@@ -1,9 +1,7 @@
 #ifndef __main_h
 #define __main_h
-#ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
+
+#include <windef.h>
 
 typedef struct {
     int version;                   // version of the plugin structure
@@ -26,4 +24,5 @@
 void conf();
 void quit();
 void update_rich_presence_details(void);
+
 #endif
\ No newline at end of file
--- a/src/include/resource.h	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/include/resource.h	Sun Feb 11 19:43:31 2024 -0500
@@ -1,3 +1,8 @@
+#ifndef __resource_h
+#define __resource_h
+
 #define DIALOG_CONFIG                   101
 #define TITLE_CHECK                     1000
 #define ELAPSED_TIME_CHECK              1001
+
+#endif // __resource_h
\ No newline at end of file
--- a/src/include/timer.h	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/include/timer.h	Sun Feb 11 19:43:31 2024 -0500
@@ -1,20 +1,17 @@
 #ifndef __timer_h
 #define __timer_h
-#ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
+
+#include <windef.h>
+#include <winuser.h>
 
 struct timer {
-	int initialized;
-	int is_timer_alive;
+	UINT_PTR id;
 	UINT interval;
-	HWND winampClientWindow;
 	TIMERPROC timer_proc;
 };
 
-void timer_init(struct timer* timer, HWND winampClientWindow, TIMERPROC timer_proc);
-void timer_set(struct timer* timer, HWND winampClientWindow);
-void timer_stop(struct timer* timer, HWND winampClientWindow);
+void timer_init(struct timer* timer, UINT interval, TIMERPROC timer_proc);
+int timer_set(struct timer* timer);
+int timer_stop(struct timer* timer);
 
 #endif // __timer_h
\ No newline at end of file
--- a/src/include/utils.h	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/include/utils.h	Sun Feb 11 19:43:31 2024 -0500
@@ -1,7 +1,9 @@
 #ifndef __utils_h
 #define __utils_h
 
+#include <stdint.h>
+
 uint64_t get_system_time_in_milliseconds(void);
 uint32_t crc32b(unsigned char *message);
 
-#endif
\ No newline at end of file
+#endif
--- a/src/main.c	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/main.c	Sun Feb 11 19:43:31 2024 -0500
@@ -1,24 +1,21 @@
 /**
  * wgsdk - Winamp plugin for Discord's GameSDK
 **/
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <Winamp/wa_ipc.h>
-#include "discord_game_sdk.h"
 #include "timer.h"
 #include "config.h"
 #include "resource.h"
 #include "utils.h"
-#ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <windowsx.h>
+
+#include <Winamp/wa_ipc.h>
+#include "discord_game_sdk.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 #define CLIENT_ID 969367220599803955
 #define DISCORD_REQUIRE(x) \
-	assert(x == DiscordResult_Ok)
+	assert((x) == DiscordResult_Ok)
 
 #define GPPHDR_VER 0x10
 
@@ -57,7 +54,7 @@
 
 struct IDiscordActivityEvents activities_events;
 
-struct application {
+struct {
     struct IDiscordCore* core;
     struct IDiscordUsers* users;
 	struct IDiscordActivityManager* activities;
@@ -65,7 +62,7 @@
 
 /* Now we get to our built-in stuff */
 
-struct timer timer_callbacks = { .interval = 16 };
+struct timer timer_callbacks = {0};
 
 struct config config = {
 	.display_title = 1,
@@ -116,6 +113,7 @@
 		case 1:
 		case 3:
 			report_current_song_status(is_playing);
+			break;
 		default:
 			break;
 	}
@@ -155,8 +153,8 @@
 
 	app.activities = app.core->get_activity_manager(app.core);
 
-	timer_init(&timer_callbacks, g_plugin.hwndParent, TimerProc);
-	timer_set(&timer_callbacks, g_plugin.hwndParent);
+	timer_init(&timer_callbacks, 16, TimerProc);
+	timer_set(&timer_callbacks);
 
 	cfg_load(&config);
 
--- a/src/timer.c	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/timer.c	Sun Feb 11 19:43:31 2024 -0500
@@ -1,32 +1,23 @@
-#include <assert.h>
-#ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
 #include "timer.h"
 
-void timer_init(struct timer* restrict timer, HWND winampClientWindow, TIMERPROC timer_proc) {
-	timer->winampClientWindow = winampClientWindow;
+#include <assert.h>
+
+void timer_init(struct timer* restrict timer, UINT interval, TIMERPROC timer_proc) {
+	timer->id = 0;
+	timer->interval = interval;
 	timer->timer_proc = timer_proc;
-	timer->initialized = 1;
 }
 
-void timer_set(struct timer* restrict timer, HWND winampClientWindow) {
-	assert(timer->initialized);
+int timer_set(struct timer* restrict timer) {
+	assert(!timer->id);
 
-	if (timer->is_timer_alive)
-		return;
-
-	timer->is_timer_alive = 1;
-	SetTimer(winampClientWindow, 1, timer->interval, timer->timer_proc);
+	return !!(timer->id = SetTimer(NULL, timer->id, timer->interval, timer->timer_proc));
 }
 
-void timer_stop(struct timer* restrict timer, HWND winampClientWindow) {
-	assert(timer->initialized);
+int timer_stop(struct timer* restrict timer) {
+	assert(timer->id);
 
-	if (!timer->is_timer_alive)
-		return;
-
-	timer->is_timer_alive = 0;
-	KillTimer(winampClientWindow, 1);
+	BOOL ret = KillTimer(NULL, timer->id);
+	timer->id = 0;
+	return ret;
 }
\ No newline at end of file
--- a/src/utils.c	Fri Dec 16 21:55:37 2022 -0500
+++ b/src/utils.c	Sun Feb 11 19:43:31 2024 -0500
@@ -3,10 +3,9 @@
  *
  * Useful utilities for general use.
 **/
-#ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
+#include "utils.h"
+
+#include <sysinfoapi.h>
 #include <stdint.h>
 
 uint64_t get_system_time_in_milliseconds(void) {