| 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 ; }; |