=== libs/libmythtv/dvbcam.h Index: libs/libmythtv/dvbcam.cpp =================================================================== --- libs/libmythtv/dvbcam.cpp.orig 2006-06-20 17:32:47.000000000 -0400 +++ libs/libmythtv/dvbcam.cpp 2006-06-20 17:39:50.000000000 -0400 @@ -36,6 +36,8 @@ #include #include +#include + #include #include #include @@ -84,6 +86,10 @@ bool DVBCam::Start() { + + if(useExternalCam()) + return true; + if (numslots == 0) return false; @@ -114,6 +120,9 @@ bool DVBCam::Stop() { + + stopExternalCam(); + if (ciThreadRunning) { exitCiThread = true; @@ -256,6 +265,9 @@ void DVBCam::SetPMT(const PMTObject *pmt) { GENERAL(QString("CA: SetPMT for ServiceID=%1").arg(pmt->ServiceID)); + + sendExternalCam(pmt); + pthread_mutex_lock(&pmt_lock); PMTList.clear(); PMTList += *pmt; @@ -343,3 +355,149 @@ } } +bool DVBCam::useExternalCam() +{ + skThreadRunning = false; + exitSkThread = false; + external_cam_fd = -1; + QString extCam = QDir::homeDirPath() + + QString("/.mythtv/externcam_%1").arg(cardnum); + if (QFileInfo(extCam).isDir()) + { + QString cmd = gContext->GetSetting("ExternalCamApp",""); + if(cmd == "") { + ERROR("CAM - No external app set in SQL db."); + return false; + } + cmd += " --dir " + extCam + QString(" --card %1").arg(cardnum); + + QString keyFifo = QDir::homeDirPath() + + QString("/.mythtv/externcam_%1/keyfifo").arg(cardnum); + unlink(keyFifo.ascii()); + + int tmppid[2]; + if (pipe(tmppid) < 0) + { + perror("Failed to create pipe\n"); + return false; + } + + int child = fork(); + if (child < 0) + { + perror("Failed to fork\n"); + return false; + } + if (child == 0) + { + dup2(tmppid[0],fileno(stdin)); + for(int i = 3; i < sysconf(_SC_OPEN_MAX) - 1; ++i) + close(i); + execl("/bin/sh", "sh", "-c", cmd.ascii(), NULL); + perror("exec"); + _exit(1); + } + close(tmppid[0]); + external_cam_fd=tmppid[1]; + + //we need to fake ciThreadRunning in oreder to get PMTs + ciThreadRunning = true; + return true; + } + return false; +} + +void DVBCam::sendExternalCam(const PMTObject *pmt) +{ + if (external_cam_fd < 0) + return; + + unsigned char newpmt[512]; + int hdr[34]; //Allow for up to 16 PIDs + int pmtlen=0, hdrlen = 0; + bool need_pcrpid = false; + + hdr[hdrlen++]=pmt->ServiceID; + hdr[hdrlen++]=1; //Place holder for transportID (future) + for (CAList::const_iterator ca = pmt->CA.begin(); ca != pmt->CA.end(); ++ca) + { + newpmt[pmtlen++] = 0x09; + newpmt[pmtlen++] = (*ca).Data_Length + + sizeof((*ca).CASystemID) + sizeof((*ca).PID); + newpmt[pmtlen++] = ((*ca).CASystemID) >> 8; + newpmt[pmtlen++] = ((*ca).CASystemID) & 0xff; + newpmt[pmtlen++] = ((*ca).PID) >> 8; + newpmt[pmtlen++] = ((*ca).PID) & 0xff; + for (int x = 0; x < (*ca).Data_Length; x++) + newpmt[pmtlen++] = ((*ca).Data[x]); + } + for (ComponentList::const_iterator e = pmt->Components.begin(); + e != pmt->Components.end(); ++e) + { + int type; + switch ((*e).Type) + { + case ES_TYPE_AUDIO_MPEG1: case ES_TYPE_AUDIO_MPEG2: + case ES_TYPE_AUDIO_AC3: case ES_TYPE_AUDIO_DTS: + case ES_TYPE_AUDIO_AAC: + type = 0; + break; + case ES_TYPE_VIDEO_MPEG1: case ES_TYPE_VIDEO_MPEG2: + case ES_TYPE_VIDEO_MPEG4: case ES_TYPE_VIDEO_H264: + if (pmt->PCRPID != 0 && pmt->PCRPID != (*e).PID) + { + hdr[hdrlen++] = pmt->PCRPID; //pid + hdr[hdrlen++] = 2; //stream type + } + type = 1; + break; + case ES_TYPE_TELETEXT: + type = 3; + break; + default: + type = 5; + } + hdr[hdrlen++] = (*e).PID; //pid + hdr[hdrlen++] = type; //stream type + for (CAList::const_iterator ca = (*e).CA.begin(); + ca != (*e).CA.end(); ++ca) + { + newpmt[pmtlen++] = 0x09; + newpmt[pmtlen++] = (*ca).Data_Length + + sizeof((*ca).CASystemID) + sizeof((*ca).PID); + newpmt[pmtlen++] = ((*ca).CASystemID) >> 8; + newpmt[pmtlen++] = ((*ca).CASystemID) & 0xff; + newpmt[pmtlen++] = ((*ca).PID) >> 8; + newpmt[pmtlen++] = ((*ca).PID) & 0xff; + for (int x = 0; x < (*ca).Data_Length; x++) + newpmt[pmtlen++] = (*ca).Data[x]; + } + } + if (pmtlen) { + QString temp = QString("SID: %1 TID: %2").arg(hdr[0]).arg(hdr[1]); + for (int x = 2; x < hdrlen; x += 2) + temp += QString(" (%1 %2)").arg(hdr[x]).arg(hdr[x + 1]); + GENERAL(temp); + temp = QString("Found CA Descriptors: (%1)").arg(pmtlen); + for (int x = 0; x < pmtlen; x++) + temp += QString(" %1").arg(newpmt[x],2,16); + GENERAL(temp); + write(external_cam_fd, &hdrlen, sizeof(hdrlen)); + write(external_cam_fd, &hdr, hdrlen * sizeof(int)); + write(external_cam_fd, &pmtlen, sizeof(pmtlen)); + write(external_cam_fd, &newpmt, pmtlen); + } +} + +void DVBCam::stopExternalCam() +{ + if(external_cam_fd != -1) { + close(external_cam_fd); + ciThreadRunning = false; + if (skThreadRunning) + { + exitSkThread = true; + pthread_join(externSoftkeyThread, NULL); + } + } +} Index: libs/libmythtv/dvbcam.h =================================================================== --- libs/libmythtv/dvbcam.h.orig 2006-06-20 17:32:47.000000000 -0400 +++ libs/libmythtv/dvbcam.h 2006-06-20 17:39:50.000000000 -0400 @@ -42,6 +42,15 @@ bool pmt_sent; bool pmt_updated; bool pmt_added; + + bool exitSkThread; + bool skThreadRunning; + pthread_t externSoftkeyThread; + int external_cam_fd; + void sendExternalCam(const PMTObject *pmt); + bool useExternalCam(); + void stopExternalCam(); + }; #endif // DVBCAM_H