/** * GraphTFT plugin for the Video Disk Recorder * * graphtft.c - A plugin for the Video Disk Recorder * * (c) 2004 Lars Tegeler, Sascha Volkenandt * (c) 2006-2013 Jörg Wendel * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * **/ #include #include #include #include #include #include //*************************************************************************** // cGraphTFTMenu //*************************************************************************** //*************************************************************************** // Object //*************************************************************************** cGraphTFTMenu::cGraphTFTMenu(const char* title, cPluginGraphTFT* aPlugin) { int i = 0; char* buf = 0; char** normalModes = Thms::theTheme->getNormalSections(); SetTitle(title ? title : ""); plugin = aPlugin; defMode = 0; dspActive = plugin->getDisplay()->displayActive; while (normalModes[i]) { if (normalModes[i] == GraphTFTSetup.normalMode) { defMode = i; break; } i++; } originalDefMode = defMode; Clear(); cOsdMenu::Add(new cOsdItem(tr("Reload themes"))); cOsdMenu::Add(new cMenuEditBoolItem(tr("Refresh Display"), &dspActive)); cOsdMenu::Add(new cMenuEditStraItem(tr("Normal Display"), &defMode, Thms::theTheme->getNormalSectionsCount(), normalModes)); // user theme variables if (!Thms::theTheme->menuVariables.empty()) { asprintf(&buf, "------ \t %s -----------------------------------------", Thms::theTheme->getName().c_str()); Add(new cOsdItem(buf)); free(buf); cList::Last()->SetSelectable(false); map::iterator iter; for (i = 0, iter = Thms::theTheme->menuVariables.begin(); i < 50 && iter != Thms::theTheme->menuVariables.end(); iter++, i++) { strncpy(variableValues[i], iter->second.c_str(), sizeVarMax); variableValues[i][sizeVarMax] = 0; cOsdMenu::Add(new cMenuEditStrItem(iter->first.c_str(), variableValues[i], sizeVarMax, FileNameChars)); } } SetHelp(tr("Snapshot"), 0, 0,0); Display(); } cGraphTFTMenu::~cGraphTFTMenu() { } //*************************************************************************** // Process Key //*************************************************************************** eOSState cGraphTFTMenu::ProcessKey(eKeys key) { eOSState state = cOsdMenu::ProcessKey(key); // RefreshCurrent(); if (state != osUnknown) return state; switch (key) { case kRed: { plugin->getDisplay()->snapshotPending = yes; return osEnd; } case kOk: { Store(); if (Current() == 0) plugin->loadThemes(); return osEnd; } default: break; } return state; } void cGraphTFTMenu::Store() { int i; if (defMode != originalDefMode) { GraphTFTSetup.normalMode = Thms::theTheme->getNormalSections()[defMode]; GraphTFTSetup.storeNormalMode = true; GraphTFTSetup.originalNormalMode = ""; plugin->SetupStore("normalMode", GraphTFTSetup.normalMode.c_str()); Setup.Save(); } plugin->getDisplay()->displayActive = dspActive; map::iterator iter; for (i = 0, iter = Thms::theTheme->menuVariables.begin(); i < 50 && iter != Thms::theTheme->menuVariables.end(); iter++, i++) { iter->second = variableValues[i]; } } //*************************************************************************** // cPluginGraphTFT //*************************************************************************** //*************************************************************************** // Object //*************************************************************************** cPluginGraphTFT::cPluginGraphTFT() { display = 0; _dev = 0; port = 2039; } cPluginGraphTFT::~cPluginGraphTFT() { if (display) delete display; if (_dev) free(_dev); Thms::theTheme = 0; themes.Clear(); } //*************************************************************************** // Command Line Help //*************************************************************************** const char *cPluginGraphTFT::CommandLineHelp() { return " -d DEV, --device=DEV sets the output-device\n" " /dev/fb0\n" " (default: autodetect)\n"; } //*************************************************************************** // Process Args //*************************************************************************** bool cPluginGraphTFT::ProcessArgs(int argc, char* argv[]) { int c; static struct option long_options[] = { { "device", required_argument, 0, 'd' }, { 0, 0, 0, 0 } }; // check the arguments while ((c = getopt_long(argc, argv, "d:", long_options, 0)) != -1) { switch (c) { case 'd': // device _dev = strdup(optarg); break; case 'p': // port port = atoi(optarg); break; default: isyslog("Graphtft: Ignoring unknown argument '%s'", optarg); } } return true; } //*************************************************************************** // Initialize //*************************************************************************** bool cPluginGraphTFT::Initialize() { return true; } //*************************************************************************** // Start //*************************************************************************** bool cPluginGraphTFT::Start() { // Start any background activities the plugin shall perform. isyslog("Device is '%s'", _dev ? _dev : "not configured, probing"); if (!_dev) { fprintf(stderr, "vdr: graphtft - try framebuffer device!\n"); asprintf(&_dev,"/dev/fb0"); } // try to get the config dir if (!ConfigDirectory()) return false; // init GraphTFTSetup.setClient(this); GraphTFTSetup.PluginConfPath = strdup(ConfigDirectory()); display = new cGraphTFTDisplay(THEMEVERSION); logDevice = GraphTFTSetup.LogDevice; logLevel = GraphTFTSetup.Level; // load the thems if (loadThemes() != 0) return false; if (display->Init(_dev, ConfigDirectory(), port) != success) { tell(0, "Error: Initializing graphTFT device faild, aborting!"); return 0; } return 1; } //*************************************************************************** // Store //*************************************************************************** void cPluginGraphTFT::Store() { GraphTFTSetup.Store(); } //*************************************************************************** // Load Themes //*************************************************************************** int cPluginGraphTFT::loadThemes() { char* buffer; FILE* p; cMutexLock lock(display->getMutex()); // look for the themes in the config directory asprintf(&buffer, "find %s/graphTFT/themes -follow -type f -name '*.theme' | sort", ConfigDirectory()); p = popen(buffer, "r"); free(buffer); // first forget loaded themes themes.Clear(); isyslog("Loading themes"); if (p) { char* s; cReadLine ReadLine; while ((s = ReadLine.Read(p))) { // Try to load the themes Thms::theTheme = new cGraphTFTTheme(); if (Thms::theTheme->load(s) != 0) { delete Thms::theTheme; Thms::theTheme = 0; continue; } Thms::theTheme->check(THEMEVERSION); themes.Add(Thms::theTheme); } } pclose(p); // Have we found themes? if (!themes.Count()) { isyslog("Error: graphTFT - no themes found, aborting!"); return fail; } else { Thms::theTheme = themes.getTheme(GraphTFTSetup.Theme); if (!Thms::theTheme) Thms::theTheme = themes.Get(0); } isyslog("Loaded %d themes", themes.Count()); display->setupChanged(); display->themesReloaded(); if (Thms::theTheme) isyslog("Activated theme '%s'", Thms::theTheme->getName().c_str()); else isyslog("Cant activate theme ;)"); return success; } //*************************************************************************** // Main Menu Action //*************************************************************************** cOsdObject* cPluginGraphTFT::MainMenuAction() { return new cGraphTFTMenu(MainMenuEntry(), this); } //*************************************************************************** // Setup Menu //*************************************************************************** cMenuSetupPage* cPluginGraphTFT::SetupMenu() { return new cMenuSetupGraphTFT(display); } //*************************************************************************** // Setup Parse //*************************************************************************** bool cPluginGraphTFT::SetupParse(const char* Name, const char* Value) { return GraphTFTSetup.SetupParse(Name, Value); } //*************************************************************************** // Service //*************************************************************************** bool cPluginGraphTFT::Service(const char* id, void* data) { if (strcmp(id, SPAN_CLIENT_CHECK_ID) == 0) { if (GraphTFTSetup.enableSpectrumAnalyzer && data) *((cSpanService::Span_Client_Check_1_0*)data)->isActive = true; return true; } else if (strcmp(id, GRAPHTFT_TOUCH_EVENT_ID) == 0) { cTftCS::GraphTftTouchEvent* event; event = (cTftCS::GraphTftTouchEvent*)data; display->mouseEvent(event->x, event->y, event->button, event->flag); return true; } else if (strcmp(id, GRAPHTFT_CALIBRATION_ID) == 0) { display->setCalibrate(((cTftCS::GraphTftCalibration*)data)->activate); return true; } else if (strcmp(id, GRAPHTFT_COVERNAME_ID) == 0) { if (data) { display->setCoverPath(((cTftCS::MusicServiceCovername*)data)->name); if (display->isMode(cGraphTFTService::ReplayMP3)) display->broadcast(yes); } return true; } else if (strcmp(id, GRAPHTFT_PLAYLIST_ID) == 0) { if (data) { cTftCS::MusicServicePlaylist* p; p = (cTftCS::MusicServicePlaylist*)data; if (strcmp(p->item, "-EOL-") != 0) display->musicAddPlaylistItem(p->item, p->index); else display->musicAddPlaylistItem(tr("--- end of playlist ---"), p->index); if (p->index == p->count && display->isMode(cGraphTFTService::ReplayMP3)) display->broadcast(yes); } return true; } else if (strcmp(id, GRAPHTFT_STATUS_ID) == 0) { if (data) { cTftCS::MusicServicePlayerInfo* p; p = (cTftCS::MusicServicePlayerInfo*)data; tell(1, "Got state update from music plugin"); display->setMusicPlayerState(p); if (display->isMode(cGraphTFTService::ReplayMP3)) display->broadcast(yes); } return true; } else if (strcmp(id, GRAPHTFT_HELPBUTTONS_ID) == 0) { if (data) { cTftCS::MusicServiceHelpButtons* p; p = (cTftCS::MusicServiceHelpButtons*)data; tell(0, "Got help buttons from music plugin"); display->setMusicPlayerHelpButtons(p); if (display->isMode(cGraphTFTService::ReplayMP3)) display->broadcast(yes); } return true; } else if (strcmp(id, GRAPHTFT_INFO_ID) == 0) { if (data) { cTftCS::MusicServiceInfo* p; p = (cTftCS::MusicServiceInfo*)data; tell(0, "Got display info from music plugin"); display->_music.currentTrack = p->info; if (display->isMode(cGraphTFTService::ReplayMP3)) display->broadcast(yes); } return true; } return false; } //*************************************************************************** // SVDRP Help Pages //*************************************************************************** const char** cPluginGraphTFT::SVDRPHelpPages() { static const char* HelpPages[] = { "ACTIVE \n" " Activate/Deactivate display refresh {ON|OFF}\n", "VIEW \n" " Set the normal view to the specified (or next) section\n", "TVIEW \n" " Set the normal view temporary to the specified section\n", "RVIEW \n" " Reset the temporary 'normal view'\n", "REFRESH \n" " force display refresh\n", "RELOAD \n" " reload the actual theme\n", "DUMP [ ]\n" " dump the actual frame to (specify a path with access rights for the vdr process)\n", 0 }; return HelpPages; } //*************************************************************************** // SVDRP Command //*************************************************************************** cString cPluginGraphTFT::SVDRPCommand(const char* Command, const char* Option, int& ReplyCode) { if (!strcasecmp(Command, "ACTIVE")) { if (Option && strcasecmp(Option, "ON") == 0) { display->displayActive = yes; ReplyCode = 550; return "graphTFT display activated"; } else if (Option && strcasecmp(Option, "OFF") == 0) { display->displayActive = no; ReplyCode = 550; return "graphTFT display deactivated!"; } else { ReplyCode = 901; return "Error: Unexpected option"; } } else if (!strcasecmp(Command, "RELOAD")) { loadThemes(); display->broadcast(yes); ReplyCode = 550; return "theme reloaded"; } else if (!strcasecmp(Command, "REFRESH")) { display->broadcast(yes); ReplyCode = 550; return "display refreshed"; } else if (!strcasecmp(Command, "PREV") || !strcasecmp(Command, "NEXT")) { if (!strcasecmp(Command, "NEXT")) GraphTFTSetup.normalMode = Thms::theTheme->nextNormalMode(GraphTFTSetup.normalMode.c_str()); else GraphTFTSetup.normalMode = Thms::theTheme->prevNormalMode(GraphTFTSetup.normalMode.c_str()); GraphTFTSetup.storeNormalMode = true; GraphTFTSetup.originalNormalMode = ""; SetupStore("normalMode", GraphTFTSetup.normalMode.c_str()); Setup.Save(); display->broadcast(yes); ReplyCode = 550; return "Normal view changed"; } else if (!strcasecmp(Command, "VIEW") || !strcasecmp(Command, "VIEWMODE") // historical (use VIEW) || !strcasecmp(Command, "NORMALVIEW")) // historical (use VIEW) { if (Str::isEmpty(Option)) // historical (use NEXT) { GraphTFTSetup.normalMode = Thms::theTheme->nextNormalMode(GraphTFTSetup.normalMode.c_str()); GraphTFTSetup.storeNormalMode = true; GraphTFTSetup.originalNormalMode = ""; } else if (Thms::theTheme->isNormalMode(Option)) { GraphTFTSetup.normalMode = Option; GraphTFTSetup.storeNormalMode = true; GraphTFTSetup.originalNormalMode = ""; } else { ReplyCode = 901; return "Error: Unexpected option"; } SetupStore("normalMode", GraphTFTSetup.normalMode.c_str()); Setup.Save(); display->broadcast(yes); ReplyCode = 550; return "Normal view changed"; } else if (!strcasecmp(Command, "TVIEW")) { if (!Str::isEmpty(Option) && Thms::theTheme->isNormalMode(Option)) { if (GraphTFTSetup.originalNormalMode.empty()) GraphTFTSetup.originalNormalMode = GraphTFTSetup.normalMode; GraphTFTSetup.normalMode = Option; GraphTFTSetup.storeNormalMode = false; } else { ReplyCode = 901; return "Error: Unexpected option"; } display->broadcast(yes); ReplyCode = 550; return "Normal view changed temporarily"; } else if (!strcasecmp(Command, "RVIEW")) { if (!GraphTFTSetup.storeNormalMode && !GraphTFTSetup.originalNormalMode.empty()) { GraphTFTSetup.normalMode = GraphTFTSetup.originalNormalMode; GraphTFTSetup.storeNormalMode = true; GraphTFTSetup.originalNormalMode = ""; } else { ReplyCode = 901; return "Error: Unexpected option"; } SetupStore("normalMode", GraphTFTSetup.normalMode.c_str()); Setup.Save(); display->broadcast(yes); ReplyCode = 550; return "Normal view reset"; } else if (!strcasecmp(Command, "DUMP")) { char* file = strdup(Option); char* p = file; int width = na; int height = na; if (!Option || !*Option) { ReplyCode = 901; return "Error: Unexpected option"; } if (p = strchr(p, ' ')) { *p = 0; width = atoi(++p); } if (p && (p = strchr(p, ' '))) { *p = 0; height = atoi(++p); } display->triggerDump(file, width, height); free(file); ReplyCode = 550; return "Dump of image triggered"; } return 0; } //*************************************************************************** VDRPLUGINCREATOR(cPluginGraphTFT)