1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | #include <vdr/plugin.h> |
13 | #include <vdr/keys.h> |
14 | #include <vdr/config.h> |
15 | |
16 | #include <getopt.h> |
17 | |
18 | using namespace std; |
19 | |
20 | #include "menu.h" |
21 | #include "txtrecv.h" |
22 | #include "setup.h" |
23 | #include "legacystorage.h" |
24 | #include "packedstorage.h" |
25 | |
26 | #if defined(APIVERSNUM20000) && APIVERSNUM20000 < 10739 |
27 | #error "VDR-1.7.39 API version or greater is required!" |
28 | #endif |
29 | |
30 | static const char *VERSION = "0.9.4"; |
31 | static const char *DESCRIPTION = trNOOP("Displays teletext on the OSD")("Displays teletext on the OSD"); |
32 | static const char *MAINMENUENTRY = trNOOP("Teletext")("Teletext"); |
33 | |
34 | class cPluginTeletextosd : public cPlugin { |
35 | private: |
36 | |
37 | cTxtStatus *txtStatus; |
38 | bool startReceiver; |
39 | bool storeTopText; |
40 | Storage *storage; |
41 | int maxStorage; |
42 | void initTexts(); |
43 | Storage::StorageSystem storageSystem; |
44 | public: |
45 | cPluginTeletextosd(void); |
46 | virtual ~cPluginTeletextosd(); |
47 | virtual const char *Version(void) { return VERSION; } |
48 | virtual const char *Description(void) { return tr(DESCRIPTION)I18nTranslate(DESCRIPTION, "vdr-" "osdteletext"); } |
49 | virtual const char *CommandLineHelp(void); |
50 | virtual bool ProcessArgs(int argc, char *argv[]); |
51 | virtual bool Start(void); |
52 | virtual void Housekeeping(void); |
53 | virtual const char *MainMenuEntry(void); |
54 | virtual cOsdObject *MainMenuAction(void); |
55 | virtual cMenuSetupPage *SetupMenu(void); |
56 | virtual bool SetupParse(const char *Name, const char *Value); |
57 | }; |
58 | |
59 | class cTeletextSetupPage; |
60 | class ActionEdit { |
61 | public: |
62 | void Init(cTeletextSetupPage*, int, cMenuEditIntItem *, cMenuEditStraItem *); |
63 | cMenuEditStraItem *action; |
64 | cMenuEditIntItem *number; |
65 | bool visible; |
66 | }; |
67 | |
68 | struct ActionKeyName { |
69 | const char *internalName; |
70 | const char *userName; |
71 | }; |
72 | |
73 | class cTeletextSetupPage : public cMenuSetupPage { |
74 | friend class ActionEdit; |
75 | private: |
76 | TeletextSetup temp; |
77 | int tempPageNumber[LastActionKey]; |
78 | int tempConfiguredClrBackground; |
79 | protected: |
80 | virtual void Store(void); |
81 | ActionEdit ActionEdits[LastActionKey]; |
82 | virtual eOSState ProcessKey(eKeys Key); |
83 | public: |
84 | cTeletextSetupPage(void); |
85 | static const ActionKeyName *actionKeyNames; |
86 | static const char **modes; |
87 | |
88 | |
89 | }; |
90 | |
91 | const ActionKeyName *cTeletextSetupPage::actionKeyNames = 0; |
92 | const char **cTeletextSetupPage::modes = 0; |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | cPluginTeletextosd::cPluginTeletextosd(void) |
106 | : txtStatus(0), startReceiver(true), storage(NULL__null), maxStorage(-1) |
107 | { |
108 | |
109 | |
110 | |
111 | } |
112 | |
113 | cPluginTeletextosd::~cPluginTeletextosd() |
114 | { |
115 | |
116 | if (txtStatus) |
117 | delete txtStatus; |
118 | if(storage) { |
119 | storage->cleanUp(); |
120 | delete storage; |
121 | } |
122 | } |
123 | |
124 | const char *cPluginTeletextosd::CommandLineHelp(void) |
125 | { |
126 | |
127 | return " -d --directory=DIR The directory where the temporary\n" |
128 | " files will be stored.\n" |
129 | " (default: /var/run/vdr/osdteletext)\n" |
130 | " Ensure that the directory exists and is writable.\n" |
131 | " -n --max-cache=NUM Maximum size in megabytes of cache used\n" |
132 | " to store the pages on the harddisk.\n" |
133 | " (default: a calculated value below 50 MB)\n" |
134 | " -s --cache-system=SYS Set the cache system to be used.\n" |
135 | " Choose \"legacy\" for the traditional\n" |
136 | " one-file-per-page system.\n" |
137 | " Default is \"packed\" for the \n" |
138 | " one-file-for-a-few-pages system.\n" |
139 | " -t, --toptext Store top text pages at cache. (unviewable pages)\n"; |
140 | } |
141 | |
142 | bool cPluginTeletextosd::ProcessArgs(int argc, char *argv[]) |
143 | { |
144 | |
145 | static struct option long_options[] = { |
146 | { "directory", required_argument1, NULL__null, 'd' }, |
147 | { "max-cache", required_argument1, NULL__null, 'n' }, |
148 | { "cache-system", required_argument1, NULL__null, 's' }, |
149 | { "toptext", no_argument0, NULL__null, 't' }, |
150 | { NULL__null } |
151 | }; |
152 | |
153 | int c; |
154 | while ((c = getopt_long(argc, argv, "s:d:n:t", long_options, NULL__null)) != -1) { |
| 1 | Loop condition is true. Entering loop body | |
|
| 6 | | Loop condition is true. Entering loop body | |
|
155 | switch (c) { |
| 2 | | Control jumps to 'case 115:' at line 156 | |
|
| 7 | | Control jumps to 'case 110:' at line 166 | |
|
156 | case 's': |
157 | if (!optarg) |
| 3 | | Assuming 'optarg' is null | |
|
| |
158 | break; |
| 5 | | Execution continues on line 154 | |
|
159 | if (strcasecmp(optarg, "legacy")==0) |
160 | storageSystem = Storage::StorageSystemLegacy; |
161 | else if (strcasecmp(optarg, "packed")==0) |
162 | storageSystem = Storage::StorageSystemPacked; |
163 | break; |
164 | case 'd': Storage::setRootDir(optarg); |
165 | break; |
166 | case 'n': if (isnumber(optarg)) { |
| |
167 | int n = atoi(optarg); |
| 9 | | Null pointer passed as an argument to a 'nonnull' parameter |
|
168 | maxStorage=n; |
169 | } |
170 | break; |
171 | case 't': storeTopText=true; |
172 | break; |
173 | } |
174 | } |
175 | return true; |
176 | } |
177 | |
178 | bool cPluginTeletextosd::Start(void) |
179 | { |
180 | |
181 | |
182 | |
183 | switch (storageSystem) { |
184 | case Storage::StorageSystemLegacy: |
185 | storage = new LegacyStorage(maxStorage); |
186 | case Storage::StorageSystemPacked: |
187 | default: |
188 | storage = new PackedStorage(maxStorage); |
189 | } |
190 | |
191 | initTexts(); |
192 | if (startReceiver) |
193 | txtStatus=new cTxtStatus(storeTopText, storage); |
194 | if (ttSetup.OSDheight<=100) ttSetup.OSDheight=Setup.OSDHeight; |
195 | if (ttSetup.OSDwidth<=100) ttSetup.OSDwidth=Setup.OSDWidth; |
196 | |
197 | return true; |
198 | } |
199 | |
200 | void cPluginTeletextosd::initTexts() { |
201 | if (cTeletextSetupPage::actionKeyNames) |
202 | return; |
203 | |
204 | static const ActionKeyName st_actionKeyNames[] = |
205 | { |
206 | { "Action_kRed", trVDR("Key$Red")I18nTranslate("Key$Red") }, |
207 | { "Action_kGreen", trVDR("Key$Green")I18nTranslate("Key$Green") }, |
208 | { "Action_kYellow", trVDR("Key$Yellow")I18nTranslate("Key$Yellow") }, |
209 | { "Action_kBlue", trVDR("Key$Blue")I18nTranslate("Key$Blue") }, |
210 | { "Action_kPlay", trVDR("Key$Play")I18nTranslate("Key$Play") }, |
211 | { "Action_kStop", trVDR("Key$Stop")I18nTranslate("Key$Stop") }, |
212 | { "Action_kFastFwd", trVDR("Key$FastFwd")I18nTranslate("Key$FastFwd") }, |
213 | { "Action_kFastRew", trVDR("Key$FastRew")I18nTranslate("Key$FastRew") } |
214 | }; |
215 | |
216 | cTeletextSetupPage::actionKeyNames = st_actionKeyNames; |
217 | |
218 | static const char *st_modes[] = |
219 | { |
220 | tr("Zoom")I18nTranslate("Zoom", "vdr-" "osdteletext"), |
221 | tr("Half page")I18nTranslate("Half page", "vdr-" "osdteletext"), |
222 | tr("Change channel")I18nTranslate("Change channel", "vdr-" "osdteletext"), |
223 | tr("Switch background")I18nTranslate("Switch background", "vdr-" "osdteletext"), |
224 | |
225 | tr("Jump to...")I18nTranslate("Jump to...", "vdr-" "osdteletext") |
226 | }; |
227 | |
228 | cTeletextSetupPage::modes = st_modes; |
229 | } |
230 | |
231 | void cPluginTeletextosd::Housekeeping(void) |
232 | { |
233 | |
234 | } |
235 | |
236 | const char *cPluginTeletextosd::MainMenuEntry(void) |
237 | { |
238 | return ttSetup.HideMainMenu ? 0 : tr(MAINMENUENTRY)I18nTranslate(MAINMENUENTRY, "vdr-" "osdteletext"); |
239 | } |
240 | |
241 | cOsdObject *cPluginTeletextosd::MainMenuAction(void) |
242 | { |
243 | |
244 | return new TeletextBrowser(txtStatus,storage); |
245 | } |
246 | |
247 | cMenuSetupPage *cPluginTeletextosd::SetupMenu(void) |
248 | { |
249 | |
250 | return new cTeletextSetupPage; |
251 | } |
252 | |
253 | |
254 | |
255 | bool cPluginTeletextosd::SetupParse(const char *Name, const char *Value) |
256 | { |
257 | initTexts(); |
258 | |
259 | |
260 | if (!strcasecmp(Name, "configuredClrBackground")) ttSetup.configuredClrBackground=( ((unsigned int)atoi(Value)) << 24); |
261 | else if (!strcasecmp(Name, "showClock")) ttSetup.showClock=atoi(Value); |
262 | |
263 | else if (!strcasecmp(Name, "suspendReceiving")) ttSetup.suspendReceiving=atoi(Value); |
264 | else if (!strcasecmp(Name, "autoUpdatePage")) ttSetup.autoUpdatePage=atoi(Value); |
265 | else if (!strcasecmp(Name, "OSDheight")) ttSetup.OSDheight=atoi(Value); |
266 | else if (!strcasecmp(Name, "OSDwidth")) ttSetup.OSDwidth=atoi(Value); |
267 | else if (!strcasecmp(Name, "OSDHAlign")) ttSetup.OSDHAlign=atoi(Value); |
268 | else if (!strcasecmp(Name, "OSDVAlign")) ttSetup.OSDVAlign=atoi(Value); |
269 | else if (!strcasecmp(Name, "inactivityTimeout")) ; |
270 | else if (!strcasecmp(Name, "HideMainMenu")) ttSetup.HideMainMenu=atoi(Value); |
271 | else { |
272 | for (int i=0;i<LastActionKey;i++) { |
273 | if (!strcasecmp(Name, cTeletextSetupPage::actionKeyNames[i].internalName)) { |
274 | ttSetup.mapKeyToAction[i]=(eTeletextAction)atoi(Value); |
275 | |
276 | |
277 | if (ttSetup.mapKeyToAction[i]<100 && ttSetup.mapKeyToAction[i]>=LastAction) |
278 | ttSetup.mapKeyToAction[i]=LastAction-1; |
279 | |
280 | return true; |
281 | } |
282 | } |
283 | |
284 | |
285 | char act[7]; |
286 | strncpy(act, Name, 7); |
287 | if (!strcasecmp(act, "Action_")) |
288 | return true; |
289 | |
290 | return false; |
291 | } |
292 | return true; |
293 | } |
294 | |
295 | void cTeletextSetupPage::Store(void) { |
296 | |
297 | for (int i=0;i<LastActionKey;i++) { |
298 | if (temp.mapKeyToAction[i] >= LastAction) |
299 | ttSetup.mapKeyToAction[i]=(eTeletextAction)tempPageNumber[i]; |
300 | else |
301 | ttSetup.mapKeyToAction[i]=temp.mapKeyToAction[i]; |
302 | } |
303 | ttSetup.configuredClrBackground=( ((unsigned int)tempConfiguredClrBackground) << 24); |
304 | ttSetup.showClock=temp.showClock; |
305 | ttSetup.suspendReceiving=temp.suspendReceiving; |
306 | ttSetup.autoUpdatePage=temp.autoUpdatePage; |
307 | ttSetup.OSDheight=temp.OSDheight; |
308 | ttSetup.OSDwidth=temp.OSDwidth; |
309 | ttSetup.OSDHAlign=temp.OSDHAlign; |
310 | ttSetup.OSDVAlign=temp.OSDVAlign; |
311 | ttSetup.HideMainMenu=temp.HideMainMenu; |
312 | |
313 | |
314 | for (int i=0;i<LastActionKey;i++) { |
315 | SetupStore(actionKeyNames[i].internalName, ttSetup.mapKeyToAction[i]); |
316 | } |
317 | SetupStore("configuredClrBackground", (int)(ttSetup.configuredClrBackground >> 24)); |
318 | SetupStore("showClock", ttSetup.showClock); |
319 | |
320 | |
321 | SetupStore("autoUpdatePage", ttSetup.autoUpdatePage); |
322 | SetupStore("OSDheight", ttSetup.OSDheight); |
323 | SetupStore("OSDwidth", ttSetup.OSDwidth); |
324 | SetupStore("OSDHAlign", ttSetup.OSDHAlign); |
325 | SetupStore("OSDVAlign", ttSetup.OSDVAlign); |
326 | SetupStore("HideMainMenu", ttSetup.HideMainMenu); |
327 | |
328 | } |
329 | |
330 | |
331 | cTeletextSetupPage::cTeletextSetupPage(void) { |
332 | cString buf; |
333 | cOsdItem *item; |
334 | |
335 | |
336 | for (int i=0;i<LastActionKey;i++) { |
337 | if (ttSetup.mapKeyToAction[i] >= LastAction) { |
338 | temp.mapKeyToAction[i]=LastAction; |
339 | tempPageNumber[i]=ttSetup.mapKeyToAction[i]; |
340 | } else { |
341 | temp.mapKeyToAction[i]=ttSetup.mapKeyToAction[i]; |
342 | tempPageNumber[i]=100; |
343 | } |
344 | } |
345 | tempConfiguredClrBackground=(ttSetup.configuredClrBackground >> 24); |
346 | temp.showClock=ttSetup.showClock; |
347 | temp.suspendReceiving=ttSetup.suspendReceiving; |
348 | temp.autoUpdatePage=ttSetup.autoUpdatePage; |
349 | temp.OSDheight=ttSetup.OSDheight; |
350 | temp.OSDwidth=ttSetup.OSDwidth; |
351 | temp.OSDHAlign=ttSetup.OSDHAlign; |
352 | temp.OSDVAlign=ttSetup.OSDVAlign; |
353 | temp.HideMainMenu=ttSetup.HideMainMenu; |
354 | |
355 | |
356 | Add(new cMenuEditIntItem(tr("Background transparency")I18nTranslate("Background transparency", "vdr-" "osdteletext" ), &tempConfiguredClrBackground, 0, 255)); |
357 | |
358 | Add(new cMenuEditBoolItem(tr("Show clock")I18nTranslate("Show clock", "vdr-" "osdteletext"), &temp.showClock )); |
359 | |
360 | |
361 | |
362 | Add(new cMenuEditBoolItem(tr("Auto-update pages")I18nTranslate("Auto-update pages", "vdr-" "osdteletext"), &temp.autoUpdatePage )); |
363 | |
364 | Add(new cMenuEditIntItem(tr("OSD height")I18nTranslate("OSD height", "vdr-" "osdteletext"), &temp.OSDheight, 250, MAXOSDHEIGHT1200)); |
365 | Add(new cMenuEditIntItem(tr("OSD width")I18nTranslate("OSD width", "vdr-" "osdteletext"), &temp.OSDwidth, 320, MAXOSDWIDTH1920)); |
366 | |
367 | Add(new cMenuEditIntItem(tr("OSD horizontal align")I18nTranslate("OSD horizontal align", "vdr-" "osdteletext"), &temp.OSDHAlign, 0, 100)); |
368 | Add(new cMenuEditIntItem(tr("OSD vertical align")I18nTranslate("OSD vertical align", "vdr-" "osdteletext"), &temp.OSDVAlign, 0, 100)); |
369 | Add(new cMenuEditBoolItem(tr("Hide mainmenu entry")I18nTranslate("Hide mainmenu entry", "vdr-" "osdteletext"), &temp.HideMainMenu)); |
370 | |
371 | |
372 | |
373 | |
374 | buf = cString::sprintf("%s:", tr("Key bindings")I18nTranslate("Key bindings", "vdr-" "osdteletext")); |
375 | item = new cOsdItem(*buf); |
376 | item->SetSelectable(false); |
377 | Add(item); |
378 | |
379 | for (int i=0;i<LastActionKey;i++) { |
380 | ActionEdits[i].Init(this, i, new cMenuEditIntItem(tr(" Page number")I18nTranslate(" Page number", "vdr-" "osdteletext"), &tempPageNumber[i], 100, 899), |
381 | new cMenuEditStraItem(actionKeyNames[i].userName, (int*)&temp.mapKeyToAction[i], LastAction+1, modes) ); |
382 | } |
383 | } |
384 | |
385 | eOSState cTeletextSetupPage::ProcessKey(eKeys Key) { |
386 | eOSState state = cMenuSetupPage::ProcessKey(Key); |
387 | if (Key != kRight && Key!=kLeft) |
388 | return state; |
389 | cOsdItem *item = Get(Current()); |
390 | for (int i=0;i<LastActionKey;i++) { |
391 | if (ActionEdits[i].action==item) { |
392 | |
393 | |
394 | if (temp.mapKeyToAction[i] == LastAction && !ActionEdits[i].visible) { |
395 | |
396 | if (i+1<LastActionKey) |
397 | |
398 | Ins( ActionEdits[i].number, false, ActionEdits[i+1].action); |
399 | else |
400 | Add( ActionEdits[i].number, false ); |
401 | |
402 | ActionEdits[i].visible=true; |
403 | Display(); |
404 | } else if (temp.mapKeyToAction[i] != LastAction && ActionEdits[i].visible) { |
405 | |
406 | cList<cOsdItem>::Del(ActionEdits[i].number, false); |
407 | ActionEdits[i].visible=false; |
408 | Display(); |
409 | } |
410 | break; |
411 | |
412 | |
413 | } |
414 | } |
415 | |
416 | return state; |
417 | |
418 | } |
419 | |
420 | |
421 | void ActionEdit::Init(cTeletextSetupPage* s, int num, cMenuEditIntItem *p, cMenuEditStraItem * a) { |
422 | action=a; |
423 | number=p; |
424 | s->Add(action); |
425 | if (s->temp.mapKeyToAction[num] == LastAction) { |
426 | s->Add(number); |
427 | visible=true; |
428 | } else |
429 | visible=false; |
430 | } |
431 | |
432 | |
433 | |
434 | |
435 | VDRPLUGINCREATOR(cPluginTeletextosd)extern "C" void *VDRPluginCreator(void) { return new cPluginTeletextosd ; }; |