diff --git a/data/locale/english.locale b/data/locale/english.locale index a9f65cb8e..e8c2ebc40 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -281,6 +281,7 @@ ci.reset_standby Reset after standby ci.save_pincode Save pincode ci.settings Conditional access ci.timeout Timeout waiting CI menu ready +ci.tuner Use CI only with tuner: ci.waiting Waiting for CI answer clock_background Show background clock_seconds Show seconds diff --git a/src/gui/cam_menu.cpp b/src/gui/cam_menu.cpp index 7247db7be..405c2c864 100644 --- a/src/gui/cam_menu.cpp +++ b/src/gui/cam_menu.cpp @@ -109,6 +109,9 @@ int CCAMMenuHandler::doMainMenu() CMenuWidget* cammenu = new CMenuWidget(LOCALE_CI_SETTINGS, NEUTRINO_ICON_SETTINGS); cammenu->addIntroItems(); + int fecount = CFEManager::getInstance()->getFrontendCount(); + char fename[fecount+1][255]; + if (!g_settings.easymenu) { if(CiSlots) { cammenu->addItem( new CMenuOptionChooser(LOCALE_CI_RESET_STANDBY, &g_settings.ci_standby_reset, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); @@ -116,6 +119,27 @@ int CCAMMenuHandler::doMainMenu() } cammenu->addItem( new CMenuOptionChooser(LOCALE_CI_IGNORE_MSG, &g_settings.ci_ignore_messages, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); cammenu->addItem( new CMenuOptionChooser(LOCALE_CI_SAVE_PINCODE, &g_settings.ci_save_pincode, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, this)); + +#ifdef BOXMODEL_APOLLO + CMenuOptionChooser::keyval_ext feselect[fecount+1]; + feselect[0].key = -1; + feselect[0].value = NONEXISTANT_LOCALE; + feselect[0].valname = g_Locale->getText(LOCALE_OPTIONS_OFF); + int select_count = 1; + + for (int i = 0; i < fecount; i++) { + CFrontend * fe = CFEManager::getInstance()->getFE(i); + int num = fe->getNumber(); + snprintf(fename[select_count], sizeof(fename[select_count]), "%d: %s", num+1, fe->getName()); + feselect[select_count].key = num; + feselect[select_count].value = NONEXISTANT_LOCALE; + feselect[select_count].valname = fename[select_count]; + select_count++; + } + CMenuOptionChooser * mc = new CMenuOptionChooser(LOCALE_CI_TUNER, &g_settings.ci_tuner, feselect, select_count, true, this); + cammenu->addItem(mc); +#endif + cammenu->addItem( GenericMenuSeparatorLine ); } @@ -537,5 +561,9 @@ bool CCAMMenuHandler::changeNotify(const neutrino_locale_t OptionName, void * Da g_settings.ci_pincode.clear(); } } + else if (ARE_LOCALES_EQUAL(OptionName, LOCALE_CI_TUNER)) { + printf("CCAMMenuHandler::changeNotify: bind CI to tuner %d\n", g_settings.ci_tuner); + CCamManager::getInstance()->SetCITuner(g_settings.ci_tuner); + } return false; } diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 20dab673a..6da9a2677 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -128,6 +128,7 @@ #include #include #include +#include #include #include @@ -418,6 +419,7 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.ci_ignore_messages = configfile.getInt32("ci_ignore_messages", 0); g_settings.ci_save_pincode = configfile.getInt32("ci_save_pincode", 0); g_settings.ci_pincode = configfile.getString("ci_pincode", ""); + g_settings.ci_tuner = configfile.getInt32("ci_tuner", -1); #ifndef CPU_FREQ g_settings.cpufreq = 0; @@ -971,6 +973,7 @@ void CNeutrinoApp::saveSetup(const char * fname) configfile.setInt32("ci_ignore_messages", g_settings.ci_ignore_messages); configfile.setInt32("ci_save_pincode", g_settings.ci_save_pincode); configfile.setString("ci_pincode", g_settings.ci_pincode); + configfile.setInt32("ci_tuner", g_settings.ci_tuner); configfile.setInt32( "make_hd_list", g_settings.make_hd_list); configfile.setInt32( "make_webtv_list", g_settings.make_webtv_list); @@ -1940,6 +1943,7 @@ TIMER_START(); ZapStart_arg.volume = g_settings.current_volume; ZapStart_arg.webtv_xml = &g_settings.webtv_xml; + CCamManager::getInstance()->SetCITuner(g_settings.ci_tuner); /* create decoders, read channels */ bool zapit_init = CZapit::getInstance()->Start(&ZapStart_arg); //get zapit config for writeChannelsNames diff --git a/src/system/locals.h b/src/system/locals.h index 82c124fae..9138c0f8a 100644 --- a/src/system/locals.h +++ b/src/system/locals.h @@ -308,6 +308,7 @@ typedef enum LOCALE_CI_SAVE_PINCODE, LOCALE_CI_SETTINGS, LOCALE_CI_TIMEOUT, + LOCALE_CI_TUNER, LOCALE_CI_WAITING, LOCALE_CLOCK_BACKGROUND, LOCALE_CLOCK_SECONDS, diff --git a/src/system/locals_intern.h b/src/system/locals_intern.h index b3012a405..2868f11ca 100644 --- a/src/system/locals_intern.h +++ b/src/system/locals_intern.h @@ -308,6 +308,7 @@ const char * locale_real_names[] = "ci.save_pincode", "ci.settings", "ci.timeout", + "ci.tuner", "ci.waiting", "clock_background", "clock_seconds", diff --git a/src/system/settings.h b/src/system/settings.h index 97b33ba1c..b108142ca 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -223,6 +223,7 @@ struct SNeutrinoSettings int ci_clock; int ci_ignore_messages; int ci_save_pincode; + int ci_tuner; std::string ci_pincode; int radiotext_enable; int easymenu; diff --git a/src/zapit/include/zapit/capmt.h b/src/zapit/include/zapit/capmt.h index 8b360bb5a..228be79cb 100644 --- a/src/zapit/include/zapit/capmt.h +++ b/src/zapit/include/zapit/capmt.h @@ -66,7 +66,7 @@ class CCam : public CBasicClient bool sendMessage(const char * const data, const size_t length, bool update = false); bool makeCaPmt(CZapitChannel * channel, bool add_private, uint8_t list = CAPMT_ONLY, const CaIdVector &caids = CaIdVector()); bool setCaPmt(bool update = false); - bool sendCaPmt(uint64_t tpid, uint8_t *rawpmt, int rawlen); + bool sendCaPmt(uint64_t tpid, uint8_t *rawpmt, int rawlen, uint8_t type); int makeMask(int demux, bool add); int getCaMask(void) { return camask; } void setCaMask(int mask) { camask = mask; } @@ -89,6 +89,7 @@ class CCamManager private: cammap_t channel_map; OpenThreads::Mutex mutex; + int tunerno; static CCamManager * manager; bool SetMode(t_channel_id id, enum runmode mode, bool enable, bool force_update = false); void StopCam(t_channel_id id, CCam *cam); @@ -99,6 +100,8 @@ class CCamManager static CCamManager * getInstance(void); bool Start(t_channel_id id, enum runmode mode, bool force_update = false) { return SetMode(id, mode, true, force_update); }; bool Stop(t_channel_id id, enum runmode mode) { return SetMode(id, mode, false); }; + void SetCITuner(int tuner); + int GetCITuner(void) { return tunerno; }; }; #endif /* __capmt_h__ */ diff --git a/src/zapit/src/capmt.cpp b/src/zapit/src/capmt.cpp index b0143759a..99de9a2d1 100644 --- a/src/zapit/src/capmt.cpp +++ b/src/zapit/src/capmt.cpp @@ -142,10 +142,10 @@ bool CCam::setCaPmt(bool update) return sendMessage((char *)cabuf, calen, update); } -bool CCam::sendCaPmt(uint64_t tpid, uint8_t *rawpmt, int rawlen) +bool CCam::sendCaPmt(uint64_t tpid, uint8_t *rawpmt, int rawlen, uint8_t type) { return cCA::GetInstance()->SendCAPMT(tpid, source_demux, camask, - rawpmt ? cabuf : NULL, rawpmt ? calen : 0, rawpmt, rawpmt ? rawlen : 0); + rawpmt ? cabuf : NULL, rawpmt ? calen : 0, rawpmt, rawpmt ? rawlen : 0, (CA_SLOT_TYPE) type); } int CCam::makeMask(int demux, bool add) @@ -170,6 +170,7 @@ CCamManager * CCamManager::manager = NULL; CCamManager::CCamManager() { channel_map.clear(); + tunerno = -1; } CCamManager::~CCamManager() @@ -190,7 +191,7 @@ CCamManager * CCamManager::getInstance(void) void CCamManager::StopCam(t_channel_id channel_id, CCam *cam) { cam->sendMessage(NULL, 0, false); - cam->sendCaPmt(channel_id, NULL, 0); + cam->sendCaPmt(channel_id, NULL, 0, CA_SLOT_TYPE_ALL); channel_map.erase(channel_id); delete cam; } @@ -253,6 +254,7 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start INFO("channel %" PRIx64 " [%s] mode %d %s src %d mask %d -> %d update %d", channel_id, channel->getName().c_str(), mode, start ? "START" : "STOP", source, oldmask, newmask, force_update); + //INFO("source %d old mask %d new mask %d force update %s", source, oldmask, newmask, force_update ? "yes" : "no"); if((oldmask != newmask) || force_update) { cam->setCaMask(newmask); @@ -292,9 +294,23 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start cam->makeCaPmt(channel, false, list, caids); int len; unsigned char * buffer = channel->getRawPmt(len); - cam->sendCaPmt(channel->getChannelID(), buffer, len); + cam->sendCaPmt(channel->getChannelID(), buffer, len, CA_SLOT_TYPE_SMARTCARD); + + if (tunerno >= 0 && tunerno != cDemux::GetSource(cam->getSource())) + INFO("CI: configured tuner %d do not match %d, skip...\n", tunerno, cam->getSource()); + else + cam->sendCaPmt(channel->getChannelID(), buffer, len, CA_SLOT_TYPE_CI); //list = CCam::CAPMT_MORE; } return true; } + +void CCamManager::SetCITuner(int tuner) +{ + tunerno = tuner; +#ifdef BOXMODEL_APOLLO + if (tunerno >= 0) + cCA::GetInstance()->SetTS((CA_DVBCI_TS_INPUT)tunerno); +#endif +} diff --git a/src/zapit/src/zapit.cpp b/src/zapit/src/zapit.cpp index 9f6bc993b..13c6a3d55 100644 --- a/src/zapit/src/zapit.cpp +++ b/src/zapit/src/zapit.cpp @@ -578,7 +578,8 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay #endif #ifdef BOXMODEL_APOLLO - cCA::GetInstance()->SetTS((CA_DVBCI_TS_INPUT)live_fe->getNumber()); + if (CCamManager::getInstance()->GetCITuner() < 0) + cCA::GetInstance()->SetTS((CA_DVBCI_TS_INPUT)live_fe->getNumber()); #endif if (current_channel->getServiceType() == ST_NVOD_REFERENCE_SERVICE) {