comparison src/main.c @ 0:d91dfd53b8b4

Initial commit
author Paper <mrpapersonic@gmail.com>
date Sun, 07 Aug 2022 07:26:27 -0400
parents
children 7abb5d8b20ea
comparison
equal deleted inserted replaced
-1:000000000000 0:d91dfd53b8b4
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <time.h>
6 #include <Winamp/wa_ipc.h>
7 #include "main.h"
8 #include "discord_game_sdk.h"
9 #include "timer.h"
10 #include "config.h"
11 #include "dirtools.h"
12 #ifndef WIN32_LEAN_AND_MEAN
13 # define WIN32_LEAN_AND_MEAN
14 #endif
15 #include <windows.h>
16
17 #define CLIENT_ID 969367220599803955
18 #define DISCORD_REQUIRE(x) \
19 assert(x == DiscordResult_Ok)
20
21 #define GPPHDR_VER 0x10
22
23 winamp_general_purpose_plugin g_plugin = {
24 GPPHDR_VER, // version of the plugin, defined in "gen_myplugin.h"
25 "Discord GameSDK", // name/title of the plugin, defined in "gen_myplugin.h"
26 init, // function name which will be executed on init event
27 NULL, // function name which will be executed on config event
28 quit, // function name which will be executed on quit event
29 0, // handle to Winamp main window, loaded by winamp when this dll is loaded
30 0 // hinstance to this dll, loaded by winamp when this dll is loaded
31 };
32
33 WNDPROC g_lpWndProcOld = 0;
34
35 struct timer_t timer_callbacks = { .interval = 16 };
36 struct config_t config = {
37 .display_title = 1,
38 .show_elapsed_time = 1
39 };
40
41 struct DiscordActivity activity = {
42 .application_id = CLIENT_ID,
43 .name = "Winamp",
44 .instance = 0
45 };
46
47 struct IDiscordActivityEvents activities_events;
48
49 struct app_t app;
50
51 void update_activity_callback(void* data, enum EDiscordResult result)
52 {
53 DISCORD_REQUIRE(result);
54 }
55
56 void report_current_song_status(int playbackState)
57 {
58 assert(playbackState != 0);
59 activity.timestamps.start = 0;
60 strcpy(activity.state, playbackState == 1 ? "(Playing)" : "(Paused)");
61
62 if (playbackState == 1) {
63 FILETIME ft;
64 GetSystemTimeAsFileTime(&ft);
65 ULARGE_INTEGER ul;
66 ul.LowPart = ft.dwLowDateTime;
67 ul.HighPart = ft.dwHighDateTime;
68 long long dtn = ((ul.QuadPart - 116444736000000000ULL)/10000000);
69
70 activity.timestamps.start = dtn - SendMessage(g_plugin.hwndParent, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000;
71 } else {
72 activity.timestamps.start = 0;
73 }
74
75 char* detailsMessage = calloc(256, sizeof(char));
76 //if (g_pluginSettings.DisplayTitleInStatus)
77 //{
78 wchar_t* title = (wchar_t*)SendMessageW(g_plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE);
79 assert(WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, title, -1, detailsMessage, 256, NULL, NULL));
80 //}
81 //else
82 //{
83 // strcpy(activity.details, "");
84 //}
85 strcpy(activity.details, detailsMessage);
86 free(detailsMessage);
87
88 app.activities->update_activity(app.activities, &activity, &app, update_activity_callback);
89 }
90
91 void report_idle_status(void)
92 {
93 activity.timestamps.start = 0;
94 strcpy(activity.state, "(Idle)");
95
96 app.activities->update_activity(app.activities, &activity, &app, update_activity_callback);
97 }
98
99 void update_rich_presence_details(void)
100 {
101 LONG isPlayingResult = SendMessageW(g_plugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING);
102
103 switch (isPlayingResult) {
104 case 1:
105 report_current_song_status(1);
106 break;
107 case 3:
108 report_current_song_status(3);
109 break;
110 case 0:
111 report_idle_status();
112 break;
113 default: break;
114 }
115 }
116
117 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
118 {
119 if (message == WM_WA_IPC && lParam == IPC_CB_MISC && wParam == IPC_CB_MISC_STATUS)
120 {
121 // Notification sent from Winamp on any change in playback.
122
123 update_rich_presence_details();
124 }
125
126 return CallWindowProc(g_lpWndProcOld, hwnd, message, wParam, lParam);
127 }
128
129 int init() {
130 char* path = dirtools_concat_paths(getenv("APPDATA"), "Winamp\\Plugins\\wgsdk");
131 printf("%s", path);
132 memset(&app, 0, sizeof(app));
133 if (IsWindowUnicode(g_plugin.hwndParent)) {
134 g_lpWndProcOld = (WNDPROC)SetWindowLongW(g_plugin.hwndParent, -4, (LONG)WndProc);
135 } else {
136 g_lpWndProcOld = (WNDPROC)SetWindowLongA(g_plugin.hwndParent, -4, (LONG)WndProc);
137 }
138
139 memset(&activity, 0, sizeof(activity));
140 memset(&activities_events, 0, sizeof(activities_events));
141
142 struct DiscordCreateParams params;
143 DiscordCreateParamsSetDefault(&params);
144 params.client_id = CLIENT_ID;
145 params.flags = DiscordCreateFlags_Default;
146 params.event_data = &app;
147 params.activity_events = &activities_events;
148
149 DISCORD_REQUIRE(DiscordCreate(DISCORD_VERSION, &params, &app.core));
150
151 app.activities = app.core->get_activity_manager(app.core);
152
153 timer_init(&timer_callbacks, g_plugin.hwndParent, TimerProc);
154 timer_set(&timer_callbacks, g_plugin.hwndParent);
155
156 cfg_load(&config);
157
158 strcpy(activity.assets.large_image, "winamp-logo");
159
160 update_rich_presence_details();
161
162 return 0;
163 }
164
165 void quit() {
166 assert(!cfg_save(config));
167 app.activities->clear_activity(app.activities, &app, update_activity_callback);
168 }
169
170 void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD) {
171 DISCORD_REQUIRE(app.core->run_callbacks(app.core));
172 }
173
174 __declspec(dllexport) winamp_general_purpose_plugin* winampGetGeneralPurposePlugin() {
175 return &g_plugin;
176 }