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
|
This is a "patch" for the Video Disk Recorder (VDR).
* History
2026-02-07: Version 1.0.5
Update for VDR 2.7.9 (Stefan Hofmann)
2025-02-26: Version 1.0.4
Update for VDR 2.7.4 (Jörg Riechardt)
2013-11-08: Version 1.0.3
Update for VDR 2.1.2 (Jörg Riechardt)
2012-04-06: Version 1.0.2
- Update for recent VDR developer versions (Manuel Reimer)
2010-10-15: Version 1.0.1
- return a cOsdObject instead of its subclass cOsdMenu (thanks to
Joe_D@vdrportal)
- version number defines in 'config.h' now follow the usual conventions:
MAINMENUHOOKSVERSNUM is now a number, the newly added define
MAINMENUHOOKSVERSION is a string (suggested by gnapheus@vdrportal)
- patch is now based on VDR 1.6.0
- updated documentation
2007-02-26: Version 1.0
- Initial revision.
* Authors:
Tobias Grimm <vdr at e-tobi dot net>
Martin Prochnow <nordlicht at martins-kabuff dot de>
Frank Schmirler <vdrdev at schmirler dot de>
Christian Wieninger <cwieninger at gmx dot de>
* Description:
This patch allows plugins to replace the VDR main menus "Schedule",
"Channels", "Timers" and "Recordings" by a different implementation.
The patch is based on a suggestion of Christian Wieninger back in 2006
(http://www.linuxtv.org/pipermail/vdr/2006-March/008234.html). It is
meant to be an interim solution for VDR 1.4 until (maybe) VDR 1.5
introduces an official API for this purpose.
* Installation
Change into the VDR source directory, then issue
patch -p1 < path/to/MainMenuHooks-v1_0_1.patch
and recompile.
* Notes for plugin authors
The following code sample shows the required plugin code for replacing
the original Schedule menu:
bool cMyPlugin::Service(const char *Id, void *Data)
{
cOsdMenu **menu = (cOsdMenu**) Data;
if (MySetup.replaceSchedule &&
strcmp(Id, "MainMenuHooksPatch-v1.0::osSchedule") == 0) {
if (menu)
*menu = (cOsdMenu*) MainMenuAction();
return true;
}
return false;
}
Since patch version 1.0.1, the service call may return a cOsdObject
instead of a 'cOsdMenu'. Use '#ifdef MAINMENUHOOKSVERSION' to detect
version 1.0.1 or later.
A plugin can replace more than one menu at a time. Simply replace the
call to MainMenuAction() in the sample above by appropriate code.
Note that a plugin *should* offer a setup option which allows the user
to enable or disable the replacement. "Disabled" would be a reasonable
default setting. By testing for a specific 'MAINMENUHOOKSVERSNUM', like
'#if MAINMENUHOOKSVERSION >= 10001', plugin can decide at compile time
which features and setup options to provide.
In case there is an internal problem when trying to open the replacement
menu, it is safe to return 'true' even though 'Data' is NULL. However an
OSD message should indicate the problem to the user.
Feel free to ship this patch along with your plugin. However if you
think you need to modify the patch, we'd encourage you to contact the
authors first or at least use a service id which differs in more than
just the version number.
---
config.h | 4 ++++
menu.c | 71 +++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 61 insertions(+), 14 deletions(-)
diff --git a/config.h b/config.h
index 96fd5dd7..fddcdc21 100644
--- a/config.h
+++ b/config.h
@@ -35,6 +35,10 @@
// only when there are changes to the plugin API. This allows compiled
// plugins to work with newer versions of the core VDR as long as no
// interfaces have changed. APIVERSNUM begins with "300.." for backwards
+
+// The MainMenuHook Patch's version number:
+#define MAINMENUHOOKSVERSION "1.0.5"
+#define MAINMENUHOOKSVERSNUM 10005 // Version * 10000 + Major * 100 + Minor
// compatibility and can be used in #if preprocessor statements to handle
// version dependent code.
diff --git a/menu.c b/menu.c
index 8798a3f1..57555d3e 100644
--- a/menu.c
+++ b/menu.c
@@ -4671,15 +4671,31 @@ cMenuMain::cMenuMain(eOSState State, bool OpenSubMenus)
// Initial submenus:
+ cOsdObject *menu = NULL;
switch (State) {
- case osSchedule: AddSubMenu(new cMenuSchedule); break;
- case osChannels: AddSubMenu(new cMenuChannels); break;
- case osTimers: AddSubMenu(new cMenuTimers); break;
- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, OpenSubMenus)); break;
- case osSetup: AddSubMenu(new cMenuSetup); break;
- case osCommands: AddSubMenu(new cMenuCommands(tr("Button$Commands"), &Commands)); break;
+ case osSchedule:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
+ menu = new cMenuSchedule;
+ break;
+ case osChannels:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
+ menu = new cMenuChannels;
+ break;
+ case osTimers:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
+ menu = new cMenuTimers;
+ break;
+ case osRecordings:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
+ menu = new cMenuRecordings(NULL, 0, OpenSubMenus);
+ break;
+ case osSetup: menu = new cMenuSetup; break;
+ case osCommands: menu = new cMenuCommands(tr("Button$Commands"), &Commands); break;
default: break;
}
+ if (menu)
+ if (menu->IsMenu())
+ AddSubMenu((cOsdMenu *) menu);
}
cOsdObject *cMenuMain::PluginOsdObject(void)
@@ -4808,15 +4824,36 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
eOSState state = cOsdMenu::ProcessKey(Key);
HadSubMenu |= HasSubMenu();
+ cOsdObject *menu = NULL;
switch (state) {
- case osSchedule: return AddSubMenu(new cMenuSchedule);
- case osChannels: return AddSubMenu(new cMenuChannels);
- case osTimers: return AddSubMenu(new cMenuTimers);
- case osRecordings: return AddSubMenu(new cMenuRecordings);
- case osRecsOpen: return AddSubMenu(new cMenuRecordings(NULL, 0, true));
- case osRecsDel: return AddSubMenu(new cMenuRecordings(NULL, 0, true, NULL, true));
- case osSetup: return AddSubMenu(new cMenuSetup);
- case osCommands: return AddSubMenu(new cMenuCommands(tr("Button$Commands"), &Commands));
+ case osSchedule:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
+ menu = new cMenuSchedule;
+ else
+ state = osContinue;
+ break;
+ case osChannels:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
+ menu = new cMenuChannels;
+ else
+ state = osContinue;
+ break;
+ case osTimers:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
+ menu = new cMenuTimers;
+ else
+ state = osContinue;
+ break;
+ case osRecordings:
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
+ menu = new cMenuRecordings;
+ else
+ state = osContinue;
+ break;
+ case osRecsOpen: menu = new cMenuRecordings(NULL, 0, true); break;
+ case osRecsDel: menu = new cMenuRecordings(NULL, 0, true, NULL, true); break;
+ case osSetup: menu = new cMenuSetup; break;
+ case osCommands: menu = new cMenuCommands(tr("Button$Commands"), &Commands); break;
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
if (cOsdItem *item = Get(Current())) {
cRecordControls::Stop(item->Text() + strlen(tr(STOP_RECORDING)));
@@ -4867,6 +4904,12 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
default: break;
}
}
+ if (menu) {
+ if (menu->IsMenu())
+ return AddSubMenu((cOsdMenu *) menu);
+ pluginOsdObject = menu;
+ return osPlugin;
+ }
bool DoDisplay = Update();
if (Key != kNone) {
if (I18nCurrentLanguage() != osdLanguage) {
--
2.43.0
|