-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTVOverlayManager.cpp
More file actions
115 lines (101 loc) · 4.22 KB
/
Copy pathTVOverlayManager.cpp
File metadata and controls
115 lines (101 loc) · 4.22 KB
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
#include "TVOverlayManager.h"
#include "ButtonComboManager.h"
#include "export.h"
#include "globals.h"
#include "logger.h"
#include <coreinit/cache.h>
#include <coreinit/debug.h>
#include <coreinit/time.h>
namespace TVOverlayManager {
namespace {
ButtonComboModule_ComboHandle sTVButtonHandle;
// Track when the TV button was last pressed to implement timeout, or zero if
// timeout expired.
OSTime sTVPressed[2];
bool sTVMenuBlocked[2];
void TVComboCallback(ButtonComboModule_ControllerTypes triggeredBy,
ButtonComboModule_ComboHandle,
void *) {
VPADChan chan;
switch (triggeredBy) {
case BUTTON_COMBO_MODULE_CONTROLLER_VPAD_0:
chan = VPAD_CHAN_0;
break;
case BUTTON_COMBO_MODULE_CONTROLLER_VPAD_1:
chan = VPAD_CHAN_1;
break;
default:
return;
}
DEBUG_FUNCTION_LINE_INFO("TV pressed");
sTVPressed[chan] = OSGetSystemTime();
OSMemoryBarrier();
}
void SetBlocked(VPADChan channel, bool blocked) {
VPADSetTVMenuInvalid(channel, blocked);
sTVMenuBlocked[channel] = blocked;
}
} // namespace
void RegisterCombo() {
ButtonComboModule_ComboOptions opt = {};
opt.version = BUTTON_COMBO_MODULE_COMBO_OPTIONS_VERSION;
opt.metaOptions.label = "TV remote overlay combo";
opt.callbackOptions.callback = TVComboCallback;
opt.callbackOptions.context = {};
opt.buttonComboOptions.type = BUTTON_COMBO_MODULE_COMBO_TYPE_PRESS_DOWN_OBSERVER;
opt.buttonComboOptions.basicCombo.combo = BCMPAD_BUTTON_TV;
opt.buttonComboOptions.basicCombo.controllerMask = BUTTON_COMBO_MODULE_CONTROLLER_VPAD;
opt.buttonComboOptions.optionalHoldForXMs = 0;
if (ButtonComboModule_AddButtonCombo(&opt, &sTVButtonHandle, nullptr) != BUTTON_COMBO_MODULE_ERROR_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("FAILED TO SET UP TV COMBO!");
}
}
void UnregisterCombo() {
ButtonComboModule_RemoveButtonCombo(sTVButtonHandle);
}
void InitVPAD(VPADChan channel) {
bool blocked = false;
if (auto mgr = gButtonComboManager) {
blocked = mgr->hasActiveComboWithTVButton();
}
SetBlocked(channel, blocked);
ResetVPAD(channel);
}
void ResetVPAD(VPADChan channel) {
sTVPressed[channel] = 0;
OSMemoryBarrier();
}
void UpdateVPAD(VPADChan channel) {
if (sTVPressed[channel]) {
OSTime elapsed = OSGetSystemTime() - sTVPressed[channel];
// TODO: this should be configurable by the public API.
const OSTime double_press_time = OSMillisecondsToTicks(100);
if (elapsed > double_press_time && sTVMenuBlocked[channel]) {
DEBUG_FUNCTION_LINE_INFO("Unblocking TV menu");
SetBlocked(channel, false);
}
// TODO: this should be configurable by the public API.
const OSTime tv_enable_timeout = OSMillisecondsToTicks(1000);
if (elapsed > tv_enable_timeout && !VPADGetTVMenuStatus(channel)) {
bool blocked = false;
if (auto mgr = gButtonComboManager) {
blocked = mgr->hasActiveComboWithTVButton();
}
DEBUG_FUNCTION_LINE_INFO("TV timeout reached, setting TV Menu block to %s",
blocked ? "blocked" : "unblocked");
SetBlocked(channel, blocked);
ResetVPAD(channel);
}
}
}
void UpdateBlocking() {
bool blocked = false;
if (auto mgr = gButtonComboManager) {
blocked = mgr->hasActiveComboWithTVButton();
}
for (VPADChan channel : {VPAD_CHAN_0, VPAD_CHAN_1}) {
SetBlocked(channel, blocked);
ResetVPAD(channel);
}
}
} // namespace TVOverlayManager