vdr  1.7.27
device.c
Go to the documentation of this file.
00001 /*
00002  * device.c: The basic device interface
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: device.c 2.58 2012/03/13 09:48:14 kls Exp $
00008  */
00009 
00010 #include "device.h"
00011 #include <errno.h>
00012 #include <sys/ioctl.h>
00013 #include <sys/mman.h>
00014 #include "audio.h"
00015 #include "channels.h"
00016 #include "i18n.h"
00017 #include "player.h"
00018 #include "receiver.h"
00019 #include "status.h"
00020 #include "transfer.h"
00021 #include "vdrttxtsubshooks.h"
00022 
00023 // --- cLiveSubtitle ---------------------------------------------------------
00024 
00025 class cLiveSubtitle : public cReceiver {
00026 protected:
00027   virtual void Receive(uchar *Data, int Length);
00028 public:
00029   cLiveSubtitle(int SPid);
00030   virtual ~cLiveSubtitle();
00031   };
00032 
00033 cLiveSubtitle::cLiveSubtitle(int SPid)
00034 {
00035   AddPid(SPid);
00036 }
00037 
00038 cLiveSubtitle::~cLiveSubtitle()
00039 {
00040   cReceiver::Detach();
00041 }
00042 
00043 void cLiveSubtitle::Receive(uchar *Data, int Length)
00044 {
00045   if (cDevice::PrimaryDevice())
00046      cDevice::PrimaryDevice()->PlayTs(Data, Length);
00047 }
00048 
00049 // --- cDeviceHook -----------------------------------------------------------
00050 
00051 cDeviceHook::cDeviceHook(void)
00052 {
00053   cDevice::deviceHooks.Add(this);
00054 }
00055 
00056 bool cDeviceHook::DeviceProvidesTransponder(const cDevice *Device, const cChannel *Channel) const
00057 {
00058   return true;
00059 }
00060 
00061 // --- cDevice ---------------------------------------------------------------
00062 
00063 // The minimum number of unknown PS1 packets to consider this a "pre 1.3.19 private stream":
00064 #define MIN_PRE_1_3_19_PRIVATESTREAM 10
00065 
00066 int cDevice::numDevices = 0;
00067 int cDevice::useDevice = 0;
00068 int cDevice::nextCardIndex = 0;
00069 int cDevice::currentChannel = 1;
00070 cDevice *cDevice::device[MAXDEVICES] = { NULL };
00071 cDevice *cDevice::primaryDevice = NULL;
00072 cList<cDeviceHook> cDevice::deviceHooks;
00073 
00074 cDevice::cDevice(void)
00075 :patPmtParser(true)
00076 {
00077   cardIndex = nextCardIndex++;
00078   dsyslog("new device number %d", CardIndex() + 1);
00079 
00080   SetDescription("receiver on device %d", CardIndex() + 1);
00081 
00082   mute = false;
00083   volume = Setup.CurrentVolume;
00084 
00085   sectionHandler = NULL;
00086   eitFilter = NULL;
00087   patFilter = NULL;
00088   sdtFilter = NULL;
00089   nitFilter = NULL;
00090 
00091   camSlot = NULL;
00092   startScrambleDetection = 0;
00093 
00094   occupiedTimeout = 0;
00095 
00096   player = NULL;
00097   isPlayingVideo = false;
00098   ClrAvailableTracks();
00099   currentAudioTrack = ttNone;
00100   currentAudioTrackMissingCount = 0;
00101   currentSubtitleTrack = ttNone;
00102   liveSubtitle = NULL;
00103   dvbSubtitleConverter = NULL;
00104   autoSelectPreferredSubtitleLanguage = true;
00105 
00106   for (int i = 0; i < MAXRECEIVERS; i++)
00107       receiver[i] = NULL;
00108 
00109   if (numDevices < MAXDEVICES)
00110      device[numDevices++] = this;
00111   else
00112      esyslog("ERROR: too many devices!");
00113 }
00114 
00115 cDevice::~cDevice()
00116 {
00117   Detach(player);
00118   DetachAllReceivers();
00119   delete liveSubtitle;
00120   delete dvbSubtitleConverter;
00121 }
00122 
00123 bool cDevice::WaitForAllDevicesReady(int Timeout)
00124 {
00125   for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
00126       bool ready = true;
00127       for (int i = 0; i < numDevices; i++) {
00128           if (device[i] && !device[i]->Ready()) {
00129              ready = false;
00130              cCondWait::SleepMs(100);
00131              }
00132           }
00133       if (ready)
00134          return true;
00135       }
00136   return false;
00137 }
00138 
00139 void cDevice::SetUseDevice(int n)
00140 {
00141   if (n < MAXDEVICES)
00142      useDevice |= (1 << n);
00143 }
00144 
00145 int cDevice::NextCardIndex(int n)
00146 {
00147   if (n > 0) {
00148      nextCardIndex += n;
00149      if (nextCardIndex >= MAXDEVICES)
00150         esyslog("ERROR: nextCardIndex too big (%d)", nextCardIndex);
00151      }
00152   else if (n < 0)
00153      esyslog("ERROR: invalid value in nextCardIndex(%d)", n);
00154   return nextCardIndex;
00155 }
00156 
00157 int cDevice::DeviceNumber(void) const
00158 {
00159   for (int i = 0; i < numDevices; i++) {
00160       if (device[i] == this)
00161          return i;
00162       }
00163   return -1;
00164 }
00165 
00166 cString cDevice::DeviceName(void) const
00167 {
00168   return "";
00169 }
00170 
00171 void cDevice::MakePrimaryDevice(bool On)
00172 {
00173   if (!On) {
00174      DELETENULL(liveSubtitle);
00175      DELETENULL(dvbSubtitleConverter);
00176      }
00177 }
00178 
00179 bool cDevice::SetPrimaryDevice(int n)
00180 {
00181   n--;
00182   if (0 <= n && n < numDevices && device[n]) {
00183      isyslog("setting primary device to %d", n + 1);
00184      if (primaryDevice)
00185         primaryDevice->MakePrimaryDevice(false);
00186      primaryDevice = device[n];
00187      primaryDevice->MakePrimaryDevice(true);
00188      primaryDevice->SetVideoFormat(Setup.VideoFormat);
00189      primaryDevice->SetVolumeDevice(Setup.CurrentVolume);
00190      return true;
00191      }
00192   esyslog("ERROR: invalid primary device number: %d", n + 1);
00193   return false;
00194 }
00195 
00196 bool cDevice::HasDecoder(void) const
00197 {
00198   return false;
00199 }
00200 
00201 cSpuDecoder *cDevice::GetSpuDecoder(void)
00202 {
00203   return NULL;
00204 }
00205 
00206 cDevice *cDevice::ActualDevice(void)
00207 {
00208   cDevice *d = cTransferControl::ReceiverDevice();
00209   if (!d)
00210      d = PrimaryDevice();
00211   return d;
00212 }
00213 
00214 cDevice *cDevice::GetDevice(int Index)
00215 {
00216   return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
00217 }
00218 
00219 static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device)
00220 {
00221   int MaxNumProvidedSystems = (1 << AvailableBits) - 1;
00222   int NumProvidedSystems = Device->NumProvidedSystems();
00223   if (NumProvidedSystems > MaxNumProvidedSystems) {
00224      esyslog("ERROR: device %d supports %d modulation systems but cDevice::GetDevice() currently only supports %d delivery systems which should be fixed", Device->CardIndex() + 1, NumProvidedSystems, MaxNumProvidedSystems);
00225      NumProvidedSystems = MaxNumProvidedSystems;
00226      }
00227   else if (NumProvidedSystems <= 0) {
00228      esyslog("ERROR: device %d reported an invalid number (%d) of supported delivery systems - assuming 1", Device->CardIndex() + 1, NumProvidedSystems);
00229      NumProvidedSystems = 1;
00230      }
00231   return NumProvidedSystems;
00232 }
00233 
00234 cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool Query)
00235 {
00236   // Collect the current priorities of all CAM slots that can decrypt the channel:
00237   int NumCamSlots = CamSlots.Count();
00238   int SlotPriority[NumCamSlots];
00239   int NumUsableSlots = 0;
00240   if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
00241      for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) {
00242          SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used
00243          if (CamSlot->ModuleStatus() == msReady) {
00244             if (CamSlot->ProvidesCa(Channel->Caids())) {
00245                if (!ChannelCamRelations.CamChecked(Channel->GetChannelID(), CamSlot->SlotNumber())) {
00246                   SlotPriority[CamSlot->Index()] = CamSlot->Priority();
00247                   NumUsableSlots++;
00248                   }
00249                }
00250             }
00251          }
00252      if (!NumUsableSlots)
00253         return NULL; // no CAM is able to decrypt this channel
00254      }
00255 
00256   bool NeedsDetachReceivers = false;
00257   cDevice *d = NULL;
00258   cCamSlot *s = NULL;
00259 
00260   uint32_t Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
00261   for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) {
00262       if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY)
00263          continue; // there is no CAM available in this slot
00264       for (int i = 0; i < numDevices; i++) {
00265           if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != device[i]->CardIndex() + 1)
00266              continue; // a specific card was requested, but not this one
00267           if (NumUsableSlots && !CamSlots.Get(j)->Assign(device[i], true))
00268              continue; // CAM slot can't be used with this device
00269           bool ndr;
00270           if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
00271              if (NumUsableSlots && device[i]->CamSlot() && device[i]->CamSlot() != CamSlots.Get(j))
00272                 ndr = true; // using a different CAM slot requires detaching receivers
00273              // Put together an integer number that reflects the "impact" using
00274              // this device would have on the overall system. Each condition is represented
00275              // by one bit in the number (or several bits, if the condition is actually
00276              // a numeric value). The sequence in which the conditions are listed corresponds
00277              // to their individual severity, where the one listed first will make the most
00278              // difference, because it results in the most significant bit of the result.
00279              uint32_t imp = 0;
00280              imp <<= 1; imp |= LiveView ? !device[i]->IsPrimaryDevice() || ndr : 0;                                  // prefer the primary device for live viewing if we don't need to detach existing receivers
00281              imp <<= 1; imp |= !device[i]->Receiving() && (device[i] != cTransferControl::ReceiverDevice() || device[i]->IsPrimaryDevice()) || ndr; // use receiving devices if we don't need to detach existing receivers, but avoid primary device in local transfer mode
00282              imp <<= 1; imp |= device[i]->Receiving();                                                               // avoid devices that are receiving
00283              imp <<= 4; imp |= GetClippedNumProvidedSystems(4, device[i]) - 1;                                       // avoid cards which support multiple delivery systems
00284              imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice();                                      // avoid the Transfer Mode receiver device
00285              imp <<= 8; imp |= device[i]->Priority() - IDLEPRIORITY;                                                 // use the device with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
00286              imp <<= 8; imp |= (NumUsableSlots ? SlotPriority[j] : IDLEPRIORITY) - IDLEPRIORITY;                     // use the CAM slot with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
00287              imp <<= 1; imp |= ndr;                                                                                  // avoid devices if we need to detach existing receivers
00288              imp <<= 1; imp |= NumUsableSlots ? 0 : device[i]->HasCi();                                              // avoid cards with Common Interface for FTA channels
00289              imp <<= 1; imp |= device[i]->AvoidRecording();                                                          // avoid SD full featured cards
00290              imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
00291              imp <<= 1; imp |= device[i]->IsPrimaryDevice();                                                         // avoid the primary device
00292              if (imp < Impact) {
00293                 // This device has less impact than any previous one, so we take it.
00294                 Impact = imp;
00295                 d = device[i];
00296                 NeedsDetachReceivers = ndr;
00297                 if (NumUsableSlots)
00298                    s = CamSlots.Get(j);
00299                 }
00300              }
00301           }
00302       if (!NumUsableSlots)
00303          break; // no CAM necessary, so just one loop over the devices
00304       }
00305   if (d && !Query) {
00306      if (NeedsDetachReceivers)
00307         d->DetachAllReceivers();
00308      if (s) {
00309         if (s->Device() != d) {
00310            if (s->Device())
00311               s->Device()->DetachAllReceivers();
00312            if (d->CamSlot())
00313               d->CamSlot()->Assign(NULL);
00314            s->Assign(d);
00315            }
00316         }
00317      else if (d->CamSlot() && !d->CamSlot()->IsDecrypting())
00318         d->CamSlot()->Assign(NULL);
00319      }
00320   return d;
00321 }
00322 
00323 cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority)
00324 {
00325   cDevice *Device = NULL;
00326   for (int i = 0; i < cDevice::NumDevices(); i++) {
00327       if (cDevice *d = cDevice::GetDevice(i)) {
00328          if (d->IsTunedToTransponder(Channel))
00329             return d; // if any device is tuned to the transponder, we're done
00330          if (d->ProvidesTransponder(Channel)) {
00331             if (d->MaySwitchTransponder(Channel))
00332                Device = d; // this device may switch to the transponder without disturbing any receiver or live view
00333             else if (!d->Occupied()) {
00334                if (d->Priority() < Priority && (!Device || d->Priority() < Device->Priority()))
00335                   Device = d; // use this one only if no other with less impact can be found
00336                }
00337             }
00338          }
00339       }
00340   return Device;
00341 }
00342 
00343 bool cDevice::HasCi(void)
00344 {
00345   return false;
00346 }
00347 
00348 void cDevice::SetCamSlot(cCamSlot *CamSlot)
00349 {
00350   camSlot = CamSlot;
00351 }
00352 
00353 void cDevice::Shutdown(void)
00354 {
00355   deviceHooks.Clear();
00356   primaryDevice = NULL;
00357   for (int i = 0; i < numDevices; i++) {
00358       delete device[i];
00359       device[i] = NULL;
00360       }
00361 }
00362 
00363 uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
00364 {
00365   return NULL;
00366 }
00367 
00368 bool cDevice::GrabImageFile(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
00369 {
00370   int result = 0;
00371   int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE);
00372   if (fd >= 0) {
00373      int ImageSize;
00374      uchar *Image = GrabImage(ImageSize, Jpeg, Quality, SizeX, SizeY);
00375      if (Image) {
00376         if (safe_write(fd, Image, ImageSize) == ImageSize)
00377            isyslog("grabbed image to %s", FileName);
00378         else {
00379            LOG_ERROR_STR(FileName);
00380            result |= 1;
00381            }
00382         free(Image);
00383         }
00384      else
00385         result |= 1;
00386      close(fd);
00387      }
00388   else {
00389      LOG_ERROR_STR(FileName);
00390      result |= 1;
00391      }
00392   return result == 0;
00393 }
00394 
00395 void cDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
00396 {
00397   cSpuDecoder *spuDecoder = GetSpuDecoder();
00398   if (spuDecoder) {
00399      if (Setup.VideoFormat)
00400         spuDecoder->setScaleMode(cSpuDecoder::eSpuNormal);
00401      else {
00402         switch (VideoDisplayFormat) {
00403                case vdfPanAndScan:
00404                     spuDecoder->setScaleMode(cSpuDecoder::eSpuPanAndScan);
00405                     break;
00406                case vdfLetterBox:
00407                     spuDecoder->setScaleMode(cSpuDecoder::eSpuLetterBox);
00408                     break;
00409                case vdfCenterCutOut:
00410                     spuDecoder->setScaleMode(cSpuDecoder::eSpuNormal);
00411                     break;
00412                default: esyslog("ERROR: invalid value for VideoDisplayFormat '%d'", VideoDisplayFormat);
00413                }
00414         }
00415      }
00416 }
00417 
00418 void cDevice::SetVideoFormat(bool VideoFormat16_9)
00419 {
00420 }
00421 
00422 eVideoSystem cDevice::GetVideoSystem(void)
00423 {
00424   return vsPAL;
00425 }
00426 
00427 void cDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
00428 {
00429   Width = 0;
00430   Height = 0;
00431   VideoAspect = 1.0;
00432 }
00433 
00434 void cDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
00435 {
00436   Width = 720;
00437   Height = 480;
00438   PixelAspect = 1.0;
00439 }
00440 
00441 //#define PRINTPIDS(s) { char b[500]; char *q = b; q += sprintf(q, "%d %s ", CardIndex(), s); for (int i = 0; i < MAXPIDHANDLES; i++) q += sprintf(q, " %s%4d %d", i == ptOther ? "* " : "", pidHandles[i].pid, pidHandles[i].used); dsyslog("%s", b); }
00442 #define PRINTPIDS(s)
00443 
00444 bool cDevice::HasPid(int Pid) const
00445 {
00446   for (int i = 0; i < MAXPIDHANDLES; i++) {
00447       if (pidHandles[i].pid == Pid)
00448          return true;
00449       }
00450   return false;
00451 }
00452 
00453 bool cDevice::AddPid(int Pid, ePidType PidType, int StreamType)
00454 {
00455   if (Pid || PidType == ptPcr) {
00456      int n = -1;
00457      int a = -1;
00458      if (PidType != ptPcr) { // PPID always has to be explicit
00459         for (int i = 0; i < MAXPIDHANDLES; i++) {
00460             if (i != ptPcr) {
00461                if (pidHandles[i].pid == Pid)
00462                   n = i;
00463                else if (a < 0 && i >= ptOther && !pidHandles[i].used)
00464                   a = i;
00465                }
00466             }
00467         }
00468      if (n >= 0) {
00469         // The Pid is already in use
00470         if (++pidHandles[n].used == 2 && n <= ptTeletext) {
00471            // It's a special PID that may have to be switched into "tap" mode
00472            PRINTPIDS("A");
00473            if (!SetPid(&pidHandles[n], n, true)) {
00474               esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1);
00475               if (PidType <= ptTeletext)
00476                  DetachAll(Pid);
00477               DelPid(Pid, PidType);
00478               return false;
00479               }
00480            if (camSlot)
00481               camSlot->SetPid(Pid, true);
00482            }
00483         PRINTPIDS("a");
00484         return true;
00485         }
00486      else if (PidType < ptOther) {
00487         // The Pid is not yet in use and it is a special one
00488         n = PidType;
00489         }
00490      else if (a >= 0) {
00491         // The Pid is not yet in use and we have a free slot
00492         n = a;
00493         }
00494      else {
00495         esyslog("ERROR: no free slot for PID %d on device %d", Pid, CardIndex() + 1);
00496         return false;
00497         }
00498      if (n >= 0) {
00499         pidHandles[n].pid = Pid;
00500         pidHandles[n].streamType = StreamType;
00501         pidHandles[n].used = 1;
00502         PRINTPIDS("C");
00503         if (!SetPid(&pidHandles[n], n, true)) {
00504            esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1);
00505            if (PidType <= ptTeletext)
00506               DetachAll(Pid);
00507            DelPid(Pid, PidType);
00508            return false;
00509            }
00510         if (camSlot)
00511            camSlot->SetPid(Pid, true);
00512         }
00513      }
00514   return true;
00515 }
00516 
00517 void cDevice::DelPid(int Pid, ePidType PidType)
00518 {
00519   if (Pid || PidType == ptPcr) {
00520      int n = -1;
00521      if (PidType == ptPcr)
00522         n = PidType; // PPID always has to be explicit
00523      else {
00524         for (int i = 0; i < MAXPIDHANDLES; i++) {
00525             if (pidHandles[i].pid == Pid) {
00526                n = i;
00527                break;
00528                }
00529             }
00530         }
00531      if (n >= 0 && pidHandles[n].used) {
00532         PRINTPIDS("D");
00533         if (--pidHandles[n].used < 2) {
00534            SetPid(&pidHandles[n], n, false);
00535            if (pidHandles[n].used == 0) {
00536               pidHandles[n].handle = -1;
00537               pidHandles[n].pid = 0;
00538               if (camSlot)
00539                  camSlot->SetPid(Pid, false);
00540               }
00541            }
00542         PRINTPIDS("E");
00543         }
00544      }
00545 }
00546 
00547 bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
00548 {
00549   return false;
00550 }
00551 
00552 void cDevice::DelLivePids(void)
00553 {
00554   for (int i = ptAudio; i < ptOther; i++) {
00555       if (pidHandles[i].pid)
00556          DelPid(pidHandles[i].pid, ePidType(i));
00557       }
00558 }
00559 
00560 void cDevice::StartSectionHandler(void)
00561 {
00562   if (!sectionHandler) {
00563      sectionHandler = new cSectionHandler(this);
00564      AttachFilter(eitFilter = new cEitFilter);
00565      AttachFilter(patFilter = new cPatFilter);
00566      AttachFilter(sdtFilter = new cSdtFilter(patFilter));
00567      AttachFilter(nitFilter = new cNitFilter);
00568      }
00569 }
00570 
00571 void cDevice::StopSectionHandler(void)
00572 {
00573   if (sectionHandler) {
00574      delete nitFilter;
00575      delete sdtFilter;
00576      delete patFilter;
00577      delete eitFilter;
00578      delete sectionHandler;
00579      nitFilter = NULL;
00580      sdtFilter = NULL;
00581      patFilter = NULL;
00582      eitFilter = NULL;
00583      sectionHandler = NULL;
00584      }
00585 }
00586 
00587 int cDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
00588 {
00589   return -1;
00590 }
00591 
00592 void cDevice::CloseFilter(int Handle)
00593 {
00594   close(Handle);
00595 }
00596 
00597 void cDevice::AttachFilter(cFilter *Filter)
00598 {
00599   if (sectionHandler)
00600      sectionHandler->Attach(Filter);
00601 }
00602 
00603 void cDevice::Detach(cFilter *Filter)
00604 {
00605   if (sectionHandler)
00606      sectionHandler->Detach(Filter);
00607 }
00608 
00609 bool cDevice::ProvidesSource(int Source) const
00610 {
00611   return false;
00612 }
00613 
00614 bool cDevice::DeviceHooksProvidesTransponder(const cChannel *Channel) const
00615 {
00616   cDeviceHook *Hook = deviceHooks.First();
00617   while (Hook) {
00618         if (!Hook->DeviceProvidesTransponder(this, Channel))
00619            return false;
00620         Hook = deviceHooks.Next(Hook);
00621         }
00622   return true;
00623 }
00624 
00625 bool cDevice::ProvidesTransponder(const cChannel *Channel) const
00626 {
00627   return false;
00628 }
00629 
00630 bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const
00631 {
00632   for (int i = 0; i < numDevices; i++) {
00633       if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
00634          return false;
00635       }
00636   return true;
00637 }
00638 
00639 bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
00640 {
00641   return false;
00642 }
00643 
00644 bool cDevice::ProvidesEIT(void) const
00645 {
00646   return false;
00647 }
00648 
00649 int cDevice::NumProvidedSystems(void) const
00650 {
00651   return 0;
00652 }
00653 
00654 int cDevice::SignalStrength(void) const
00655 {
00656   return -1;
00657 }
00658 
00659 int cDevice::SignalQuality(void) const
00660 {
00661   return -1;
00662 }
00663 
00664 const cChannel *cDevice::GetCurrentlyTunedTransponder(void) const
00665 {
00666   return NULL;
00667 }
00668 
00669 bool cDevice::IsTunedToTransponder(const cChannel *Channel) const
00670 {
00671   return false;
00672 }
00673 
00674 bool cDevice::MaySwitchTransponder(const cChannel *Channel) const
00675 {
00676   return time(NULL) > occupiedTimeout && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid);
00677 }
00678 
00679 bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
00680 {
00681   if (LiveView) {
00682      isyslog("switching to channel %d", Channel->Number());
00683      cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
00684      }
00685   for (int i = 3; i--;) {
00686       switch (SetChannel(Channel, LiveView)) {
00687         case scrOk:           return true;
00688         case scrNotAvailable: Skins.Message(mtInfo, tr("Channel not available!"));
00689                               return false;
00690         case scrNoTransfer:   Skins.Message(mtError, tr("Can't start Transfer Mode!"));
00691                               return false;
00692         case scrFailed:       break; // loop will retry
00693         default:              esyslog("ERROR: invalid return value from SetChannel");
00694         }
00695       esyslog("retrying");
00696       }
00697   return false;
00698 }
00699 
00700 bool cDevice::SwitchChannel(int Direction)
00701 {
00702   bool result = false;
00703   Direction = sgn(Direction);
00704   if (Direction) {
00705      cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
00706      int n = CurrentChannel() + Direction;
00707      int first = n;
00708      cChannel *channel;
00709      while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
00710            // try only channels which are currently available
00711            if (GetDevice(channel, LIVEPRIORITY, true, true))
00712               break;
00713            n = channel->Number() + Direction;
00714            }
00715      if (channel) {
00716         int d = n - first;
00717         if (abs(d) == 1)
00718            dsyslog("skipped channel %d", first);
00719         else if (d)
00720            dsyslog("skipped channels %d..%d", first, n - sgn(d));
00721         if (PrimaryDevice()->SwitchChannel(channel, true))
00722            result = true;
00723         }
00724      else if (n != first)
00725         Skins.Message(mtError, tr("Channel not available!"));
00726      }
00727   return result;
00728 }
00729 
00730 eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
00731 {
00732   cStatus::MsgChannelSwitch(this, 0, LiveView);
00733 
00734   if (LiveView) {
00735      StopReplay();
00736      DELETENULL(liveSubtitle);
00737      DELETENULL(dvbSubtitleConverter);
00738      }
00739 
00740   cDevice *Device = (LiveView && IsPrimaryDevice()) ? GetDevice(Channel, LIVEPRIORITY, true) : this;
00741 
00742   bool NeedsTransferMode = Device != this;
00743 
00744   eSetChannelResult Result = scrOk;
00745 
00746   // If this DVB card can't receive this channel, let's see if we can
00747   // use the card that actually can receive it and transfer data from there:
00748 
00749   if (NeedsTransferMode) {
00750      if (Device && CanReplay()) {
00751         if (Device->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
00752            cControl::Launch(new cTransferControl(Device, Channel));
00753         else
00754            Result = scrNoTransfer;
00755         }
00756      else
00757         Result = scrNotAvailable;
00758      }
00759   else {
00760      Channels.Lock(false);
00761      // Stop section handling:
00762      if (sectionHandler) {
00763         sectionHandler->SetStatus(false);
00764         sectionHandler->SetChannel(NULL);
00765         }
00766      // Tell the camSlot about the channel switch and add all PIDs of this
00767      // channel to it, for possible later decryption:
00768      if (camSlot)
00769         camSlot->AddChannel(Channel);
00770      if (SetChannelDevice(Channel, LiveView)) {
00771         // Start section handling:
00772         if (sectionHandler) {
00773            sectionHandler->SetChannel(Channel);
00774            sectionHandler->SetStatus(true);
00775            }
00776         // Start decrypting any PIDs that might have been set in SetChannelDevice():
00777         if (camSlot)
00778            camSlot->StartDecrypting();
00779         }
00780      else
00781         Result = scrFailed;
00782      Channels.Unlock();
00783      }
00784 
00785   if (Result == scrOk) {
00786      if (LiveView && IsPrimaryDevice()) {
00787         currentChannel = Channel->Number();
00788         // Set the available audio tracks:
00789         ClrAvailableTracks();
00790         for (int i = 0; i < MAXAPIDS; i++)
00791             SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
00792         if (Setup.UseDolbyDigital) {
00793            for (int i = 0; i < MAXDPIDS; i++)
00794                SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
00795            }
00796         for (int i = 0; i < MAXSPIDS; i++)
00797             SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
00798         if (!NeedsTransferMode)
00799            EnsureAudioTrack(true);
00800         EnsureSubtitleTrack();
00801         }
00802      cStatus::MsgChannelSwitch(this, Channel->Number(), LiveView); // only report status if channel switch successfull
00803      }
00804 
00805   return Result;
00806 }
00807 
00808 void cDevice::ForceTransferMode(void)
00809 {
00810   if (!cTransferControl::ReceiverDevice()) {
00811      cChannel *Channel = Channels.GetByNumber(CurrentChannel());
00812      if (Channel)
00813         SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
00814      }
00815 }
00816 
00817 int cDevice::Occupied(void) const
00818 {
00819   int Seconds = occupiedTimeout - time(NULL);
00820   return Seconds > 0 ? Seconds : 0;
00821 }
00822 
00823 void cDevice::SetOccupied(int Seconds)
00824 {
00825   if (Seconds >= 0)
00826      occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
00827 }
00828 
00829 bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
00830 {
00831   return false;
00832 }
00833 
00834 bool cDevice::HasLock(int TimeoutMs)
00835 {
00836   return true;
00837 }
00838 
00839 bool cDevice::HasProgramme(void)
00840 {
00841   return Replaying() || pidHandles[ptAudio].pid || pidHandles[ptVideo].pid;
00842 }
00843 
00844 int cDevice::GetAudioChannelDevice(void)
00845 {
00846   return 0;
00847 }
00848 
00849 void cDevice::SetAudioChannelDevice(int AudioChannel)
00850 {
00851 }
00852 
00853 void cDevice::SetVolumeDevice(int Volume)
00854 {
00855 }
00856 
00857 void cDevice::SetDigitalAudioDevice(bool On)
00858 {
00859 }
00860 
00861 void cDevice::SetAudioTrackDevice(eTrackType Type)
00862 {
00863 }
00864 
00865 void cDevice::SetSubtitleTrackDevice(eTrackType Type)
00866 {
00867 }
00868 
00869 bool cDevice::ToggleMute(void)
00870 {
00871   int OldVolume = volume;
00872   mute = !mute;
00873   //XXX why is it necessary to use different sequences???
00874   if (mute) {
00875      SetVolume(0, true);
00876      Audios.MuteAudio(mute); // Mute external audio after analog audio
00877      }
00878   else {
00879      Audios.MuteAudio(mute); // Enable external audio before analog audio
00880      SetVolume(OldVolume, true);
00881      }
00882   volume = OldVolume;
00883   return mute;
00884 }
00885 
00886 int cDevice::GetAudioChannel(void)
00887 {
00888   int c = GetAudioChannelDevice();
00889   return (0 <= c && c <= 2) ? c : 0;
00890 }
00891 
00892 void cDevice::SetAudioChannel(int AudioChannel)
00893 {
00894   if (0 <= AudioChannel && AudioChannel <= 2)
00895      SetAudioChannelDevice(AudioChannel);
00896 }
00897 
00898 void cDevice::SetVolume(int Volume, bool Absolute)
00899 {
00900   int OldVolume = volume;
00901   volume = constrain(Absolute ? Volume : volume + Volume, 0, MAXVOLUME);
00902   SetVolumeDevice(volume);
00903   Absolute |= mute;
00904   cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute);
00905   if (volume > 0) {
00906      mute = false;
00907      Audios.MuteAudio(mute);
00908      }
00909 }
00910 
00911 void cDevice::ClrAvailableTracks(bool DescriptionsOnly, bool IdsOnly)
00912 {
00913   if (DescriptionsOnly) {
00914      for (int i = ttNone; i < ttMaxTrackTypes; i++)
00915          *availableTracks[i].description = 0;
00916      }
00917   else {
00918      if (IdsOnly) {
00919         for (int i = ttNone; i < ttMaxTrackTypes; i++)
00920             availableTracks[i].id = 0;
00921         }
00922      else
00923         memset(availableTracks, 0, sizeof(availableTracks));
00924      pre_1_3_19_PrivateStream = 0;
00925      SetAudioChannel(0); // fall back to stereo
00926      currentAudioTrackMissingCount = 0;
00927      currentAudioTrack = ttNone;
00928      currentSubtitleTrack = ttNone;
00929      }
00930 }
00931 
00932 bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description)
00933 {
00934   eTrackType t = eTrackType(Type + Index);
00935   if (Type == ttAudio && IS_AUDIO_TRACK(t) ||
00936       Type == ttDolby && IS_DOLBY_TRACK(t) ||
00937       Type == ttSubtitle && IS_SUBTITLE_TRACK(t)) {
00938      if (Language)
00939         strn0cpy(availableTracks[t].language, Language, sizeof(availableTracks[t].language));
00940      if (Description)
00941         Utf8Strn0Cpy(availableTracks[t].description, Description, sizeof(availableTracks[t].description));
00942      if (Id) {
00943         availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking
00944         if (Type == ttAudio || Type == ttDolby) {
00945            int numAudioTracks = NumAudioTracks();
00946            if (!availableTracks[currentAudioTrack].id && numAudioTracks && currentAudioTrackMissingCount++ > numAudioTracks * 10)
00947               EnsureAudioTrack();
00948            else if (t == currentAudioTrack)
00949               currentAudioTrackMissingCount = 0;
00950            }
00951         else if (Type == ttSubtitle && autoSelectPreferredSubtitleLanguage)
00952            EnsureSubtitleTrack();
00953         }
00954      return true;
00955      }
00956   else
00957      esyslog("ERROR: SetAvailableTrack called with invalid Type/Index (%d/%d)", Type, Index);
00958   return false;
00959 }
00960 
00961 const tTrackId *cDevice::GetTrack(eTrackType Type)
00962 {
00963   return (ttNone < Type && Type < ttMaxTrackTypes) ? &availableTracks[Type] : NULL;
00964 }
00965 
00966 int cDevice::NumTracks(eTrackType FirstTrack, eTrackType LastTrack) const
00967 {
00968   int n = 0;
00969   for (int i = FirstTrack; i <= LastTrack; i++) {
00970       if (availableTracks[i].id)
00971          n++;
00972       }
00973   return n;
00974 }
00975 
00976 int cDevice::NumAudioTracks(void) const
00977 {
00978   return NumTracks(ttAudioFirst, ttDolbyLast);
00979 }
00980 
00981 int cDevice::NumSubtitleTracks(void) const
00982 {
00983   return NumTracks(ttSubtitleFirst, ttSubtitleLast);
00984 }
00985 
00986 bool cDevice::SetCurrentAudioTrack(eTrackType Type)
00987 {
00988   if (ttNone < Type && Type <= ttDolbyLast) {
00989      cMutexLock MutexLock(&mutexCurrentAudioTrack);
00990      if (IS_DOLBY_TRACK(Type))
00991         SetDigitalAudioDevice(true);
00992      currentAudioTrack = Type;
00993      if (player)
00994         player->SetAudioTrack(currentAudioTrack, GetTrack(currentAudioTrack));
00995      else
00996         SetAudioTrackDevice(currentAudioTrack);
00997      if (IS_AUDIO_TRACK(Type))
00998         SetDigitalAudioDevice(false);
00999      return true;
01000      }
01001   return false;
01002 }
01003 
01004 bool cDevice::SetCurrentSubtitleTrack(eTrackType Type, bool Manual)
01005 {
01006   if (Type == ttNone || IS_SUBTITLE_TRACK(Type)) {
01007      currentSubtitleTrack = Type;
01008      autoSelectPreferredSubtitleLanguage = !Manual;
01009      if (dvbSubtitleConverter)
01010         dvbSubtitleConverter->Reset();
01011      if (Type == ttNone && dvbSubtitleConverter) {
01012         cMutexLock MutexLock(&mutexCurrentSubtitleTrack);
01013         DELETENULL(dvbSubtitleConverter);
01014         }
01015      DELETENULL(liveSubtitle);
01016      if (player)
01017         player->SetSubtitleTrack(currentSubtitleTrack, GetTrack(currentSubtitleTrack));
01018      else
01019         SetSubtitleTrackDevice(currentSubtitleTrack);
01020      if (currentSubtitleTrack != ttNone && !Replaying() && !Transferring()) {
01021         const tTrackId *TrackId = GetTrack(currentSubtitleTrack);
01022         if (TrackId && TrackId->id) {
01023            liveSubtitle = new cLiveSubtitle(TrackId->id);
01024            AttachReceiver(liveSubtitle);
01025            }
01026         }
01027      return true;
01028      }
01029   return false;
01030 }
01031 
01032 void cDevice::EnsureAudioTrack(bool Force)
01033 {
01034   if (Force || !availableTracks[currentAudioTrack].id) {
01035      eTrackType PreferredTrack = ttAudioFirst;
01036      int PreferredAudioChannel = 0;
01037      int LanguagePreference = -1;
01038      int StartCheck = Setup.CurrentDolby ? ttDolbyFirst : ttAudioFirst;
01039      int EndCheck = ttDolbyLast;
01040      for (int i = StartCheck; i <= EndCheck; i++) {
01041          const tTrackId *TrackId = GetTrack(eTrackType(i));
01042          int pos = 0;
01043          if (TrackId && TrackId->id && I18nIsPreferredLanguage(Setup.AudioLanguages, TrackId->language, LanguagePreference, &pos)) {
01044             PreferredTrack = eTrackType(i);
01045             PreferredAudioChannel = pos;
01046             }
01047          if (Setup.CurrentDolby && i == ttDolbyLast) {
01048             i = ttAudioFirst - 1;
01049             EndCheck = ttAudioLast;
01050             }
01051          }
01052      // Make sure we're set to an available audio track:
01053      const tTrackId *Track = GetTrack(GetCurrentAudioTrack());
01054      if (Force || !Track || !Track->id || PreferredTrack != GetCurrentAudioTrack()) {
01055         if (!Force) // only log this for automatic changes
01056            dsyslog("setting audio track to %d (%d)", PreferredTrack, PreferredAudioChannel);
01057         SetCurrentAudioTrack(PreferredTrack);
01058         SetAudioChannel(PreferredAudioChannel);
01059         }
01060      }
01061 }
01062 
01063 void cDevice::EnsureSubtitleTrack(void)
01064 {
01065   if (Setup.DisplaySubtitles) {
01066      eTrackType PreferredTrack = ttNone;
01067      int LanguagePreference = INT_MAX; // higher than the maximum possible value
01068      for (int i = ttSubtitleFirst; i <= ttSubtitleLast; i++) {
01069          const tTrackId *TrackId = GetTrack(eTrackType(i));
01070          if (TrackId && TrackId->id && (I18nIsPreferredLanguage(Setup.SubtitleLanguages, TrackId->language, LanguagePreference) ||
01071             (i == ttSubtitleFirst + 8 && !*TrackId->language && LanguagePreference == INT_MAX))) // compatibility mode for old subtitles plugin
01072             PreferredTrack = eTrackType(i);
01073          }
01074      // Make sure we're set to an available subtitle track:
01075      const tTrackId *Track = GetTrack(GetCurrentSubtitleTrack());
01076      if (!Track || !Track->id || PreferredTrack != GetCurrentSubtitleTrack())
01077         SetCurrentSubtitleTrack(PreferredTrack);
01078      }
01079   else
01080      SetCurrentSubtitleTrack(ttNone);
01081 }
01082 
01083 bool cDevice::CanReplay(void) const
01084 {
01085   return HasDecoder();
01086 }
01087 
01088 bool cDevice::SetPlayMode(ePlayMode PlayMode)
01089 {
01090   return false;
01091 }
01092 
01093 int64_t cDevice::GetSTC(void)
01094 {
01095   return -1;
01096 }
01097 
01098 void cDevice::TrickSpeed(int Speed)
01099 {
01100 }
01101 
01102 void cDevice::Clear(void)
01103 {
01104   Audios.ClearAudio();
01105   if (dvbSubtitleConverter)
01106      dvbSubtitleConverter->Reset();
01107 }
01108 
01109 void cDevice::Play(void)
01110 {
01111   Audios.MuteAudio(mute);
01112   if (dvbSubtitleConverter)
01113      dvbSubtitleConverter->Freeze(false);
01114 }
01115 
01116 void cDevice::Freeze(void)
01117 {
01118   Audios.MuteAudio(true);
01119   if (dvbSubtitleConverter)
01120      dvbSubtitleConverter->Freeze(true);
01121 }
01122 
01123 void cDevice::Mute(void)
01124 {
01125   Audios.MuteAudio(true);
01126 }
01127 
01128 void cDevice::StillPicture(const uchar *Data, int Length)
01129 {
01130   if (Data[0] == 0x47) {
01131      // TS data
01132      cTsToPes TsToPes;
01133      uchar *buf = NULL;
01134      int Size = 0;
01135      while (Length >= TS_SIZE) {
01136            int Pid = TsPid(Data);
01137            if (Pid == 0)
01138               patPmtParser.ParsePat(Data, TS_SIZE);
01139            else if (Pid == patPmtParser.PmtPid())
01140               patPmtParser.ParsePmt(Data, TS_SIZE);
01141            else if (Pid == patPmtParser.Vpid()) {
01142               if (TsPayloadStart(Data)) {
01143                  int l;
01144                  while (const uchar *p = TsToPes.GetPes(l)) {
01145                        int Offset = Size;
01146                        int NewSize = Size + l;
01147                        if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) {
01148                           Size = NewSize;
01149                           buf = NewBuffer;
01150                           memcpy(buf + Offset, p, l);
01151                           }
01152                        else {
01153                           LOG_ERROR_STR("out of memory");
01154                           free(buf);
01155                           return;
01156                           }
01157                        }
01158                  TsToPes.Reset();
01159                  }
01160               TsToPes.PutTs(Data, TS_SIZE);
01161               }
01162            Length -= TS_SIZE;
01163            Data += TS_SIZE;
01164            }
01165      int l;
01166      while (const uchar *p = TsToPes.GetPes(l)) {
01167            int Offset = Size;
01168            int NewSize = Size + l;
01169            if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) {
01170               Size = NewSize;
01171               buf = NewBuffer;
01172               memcpy(buf + Offset, p, l);
01173               }
01174            else {
01175               esyslog("ERROR: out of memory");
01176               free(buf);
01177               return;
01178               }
01179            }
01180      StillPicture(buf, Size);
01181      free(buf);
01182      }
01183 }
01184 
01185 bool cDevice::Replaying(void) const
01186 {
01187   return player != NULL;
01188 }
01189 
01190 bool cDevice::Transferring(void) const
01191 {
01192   return ActualDevice() != PrimaryDevice();
01193 }
01194 
01195 bool cDevice::AttachPlayer(cPlayer *Player)
01196 {
01197   if (CanReplay()) {
01198      if (player)
01199         Detach(player);
01200      DELETENULL(liveSubtitle);
01201      DELETENULL(dvbSubtitleConverter);
01202      patPmtParser.Reset();
01203      player = Player;
01204      if (!Transferring())
01205         ClrAvailableTracks(false, true);
01206      SetPlayMode(player->playMode);
01207      player->device = this;
01208      player->Activate(true);
01209      return true;
01210      }
01211   return false;
01212 }
01213 
01214 void cDevice::Detach(cPlayer *Player)
01215 {
01216   if (Player && player == Player) {
01217      cPlayer *p = player;
01218      player = NULL; // avoids recursive calls to Detach()
01219      p->Activate(false);
01220      p->device = NULL;
01221      cMutexLock MutexLock(&mutexCurrentSubtitleTrack);
01222      delete dvbSubtitleConverter;
01223      dvbSubtitleConverter = NULL;
01224      SetPlayMode(pmNone);
01225      SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
01226      PlayTs(NULL, 0);
01227      patPmtParser.Reset();
01228      Audios.ClearAudio();
01229      isPlayingVideo = false;
01230      }
01231 }
01232 
01233 void cDevice::StopReplay(void)
01234 {
01235   if (player) {
01236      Detach(player);
01237      if (IsPrimaryDevice())
01238         cControl::Shutdown();
01239      }
01240 }
01241 
01242 bool cDevice::Poll(cPoller &Poller, int TimeoutMs)
01243 {
01244   return false;
01245 }
01246 
01247 bool cDevice::Flush(int TimeoutMs)
01248 {
01249   return true;
01250 }
01251 
01252 int cDevice::PlayVideo(const uchar *Data, int Length)
01253 {
01254   return -1;
01255 }
01256 
01257 int cDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
01258 {
01259   return -1;
01260 }
01261 
01262 int cDevice::PlaySubtitle(const uchar *Data, int Length)
01263 {
01264   if (!dvbSubtitleConverter)
01265      dvbSubtitleConverter = new cDvbSubtitleConverter;
01266   return dvbSubtitleConverter->ConvertFragments(Data, Length);
01267 }
01268 
01269 int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly)
01270 {
01271   cMutexLock MutexLock(&mutexCurrentAudioTrack);
01272   bool FirstLoop = true;
01273   uchar c = Data[3];
01274   const uchar *Start = Data;
01275   const uchar *End = Start + Length;
01276   while (Start < End) {
01277         int d = End - Start;
01278         int w = d;
01279         switch (c) {
01280           case 0xBE:          // padding stream, needed for MPEG1
01281           case 0xE0 ... 0xEF: // video
01282                isPlayingVideo = true;
01283                w = PlayVideo(Start, d);
01284                break;
01285           case 0xC0 ... 0xDF: // audio
01286                SetAvailableTrack(ttAudio, c - 0xC0, c);
01287                if ((!VideoOnly || HasIBPTrickSpeed()) && c == availableTracks[currentAudioTrack].id) {
01288                   w = PlayAudio(Start, d, c);
01289                   if (FirstLoop)
01290                      Audios.PlayAudio(Data, Length, c);
01291                   }
01292                break;
01293           case 0xBD: { // private stream 1
01294                // EBU Teletext data, ETSI EN 300 472
01295                // if PES data header length = 24 and data_identifier = 0x10..0x1F (EBU Data)
01296                if (Data[8] == 0x24 && Data[45] >= 0x10 && Data[45] < 0x20) {
01297                   cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uint8_t*)Data, Length);
01298                   break;
01299                   }
01300 
01301                int PayloadOffset = Data[8] + 9;
01302 
01303                // Compatibility mode for old subtitles plugin:
01304                if ((Data[7] & 0x01) && (Data[PayloadOffset - 3] & 0x81) == 0x01 && Data[PayloadOffset - 2] == 0x81)
01305                   PayloadOffset--;
01306 
01307                uchar SubStreamId = Data[PayloadOffset];
01308                uchar SubStreamType = SubStreamId & 0xF0;
01309                uchar SubStreamIndex = SubStreamId & 0x1F;
01310 
01311                // Compatibility mode for old VDR recordings, where 0xBD was only AC3:
01312 pre_1_3_19_PrivateStreamDetected:
01313                if (pre_1_3_19_PrivateStream > MIN_PRE_1_3_19_PRIVATESTREAM) {
01314                   SubStreamId = c;
01315                   SubStreamType = 0x80;
01316                   SubStreamIndex = 0;
01317                   }
01318                else if (pre_1_3_19_PrivateStream)
01319                   pre_1_3_19_PrivateStream--; // every known PS1 packet counts down towards 0 to recover from glitches...
01320                switch (SubStreamType) {
01321                  case 0x20: // SPU
01322                  case 0x30: // SPU
01323                       SetAvailableTrack(ttSubtitle, SubStreamIndex, SubStreamId);
01324                       if ((!VideoOnly || HasIBPTrickSpeed()) && currentSubtitleTrack != ttNone && SubStreamId == availableTracks[currentSubtitleTrack].id)
01325                          w = PlaySubtitle(Start, d);
01326                       break;
01327                  case 0x80: // AC3 & DTS
01328                       if (Setup.UseDolbyDigital) {
01329                          SetAvailableTrack(ttDolby, SubStreamIndex, SubStreamId);
01330                          if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) {
01331                             w = PlayAudio(Start, d, SubStreamId);
01332                             if (FirstLoop)
01333                                Audios.PlayAudio(Data, Length, SubStreamId);
01334                             }
01335                          }
01336                       break;
01337                  case 0xA0: // LPCM
01338                       SetAvailableTrack(ttAudio, SubStreamIndex, SubStreamId);
01339                       if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) {
01340                          w = PlayAudio(Start, d, SubStreamId);
01341                          if (FirstLoop)
01342                             Audios.PlayAudio(Data, Length, SubStreamId);
01343                          }
01344                       break;
01345                  default:
01346                       // Compatibility mode for old VDR recordings, where 0xBD was only AC3:
01347                       if (pre_1_3_19_PrivateStream <= MIN_PRE_1_3_19_PRIVATESTREAM) {
01348                          dsyslog("unknown PS1 packet, substream id = %02X (counter is at %d)", SubStreamId, pre_1_3_19_PrivateStream);
01349                          pre_1_3_19_PrivateStream += 2; // ...and every unknown PS1 packet counts up (the very first one counts twice, but that's ok)
01350                          if (pre_1_3_19_PrivateStream > MIN_PRE_1_3_19_PRIVATESTREAM) {
01351                             dsyslog("switching to pre 1.3.19 Dolby Digital compatibility mode - substream id = %02X", SubStreamId);
01352                             ClrAvailableTracks();
01353                             pre_1_3_19_PrivateStream = MIN_PRE_1_3_19_PRIVATESTREAM + 1;
01354                             goto pre_1_3_19_PrivateStreamDetected;
01355                             }
01356                          }
01357                  }
01358                }
01359                break;
01360           default:
01361                ;//esyslog("ERROR: unexpected packet id %02X", c);
01362           }
01363         if (w > 0)
01364            Start += w;
01365         else {
01366            if (Start != Data)
01367               esyslog("ERROR: incomplete PES packet write!");
01368            return Start == Data ? w : Start - Data;
01369            }
01370         FirstLoop = false;
01371         }
01372   return Length;
01373 }
01374 
01375 int cDevice::PlayPes(const uchar *Data, int Length, bool VideoOnly)
01376 {
01377   if (!Data) {
01378      if (dvbSubtitleConverter)
01379         dvbSubtitleConverter->Reset();
01380      return 0;
01381      }
01382   int i = 0;
01383   while (i <= Length - 6) {
01384         if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
01385            int l = PesLength(Data + i);
01386            if (i + l > Length) {
01387               esyslog("ERROR: incomplete PES packet!");
01388               return Length;
01389               }
01390            int w = PlayPesPacket(Data + i, l, VideoOnly);
01391            if (w > 0)
01392               i += l;
01393            else
01394               return i == 0 ? w : i;
01395            }
01396         else
01397            i++;
01398         }
01399   if (i < Length)
01400      esyslog("ERROR: leftover PES data!");
01401   return Length;
01402 }
01403 
01404 int cDevice::PlayTsVideo(const uchar *Data, int Length)
01405 {
01406   // Video PES has no explicit length, so we can only determine the end of
01407   // a PES packet when the next TS packet that starts a payload comes in:
01408   if (TsPayloadStart(Data)) {
01409      int l;
01410      while (const uchar *p = tsToPesVideo.GetPes(l)) {
01411            int w = PlayVideo(p, l);
01412            if (w <= 0) {
01413               tsToPesVideo.SetRepeatLast();
01414               return w;
01415               }
01416            }
01417      tsToPesVideo.Reset();
01418      }
01419   tsToPesVideo.PutTs(Data, Length);
01420   return Length;
01421 }
01422 
01423 int cDevice::PlayTsAudio(const uchar *Data, int Length)
01424 {
01425   // Audio PES always has an explicit length and consists of single packets:
01426   int l;
01427   if (const uchar *p = tsToPesAudio.GetPes(l)) {
01428      int w = PlayAudio(p, l, p[3]);
01429      if (w <= 0) {
01430         tsToPesAudio.SetRepeatLast();
01431         return w;
01432         }
01433      tsToPesAudio.Reset();
01434      }
01435   tsToPesAudio.PutTs(Data, Length);
01436   return Length;
01437 }
01438 
01439 int cDevice::PlayTsSubtitle(const uchar *Data, int Length)
01440 {
01441   if (!dvbSubtitleConverter)
01442      dvbSubtitleConverter = new cDvbSubtitleConverter;
01443   tsToPesSubtitle.PutTs(Data, Length);
01444   int l;
01445   if (const uchar *p = tsToPesSubtitle.GetPes(l)) {
01446      dvbSubtitleConverter->Convert(p, l);
01447      tsToPesSubtitle.Reset();
01448      }
01449   return Length;
01450 }
01451 
01452 //TODO detect and report continuity errors?
01453 int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
01454 {
01455   int Played = 0;
01456   if (Data == NULL) {
01457      tsToPesVideo.Reset();
01458      tsToPesAudio.Reset();
01459      tsToPesSubtitle.Reset();
01460      tsToPesTeletext.Reset();
01461      }
01462   else if (Length < TS_SIZE) {
01463      esyslog("ERROR: skipped %d bytes of TS fragment", Length);
01464      return Length;
01465      }
01466   else {
01467      cMutexLock MutexLock(&mutexCurrentAudioTrack);
01468      while (Length >= TS_SIZE) {
01469            if (Data[0] != TS_SYNC_BYTE) {
01470               int Skipped = 1;
01471               while (Skipped < Length && (Data[Skipped] != TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] != TS_SYNC_BYTE))
01472                     Skipped++;
01473               esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
01474               return Played + Skipped;
01475               }
01476            int Pid = TsPid(Data);
01477            if (TsHasPayload(Data)) { // silently ignore TS packets w/o payload
01478               int PayloadOffset = TsPayloadOffset(Data);
01479               if (PayloadOffset < TS_SIZE) {
01480                  if (Pid == 0)
01481                     patPmtParser.ParsePat(Data, TS_SIZE);
01482                  else if (Pid == patPmtParser.PmtPid())
01483                     patPmtParser.ParsePmt(Data, TS_SIZE);
01484                  else if (Pid == patPmtParser.Vpid()) {
01485                     isPlayingVideo = true;
01486                     int w = PlayTsVideo(Data, TS_SIZE);
01487                     if (w < 0)
01488                        return Played ? Played : w;
01489                     if (w == 0)
01490                        break;
01491                     }
01492                  else if (Pid == availableTracks[currentAudioTrack].id) {
01493                     if (!VideoOnly || HasIBPTrickSpeed()) {
01494                        int w = PlayTsAudio(Data, TS_SIZE);
01495                        if (w < 0)
01496                           return Played ? Played : w;
01497                        if (w == 0)
01498                           break;
01499                        Audios.PlayTsAudio(Data, TS_SIZE);
01500                        }
01501                     }
01502                  else if (Pid == availableTracks[currentSubtitleTrack].id) {
01503                     if (!VideoOnly || HasIBPTrickSpeed())
01504                        PlayTsSubtitle(Data, TS_SIZE);
01505                     }
01506                  else if (Pid == patPmtParser.Tpid()) {
01507                     if (!VideoOnly || HasIBPTrickSpeed()) {
01508                        int l;
01509                        tsToPesTeletext.PutTs(Data, Length);
01510                        if (const uchar *p = tsToPesTeletext.GetPes(l)) {
01511                           if ((l > 45) && (p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xbd) && (p[8] == 0x24) && (p[45] >= 0x10) && (p[45] < 0x20))
01512                              cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uchar *)p, l, false, patPmtParser.TeletextSubtitlePages(), patPmtParser.TotalTeletextSubtitlePages());
01513                           tsToPesTeletext.Reset();
01514                           }
01515                        }
01516                     }
01517                  }
01518               }
01519            else if (Pid == patPmtParser.Ppid()) {
01520               int w = PlayTsVideo(Data, TS_SIZE);
01521               if (w < 0)
01522                  return Played ? Played : w;
01523               if (w == 0)
01524                  break;
01525               }
01526            Played += TS_SIZE;
01527            Length -= TS_SIZE;
01528            Data += TS_SIZE;
01529            }
01530      }
01531   return Played;
01532 }
01533 
01534 int cDevice::Priority(void) const
01535 {
01536   int priority = IDLEPRIORITY;
01537   if (IsPrimaryDevice() && !Replaying() && ActualDevice() == PrimaryDevice())
01538      priority = TRANSFERPRIORITY; // we use the same value here, no matter whether it's actual Transfer Mode or real live viewing
01539   cMutexLock MutexLock(&mutexReceiver);
01540   for (int i = 0; i < MAXRECEIVERS; i++) {
01541       if (receiver[i])
01542          priority = max(receiver[i]->priority, priority);
01543       }
01544   return priority;
01545 }
01546 
01547 bool cDevice::Ready(void)
01548 {
01549   return true;
01550 }
01551 
01552 bool cDevice::Receiving(bool Dummy) const
01553 {
01554   cMutexLock MutexLock(&mutexReceiver);
01555   for (int i = 0; i < MAXRECEIVERS; i++) {
01556       if (receiver[i])
01557          return true;
01558       }
01559   return false;
01560 }
01561 
01562 #define TS_SCRAMBLING_TIMEOUT     3 // seconds to wait until a TS becomes unscrambled
01563 #define TS_SCRAMBLING_TIME_OK    10 // seconds before a Channel/CAM combination is marked as known to decrypt
01564 
01565 void cDevice::Action(void)
01566 {
01567   if (Running() && OpenDvr()) {
01568      while (Running()) {
01569            // Read data from the DVR device:
01570            uchar *b = NULL;
01571            if (GetTSPacket(b)) {
01572               if (b) {
01573                  int Pid = TsPid(b);
01574                  // Check whether the TS packets are scrambled:
01575                  bool DetachReceivers = false;
01576                  bool DescramblingOk = false;
01577                  int CamSlotNumber = 0;
01578                  if (startScrambleDetection) {
01579                     cCamSlot *cs = CamSlot();
01580                     CamSlotNumber = cs ? cs->SlotNumber() : 0;
01581                     if (CamSlotNumber) {
01582                        bool Scrambled = b[3] & TS_SCRAMBLING_CONTROL;
01583                        int t = time(NULL) - startScrambleDetection;
01584                        if (Scrambled) {
01585                           if (t > TS_SCRAMBLING_TIMEOUT)
01586                              DetachReceivers = true;
01587                           }
01588                        else if (t > TS_SCRAMBLING_TIME_OK) {
01589                           DescramblingOk = true;
01590                           startScrambleDetection = 0;
01591                           }
01592                        }
01593                     }
01594                  // Distribute the packet to all attached receivers:
01595                  Lock();
01596                  for (int i = 0; i < MAXRECEIVERS; i++) {
01597                      if (receiver[i] && receiver[i]->WantsPid(Pid)) {
01598                         if (DetachReceivers) {
01599                            ChannelCamRelations.SetChecked(receiver[i]->ChannelID(), CamSlotNumber);
01600                            Detach(receiver[i]);
01601                            }
01602                         else
01603                            receiver[i]->Receive(b, TS_SIZE);
01604                         if (DescramblingOk)
01605                            ChannelCamRelations.SetDecrypt(receiver[i]->ChannelID(), CamSlotNumber);
01606                         }
01607                      }
01608                  Unlock();
01609                  }
01610               }
01611            else
01612               break;
01613            }
01614      CloseDvr();
01615      }
01616 }
01617 
01618 bool cDevice::OpenDvr(void)
01619 {
01620   return false;
01621 }
01622 
01623 void cDevice::CloseDvr(void)
01624 {
01625 }
01626 
01627 bool cDevice::GetTSPacket(uchar *&Data)
01628 {
01629   return false;
01630 }
01631 
01632 bool cDevice::AttachReceiver(cReceiver *Receiver)
01633 {
01634   if (!Receiver)
01635      return false;
01636   if (Receiver->device == this)
01637      return true;
01638 // activate the following line if you need it - actually the driver should be fixed!
01639 //#define WAIT_FOR_TUNER_LOCK
01640 #ifdef WAIT_FOR_TUNER_LOCK
01641 #define TUNER_LOCK_TIMEOUT 5000 // ms
01642   if (!HasLock(TUNER_LOCK_TIMEOUT)) {
01643      esyslog("ERROR: device %d has no lock, can't attach receiver!", CardIndex() + 1);
01644      return false;
01645      }
01646 #endif
01647   cMutexLock MutexLock(&mutexReceiver);
01648   for (int i = 0; i < MAXRECEIVERS; i++) {
01649       if (!receiver[i]) {
01650          for (int n = 0; n < Receiver->numPids; n++) {
01651              if (!AddPid(Receiver->pids[n])) {
01652                 for ( ; n-- > 0; )
01653                     DelPid(Receiver->pids[n]);
01654                 return false;
01655                 }
01656              }
01657          Receiver->Activate(true);
01658          Lock();
01659          Receiver->device = this;
01660          receiver[i] = Receiver;
01661          Unlock();
01662          if (camSlot) {
01663             camSlot->StartDecrypting();
01664             startScrambleDetection = time(NULL);
01665             }
01666          Start();
01667          return true;
01668          }
01669       }
01670   esyslog("ERROR: no free receiver slot!");
01671   return false;
01672 }
01673 
01674 void cDevice::Detach(cReceiver *Receiver)
01675 {
01676   if (!Receiver || Receiver->device != this)
01677      return;
01678   bool receiversLeft = false;
01679   cMutexLock MutexLock(&mutexReceiver);
01680   for (int i = 0; i < MAXRECEIVERS; i++) {
01681       if (receiver[i] == Receiver) {
01682          Receiver->Activate(false);
01683          Lock();
01684          receiver[i] = NULL;
01685          Receiver->device = NULL;
01686          Unlock();
01687          for (int n = 0; n < Receiver->numPids; n++)
01688              DelPid(Receiver->pids[n]);
01689          }
01690       else if (receiver[i])
01691          receiversLeft = true;
01692       }
01693   if (camSlot)
01694      camSlot->StartDecrypting();
01695   if (!receiversLeft)
01696      Cancel(-1);
01697 }
01698 
01699 void cDevice::DetachAll(int Pid)
01700 {
01701   if (Pid) {
01702      cMutexLock MutexLock(&mutexReceiver);
01703      for (int i = 0; i < MAXRECEIVERS; i++) {
01704          cReceiver *Receiver = receiver[i];
01705          if (Receiver && Receiver->WantsPid(Pid))
01706             Detach(Receiver);
01707          }
01708      }
01709 }
01710 
01711 void cDevice::DetachAllReceivers(void)
01712 {
01713   cMutexLock MutexLock(&mutexReceiver);
01714   for (int i = 0; i < MAXRECEIVERS; i++)
01715       Detach(receiver[i]);
01716 }
01717 
01718 // --- cTSBuffer -------------------------------------------------------------
01719 
01720 cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
01721 {
01722   SetDescription("TS buffer on device %d", CardIndex);
01723   f = File;
01724   cardIndex = CardIndex;
01725   delivered = false;
01726   ringBuffer = new cRingBufferLinear(Size, TS_SIZE, true, "TS");
01727   ringBuffer->SetTimeouts(100, 100);
01728   Start();
01729 }
01730 
01731 cTSBuffer::~cTSBuffer()
01732 {
01733   Cancel(3);
01734   delete ringBuffer;
01735 }
01736 
01737 void cTSBuffer::Action(void)
01738 {
01739   if (ringBuffer) {
01740      bool firstRead = true;
01741      cPoller Poller(f);
01742      while (Running()) {
01743            if (firstRead || Poller.Poll(100)) {
01744               firstRead = false;
01745               int r = ringBuffer->Read(f);
01746               if (r < 0 && FATALERRNO) {
01747                  if (errno == EOVERFLOW)
01748                     esyslog("ERROR: driver buffer overflow on device %d", cardIndex);
01749                  else {
01750                     LOG_ERROR;
01751                     break;
01752                     }
01753                  }
01754               }
01755            }
01756      }
01757 }
01758 
01759 uchar *cTSBuffer::Get(void)
01760 {
01761   int Count = 0;
01762   if (delivered) {
01763      ringBuffer->Del(TS_SIZE);
01764      delivered = false;
01765      }
01766   uchar *p = ringBuffer->Get(Count);
01767   if (p && Count >= TS_SIZE) {
01768      if (*p != TS_SYNC_BYTE) {
01769         for (int i = 1; i < Count; i++) {
01770             if (p[i] == TS_SYNC_BYTE) {
01771                Count = i;
01772                break;
01773                }
01774             }
01775         ringBuffer->Del(Count);
01776         esyslog("ERROR: skipped %d bytes to sync on TS packet on device %d", Count, cardIndex);
01777         return NULL;
01778         }
01779      delivered = true;
01780      return p;
01781      }
01782   return NULL;
01783 }