diff options
author | Lars Heer <l.heer@gmx.de> | 2013-09-18 05:50:03 +0200 |
---|---|---|
committer | Lars Heer <l.heer@gmx.de> | 2013-09-18 05:50:03 +0200 |
commit | ccf6e0f9c6b0481ed13e0f4794e3fbead750f385 (patch) | |
tree | ed86efb54f7ee41edfba5c89ca519b5fd10aa0d5 /mcli.c | |
download | vdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.gz vdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.bz2 |
added vdr-plugin-mcli-0.0.1+svn20120927
Diffstat (limited to 'mcli.c')
-rw-r--r-- | mcli.c | 1122 |
1 files changed, 1122 insertions, 0 deletions
@@ -0,0 +1,1122 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +/* + * mcli.c: A plugin for the Video Disk Recorder + */ + +#include <vdr/plugin.h> +#include <vdr/player.h> + +#include "filter.h" +#include "device.h" +#include "cam_menu.h" +#include "mcli_service.h" +#include "mcli.h" +#include <sstream> + +static int reconf = 0; + +//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +class cMenuSetupMcli:public cMenuSetupPage +{ + private: + cmdline_t * m_cmd; + protected: + virtual void Store (void); + public: + cMenuSetupMcli (cmdline_t * cmd); +}; + +cMenuSetupMcli::cMenuSetupMcli (cmdline_t * cmd) +{ + m_cmd = cmd; + Add (new cMenuEditIntItem (trNOOP ("DVB-C"), &m_cmd->tuner_type_limit[FE_QAM])); + Add (new cMenuEditIntItem (trNOOP ("DVB-T"), &m_cmd->tuner_type_limit[FE_OFDM])); + Add (new cMenuEditIntItem (trNOOP ("DVB-S"), &m_cmd->tuner_type_limit[FE_QPSK])); + Add (new cMenuEditIntItem (trNOOP ("DVB-S2"), &m_cmd->tuner_type_limit[FE_DVBS2])); +} + +void cMenuSetupMcli::Store (void) +{ + SetupStore ("DVB-C", m_cmd->tuner_type_limit[FE_QAM]); + SetupStore ("DVB-T", m_cmd->tuner_type_limit[FE_OFDM]); + SetupStore ("DVB-S", m_cmd->tuner_type_limit[FE_QPSK]); + SetupStore ("DVB-S2", m_cmd->tuner_type_limit[FE_DVBS2]); + reconf = 1; +} + +cOsdObject *cPluginMcli::AltMenuAction (void) +{ + // Call this code periodically to find out if any CAM out there want's us to tell something. + // If it's relevant to us we need to check if any of our DVB-Devices gets programm from a NetCeiver with this UUID. + // The text received should pop up via OSD with a CAM-Session opened afterwards (CamMenuOpen...CamMenuReceive...CamMenuSend...CamMenuClose). + mmi_info_t m; + if (CamPollText (&m) > 0) { + printf ("NetCeiver %s CAM slot %d Received %s valid for:\n", m.uuid, m.slot, m.mmi_text); + for (int i = 0; i < m.caid_num; i++) { + caid_mcg_t *c = m.caids + i; + int satpos; + fe_type_t type; + recv_sec_t sec; + struct dvb_frontend_parameters fep; + int vpid; + + mcg_get_satpos (&c->mcg, &satpos); + mcg_to_fe_parms (&c->mcg, &type, &sec, &fep, &vpid); + + for (cMcliDeviceObject * dev = m_devs.First (); dev; dev = m_devs.Next (dev)) { + cMcliDevice *d = dev->d (); + //printf("satpos: %i vpid: %i fep.freq: %i dev.freq: %i\n", satpos, vpid, fep.frequency, dev->CurChan()->Frequency()); + struct in6_addr mcg = d->GetTenData ()->mcg; + mcg_set_id (&mcg, 0); + +#if 1 //def DEBUG + char str[INET6_ADDRSTRLEN]; + inet_ntop (AF_INET6, &c->mcg, str, INET6_ADDRSTRLEN); + printf ("MCG from MMI: %s\n", str); + inet_ntop (AF_INET6, &mcg, str, INET6_ADDRSTRLEN); + printf ("MCG from DEV: %s\n", str); +#endif + + if (IN6_IS_ADDR_UNSPECIFIED (&c->mcg) || !memcmp (&c->mcg, &mcg, sizeof (struct in6_addr))) + return new cCamMenu (&m_cmd, &m); + } + printf ("SID/Program Number:%04x, SatPos:%d Freqency:%d\n", c->caid, satpos, fep.frequency); + } + if (m.caid_num && m.caids) { + free (m.caids); + } + } + return NULL; +} + +int cPluginMcli::CamPollText (mmi_info_t * text) +{ + if (m_mmi_init_done && !reconf) { + return mmi_poll_for_menu_text (m_cam_mmi, text, 10); + } else { + return 0; + } +} + +cPluginMcli::cPluginMcli (void) +{ + // printf ("cPluginMcli::cPluginMcli\n"); + int i; + //init parameters + memset (&m_cmd, 0, sizeof (cmdline_t)); + + for (i = 0; i <= FE_DVBS2; i++) { + m_cmd.tuner_type_limit[i] = MCLI_MAX_DEVICES; + } + m_cmd.port = 23000; + m_cmd.mld_start = 1; + m_mmi_init_done = 0; + m_recv_init_done = 0; + m_mld_init_done = 0; + m_api_init_done = 0; + memset (m_cam_pool, 0, sizeof (cam_pool_t) * CAM_POOL_MAX); + for(i=0; i<CAM_POOL_MAX; i++) { + m_cam_pool[i].max = -1; + } + strcpy (m_cmd.cmd_sock_path, API_SOCK_NAMESPACE); + memset (m_tuner_pool, 0, sizeof(tuner_pool_t)*TUNER_POOL_MAX); + for(i=0; i<TUNER_POOL_MAX; i++) { + m_tuner_pool[i].type = -1; + } +} + +cPluginMcli::~cPluginMcli () +{ +// printf ("cPluginMcli::~cPluginMcli\n"); + ExitMcli (); + +} + +bool cPluginMcli::InitMcli (void) +{ + if (!recv_init (m_cmd.iface, m_cmd.port)) { + m_recv_init_done = 1; + } + if (m_cmd.mld_start && !mld_client_init (m_cmd.iface)) { + m_mld_init_done = 1; + } + if (!api_sock_init (m_cmd.cmd_sock_path)) { + m_api_init_done = 1; + } + m_cam_mmi = mmi_broadcast_client_init (m_cmd.port, m_cmd.iface); + if (m_cam_mmi > 0) { + m_mmi_init_done = 1; + } + for(int i=m_devs.Count(); i < MCLI_MAX_DEVICES; i++) { + cMcliDevice *m = NULL; + cPluginManager::CallAllServices ("OnNewMcliDevice-" MCLI_DEVICE_VERSION, &m); + if(!m) { + m = new cMcliDevice; + } + if(m) { + m->SetMcliRef (this); + cMcliDeviceObject *d = new cMcliDeviceObject (m); + m_devs.Add (d); + } + } + return true; +} + +void cPluginMcli::ExitMcli (void) +{ + if (m_mmi_init_done) { + mmi_broadcast_client_exit (m_cam_mmi); + } + if (m_api_init_done) { + api_sock_exit (); + } + if (m_mld_init_done) { + mld_client_exit (); + } + if (m_recv_init_done) { + recv_exit (); + } +} + +const char *cPluginMcli::CommandLineHelp (void) +{ + return (" --ifname <network interface>\n" " --port <port> (default: -port 23000)\n" " --dvb-s <num> --dvb-c <num> --dvb-t <num> --atsc <num> --dvb-s2 <num>\n" " limit number of device types (default: 8 of every type)\n" " --mld-reporter-disable\n" " --sock-path <filepath>\n" "\n"); +} + +bool cPluginMcli::ProcessArgs (int argc, char *argv[]) +{ +// printf ("cPluginMcli::ProcessArgs\n"); + int tuners = 0, i; + char c; + int ret; + + while (1) { + //int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"port", 1, 0, 0}, //0 + {"ifname", 1, 0, 0}, //1 + {"dvb-s", 1, 0, 0}, //2 + {"dvb-c", 1, 0, 0}, //3 + {"dvb-t", 1, 0, 0}, //4 + {"atsc", 1, 0, 0}, //5 + {"dvb-s2", 1, 0, 0}, //6 + {"mld-reporter-disable", 0, 0, 0}, //7 + {"sock-path", 1, 0, 0}, //8 + {NULL, 0, 0, 0} + }; + + ret = getopt_long_only (argc, argv, "", long_options, &option_index); + c = (char) ret; + if (ret == -1 || c == '?') { + break; + } + + switch (option_index) { + case 0: + m_cmd.port = atoi (optarg); + break; + case 1: + strncpy (m_cmd.iface, optarg, IFNAMSIZ - 1); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + i = atoi (optarg); + if (!tuners) { + memset (m_cmd.tuner_type_limit, 0, sizeof (m_cmd.tuner_type_limit)); + } + m_cmd.tuner_type_limit[option_index - 2] = i; + tuners += i; + break; + case 7: + m_cmd.mld_start = 0; + break; + case 8: + strncpy (m_cmd.cmd_sock_path, optarg, _POSIX_PATH_MAX - 1); + break; + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + // Implement command line argument processing here if applicable. + return true; +} + +cam_pool_t *cPluginMcli::CAMFindByUUID (const char *uuid, int slot) +{ + cam_pool_t *cp; + for(int i=0; i<CAM_POOL_MAX; i++) { + cp = m_cam_pool + i; + if(cp->max >= 0 && !strcmp(cp->uuid, uuid) && (slot == -1 || slot == cp->slot)) { + return cp; + } + } + return NULL; +} + +cam_pool_t *cPluginMcli::CAMPoolFindFree(void) +{ + for(int i=0; i<CAM_POOL_MAX; i++) { + cam_pool_t *cp = m_cam_pool + i; + if(cp->max == -1) { + return cp; + } + } + return NULL; +} +int cPluginMcli::CAMPoolAdd(netceiver_info_t *nci) +{ + bool update = false; + int ret = 0; + for(int j=0; j < nci->cam_num; j++) { + update = false; + cam_pool_t *cp=CAMFindByUUID(nci->uuid, nci->cam[j].slot); + if(!cp) { + cp=CAMPoolFindFree(); + if(!ret) { + ret = 1; + } + } else { + update = true; + ret = 2; + } + if(!cp){ + return ret; + } + if (nci->cam[j].status) { + switch (nci->cam[j].flags) { + case CA_SINGLE: + case CA_MULTI_SID: + cp->max = 1; + break; + case CA_MULTI_TRANSPONDER: + cp->max = nci->cam[j].max_sids/* - nci->cam[j].use_sids*/; + break; + } + } else { + cp->max = 0; + } + cp->status = nci->cam[j].status; + if(!update) { + cp->slot = nci->cam[j].slot; + strcpy(cp->uuid, nci->uuid); + cp->use = 0; + } + } + return ret; +} +bool cPluginMcli::CAMPoolDel(const char *uuid) +{ + cam_pool_t *cp; + bool ret=false; + for(int i=0; i<CAM_POOL_MAX; i++) { + cp = m_cam_pool + i; + if(cp->max>=0 && !strcmp(cp->uuid, uuid)) { + cp->max = -1; + ret=true; + } + } + return ret; +} + +cam_pool_t *cPluginMcli::CAMAvailable (const char *uuid, int slot, bool lock) +{ + cam_pool_t *ret = NULL; + if(lock) { + Lock(); + } + cam_pool_t *cp; + for(int i=0; i<CAM_POOL_MAX; i++) { + cp = m_cam_pool + i; + if(cp->max>0 && (!uuid || !strcmp(cp->uuid, uuid)) && (slot == -1 || (cp->slot == slot))) { + if((cp->max - cp->use) > 0){ + ret = cp; + break; + } + } + } +#ifdef DEBUG_RESOURCES + if(ret) { + printf("CAMAvailable %s %d -> %s %d\n", uuid, slot, ret->uuid, ret->slot); + } +#endif + if(lock) { + Unlock(); + } + return ret; +} +cam_pool_t *cPluginMcli::CAMAlloc (const char *uuid, int slot) +{ + LOCK_THREAD; +#ifdef DEBUG_RESOURCES + printf ("Alloc CAM %s %d\n", uuid, slot); +#endif + cam_pool_t *cp; + if ((cp = CAMAvailable (uuid, slot, false))) { + cp->use++; + return cp; + } + return NULL; +} +int cPluginMcli::CAMFree (cam_pool_t *cp) +{ + LOCK_THREAD; +#ifdef DEBUG_RESOURCES + printf ("FreeCAM %s %d\n", cp->uuid, cp->slot); +#endif + if (cp->use > 0) { + cp->use--; + } + return cp->use; +} +bool cPluginMcli::CAMSteal(const char *uuid, int slot, bool force) +{ + for (cMcliDeviceObject * d = m_devs.First (); d; d = m_devs.Next (d)) { + cam_pool_t *cp=d->d()->GetCAMref(); + if(d->d()->Priority()<0 && d->d()->GetCaEnable() && (slot == -1 || slot == cp->slot)) { +#ifdef DEBUG_RESOURCES + printf("Can Steal CAM on slot %d from %d\n", slot, d->d()->CardIndex()+1); +#endif + if(force) { + d->d ()->SetTempDisable (true); +#ifdef DEBUG_RESOURCES + printf("Stole CAM on slot %d from %d\n", slot, d->d()->CardIndex()+1); +#endif + } + return true; + } + } + return false; +} + +satellite_list_t *cPluginMcli::TunerFindSatList(const netceiver_info_t *nc_info, const char *SatelliteListName) const +{ + if(SatelliteListName == NULL) { + return NULL; + } + + for (int i = 0; i < nc_info->sat_list_num; i++) { + if (!strcmp (SatelliteListName, nc_info->sat_list[i].Name)) { +// printf ("found uuid in sat list %d\n", i); + return nc_info->sat_list + i; + } + } + return NULL; +} + +bool cPluginMcli::SatelitePositionLookup(const satellite_list_t *satlist, int pos) const +{ + if(satlist == NULL) { + return false; + } + for(int i=0; i<satlist->sat_num;i ++) { + satellite_info_t *s=satlist->sat+i; + switch(s->type){ + case SAT_SRC_LNB: + case SAT_SRC_UNI: + if(pos == s->SatPos) { +// printf("satlist found\n"); + return true; + } + break; + case SAT_SRC_ROTOR: + if(pos>=s->SatPosMin && pos <=s->SatPosMax) { +// printf("satlist found\n"); + return true; + } + break; + } + } +// printf("satlist not found\n"); + + return false; +} + +bool cPluginMcli::TunerSatelitePositionLookup(tuner_pool_t *tp, int pos) const +{ + if((tp->type != FE_QPSK) && (tp->type != FE_DVBS2)) { + return true; + } + if(pos == NO_SAT_POS) { + return true; + } + nc_lock_list (); + netceiver_info_list_t *nc_list = nc_get_list (); + satellite_list_t *satlist=NULL; + for (int n = 0; n < nc_list->nci_num; n++) { + netceiver_info_t *nci = nc_list->nci + n; + int l=strlen(tp->uuid)-5; + if(strncmp(nci->uuid, tp->uuid, l)) { + continue; + } + satlist=TunerFindSatList(nci, tp->SatListName); + if(satlist) { + break; + } + } + bool ret; + if(satlist == NULL) { + ret = false; + } else { + ret=SatelitePositionLookup(satlist, pos); + } + nc_unlock_list (); + return ret; +} +tuner_pool_t *cPluginMcli::TunerFindByUUID (const char *uuid) +{ + tuner_pool_t *tp; + for(int i=0; i<TUNER_POOL_MAX; i++) { + tp=m_tuner_pool+i; + if(tp->type != -1 && !strcmp(tp->uuid, uuid)) { + return tp; + } + } + return NULL; +} + +bool cPluginMcli::Ready() +{ + for(int i=0; i<CAM_POOL_MAX; i++) + if((m_cam_pool[i].max >= 0) && (DVBCA_CAMSTATE_INITIALISING == m_cam_pool[i].status)) return false; + for (cMcliDeviceObject * d = m_devs.First (); d; d = m_devs.Next (d)) + if(d->d ()->HasInput()) return true; + return false; +} + +#define MAX_TUNER_TYPE_COUNT (FE_DVBS2+1) +int cPluginMcli::TunerCount() { + tuner_pool_t *tp; + int tct[MAX_TUNER_TYPE_COUNT]; + memset(&tct, 0, sizeof(tct)); + for(int i=0; i<TUNER_POOL_MAX; i++) { + tp=m_tuner_pool+i; + if((tp->type >= 0) && (tp->type < MAX_TUNER_TYPE_COUNT)) + if(tct[tp->type] < m_cmd.tuner_type_limit[tp->type]) + tct[tp->type]++; + } + int tc=0; + for(int i=0; i<MAX_TUNER_TYPE_COUNT; i++) + tc+=tct[i]; + return tc; +} + +int cPluginMcli::TunerCountByType (const fe_type_t type) +{ + int ret=0; + tuner_pool_t *tp; + for(int i=0; i<TUNER_POOL_MAX; i++) { + tp=m_tuner_pool+i; + if(tp->inuse && tp->type == type) { + ret++; + } + } + return ret; +} + +bool cPluginMcli::TunerPoolAdd(tuner_info_t *t) +{ + tuner_pool_t *tp; + for(int i=0; i<TUNER_POOL_MAX; i++) { + tp=m_tuner_pool+i; + if(tp->type == -1) { + tp->type=t->fe_info.type; + strcpy(tp->uuid, t->uuid); + strcpy(tp->SatListName, t->SatelliteListName); + return true; + } + } + return false; +} +bool cPluginMcli::TunerPoolDel(tuner_pool_t *tp) +{ + if(tp->type != -1) { + tp->type=-1; + return true; + } + return false; +} + +tuner_pool_t *cPluginMcli::TunerAvailable(fe_type_t type, int pos, bool lock) +{ + tuner_pool_t *tp; + if(lock) { + Lock(); + } +// printf("TunerAvailable: %d %d\n",type, pos); + if (TunerCountByType (type) == m_cmd.tuner_type_limit[type]) { +#ifdef DEBUG_RESOURCES + //printf("Type %d limit (%d) reached\n", type, m_cmd.tuner_type_limit[type]); +#endif + if(lock) { + Unlock(); + } + return NULL; + } + + for(int i=0; i<TUNER_POOL_MAX; i++) { + tp=m_tuner_pool+i; +// printf("Tuner %d(%p), type %d, inuse %d\n", i, tp, tp->type, tp->inuse); + + if(tp->inuse) { + continue; + } + if(tp->type != type) { + continue; + } + if(TunerSatelitePositionLookup(tp, pos)) { +// printf("TunerAvailable: %d/%p\n",i,tp); + if(lock) { + Unlock(); + } + return tp; + } + } + if(lock) { + Unlock(); + } + return NULL; +} + +tuner_pool_t *cPluginMcli::TunerAlloc(fe_type_t type, int pos, bool lock) +{ + tuner_pool_t *tp; + if(lock) { + Lock(); + } + tp=TunerAvailable(type, pos, false); + if(tp) { + tp->inuse=true; +#ifdef DEBUG_RESOURCES + printf("TunerAlloc: %p type %d\n",tp, tp->type); +#endif + if(lock) { + Unlock(); + } + return tp; + } + if(lock) { + Unlock(); + } + return NULL; +} +bool cPluginMcli::TunerFree(tuner_pool_t *tp, bool lock) +{ + if(lock) { + Lock(); + } + if(tp->inuse) { + tp->inuse=false; +#ifdef DEBUG_RESOURCES + printf("TunerFree: %p type %d\n",tp, tp->type); +#endif + if(lock) { + Unlock(); + } + return true; + } + if(lock) { + Unlock(); + } + return false; +} + +void cPluginMcli::Action (void) +{ + netceiver_info_list_t *nc_list = nc_get_list (); +// printf ("Looking for netceivers out there....\n"); +#if 1 //ndef REELVDR + bool channel_switch_ok = false; +#endif +#define NOTIFY_CAM_CHANGE 1 +#ifdef NOTIFY_CAM_CHANGE + int cam_stats[CAM_POOL_MAX] = { 0 }; + char menu_strings[CAM_POOL_MAX][MAX_MENU_STR_LEN]; + bool first_run = true; + + for (int i = 0; i < CAM_POOL_MAX; i++) + menu_strings[i][0] = '\0'; +#endif + /** lets inform vdr and its plugins if TunerChange event happened */ + bool netCVChanged; + + while (Running ()) { + netCVChanged = false; + Lock (); + nc_lock_list (); + time_t now = time (NULL); + bool tpa = false; + + for (int n = 0; n < nc_list->nci_num; n++) { + netceiver_info_t *nci = nc_list->nci + n; + if ((now - nci->lastseen) > MCLI_DEVICE_TIMEOUT) { + if(CAMPoolDel(nci->uuid)) { + printf ("mcli: Remove CAMs from NetCeiver %s\n", nci->uuid); + isyslog ("mcli: Remove CAMs from NetCeiver %s\n", nci->uuid); + netCVChanged = true; + } + } else { + int cpa = CAMPoolAdd(nci); + if(cpa==1) { + printf ("mcli: Add CAMs from NetCeiver %s -> %d\n", nci->uuid, cpa); + isyslog ("mcli: Add CAMs from NetCeiver %s -> %d\n", nci->uuid, cpa); + netCVChanged = true; + } + } + +#if NOTIFY_CAM_CHANGE + if (n == 0) { + for(int j = 0; j < nci->cam_num && j < CAM_POOL_MAX; j++) { + if (nci->cam[j].status != cam_stats[j]) { + char buf[64]; + if (nci->cam[j].status) { + if(nci->cam[j].status == 2 && !first_run) { + snprintf(buf, 64, tr("Module '%s' ready"), nci->cam[j].menu_string); + Skins.QueueMessage(mtInfo, buf); + } + cam_stats[j] = nci->cam[j].status; + strncpy(menu_strings[j], nci->cam[j].menu_string, MAX_MENU_STR_LEN); + } else if (nci->cam[j].status == 0) { + cam_stats[j] = nci->cam[j].status; + if (!first_run) { + snprintf(buf, 64, tr("Module '%s' removed"), (char*)menu_strings[j]); + Skins.QueueMessage(mtInfo, buf); + } + menu_strings[j][0] = '\0'; + } + } + } + first_run = false; + } +#endif + + for (int i = 0; i < nci->tuner_num; i++) { + tuner_pool_t *t = TunerFindByUUID (nci->tuner[i].uuid); + if (((now - nci->lastseen) > MCLI_DEVICE_TIMEOUT) || (nci->tuner[i].preference < 0) || !strlen (nci->tuner[i].uuid)) { + if (t) { + int pos=TunerPoolDel(t); + printf ("mcli: Remove Tuner %s [%s] @ %d\n", nci->tuner[i].fe_info.name, nci->tuner[i].uuid, pos); + isyslog ("mcli: Remove Tuner %s [%s] @ %d", nci->tuner[i].fe_info.name, nci->tuner[i].uuid, pos); + netCVChanged = true; + } + continue; + } + if (!t) { + tpa=TunerPoolAdd(nci->tuner+i); + printf ("mcli: Add Tuner: %s [%s], Type %d @ %d\n", nci->tuner[i].fe_info.name, nci->tuner[i].uuid, nci->tuner[i].fe_info.type, tpa); + isyslog ("mcli: Add Tuner: %s [%s], Type %d @ %d", nci->tuner[i].fe_info.name, nci->tuner[i].uuid, nci->tuner[i].fe_info.type, tpa); + netCVChanged = true; + } + } + } + nc_unlock_list (); + Unlock (); + UpdateDevices(); + + if (netCVChanged) { + cPluginManager::CallAllServices("NetCeiver changed"); + } + +//TB: reelvdr itself tunes if the first tuner appears, don't do it twice +#if 1 //ndef REELVDR + if (tpa) { + if (!channel_switch_ok) { // the first tuner that was found, so make VDR retune to the channel it wants... + cChannel *ch = Channels.GetByNumber (cDevice::CurrentChannel ()); + if (ch) { + printf("cDevice::PrimaryDevice ()%p\n", cDevice::PrimaryDevice ()); + channel_switch_ok = cDevice::PrimaryDevice ()->SwitchChannel (ch, true); + } + } + } else { + channel_switch_ok = 0; + } +#endif + +#ifdef TEMP_DISABLE_DEVICE + TempDisableDevices(); +#endif + usleep (250 * 1000); + } +} +void cPluginMcli::TempDisableDevices(bool now) +{ + for (cMcliDeviceObject * d = m_devs.First (); d; d = m_devs.Next (d)) { + d->d ()->SetTempDisable (now); + } + +} +bool cPluginMcli::Initialize (void) +{ + return InitMcli (); +} + + +bool cPluginMcli::Start (void) +{ +// printf ("cPluginMcli::Start\n"); + isyslog("mcli v"MCLI_PLUGIN_VERSION" started"); +#ifdef REELVDR + if (access("/dev/dvb/adapter0", F_OK) != 0) //TB: this line allows the client to be used with usb-sticks without conflicts +#endif + cThread::Start (); + // Start any background activities the plugin shall perform. + return true; +} + +void cPluginMcli::Stop (void) +{ +// printf ("cPluginMcli::Stop\n"); + cThread::Cancel (0); + for (cMcliDeviceObject * d = m_devs.First (); d; d = m_devs.Next (d)) { + d->d ()->SetEnable (false); + } + // Stop any background activities the plugin is performing. +} + +void cPluginMcli::Housekeeping (void) +{ + // printf ("cPluginMcli::Housekeeping\n"); +} + +void cPluginMcli::MainThreadHook (void) +{ +// printf("cPluginMcli::MainThreadHook\n"); + if (reconf) { + reconfigure (); + reconf = 0; + } +#if 0 + cOsdObject *MyMenu = AltMenuAction (); + if (MyMenu) { // is there any cam-menu waiting? + if (cControl::Control ()) { + cControl::Control ()->Hide (); + } + MyMenu->Show (); + } +#endif +} + +cString cPluginMcli::Active (void) +{ +// printf ("cPluginMcli::Active\n"); + // Return a message string if shutdown should be postponed + return NULL; +} + +time_t cPluginMcli::WakeupTime (void) +{ +// printf ("cPluginMcli::WakeupTime\n"); + // Return custom wakeup time for shutdown script + return 0; +} + +void cPluginMcli::reconfigure (void) +{ + Lock(); + for (cMcliDeviceObject * d = m_devs.First (); d;) { + cMcliDeviceObject *next = m_devs.Next (d); + d->d ()->SetEnable (false); + d->d ()->ExitMcli (); + d = next; + } + ExitMcli (); + memset (m_tuner_pool, 0, sizeof(tuner_pool_t)*TUNER_POOL_MAX); + for(int i=0; i<TUNER_POOL_MAX; i++) { + m_tuner_pool[i].type = -1; + } + for(int i=0; i<CAM_POOL_MAX; i++) { + m_cam_pool[i].max = -1; + } + InitMcli (); + for (cMcliDeviceObject * d = m_devs.First (); d; d = m_devs.Next (d)) { + d->d ()->InitMcli (); + } + Unlock(); + usleep(3*1000*1000); + UpdateDevices(); +} + +void cPluginMcli::UpdateDevices() { + int tc = TunerCount(); + int dc = min(tc, m_devs.Count()); + int c = dc; + for (cMcliDeviceObject * d = m_devs.First (); d; d = m_devs.Next (d)) { + if(c>0) { + if(!d->d ()->HasInput()) + d->d ()->SetEnable(true); + c--; + } else if(d->d ()->HasInput()) + if(!d->d ()->Receiving()) + d->d ()->SetEnable(false); + } + static int last_dc=0; + if(last_dc != dc) isyslog("%d tuner available: enabling %d devices", tc, dc); + last_dc = dc; +} + +cOsdObject *cPluginMcli::MainMenuAction (void) +{ +// printf ("cPluginMcli::MainMenuAction\n"); + // Perform the action when selected from the main VDR menu. + return new cCamMenu (&m_cmd); +} + + +cMenuSetupPage *cPluginMcli::SetupMenu (void) +{ +// printf ("cPluginMcli::SetupMenu\n"); + // Return a setup menu in case the plugin supports one. + return new cMenuSetupMcli (&m_cmd); +} + +bool cPluginMcli::SetupParse (const char *Name, const char *Value) +{ +// printf ("cPluginMcli::SetupParse\n"); + if (!strcasecmp (Name, "DVB-C") && m_cmd.tuner_type_limit[FE_QAM] == MCLI_MAX_DEVICES) + m_cmd.tuner_type_limit[FE_QAM] = atoi (Value); + else if (!strcasecmp (Name, "DVB-T") && m_cmd.tuner_type_limit[FE_OFDM] == MCLI_MAX_DEVICES) + m_cmd.tuner_type_limit[FE_OFDM] = atoi (Value); + else if (!strcasecmp (Name, "DVB-S") && m_cmd.tuner_type_limit[FE_QPSK] == MCLI_MAX_DEVICES) + m_cmd.tuner_type_limit[FE_QPSK] = atoi (Value); + else if (!strcasecmp (Name, "DVB-S2") && m_cmd.tuner_type_limit[FE_DVBS2] == MCLI_MAX_DEVICES) + m_cmd.tuner_type_limit[FE_DVBS2] = atoi (Value); + else + return false; + return true; +} + +bool cPluginMcli::Service (const char *Id, void *Data) +{ + //printf ("cPluginMcli::Service: \"%s\"\n", Id); + mclituner_info_t *infos = (mclituner_info_t *) Data; + + if (Id && strcmp (Id, "GetTunerInfo") == 0) { + int j=0; + time_t now = time (NULL); + netceiver_info_list_t *nc_list = nc_get_list (); + nc_lock_list (); + for (int n = 0; n < nc_list->nci_num; n++) { + netceiver_info_t *nci = nc_list->nci + n; + if ((now - nci->lastseen) > MCLI_DEVICE_TIMEOUT) { + continue; + } + for (int i = 0; i < nci->tuner_num && j < MAX_TUNERS_IN_MENU; i++) { + strcpy (infos->name[j], nci->tuner[i].fe_info.name); + infos->type[j] = nci->tuner[i].fe_info.type; + infos->preference[j++] = nci->tuner[i].preference; + //printf("Tuner: %s\n", nci->tuner[i].fe_info.name); + } + } + nc_unlock_list (); + return true; + } else if (Id && strcmp (Id, "Reinit") == 0) { + if (Data && strlen ((char *) Data) && (strncmp ((char *) Data, "eth", 3) || strncmp ((char *) Data, "br", 2))) { + strncpy (m_cmd.iface, (char *) Data, IFNAMSIZ - 1); + } + reconfigure (); + return true; + } else if (Id && strcmp (Id, "Set tuner count") == 0) { + if (Data) { + mcli_tuner_count_t *tuner_count = (mcli_tuner_count_t*)Data; + int count; + + count = tuner_count->dvb_c; + if (count < 0) count = MCLI_MAX_DEVICES; + //SetupParse("DVB-C", itoa(count)); + m_cmd.tuner_type_limit[FE_QAM] = count; + /* save settings to .conf*/ + SetupStore("DVB-C", count); + + count = tuner_count->dvb_t; + if (count < 0) count = MCLI_MAX_DEVICES; + //SetupParse("DVB-T", itoa(count)); + m_cmd.tuner_type_limit[FE_OFDM] = count; + /* save settings to .conf*/ + SetupStore("DVB-T", count); + + count = tuner_count->dvb_s; + if (count < 0) count = MCLI_MAX_DEVICES; + //SetupParse("DVB-S", itoa(count)); + m_cmd.tuner_type_limit[FE_QPSK] = count; + /* save settings to .conf*/ + SetupStore("DVB-S", count); + + count = tuner_count->dvb_s2; + if (count < 0) count = MCLI_MAX_DEVICES; + //SetupParse("DVB-S2", itoa(count)); + m_cmd.tuner_type_limit[FE_DVBS2] = count; + /* save settings to .conf*/ + SetupStore("DVB-S2", count); + } + return true; + } // set tuner count + else if (Id && strcmp (Id, "Get tuner count") == 0) { + if (Data) { + mcli_tuner_count_t *tuner_count = (mcli_tuner_count_t*)Data; + + tuner_count->dvb_c = TunerCountByType(FE_QAM); + tuner_count->dvb_t = TunerCountByType(FE_OFDM); + tuner_count->dvb_s = TunerCountByType(FE_QPSK); + tuner_count->dvb_s2 = TunerCountByType((fe_type_t)FE_DVBS2); + } + return true; + } + // Handle custom service requests from other plugins + return false; +} + +const char **cPluginMcli::SVDRPHelpPages (void) +{ +// printf ("cPluginMcli::SVDRPHelpPages\n"); + // Return help text for SVDRP commands this plugin implements + static const char *HelpPages[] = { + "GETTC\n" " List available tuners.", + "REINIT [dev]\n" " Reinitalize the plugin on a certain network device - e.g.: plug mcli REINIT eth0", + NULL + }; + return HelpPages; +} + +cString cPluginMcli::SVDRPCommand (const char *Command, const char *Option, int &ReplyCode) +{ + typedef struct nrTuners + { + int sat; + int satS2; + int cable; + int terr; + } nrTuners_t; + +// printf ("cPluginMcli::SVDRPCommand\n"); + // Process SVDRP commands this plugin implements + + if (strcasecmp (Command, "REINIT") == 0) { + if (Option && (strncmp (Option, "eth", 3) || strncmp (Option, "br", 2))) { + strncpy (m_cmd.iface, (char *) Option, IFNAMSIZ - 1); + } + reconfigure (); + return cString ("Mcli-plugin: reconfiguring..."); + } + else if (strcasecmp(Command, "GETTC") == 0) + { + std::stringstream sdat; + std::string sout; + + char *buffer = NULL; + std::string strBuff; + FILE *file = NULL; + + int cable =0; + int sat =0; + int satS2 = 0; + int terr = 0; + file = fopen("/etc/default/mcli", "r"); + if(file) + { + cReadLine readline; + buffer = readline.Read(file); + while(buffer) + { + if(strstr(buffer, "DVB_C_DEVICES=\"") && !strstr(buffer, "\"\"")) + cable = atoi(buffer+15); + if(strstr(buffer, "DVB_S_DEVICES=\"") && !strstr(buffer, "\"\"")) + sat = atoi(buffer+15); + if(strstr(buffer, "DVB_S2_DEVICES=\"") && !strstr(buffer, "\"\"")) + satS2 = atoi(buffer+16); + if(strstr(buffer, "DVB_T_DEVICES=\"") && !strstr(buffer, "\"\"")) + terr = atoi(buffer+15); + + buffer = readline.Read(file); + } + fclose(file); + } + + nrTuners_t nrTunersPhys; + nrTunersPhys.sat = nrTunersPhys.satS2 = nrTunersPhys.terr = nrTunersPhys.cable = 0; + cPlugin *mcliPlugin = cPluginManager::GetPlugin("mcli"); + if (mcliPlugin) + { + mclituner_info_t info; + for (int i = 0; i < MAX_TUNERS_IN_MENU; i++) + info.name[i][0] = '\0'; + mcliPlugin->Service("GetTunerInfo", &info); + for (int i = 0; i < MAX_TUNERS_IN_MENU; i++) + { + if (info.preference[i] == -1 || strlen(info.name[i]) == 0) + break; + else + { + switch(info.type[i]) + { + case FE_QPSK: // DVB-S + nrTunersPhys.sat++; + break; + case FE_DVBS2: // DVB-S2 + nrTunersPhys.satS2++; + break; + case FE_OFDM: // DVB-T + nrTunersPhys.terr++; + break; + case FE_QAM: // DVB-C + nrTunersPhys.cable++; + break; + } + } + } + } + + if ( cable > nrTunersPhys.cable ) + cable = nrTunersPhys.cable; + if ( sat > nrTunersPhys.sat ) + sat = nrTunersPhys.sat; + if ( satS2 > nrTunersPhys.satS2 ) + satS2 = nrTunersPhys.sat; + if ( terr > nrTunersPhys.terr ) + terr = nrTunersPhys.terr; + + sdat.str(""); + if ( asprintf( &buffer, "DVB_C_DEVICES=%d\n", cable ) >= 0 ) + { + sdat.str(""); sdat << buffer; + sout += sdat.str(); + free(buffer); + } + + if ( asprintf( &buffer, "DVB_S_DEVICES=%d\n", sat ) >= 0 ) + { + sdat.str(""); sdat << buffer; + sout += sdat.str(); + free(buffer); + } + + if ( asprintf( &buffer, "DVB_S2_DEVICES=%d\n", satS2 ) >= 0 ) + { + sdat.str(""); sdat << buffer; + sout += sdat.str(); + free(buffer); + } + + if ( asprintf( &buffer, "DVB_T_DEVICES=%d\n", terr ) >= 0 ) + { + sdat.str(""); sdat << buffer; + sout += sdat.str(); + free(buffer); + } + ReplyCode = 215; + return cString( sout.c_str() ); + } + return NULL; +} + +VDRPLUGINCREATOR (cPluginMcli); // Don't touch this! |