From 1b8d223483b977b7b31d7c696081ee7ad0312599 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 4 Nov 2012 13:13:24 +0100 Subject: [PATCH] SDTV support --- command.cc | 29 ++++++++++- vconnect.cc | 2 +- video.h | 9 ++++ videomvp.h | 6 ++- videoomx.cc | 137 +++++++++++++++++++++++++++++++++------------------- videoomx.h | 8 +++ videowin.h | 5 +- vopts.cc | 129 +++++++++++++++++++++++++++++++++++++++++-------- vopts.h | 8 +++ 9 files changed, 258 insertions(+), 75 deletions(-) diff --git a/command.cc b/command.cc index cbdd0a8..814f053 100644 --- a/command.cc +++ b/command.cc @@ -666,6 +666,7 @@ void Command::doJustConnected(VConnect* vconnect) { I18n::initialize(); if (!VDR::getInstance()->isConnected()) { connectionLost(); return; } + logger->log("Command", Log::INFO, "Entering doJustConnected"); Video* video = Video::getInstance(); Audio* audio = Audio::getInstance(); @@ -706,8 +707,11 @@ void Command::doJustConnected(VConnect* vconnect) { logger->log("Command", Log::DEBUG, "Override Video Format is present"); - if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC)) - || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) ) + if ( (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL)) + || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC)) + || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M)) + || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J)) + ) { // Oh sheesh, need to switch format. Bye bye TV... @@ -720,6 +724,9 @@ void Command::doJustConnected(VConnect* vconnect) #endif video->shutdown(); + remote->shutdown(); // need on raspberry shut not do any harm, hopefully + remote->init(RemoteStartDev); + // Get video and osd back up with the new mode if (!strcmp(config, "PAL")) { @@ -730,6 +737,14 @@ void Command::doJustConnected(VConnect* vconnect) { logger->log("Command", Log::DEBUG, "Switching to NTSC"); video->init(Video::NTSC); + } else if (!strcmp(config, "PAL_M")) + { + logger->log("Command", Log::DEBUG, "Switching to PAL_M"); + video->init(Video::PAL_M); + } else if (!strcmp(config, "NTSC_J")) + { + logger->log("Command", Log::DEBUG, "Switching to NTSC_J"); + video->init(Video::NTSC_J); } #ifndef __ANDROID__ //we do not init twice @@ -834,6 +849,14 @@ void Command::doJustConnected(VConnect* vconnect) { logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config); video->setConnection(Video::SVIDEO); + } else if (!STRCASECMP(config, "HDMI")) + { + logger->log("Command", Log::INFO, "Switching to HDMI as Connection=%s", config); + video->setConnection(Video::HDMI); + } else if (!STRCASECMP(config, "HDMI3D")) + { + logger->log("Command", Log::INFO, "Switching to HDMI3D as Connection=%s", config); + video->setConnection(Video::HDMI3D); } else { @@ -963,6 +986,8 @@ void Command::doJustConnected(VConnect* vconnect) audio->loadOptionsfromServer(vdr); video->loadOptionsfromServer(vdr); remote->loadOptionsfromServer(vdr); + + video->executePendingModeChanges(); // config done // Save power state = on diff --git a/vconnect.cc b/vconnect.cc index 7c0b66e..724b3fc 100644 --- a/vconnect.cc +++ b/vconnect.cc @@ -189,7 +189,7 @@ void VConnect::threadMethod() } while(!success); - + logger->log("VConnect", Log::INFO, "Send VDR connected message"); Message* m = new Message(); // Must be done after this thread ends m->from = this; m->to = Command::getInstance(); diff --git a/video.h b/video.h index 2980d2c..9c9611f 100644 --- a/video.h +++ b/video.h @@ -46,10 +46,14 @@ class Video: public DrainTarget, public AbstractOption virtual int shutdown()=0; virtual int setFormat(UCHAR format)=0; virtual UCHAR getSupportedFormats() { return COMPOSITERGB | SVIDEO;}; // if it returns zero there are no different formats + virtual UINT supportedTVsize() { return 0;}; // if no selection is allowed + virtual UCHAR supportedTVFormats() { return 0;}; // if no selection is allowed + virtual int setConnection(UCHAR connection)=0; virtual int setAspectRatio(UCHAR aspectRatio)=0; // This one does the pin 8 scart widescreen switching virtual int setMode(UCHAR mode)=0; virtual int setTVsize(UCHAR size)=0; // Is the TV a widescreen? + virtual void executePendingModeChanges() {}; // This is called if you change the output mode and the device take a while for reinitialization virtual int setDefaultAspect()=0; virtual int setSource()=0; virtual int setPosition(int x, int y)=0; @@ -103,12 +107,16 @@ class Video: public DrainTarget, public AbstractOption UINT getScreenHeight() { return screenHeight; } UCHAR getTVsize() { return tvsize; } + + //hmsf framesToHMSF(ULONG frames,double fps); // UINT getFPS(); //removed // Video formats - AV_SET_VID_DISP_FMT const static UCHAR NTSC = 0; const static UCHAR PAL = 1; + const static UCHAR PAL_M = 2; + const static UCHAR NTSC_J = 4; // Video connections - AV_SET_VID_OUTPUT const static UCHAR COMPOSITERGB = 1; @@ -119,6 +127,7 @@ class Video: public DrainTarget, public AbstractOption // Video aspect ratios - AV_SET_VID_RATIO const static UCHAR ASPECT4X3 = 0; const static UCHAR ASPECT16X9 = 1; + const static UCHAR ASPECT14X9 = 2; //future use // Video modes - AV_SET_VID_MODE const static UCHAR NORMAL = 0; diff --git a/videomvp.h b/videomvp.h index 9184bc3..aabad63 100644 --- a/videomvp.h +++ b/videomvp.h @@ -103,11 +103,15 @@ class VideoMVP : public Video { public: VideoMVP(); - ~VideoMVP(); + virtual ~VideoMVP(); int init(UCHAR format); int shutdown(); + UCHAR getSupportedFormats() { return COMPOSITERGB | SVIDEO;}; + UINT supportedTVsize() { return ASPECT4X3|ASPECT16X9;}; + UCHAR supportedTVFormats() { return 0;}; /* We cannot change this here + int setFormat(UCHAR format); int setConnection(UCHAR connection); int setAspectRatio(UCHAR aspectRatio); // This one does the pin 8 scart widescreen switching diff --git a/videoomx.cc b/videoomx.cc index faae9a1..45946e8 100644 --- a/videoomx.cc +++ b/videoomx.cc @@ -75,7 +75,7 @@ int VideoOMX::init(UCHAR tformat) initted = 1; if (!setFormat(tformat)) { shutdown(); return 0; } - if (!setConnection(COMPOSITERGB)) { shutdown(); return 0; } + if (!setConnection(HDMI)) { shutdown(); return 0; } if (!setAspectRatio(ASPECT4X3)) { shutdown(); return 0; } if (!setMode(NORMAL)) { shutdown(); return 0; } if (!setSource()) { shutdown(); return 0; } @@ -84,6 +84,7 @@ int VideoOMX::init(UCHAR tformat) setTVsize(ASPECT4X3); selectVideoMode(0); + OMX_ERRORTYPE error; error = OMX_Init(); if (error != OMX_ErrorNone) { @@ -299,25 +300,24 @@ bool VideoOMX::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pa int VideoOMX::setTVsize(UCHAR ttvsize) { -/* tvsize = ttvsize; - - // Override the aspect ratio usage, temporarily use to set the video chip mode - if (!setAspectRatio(tvsize)) { shutdown(); return 0; } - close(fdVideo); - if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0; - if (!setSource()) { shutdown(); return 0; } - if (!attachFramebuffer()) { shutdown(); return 0; } - - // Reopening the fd causes the scart aspect line to go back to 4:3 - // Set this again to the same as the tv screen size - if (!setAspectRatio(tvsize)) { shutdown(); return 0; } - - // mode == LETTERBOX is invalid if the TV is widescreen - if (tvsize == ASPECT16X9) setMode(NORMAL); -*/ + if (tvsize!=ttvsize) pendingmodechange=true; + tvsize=ttvsize; return 1; } +void VideoOMX::executePendingModeChanges() +{ + if (pendingmodechange) { + Log::getInstance()->log("Video", Log::NOTICE, "Execute pending mode change"); + Osd::getInstance()->shutdown(); + selectVideoMode(0); + Osd::getInstance()->restore(); + Osd::getInstance()->init((void*) ""); + BoxStack::getInstance()->redrawAllBoxes(); + initted = 1; + } +} + int VideoOMX::setDefaultAspect() { return setAspectRatio(tvsize); @@ -328,7 +328,8 @@ int VideoOMX::setDefaultAspect() int VideoOMX::setFormat(UCHAR tformat) { if (!initted) return 0; - if ((tformat != PAL) && (tformat != NTSC)) return 0; + if ((tformat != PAL) && (tformat != NTSC) + && (tformat != PAL_M) && (tformat != NTSC_J)) return 0; format = PAL; tvsystem = tformat; @@ -345,23 +346,57 @@ int VideoOMX::setFormat(UCHAR tformat) void VideoOMX::selectVideoMode(int interlaced) { - if (/*hdmi*/ true) { - TV_SUPPORTED_MODE_T all_supp_modes[TV_MAX_SUPPORTED_MODES]; - HDMI_RES_GROUP_T pref_group; - TV_SUPPORTED_MODE_T *mymode=NULL; - TV_SUPPORTED_MODE_T *mymode_second_best=NULL; - bool got_optimum=false; - uint32_t pref_mode; - int all_my_modes=vc_tv_hdmi_get_supported_modes(HDMI_RES_GROUP_CEA, - all_supp_modes,TV_MAX_SUPPORTED_MODES, - &pref_group,&pref_mode); + + TV_SUPPORTED_MODE_T all_supp_modes[TV_MAX_SUPPORTED_MODES]; + HDMI_RES_GROUP_T pref_group; + TV_SUPPORTED_MODE_T *mymode=NULL; + TV_SUPPORTED_MODE_T *mymode_second_best=NULL; + bool got_optimum=false; + uint32_t pref_mode; + HDMI_RES_GROUP_T group=HDMI_RES_GROUP_CEA; + int all_my_modes=vc_tv_hdmi_get_supported_modes(HDMI_RES_GROUP_CEA, + all_supp_modes,TV_MAX_SUPPORTED_MODES, + &pref_group,&pref_mode); + if (all_my_modes<=0) { + group=HDMI_RES_GROUP_DMT; + all_my_modes=vc_tv_hdmi_get_supported_modes(HDMI_RES_GROUP_DMT, + all_supp_modes,TV_MAX_SUPPORTED_MODES, + &pref_group,&pref_mode); + Log::getInstance()->log("Video", Log::NOTICE, "No CEA fall back to DMT modes "); + } + + if (all_my_modes<=0 || connection==COMPOSITERGB ) { + /* analog tv case */ + Log::getInstance()->log("Video", Log::NOTICE, "No CEA and DMT modes found analog tv case?"); + vc_tv_power_off(); + Remote::getInstance()->shutdown(); + SDTV_MODE_T setmode=SDTV_MODE_PAL; + SDTV_OPTIONS_T options; + + switch (tvsize) { + default: + case ASPECT16X9: + Log::getInstance()->log("Video", Log::NOTICE, "SDTV aspect 16:9"); + options.aspect=SDTV_ASPECT_16_9; break; + case ASPECT4X3: + Log::getInstance()->log("Video", Log::NOTICE, "SDTV aspect 4:3"); + options.aspect=SDTV_ASPECT_4_3; break; + case ASPECT14X9: + Log::getInstance()->log("Video", Log::NOTICE, "SDTV aspect 14:9"); + options.aspect=SDTV_ASPECT_14_9; break; + }; + + if (format==PAL) setmode=SDTV_MODE_PAL; + else if (format==NTSC) setmode=SDTV_MODE_NTSC; + else if (format==PAL_M)setmode=SDTV_MODE_PAL_M; + else if (format==NTSC_J) setmode=SDTV_MODE_NTSC_J; + vc_tv_sdtv_power_on(setmode,&options); + hdmi=false; + + } else { int target_fps=50; if (format==PAL)target_fps=50; else if (format==NTSC) target_fps=60; - if (all_my_modes<=0) { - Log::getInstance()->log("Video", Log::NOTICE, "No CEA modes found abort"); - return; - } //Now first determine native resolution int native_width=1920; @@ -380,18 +415,18 @@ void VideoOMX::selectVideoMode(int interlaced) for (int i=0;iwidth==native_width && - curmode->height==native_height && - curmode->frame_rate==target_fps) { - if(curmode->scan_mode==interlaced) { - got_optimum=true; - mymode=curmode; - Log::getInstance()->log("Video", Log::NOTICE, "Found optimum mode %dx%d %d Hz i: %d", - mymode->width,mymode->height,mymode->frame_rate,mymode->scan_mode); - } else { - mymode_second_best=curmode; - Log::getInstance()->log("Video", Log::NOTICE, "Found close to optimum mode %dx%d %d Hz i: %d", - mymode_second_best->width,mymode_second_best->height, - mymode_second_best->frame_rate,mymode_second_best->scan_mode); + curmode->height==native_height && + curmode->frame_rate==target_fps) { + if(curmode->scan_mode==interlaced) { + got_optimum=true; + mymode=curmode; + Log::getInstance()->log("Video", Log::NOTICE, "Found optimum mode %dx%d %d Hz i: %d", + mymode->width,mymode->height,mymode->frame_rate,mymode->scan_mode); + } else { + mymode_second_best=curmode; + Log::getInstance()->log("Video", Log::NOTICE, "Found close to optimum mode %dx%d %d Hz i: %d", + mymode_second_best->width,mymode_second_best->height, + mymode_second_best->frame_rate,mymode_second_best->scan_mode); } } @@ -400,20 +435,23 @@ void VideoOMX::selectVideoMode(int interlaced) Remote::getInstance()->shutdown(); if (mymode) { Log::getInstance()->log("Video", Log::NOTICE, "Switch to optimum mode"); - vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI,HDMI_RES_GROUP_CEA,mymode->code); + vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI,group,mymode->code); } else if (mymode_second_best) { Log::getInstance()->log("Video", Log::NOTICE, "Switch to close to optimum mode"); - vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI,HDMI_RES_GROUP_CEA,mymode_second_best->code); + vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI,group,mymode_second_best->code); } else { Log::getInstance()->log("Video", Log::NOTICE, "Switch to prefered mode"); vc_tv_hdmi_power_on_best(1920,1080,target_fps,interlaced?HDMI_INTERLACED:HDMI_NONINTERLACED, (EDID_MODE_MATCH_FLAG_T)(HDMI_MODE_MATCH_FRAMERATE|HDMI_MODE_MATCH_RESOLUTION|HDMI_MODE_MATCH_SCANMODE)); } - Remote::getInstance()->init(""); - + hdmi=true; } + Remote::getInstance()->init(""); + + signalon=true; + pendingmodechange=false; } @@ -421,7 +459,8 @@ void VideoOMX::selectVideoMode(int interlaced) int VideoOMX::setConnection(UCHAR tconnection) { if (!initted) return 0; - if ((tconnection != COMPOSITERGB) && (tconnection != SVIDEO)) return 0; + if ((tconnection != COMPOSITERGB) && (tconnection != HDMI)) return 0; + if (connection!=tconnection) pendingmodechange=true; connection = tconnection; // if (ioctl(fdVideo, AV_SET_VID_OUTPUT, connection) != 0) return 0; diff --git a/videoomx.h b/videoomx.h index 332c38c..dd0ee0e 100644 --- a/videoomx.h +++ b/videoomx.h @@ -72,11 +72,17 @@ class VideoOMX : public Video int init(UCHAR format); int shutdown(); + UCHAR getSupportedFormats() { return COMPOSITERGB | HDMI;}; + UINT supportedTVsize() { return ASPECT4X3|ASPECT16X9|ASPECT14X9 ;}; + UCHAR supportedTVFormats() { return NTSC|PAL|PAL_M|NTSC_J;}; + int setFormat(UCHAR format); int setConnection(UCHAR connection); int setAspectRatio(UCHAR aspectRatio); // This one does the pin 8 scart widescreen switching int setMode(UCHAR mode); int setTVsize(UCHAR size); // Is the TV a widescreen? + + void executePendingModeChanges(); int setDefaultAspect(); int setSource(); int setPosition(int x, int y); @@ -267,6 +273,8 @@ class VideoOMX : public Video void selectVideoMode(int interlaced); UCHAR tvsystem; bool signalon; + bool pendingmodechange; + bool hdmi; diff --git a/videowin.h b/videowin.h index dc9fa77..4293d21 100644 --- a/videowin.h +++ b/videowin.h @@ -59,7 +59,10 @@ public: int shutdown(); int setFormat(UCHAR format); - virtual UCHAR getSupportedFormats() { return 0;}; + UCHAR getSupportedFormats() { return 0;}; + UINT supportedTVsize() { return ASPECT4X3|ASPECT16X9;}; + UCHAR supportedTVFormats() { return 0;}; + int setConnection(UCHAR connection); int setAspectRatio(UCHAR aspectRatio); // This one does the pin 8 scart widescreen switching UCHAR getAspectRatio(){return aspectRatio;}; diff --git a/vopts.cc b/vopts.cc index 2772167..3ea90a4 100644 --- a/vopts.cc +++ b/vopts.cc @@ -62,8 +62,7 @@ VOpts::VOpts() // --- edit options start here static const char* options1[] = {"Old", "New"}; - static const char* options3[] = {"RGB+composite", "S-Video"}; - static const char* options4[] = {"4:3", "16:9"}; + static const char* options5[] = {"Chop sides", "Letterbox"}; static const char* options6[] = {"On", "Off", "Last state"}; static const char* options7[] = {"All", "FTA only"}; @@ -97,12 +96,85 @@ VOpts::VOpts() option = new Option(2, "Language", "General", "LangCode", Option::TYPE_KEYED_TEXT, LangCode.size(), 0, 0, options2, options2keys); options.push_back(option); wop->addOptionLine(option); - option = new Option(3, "TV connection type", "TV", "Connection", Option::TYPE_TEXT, 2, 0, 0, options3); - options.push_back(option); - wop->addOptionLine(option); - option = new Option(4, "TV aspect ratio", "TV", "Aspect", Option::TYPE_TEXT, 2, 0, 0, options4); - options.push_back(option); - wop->addOptionLine(option); + + + UINT suppconn = Video::getInstance()->getSupportedFormats(); + if (suppconn) { + int defaultch = 0; + if (suppconn & Video::COMPOSITERGB) { + defaultch = 0; + options3.push_back("RGB+composite"); + options3keys.push_back("RGB+composite"); + } + if (Video::SVIDEO & suppconn) { + options3.push_back("S-Video"); + options3keys.push_back("S-Video"); + } + if (Video::HDMI & suppconn) { + defaultch = options3.size(); + options3.push_back("HDMI"); + options3keys.push_back("HDMI"); + } + if (Video::HDMI3D & suppconn) { + options3.push_back("HDMI3D"); + options3keys.push_back("HDMI3D"); + } + option = new Option(3, "TV connection type", "TV", "Connection", + Option::TYPE_KEYED_TEXT, options3.size(), defaultch, 0, + &(options3[0]), &(options3keys[0])); + + options.push_back(option); + wop->addOptionLine(option); + } + + UINT suppformats = Video::getInstance()->supportedTVFormats(); + if (suppformats) { + int defaultch = 0; + options16.push_back("NTSC"); + options16keys.push_back("NTSC"); + if (suppformats & Video::PAL) { + defaultch = 1; + options16.push_back("PAL"); + options16keys.push_back("PAL"); + } + if (Video::NTSC_J & suppformats) { + options16.push_back("NTSC-J"); + options16keys.push_back("NTSC-J"); + } + if (Video::PAL_M & suppformats) { + options16.push_back("PAL-M"); + options16keys.push_back("PAL-M"); + } + + option = new Option(16, "TV standard (needs restart)", "General", "Override Video Format", + Option::TYPE_KEYED_TEXT, options16.size(), defaultch, 0, + &(options16[0]), &(options16keys[0])); + + options.push_back(option); + wop->addOptionLine(option); + } + + UINT supptvsize=Video::getInstance()->supportedTVsize(); + if (supptvsize) { + int defaultch=0; + options4.push_back("4:3"); + options4keys.push_back("4:3"); + if (Video::ASPECT16X9 & supptvsize) { + options4.push_back("16:9"); + options4keys.push_back("16:9"); + defaultch=1; + } + if (Video::ASPECT14X9 & supptvsize) { + options4.push_back("14:9"); + options4keys.push_back("14:9"); + } + option = new Option(4, "TV aspect ratio", "TV", "Aspect", + Option::TYPE_KEYED_TEXT, options4.size(), defaultch, 0, + &(options4[0]), &(options4keys[0])); + options.push_back(option); + wop->addOptionLine(option); + } + option = new Option(5, "16:9 on 4:3 display mode", "TV", "Widemode", Option::TYPE_TEXT, 2, 0, 0, options5); options.push_back(option); wop->addOptionLine(option); @@ -290,30 +362,45 @@ void VOpts::doSave() } case 3: { - if (options[i]->userSetChoice == 1) - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting S-Video"); - Video::getInstance()->setConnection(Video::SVIDEO); - } - else - { - Log::getInstance()->log("Options", Log::DEBUG, "Setting RGB/Composite"); - Video::getInstance()->setConnection(Video::COMPOSITERGB); - } - break; + if (STRCASECMP(options[i]->optionkeys[options[i]->userSetChoice], "RGB+composite")==0) + { + Log::getInstance()->log("Options", Log::DEBUG, "Setting RGB/Composite"); + Video::getInstance()->setConnection(Video::COMPOSITERGB); + } + else if (STRCASECMP(options[i]->optionkeys[options[i]->userSetChoice], "S-Video")==0) + { + Log::getInstance()->log("Options", Log::DEBUG, "Setting S-Video"); + Video::getInstance()->setConnection(Video::SVIDEO); + } + else if (STRCASECMP(options[i]->optionkeys[options[i]->userSetChoice], "HDMI")==0) + { + Log::getInstance()->log("Options", Log::DEBUG, "Setting HDMI"); + Video::getInstance()->setConnection(Video::HDMI); + } + else if (STRCASECMP(options[i]->optionkeys[options[i]->userSetChoice], "HDMI3D")==0) + { + Log::getInstance()->log("Options", Log::DEBUG, "Setting HDMI"); + Video::getInstance()->setConnection(Video::HDMI3D); + } + break; } case 4: { - if (options[i]->userSetChoice == 1) + if (STRCASECMP(options[i]->optionkeys[options[i]->userSetChoice], "16:9")==0) { Log::getInstance()->log("Options", Log::DEBUG, "Setting 16:9 TV"); Video::getInstance()->setTVsize(Video::ASPECT16X9); } - else + else if (STRCASECMP(options[i]->optionkeys[options[i]->userSetChoice], "4:3")==0) { Log::getInstance()->log("Options", Log::DEBUG, "Setting 4:3 TV"); Video::getInstance()->setTVsize(Video::ASPECT4X3); } + else if (STRCASECMP(options[i]->optionkeys[options[i]->userSetChoice], "14:9")==0) + { + Log::getInstance()->log("Options", Log::DEBUG, "Setting 14:9 TV"); + Video::getInstance()->setTVsize(Video::ASPECT14X9); + } break; } case 5: diff --git a/vopts.h b/vopts.h index 17ee301..416aeb7 100644 --- a/vopts.h +++ b/vopts.h @@ -27,6 +27,7 @@ #include "wtabbar.h" #include "i18n.h" #include "option.h" +#include class Boxx; @@ -56,5 +57,12 @@ class VOpts : public TBBoxx // Although LangCode is only used in the constructor, it has to // be valid for the lifetime of the VOpts instance, because we // create Option objects with pointers into LangCode's data. + + vector options4; // this is for tv size + vector options4keys; + vector options3; // this is for tv size + vector options3keys; + vector options16; // this is for tv standard + vector options16keys; }; #endif -- 2.39.5