-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.cpp
377 lines (356 loc) · 10.4 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
//---------------------------------------------------------------------
// AviUtlでDiscord RPCを表示するプラグイン
//---------------------------------------------------------------------
#include <Windows.h>
#include <string>
#include <chrono>
#include <sstream>
#include <istream>
#include "aviutl-sdk/filter.h"
#include "main.h"
#include "discord-files/discord.h"
#include "util.h"
#include "strutil.h"
// バッファー
static void* buf0 = NULL;
// RPCプラグインが有効かどうか
static BOOL RPC_Enabled = TRUE;
// ファイル名を表示するかどうか
static BOOL RPC_Display_Filename = TRUE;
// ステータス
static int Status = RPC_STATUS_IDLING;
// タイマーの識別子
static UINT_PTR timer_identifer = NULL;
// RPCが破棄されているかどうか
static BOOL IS_Disposed = TRUE;
// システム情報
static std::string SYS_INFO_STR = "";
// 開始時刻が一度でも設定されているか
static BOOL RPC_Timestamp_Set = FALSE;
// 起動時の設定反映がされているか
static BOOL RPC_func_update_fisrt_called = FALSE;
// Discord Core
discord::Core* core{};
// Discord Acticity
discord::Activity activity{};
//---------------------------------------------------------------------
// フィルタ構造体定義
//---------------------------------------------------------------------
TCHAR FILTER_NAME[] = "AviUtl Discord RPC";
#define CHECK_NUM 2
#if R_ENGLISH
TCHAR* CHECKBOX_NAMES[] = { "Enable RPC", "Show filenames" };
#else
TCHAR* CHECKBOX_NAMES[] = { "有効にする", "ファイル名を表示する" };
#endif
int CHECKBOX_INITIAL_VAL[] = { 0, 0 };
TCHAR FILTER_INFO[] = "AviUtl Discord RPC version 1.0 by mtripg6666tdr";
TCHAR VERSION[] = "1.0";
FILTER_DLL filter = {
// flag
FILTER_FLAG_ALWAYS_ACTIVE | FILTER_FLAG_DISP_FILTER | FILTER_FLAG_EX_INFORMATION,
// x, y
NULL, NULL,
// name
FILTER_NAME,
// Trackbar
NULL, NULL, NULL, NULL, NULL,
// Checkbox
CHECK_NUM, CHECKBOX_NAMES, CHECKBOX_INITIAL_VAL,
// func_proc: フィルタ処理関数
NULL,
// func_init: フィルタ初期化関数
func_init,
// func_exit: フィルタ終了関数
func_exit,
// func_update: フィルタ設定変更適用関数
func_update,
// func_WndProc: ウインドウプロシージャ
func_WndProc,
// システム使用部分
NULL, NULL,
// 拡張データ関連
NULL, NULL,
// 拡張プラグイン情報
FILTER_INFO,
// 出力開始関数
NULL,
// 出力終了関数
NULL,
/*外部関数テーブル*/NULL,/*システム使用*/NULL,NULL,NULL,/*I解除プラグインのみ*/NULL,
// プロジェクトファイル保存関連
NULL, func_project_save,
// タイトルバー表示関数
func_modify_title,
NULL, NULL
};
//---------------------------------------------------------------------
// フィルタ構造体のポインタを渡す関数
//---------------------------------------------------------------------
EXTERN_C FILTER_DLL __declspec(dllexport)* __stdcall GetFilterTable(void) {
return &filter;
}
//---------------------------------------------------------------------
// メモリ管理
//---------------------------------------------------------------------
void mem_alloc(FILTER* fp) {
int size;
SYS_INFO si;
fp->exfunc->get_sys_info(NULL, &si);
size = si.vram_w * si.vram_h * 3;
if (buf0 == NULL) {
buf0 = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
}
}
void mem_free(void) {
if (buf0) {
VirtualFree(buf0, NULL, MEM_RELEASE);
buf0 = NULL;
}
}
//---------------------------------------------------------------------
// 初期化
//---------------------------------------------------------------------
BOOL func_init(FILTER* fp) {
// コールバックを実行するためのタイマーを設定
UINT_PTR timer = SetTimer(
// ウインドウハンドル
// *今回はプラグインのウインドウが表示されているとは限らないためNULL
NULL,
// タイマーID
// 上と同じ。
NULL,
// タイマー間隔
RPC_UPDATE_TICK,
// コールバック関数
func_timer_tick
);
if (timer) {
timer_identifer = timer;
}
else {
throw;
}
Update_PluginMetaInfo(fp);
return TRUE;
}
//---------------------------------------------------------------------
// 終了
//---------------------------------------------------------------------
BOOL func_exit(FILTER* fp) {
mem_free();
KillTimer(NULL, timer_identifer);
Dispose_RPC();
return TRUE;
}
//---------------------------------------------------------------------
// 設定変更
//---------------------------------------------------------------------
BOOL func_update(FILTER* fp, int status) {
BOOL initialized = FALSE;
switch (fp->check[0]) {
case FILTER_CHECKBOX_STATUS_ON:
if (!RPC_Enabled || !RPC_func_update_fisrt_called) {
initialized = RPC_Enabled = TRUE;
Initialize_RPC();
Update_RPC(fp, NULL, Status, TRUE, FALSE);
}
break;
case FILTER_CHECKBOX_STATUS_OFF:
if (RPC_Enabled) {
RPC_Enabled = FALSE;
Dispose_RPC();
}
break;
}
BOOL fn_now = fp->check[1] == FILTER_CHECKBOX_STATUS_ON;
if (fn_now != RPC_Display_Filename || initialized) {
RPC_Display_Filename = fn_now;
PostMessage(fp->hwnd, WM_FILTER_CHANGE_PARAM_POST_EVENT, NULL, NULL);
}
RPC_func_update_fisrt_called = TRUE;
return TRUE;
}
//---------------------------------------------------------------------
// プロジェクトファイルの保存
//---------------------------------------------------------------------
BOOL func_project_save(FILTER* fp, void* editp, void* data, int* size) {
Update_RPC(fp, editp, RPC_STATUS_EDITING, FALSE, FALSE);
return FALSE;
}
//---------------------------------------------------------------------
// ウインドウタイトル変更
//---------------------------------------------------------------------
BOOL func_modify_title(FILTER* fp, void* editP, int frame, LPSTR title, int max_title) {
return TRUE;
}
//---------------------------------------------------------------------
// タイマーティック
// コールバックを実行
//---------------------------------------------------------------------
void __stdcall func_timer_tick(HWND hWnd, UINT uMsg, UINT_PTR timer_id, DWORD dwTime) {
if (core != NULL && RPC_Enabled) {
core->RunCallbacks();
}
}
//---------------------------------------------------------------------
// ウインドウプロシージャ
//---------------------------------------------------------------------
BOOL func_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, void* editPtr, FILTER* filterPtr) {
if (core != NULL && RPC_Enabled) {
core->RunCallbacks();
}
switch (message) {
case WM_FILTER_CHANGE_WINDOW:
if (filterPtr->exfunc->is_filter_window_disp(filterPtr)) {
mem_alloc(filterPtr);
return TRUE;
}
else {
mem_free();
}
break;
case WM_FILTER_FILE_OPEN:
case WM_FILTER_SAVE_END:
Update_RPC(filterPtr, editPtr, RPC_STATUS_EDITING, TRUE, FALSE);
break;
case WM_FILTER_FILE_CLOSE:
Update_RPC(filterPtr, editPtr, RPC_STATUS_IDLING, TRUE, TRUE);
break;
case WM_FILTER_SAVE_START:
Update_RPC(filterPtr, editPtr, RPC_STATUS_SAVING, TRUE, FALSE);
break;
case WM_FILTER_CHANGE_PARAM_POST_EVENT:
Update_RPC(filterPtr, editPtr, Status, FALSE, FALSE);
break;
}
return FALSE;
}
// プラグインメタデータアップデート
BOOL Update_PluginMetaInfo(FILTER* fp) {
SYS_INFO info;
if (fp->exfunc->get_sys_info(NULL, &info)) {
SYS_INFO_STR = "AviUtl ";
SYS_INFO_STR += info.info;
SYS_INFO_STR += " (RPC v";
SYS_INFO_STR += VERSION;
SYS_INFO_STR += ")";
SYS_INFO_STR = multi_to_utf8_winapi(SYS_INFO_STR);
return TRUE;
}
else
return FALSE;
}
//---------------------------------------------------------------------
// Discord RPC 設定関数
//---------------------------------------------------------------------
// DiscordのアプリケーションのクライアントID
#define FILTER_RPC_CLIENT_ID 779296320019497020
BOOL Initialize_RPC() {
if (!RPC_Enabled) {
return false;
}
if (IS_Disposed) {
discord::Core::Create(FILTER_RPC_CLIENT_ID, DiscordCreateFlags_NoRequireDiscord, &core);
RPC_Timestamp_Set = FALSE;
IS_Disposed = FALSE;
}
return TRUE;
}
BOOL Update_RPC(FILTER* filterPtr, void* editPtr, int status, bool isStart, bool isClose = FALSE) {
// ステータスを保存
Status = status;
// 無効なら終わり
if (!RPC_Enabled) {
return FALSE;
}
if (!IS_Disposed) {
if (core == NULL) {
return FALSE;
}
std::string detail = "";
if (RPC_Display_Filename && editPtr != NULL && filterPtr != NULL && !isClose) {
FILE_INFO fi;
SYS_INFO si;
if (filterPtr->exfunc->is_editing(editPtr) &&
filterPtr->exfunc->get_sys_info(editPtr, &si) &&
filterPtr->exfunc->get_file_info(editPtr, &fi)
) {
// プロジェクト名のパスを削除
std::string projectName = multi_to_utf8_winapi(GetFileName(fi.name));
detail += projectName;
// ファイル名のパスを削除
std::string filename = multi_to_utf8_winapi(GetFileName(si.project_name));
detail += "(";
#if R_ENGLISH
detail += filename == "" ? u8"Unsaved" : filename;
#else
detail += filename == "" ? u8"未保存" : filename;
#endif
detail += ")";
}
}
else
detail = "";
std::string StateStr = "";
// Ref: https://stackoverflow.com/questions/6012663/get-unix-timestamp-with-c
switch (status) {
case RPC_STATUS_SAVING:
#if R_ENGLISH
StateStr = u8"Encoding";
activity.GetAssets().SetSmallText(u8"Encode");
#else
StateStr = u8"エンコード中";
activity.GetAssets().SetSmallText(u8"エンコード");
#endif
activity.GetAssets().SetSmallImage("status_encoding");
break;
case RPC_STATUS_IDLING:
#if R_ENGLISH
StateStr = u8"Idling";
activity.GetAssets().SetSmallText(u8"Idle");
#else
StateStr = u8"アイドル中";
activity.GetAssets().SetSmallText(u8"アイドル状態");
#endif
activity.GetAssets().SetSmallImage("status_idle");
break;
case RPC_STATUS_EDITING:
#if R_ENGLISH
StateStr = u8"Editing";
activity.GetAssets().SetSmallText(u8"Editing");
#else
StateStr = u8"編集中";
activity.GetAssets().SetSmallText(u8"編集中");
#endif
activity.GetAssets().SetSmallImage("status_editing");
break;
}
activity.SetState(StateStr.c_str());
activity.GetAssets().SetLargeImage("aviutl_icon_large");
if (SYS_INFO_STR == "") Update_PluginMetaInfo(filterPtr);
activity.GetAssets().SetLargeText(SYS_INFO_STR == "" ? "AviUtl" : SYS_INFO_STR.c_str());
if (isStart || !RPC_Timestamp_Set) {
activity.GetTimestamps().SetStart(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count());
RPC_Timestamp_Set = TRUE;
}
activity.SetDetails(detail.c_str());
core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {
});
}
else {
Initialize_RPC();
}
return TRUE;
}
BOOL Dispose_RPC() {
IS_Disposed = TRUE;
if (core != NULL) {
core->ActivityManager().ClearActivity([](discord::Result result) {
});
core->~Core();
core = NULL;
}
SYS_INFO_STR.~basic_string();
return TRUE;
}