1
0

OBSBasic_Hotkeys.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /******************************************************************************
  2. Copyright (C) 2023 by Lain Bailey <[email protected]>
  3. Zachary Lund <[email protected]>
  4. Philippe Groarke <[email protected]>
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ******************************************************************************/
  16. #include "OBSBasic.hpp"
  17. #include <widgets/OBSBasicStats.hpp>
  18. void OBSBasic::InitHotkeys()
  19. {
  20. ProfileScope("OBSBasic::InitHotkeys");
  21. struct obs_hotkeys_translations t = {};
  22. t.insert = Str("Hotkeys.Insert");
  23. t.del = Str("Hotkeys.Delete");
  24. t.home = Str("Hotkeys.Home");
  25. t.end = Str("Hotkeys.End");
  26. t.page_up = Str("Hotkeys.PageUp");
  27. t.page_down = Str("Hotkeys.PageDown");
  28. t.num_lock = Str("Hotkeys.NumLock");
  29. t.scroll_lock = Str("Hotkeys.ScrollLock");
  30. t.caps_lock = Str("Hotkeys.CapsLock");
  31. t.backspace = Str("Hotkeys.Backspace");
  32. t.tab = Str("Hotkeys.Tab");
  33. t.print = Str("Hotkeys.Print");
  34. t.pause = Str("Hotkeys.Pause");
  35. t.left = Str("Hotkeys.Left");
  36. t.right = Str("Hotkeys.Right");
  37. t.up = Str("Hotkeys.Up");
  38. t.down = Str("Hotkeys.Down");
  39. #ifdef _WIN32
  40. t.meta = Str("Hotkeys.Windows");
  41. #else
  42. t.meta = Str("Hotkeys.Super");
  43. #endif
  44. t.menu = Str("Hotkeys.Menu");
  45. t.space = Str("Hotkeys.Space");
  46. t.numpad_num = Str("Hotkeys.NumpadNum");
  47. t.numpad_multiply = Str("Hotkeys.NumpadMultiply");
  48. t.numpad_divide = Str("Hotkeys.NumpadDivide");
  49. t.numpad_plus = Str("Hotkeys.NumpadAdd");
  50. t.numpad_minus = Str("Hotkeys.NumpadSubtract");
  51. t.numpad_decimal = Str("Hotkeys.NumpadDecimal");
  52. t.apple_keypad_num = Str("Hotkeys.AppleKeypadNum");
  53. t.apple_keypad_multiply = Str("Hotkeys.AppleKeypadMultiply");
  54. t.apple_keypad_divide = Str("Hotkeys.AppleKeypadDivide");
  55. t.apple_keypad_plus = Str("Hotkeys.AppleKeypadAdd");
  56. t.apple_keypad_minus = Str("Hotkeys.AppleKeypadSubtract");
  57. t.apple_keypad_decimal = Str("Hotkeys.AppleKeypadDecimal");
  58. t.apple_keypad_equal = Str("Hotkeys.AppleKeypadEqual");
  59. t.mouse_num = Str("Hotkeys.MouseButton");
  60. t.escape = Str("Hotkeys.Escape");
  61. obs_hotkeys_set_translations(&t);
  62. obs_hotkeys_set_audio_hotkeys_translations(Str("Mute"), Str("Unmute"), Str("Push-to-mute"),
  63. Str("Push-to-talk"));
  64. obs_hotkeys_set_sceneitem_hotkeys_translations(Str("SceneItemShow"), Str("SceneItemHide"));
  65. obs_hotkey_enable_callback_rerouting(true);
  66. obs_hotkey_set_callback_routing_func(OBSBasic::HotkeyTriggered, this);
  67. }
  68. void OBSBasic::ProcessHotkey(obs_hotkey_id id, bool pressed)
  69. {
  70. obs_hotkey_trigger_routed_callback(id, pressed);
  71. }
  72. void OBSBasic::HotkeyTriggered(void *data, obs_hotkey_id id, bool pressed)
  73. {
  74. OBSBasic &basic = *static_cast<OBSBasic *>(data);
  75. QMetaObject::invokeMethod(&basic, "ProcessHotkey", Q_ARG(obs_hotkey_id, id), Q_ARG(bool, pressed));
  76. }
  77. void OBSBasic::CreateHotkeys()
  78. {
  79. ProfileScope("OBSBasic::CreateHotkeys");
  80. auto LoadHotkeyData = [&](const char *name) -> OBSData {
  81. const char *info = config_get_string(activeConfiguration, "Hotkeys", name);
  82. if (!info)
  83. return {};
  84. OBSDataAutoRelease data = obs_data_create_from_json(info);
  85. if (!data)
  86. return {};
  87. return data.Get();
  88. };
  89. auto LoadHotkey = [&](obs_hotkey_id id, const char *name) {
  90. OBSDataArrayAutoRelease array = obs_data_get_array(LoadHotkeyData(name), "bindings");
  91. obs_hotkey_load(id, array);
  92. };
  93. auto LoadHotkeyPair = [&](obs_hotkey_pair_id id, const char *name0, const char *name1,
  94. const char *oldName = NULL) {
  95. if (oldName) {
  96. const auto info = config_get_string(activeConfiguration, "Hotkeys", oldName);
  97. if (info) {
  98. config_set_string(activeConfiguration, "Hotkeys", name0, info);
  99. config_set_string(activeConfiguration, "Hotkeys", name1, info);
  100. config_remove_value(activeConfiguration, "Hotkeys", oldName);
  101. activeConfiguration.Save();
  102. }
  103. }
  104. OBSDataArrayAutoRelease array0 = obs_data_get_array(LoadHotkeyData(name0), "bindings");
  105. OBSDataArrayAutoRelease array1 = obs_data_get_array(LoadHotkeyData(name1), "bindings");
  106. obs_hotkey_pair_load(id, array0, array1);
  107. };
  108. #define MAKE_CALLBACK(pred, method, log_action) \
  109. [](void *data, obs_hotkey_pair_id, obs_hotkey_t *, bool pressed) { \
  110. OBSBasic &basic = *static_cast<OBSBasic *>(data); \
  111. if ((pred) && pressed) { \
  112. blog(LOG_INFO, log_action " due to hotkey"); \
  113. method(); \
  114. return true; \
  115. } \
  116. return false; \
  117. }
  118. streamingHotkeys = obs_hotkey_pair_register_frontend(
  119. "OBSBasic.StartStreaming", Str("Basic.Main.StartStreaming"), "OBSBasic.StopStreaming",
  120. Str("Basic.Main.StopStreaming"),
  121. MAKE_CALLBACK(!basic.outputHandler->StreamingActive() && !basic.streamingStarting, basic.StartStreaming,
  122. "Starting stream"),
  123. MAKE_CALLBACK(basic.outputHandler->StreamingActive() && !basic.streamingStarting, basic.StopStreaming,
  124. "Stopping stream"),
  125. this, this);
  126. LoadHotkeyPair(streamingHotkeys, "OBSBasic.StartStreaming", "OBSBasic.StopStreaming");
  127. auto cb = [](void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
  128. OBSBasic &basic = *static_cast<OBSBasic *>(data);
  129. if (basic.outputHandler->StreamingActive() && pressed) {
  130. basic.ForceStopStreaming();
  131. }
  132. };
  133. forceStreamingStopHotkey = obs_hotkey_register_frontend("OBSBasic.ForceStopStreaming",
  134. Str("Basic.Main.ForceStopStreaming"), cb, this);
  135. LoadHotkey(forceStreamingStopHotkey, "OBSBasic.ForceStopStreaming");
  136. recordingHotkeys = obs_hotkey_pair_register_frontend(
  137. "OBSBasic.StartRecording", Str("Basic.Main.StartRecording"), "OBSBasic.StopRecording",
  138. Str("Basic.Main.StopRecording"),
  139. MAKE_CALLBACK(!basic.outputHandler->RecordingActive() && !basic.recordingStarted, basic.StartRecording,
  140. "Starting recording"),
  141. MAKE_CALLBACK(basic.outputHandler->RecordingActive() && basic.recordingStarted, basic.StopRecording,
  142. "Stopping recording"),
  143. this, this);
  144. LoadHotkeyPair(recordingHotkeys, "OBSBasic.StartRecording", "OBSBasic.StopRecording");
  145. pauseHotkeys =
  146. obs_hotkey_pair_register_frontend("OBSBasic.PauseRecording", Str("Basic.Main.PauseRecording"),
  147. "OBSBasic.UnpauseRecording", Str("Basic.Main.UnpauseRecording"),
  148. MAKE_CALLBACK(basic.isRecordingPausable && !basic.recordingPaused,
  149. basic.PauseRecording, "Pausing recording"),
  150. MAKE_CALLBACK(basic.isRecordingPausable && basic.recordingPaused,
  151. basic.UnpauseRecording, "Unpausing recording"),
  152. this, this);
  153. LoadHotkeyPair(pauseHotkeys, "OBSBasic.PauseRecording", "OBSBasic.UnpauseRecording");
  154. splitFileHotkey = obs_hotkey_register_frontend(
  155. "OBSBasic.SplitFile", Str("Basic.Main.SplitFile"),
  156. [](void *, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
  157. if (pressed)
  158. obs_frontend_recording_split_file();
  159. },
  160. this);
  161. LoadHotkey(splitFileHotkey, "OBSBasic.SplitFile");
  162. addChapterHotkey = obs_hotkey_register_frontend(
  163. "OBSBasic.AddChapterMarker", Str("Basic.Main.AddChapterMarker"),
  164. [](void *, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
  165. if (pressed)
  166. obs_frontend_recording_add_chapter(nullptr);
  167. },
  168. this);
  169. LoadHotkey(addChapterHotkey, "OBSBasic.AddChapterMarker");
  170. replayBufHotkeys =
  171. obs_hotkey_pair_register_frontend("OBSBasic.StartReplayBuffer", Str("Basic.Main.StartReplayBuffer"),
  172. "OBSBasic.StopReplayBuffer", Str("Basic.Main.StopReplayBuffer"),
  173. MAKE_CALLBACK(!basic.outputHandler->ReplayBufferActive(),
  174. basic.StartReplayBuffer, "Starting replay buffer"),
  175. MAKE_CALLBACK(basic.outputHandler->ReplayBufferActive(),
  176. basic.StopReplayBuffer, "Stopping replay buffer"),
  177. this, this);
  178. LoadHotkeyPair(replayBufHotkeys, "OBSBasic.StartReplayBuffer", "OBSBasic.StopReplayBuffer");
  179. if (vcamEnabled) {
  180. vcamHotkeys = obs_hotkey_pair_register_frontend(
  181. "OBSBasic.StartVirtualCam", Str("Basic.Main.StartVirtualCam"), "OBSBasic.StopVirtualCam",
  182. Str("Basic.Main.StopVirtualCam"),
  183. MAKE_CALLBACK(!basic.outputHandler->VirtualCamActive(), basic.StartVirtualCam,
  184. "Starting virtual camera"),
  185. MAKE_CALLBACK(basic.outputHandler->VirtualCamActive(), basic.StopVirtualCam,
  186. "Stopping virtual camera"),
  187. this, this);
  188. LoadHotkeyPair(vcamHotkeys, "OBSBasic.StartVirtualCam", "OBSBasic.StopVirtualCam");
  189. }
  190. togglePreviewHotkeys = obs_hotkey_pair_register_frontend(
  191. "OBSBasic.EnablePreview", Str("Basic.Main.PreviewConextMenu.Enable"), "OBSBasic.DisablePreview",
  192. Str("Basic.Main.Preview.Disable"),
  193. MAKE_CALLBACK(!basic.previewEnabled, basic.EnablePreview, "Enabling preview"),
  194. MAKE_CALLBACK(basic.previewEnabled, basic.DisablePreview, "Disabling preview"), this, this);
  195. LoadHotkeyPair(togglePreviewHotkeys, "OBSBasic.EnablePreview", "OBSBasic.DisablePreview");
  196. togglePreviewProgramHotkeys = obs_hotkey_pair_register_frontend(
  197. "OBSBasic.EnablePreviewProgram", Str("Basic.EnablePreviewProgramMode"),
  198. "OBSBasic.DisablePreviewProgram", Str("Basic.DisablePreviewProgramMode"),
  199. MAKE_CALLBACK(!basic.IsPreviewProgramMode(), basic.EnablePreviewProgram, "Enabling preview program"),
  200. MAKE_CALLBACK(basic.IsPreviewProgramMode(), basic.DisablePreviewProgram, "Disabling preview program"),
  201. this, this);
  202. LoadHotkeyPair(togglePreviewProgramHotkeys, "OBSBasic.EnablePreviewProgram", "OBSBasic.DisablePreviewProgram",
  203. "OBSBasic.TogglePreviewProgram");
  204. contextBarHotkeys = obs_hotkey_pair_register_frontend(
  205. "OBSBasic.ShowContextBar", Str("Basic.Main.ShowContextBar"), "OBSBasic.HideContextBar",
  206. Str("Basic.Main.HideContextBar"),
  207. MAKE_CALLBACK(!basic.ui->contextContainer->isVisible(), basic.ShowContextBar, "Showing Context Bar"),
  208. MAKE_CALLBACK(basic.ui->contextContainer->isVisible(), basic.HideContextBar, "Hiding Context Bar"),
  209. this, this);
  210. LoadHotkeyPair(contextBarHotkeys, "OBSBasic.ShowContextBar", "OBSBasic.HideContextBar");
  211. #undef MAKE_CALLBACK
  212. auto transition = [](void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
  213. if (pressed)
  214. QMetaObject::invokeMethod(static_cast<OBSBasic *>(data), "TransitionClicked",
  215. Qt::QueuedConnection);
  216. };
  217. transitionHotkey = obs_hotkey_register_frontend("OBSBasic.Transition", Str("Transition"), transition, this);
  218. LoadHotkey(transitionHotkey, "OBSBasic.Transition");
  219. auto resetStats = [](void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
  220. if (pressed)
  221. QMetaObject::invokeMethod(static_cast<OBSBasic *>(data), "ResetStatsHotkey",
  222. Qt::QueuedConnection);
  223. };
  224. statsHotkey =
  225. obs_hotkey_register_frontend("OBSBasic.ResetStats", Str("Basic.Stats.ResetStats"), resetStats, this);
  226. LoadHotkey(statsHotkey, "OBSBasic.ResetStats");
  227. auto screenshot = [](void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
  228. if (pressed)
  229. QMetaObject::invokeMethod(static_cast<OBSBasic *>(data), "Screenshot", Qt::QueuedConnection);
  230. };
  231. screenshotHotkey = obs_hotkey_register_frontend("OBSBasic.Screenshot", Str("Screenshot"), screenshot, this);
  232. LoadHotkey(screenshotHotkey, "OBSBasic.Screenshot");
  233. auto screenshotSource = [](void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed) {
  234. if (pressed)
  235. QMetaObject::invokeMethod(static_cast<OBSBasic *>(data), "ScreenshotSelectedSource",
  236. Qt::QueuedConnection);
  237. };
  238. sourceScreenshotHotkey = obs_hotkey_register_frontend("OBSBasic.SelectedSourceScreenshot",
  239. Str("Screenshot.SourceHotkey"), screenshotSource, this);
  240. LoadHotkey(sourceScreenshotHotkey, "OBSBasic.SelectedSourceScreenshot");
  241. }
  242. void OBSBasic::ClearHotkeys()
  243. {
  244. obs_hotkey_pair_unregister(streamingHotkeys);
  245. obs_hotkey_pair_unregister(recordingHotkeys);
  246. obs_hotkey_pair_unregister(pauseHotkeys);
  247. obs_hotkey_unregister(splitFileHotkey);
  248. obs_hotkey_unregister(addChapterHotkey);
  249. obs_hotkey_pair_unregister(replayBufHotkeys);
  250. obs_hotkey_pair_unregister(vcamHotkeys);
  251. obs_hotkey_pair_unregister(togglePreviewHotkeys);
  252. obs_hotkey_pair_unregister(contextBarHotkeys);
  253. obs_hotkey_pair_unregister(togglePreviewProgramHotkeys);
  254. obs_hotkey_unregister(forceStreamingStopHotkey);
  255. obs_hotkey_unregister(transitionHotkey);
  256. obs_hotkey_unregister(statsHotkey);
  257. obs_hotkey_unregister(screenshotHotkey);
  258. obs_hotkey_unregister(sourceScreenshotHotkey);
  259. }
  260. void OBSBasic::ResetStatsHotkey()
  261. {
  262. const QList<OBSBasicStats *> list = findChildren<OBSBasicStats *>();
  263. for (OBSBasicStats *s : list) {
  264. s->Reset();
  265. }
  266. }