vdr  2.7.6
device.c
Go to the documentation of this file.
1 /*
2  * device.c: The basic device interface
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: device.c 5.17 2025/04/18 09:48:11 kls Exp $
8  */
9 
10 #include "device.h"
11 #include <errno.h>
12 #include <math.h>
13 #include <sys/ioctl.h>
14 #include <sys/mman.h>
15 #include "audio.h"
16 #include "channels.h"
17 #include "i18n.h"
18 #include "player.h"
19 #include "receiver.h"
20 #include "status.h"
21 #include "transfer.h"
22 
23 // --- cLiveSubtitle ---------------------------------------------------------
24 
25 class cLiveSubtitle : public cReceiver {
26 protected:
27  virtual void Receive(const uchar *Data, int Length) override;
28 public:
29  cLiveSubtitle(int SPid);
30  virtual ~cLiveSubtitle() override;
31  };
32 
34 {
35  AddPid(SPid);
36 }
37 
39 {
41 }
42 
43 void cLiveSubtitle::Receive(const uchar *Data, int Length)
44 {
46  cDevice::PrimaryDevice()->PlayTs(Data, Length);
47 }
48 
49 // --- cDeviceHook -----------------------------------------------------------
50 
52 {
54 }
55 
56 bool cDeviceHook::DeviceProvidesTransponder(const cDevice *Device, const cChannel *Channel) const
57 {
58  return true;
59 }
60 
61 bool cDeviceHook::DeviceProvidesEIT(const cDevice *Device) const
62 {
63  return true;
64 }
65 
66 // --- cDevice ---------------------------------------------------------------
67 
68 // The minimum number of unknown PS1 packets to consider this a "pre 1.3.19 private stream":
69 #define MIN_PRE_1_3_19_PRIVATESTREAM 10
70 
71 int cDevice::numDevices = 0;
72 int cDevice::useDevice = 0;
78 
80 :patPmtParser(true)
81 {
83  dsyslog("new device number %d (card index %d)", numDevices + 1, CardIndex() + 1);
84 
85  SetDescription("device %d receiver", numDevices + 1);
86 
87  mute = false;
89 
90  sectionHandler = NULL;
91  eitFilter = NULL;
92  patFilter = NULL;
93  sdtFilter = NULL;
94  nitFilter = NULL;
95 
96  camSlot = NULL;
97 
98  occupiedFrom = 0;
99  occupiedTimeout = 0;
101 
102  player = NULL;
103  isPlayingVideo = false;
104  keepTracks = false; // used in ClrAvailableTracks()!
109  liveSubtitle = NULL;
110  dvbSubtitleConverter = NULL;
112 
113  for (int i = 0; i < MAXRECEIVERS; i++)
114  receiver[i] = NULL;
115 
116  if (numDevices < MAXDEVICES)
117  device[numDevices++] = this;
118  else
119  esyslog("ERROR: too many devices!");
120 }
121 
123 {
124  Detach(player);
126  delete liveSubtitle;
127  delete dvbSubtitleConverter;
128  if (this == primaryDevice)
129  primaryDevice = NULL;
130  Cancel(3);
131 }
132 
134 {
135  for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
136  bool ready = true;
137  for (int i = 0; i < numDevices; i++) {
138  if (device[i] && !device[i]->Ready()) {
139  ready = false;
140  cCondWait::SleepMs(100);
141  }
142  }
143  if (ready)
144  return true;
145  }
146  return false;
147 }
148 
150 {
151  if (n < MAXDEVICES)
152  useDevice |= (1 << n);
153 }
154 
156 {
157  if (n > 0) {
158  nextCardIndex += n;
159  if (nextCardIndex >= MAXDEVICES)
160  esyslog("ERROR: nextCardIndex too big (%d)", nextCardIndex);
161  }
162  else if (n < 0)
163  esyslog("ERROR: invalid value in nextCardIndex(%d)", n);
164  return nextCardIndex;
165 }
166 
167 int cDevice::DeviceNumber(void) const
168 {
169  for (int i = 0; i < numDevices; i++) {
170  if (device[i] == this)
171  return i;
172  }
173  return -1;
174 }
175 
177 {
178  return "";
179 }
180 
182 {
183  return "";
184 }
185 
187 {
188  if (!On) {
191  }
192 }
193 
195 {
196  n--;
197  if (0 <= n && n < numDevices && device[n]) {
198  isyslog("setting primary device to %d", n + 1);
199  if (primaryDevice)
201  primaryDevice = device[n];
205  Setup.PrimaryDVB = n + 1;
206  return true;
207  }
208  esyslog("ERROR: invalid primary device number: %d", n + 1);
209  return false;
210 }
211 
212 bool cDevice::HasDecoder(void) const
213 {
214  return false;
215 }
216 
218 {
219  return NULL;
220 }
221 
223 {
225  if (!d)
226  d = PrimaryDevice();
227  return d;
228 }
229 
231 {
232  return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
233 }
234 
235 static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device)
236 {
237  int MaxNumProvidedSystems = (1 << AvailableBits) - 1;
238  int NumProvidedSystems = Device->NumProvidedSystems();
239  if (NumProvidedSystems > MaxNumProvidedSystems) {
240  esyslog("ERROR: device %d supports %d modulation systems but cDevice::GetDevice() currently only supports %d delivery systems which should be fixed", Device->DeviceNumber() + 1, NumProvidedSystems, MaxNumProvidedSystems);
241  NumProvidedSystems = MaxNumProvidedSystems;
242  }
243  else if (NumProvidedSystems <= 0) {
244  esyslog("ERROR: device %d reported an invalid number (%d) of supported delivery systems - assuming 1", Device->DeviceNumber() + 1, NumProvidedSystems);
245  NumProvidedSystems = 1;
246  }
247  return NumProvidedSystems;
248 }
249 
250 cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool Query)
251 {
252  // Collect the current priorities of all CAM slots that can decrypt the channel:
253  int NumCamSlots = CamSlots.Count();
254  int SlotPriority[NumCamSlots + 1]; // +1 to avoid a zero sized array in case there are no CAM slots
255  int NumUsableSlots = 0;
256  bool InternalCamNeeded = false;
257  if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
259  SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used
260  if (CamSlot->ModuleStatus() == msReady) {
261  if (CamSlot->ProvidesCa(Channel->Caids())) {
263  SlotPriority[CamSlot->Index()] = CamSlot->MtdActive() ? IDLEPRIORITY : CamSlot->Priority(); // we don't need to take the priority into account here for MTD CAM slots, because they can be used with several devices in parallel
264  NumUsableSlots++;
265  }
266  }
267  }
268  }
269  if (!NumUsableSlots)
270  InternalCamNeeded = true; // no CAM is able to decrypt this channel
271  }
272 
273  bool NeedsDetachReceivers = false;
274  cDevice *d = NULL;
275  cCamSlot *s = NULL;
276 
277  uint32_t Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
278  for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) {
279  if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY)
280  continue; // there is no CAM available in this slot
281  for (int i = 0; i < numDevices; i++) {
282  if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != device[i]->DeviceNumber() + 1)
283  continue; // a specific card was requested, but not this one
284  bool HasInternalCam = device[i]->HasInternalCam();
285  if (InternalCamNeeded && !HasInternalCam)
286  continue; // no CAM is able to decrypt this channel and the device uses vdr handled CAMs
287  if (NumUsableSlots && !HasInternalCam && !CamSlots.Get(j)->Assign(device[i], true))
288  continue; // CAM slot can't be used with this device
289  bool ndr = false;
290  bool TunedToTransponder = device[i]->IsTunedToTransponder(Channel);
291  if (TunedToTransponder || device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job
292  bool OccupiedOtherTransponder = !TunedToTransponder && device[i]->Occupied();
293  if (OccupiedOtherTransponder)
294  ndr = true;
295  if (NumUsableSlots && !HasInternalCam) {
296  if (cCamSlot *csi = device[i]->CamSlot()) {
297  cCamSlot *csj = CamSlots.Get(j);
298  if ((csj->MtdActive() ? csi->MasterSlot() : csi) != csj)
299  ndr = true; // using a different CAM slot requires detaching receivers
300  }
301  }
302  // Put together an integer number that reflects the "impact" using
303  // this device would have on the overall system. Each condition is represented
304  // by one bit in the number (or several bits, if the condition is actually
305  // a numeric value). The sequence in which the conditions are listed corresponds
306  // to their individual severity, where the one listed first will make the most
307  // difference, because it results in the most significant bit of the result.
308  uint32_t imp = 0;
309  imp <<= 1; imp |= (LiveView && NumUsableSlots && !HasInternalCam) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlots.Get(j)->MasterSlotNumber()) || ndr : 0; // prefer CAMs that are known to decrypt this channel for live viewing, if we don't need to detach existing receivers
310  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
311  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
312  imp <<= 1; imp |= device[i]->Receiving() || OccupiedOtherTransponder; // avoid devices that are receiving
313  imp <<= 5; imp |= GetClippedNumProvidedSystems(5, device[i]) - 1; // avoid cards which support multiple delivery systems
314  imp <<= 8; imp |= device[i]->Priority() - IDLEPRIORITY; // use the device with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
315  imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device
316  imp <<= 8; imp |= ((NumUsableSlots && !HasInternalCam) ? SlotPriority[j] : IDLEPRIORITY) - IDLEPRIORITY;// use the CAM slot with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
317  imp <<= 1; imp |= ndr; // avoid devices if we need to detach existing receivers
318  imp <<= 1; imp |= (NumUsableSlots || InternalCamNeeded) ? 0 : device[i]->HasCi(); // avoid cards with Common Interface for FTA channels
319  imp <<= 1; imp |= device[i]->AvoidRecording(); // avoid SD full featured cards
320  imp <<= 1; imp |= (NumUsableSlots && !HasInternalCam) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlots.Get(j)->MasterSlotNumber()) : 0; // prefer CAMs that are known to decrypt this channel
321  imp <<= 1; imp |= device[i]->IsPrimaryDevice(); // avoid the primary device
322  if (imp < Impact) {
323  // This device has less impact than any previous one, so we take it.
324  Impact = imp;
325  d = device[i];
326  NeedsDetachReceivers = ndr;
327  if (NumUsableSlots && !HasInternalCam)
328  s = CamSlots.Get(j);
329  }
330  //dsyslog("device %d provides channel %d prio %d ndr %d imp %.8X", device[i]->DeviceNumber() + 1, Channel->Number(), Priority, ndr, imp);
331  }
332  }
333  if (!NumUsableSlots)
334  break; // no CAM necessary, so just one loop over the devices
335  }
336  if (d) {
337  if (!Query && NeedsDetachReceivers)
338  d->DetachAllReceivers();
339  if (s) {
340  // Some of the following statements could probably be combined, but let's keep them
341  // explicit so we can clearly see every single aspect of the decisions made here.
342  if (d->CamSlot()) {
343  if (s->MtdActive()) {
344  if (s == d->CamSlot()->MasterSlot()) {
345  // device d already has a proper CAM slot, so nothing to do here
346  }
347  else {
348  // device d has a CAM slot, but it's not the right one
349  if (!Query) {
350  d->CamSlot()->Assign(NULL);
351  s = s->MtdSpawn();
352  s->Assign(d);
353  }
354  }
355  }
356  else {
357  if (s->Device()) {
358  if (s->Device() != d) {
359  // CAM slot s is currently assigned to a different device than d
360  if (Priority > s->Priority()) {
361  if (!Query) {
362  d->CamSlot()->Assign(NULL);
363  s->Assign(d);
364  }
365  }
366  else {
367  d = NULL;
368  s = NULL;
369  }
370  }
371  else {
372  // device d already has a proper CAM slot, so nothing to do here
373  }
374  }
375  else {
376  if (s != d->CamSlot()) {
377  // device d has a CAM slot, but it's not the right one
378  if (!Query) {
379  d->CamSlot()->Assign(NULL);
380  s->Assign(d);
381  }
382  }
383  else {
384  // device d already has a proper CAM slot, so nothing to do here
385  }
386  }
387  }
388  }
389  else {
390  // device d has no CAM slot, ...
391  if (s->MtdActive()) {
392  // ... so we assign s with MTD support
393  if (!Query) {
394  s = s->MtdSpawn();
395  s->Assign(d);
396  }
397  }
398  else {
399  // CAM slot s has no MTD support ...
400  if (s->Device()) {
401  // ... but it is assigned to a different device, so we reassign it to d
402  if (Priority > s->Priority()) {
403  if (!Query) {
404  s->Device()->DetachAllReceivers();
405  s->Assign(d);
406  }
407  }
408  else {
409  d = NULL;
410  s = NULL;
411  }
412  }
413  else {
414  // ... and is not assigned to any device, so we just assign it to d
415  if (!Query)
416  s->Assign(d);
417  }
418  }
419  }
420  }
421  else if (d->CamSlot() && !d->CamSlot()->IsDecrypting())
422  d->CamSlot()->Assign(NULL);
423  }
424  return d;
425 }
426 
427 cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority)
428 {
429  cDevice *Device = NULL;
430  for (int i = 0; i < cDevice::NumDevices(); i++) {
431  if (cDevice *d = cDevice::GetDevice(i)) {
432  if (d->IsTunedToTransponder(Channel))
433  return d; // if any device is tuned to the transponder, we're done
434  if (d->ProvidesTransponder(Channel)) {
435  if (d->MaySwitchTransponder(Channel))
436  return d; // this device may switch to the transponder without disturbing any receiver or live view
437  else if (!d->Occupied(Priority) && !d->IsBonded() && d->Priority(true) < LIVEPRIORITY) { // MaySwitchTransponder() implicitly calls Occupied()
438  // we select only devices with priority < LIVEPRIORITY, so device can be switched without impact on recordings or live viewing
439  if (d->Priority() < Priority && (!Device || d->Priority() < Device->Priority()))
440  Device = d; // use this one only if no other with less impact can be found
441  }
442  }
443  }
444  }
445  return Device;
446 }
447 
449 {
450  if (camSlot && !camSlot->IsDecrypting() && !camSlot->IsActivating())
451  camSlot->Assign(NULL);
452 }
453 
454 bool cDevice::HasCi(void)
455 {
456  return false;
457 }
458 
460 {
461  LOCK_THREAD;
462  camSlot = CamSlot;
463 }
464 
466 {
467  deviceHooks.Clear();
468  for (int i = 0; i < numDevices; i++) {
469  delete device[i];
470  device[i] = NULL;
471  }
472 }
473 
474 uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
475 {
476  return NULL;
477 }
478 
479 bool cDevice::GrabImageFile(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
480 {
481  int result = 0;
482  int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE);
483  if (fd >= 0) {
484  int ImageSize;
485  uchar *Image = GrabImage(ImageSize, Jpeg, Quality, SizeX, SizeY);
486  if (Image) {
487  if (safe_write(fd, Image, ImageSize) == ImageSize)
488  isyslog("grabbed image to %s", FileName);
489  else {
490  LOG_ERROR_STR(FileName);
491  result |= 1;
492  }
493  free(Image);
494  }
495  else
496  result |= 1;
497  close(fd);
498  }
499  else {
500  LOG_ERROR_STR(FileName);
501  result |= 1;
502  }
503  return result == 0;
504 }
505 
507 {
508  cSpuDecoder *spuDecoder = GetSpuDecoder();
509  if (spuDecoder) {
510  if (Setup.VideoFormat)
512  else {
513  switch (VideoDisplayFormat) {
514  case vdfPanAndScan:
516  break;
517  case vdfLetterBox:
519  break;
520  case vdfCenterCutOut:
522  break;
523  default: esyslog("ERROR: invalid value for VideoDisplayFormat '%d'", VideoDisplayFormat);
524  }
525  }
526  }
527 }
528 
529 void cDevice::SetVideoFormat(bool VideoFormat16_9)
530 {
531 }
532 
533 void cDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
534 {
535  Width = 0;
536  Height = 0;
537  VideoAspect = 1.0;
538 }
539 
540 void cDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
541 {
542  Width = 720;
543  Height = 480;
544  PixelAspect = 1.0;
545 }
546 
547 //#define PRINTPIDS(s) { char b[500]; char *q = b; q += sprintf(q, "%d %s ", DeviceNumber() + 1, 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); }
548 #define PRINTPIDS(s)
549 
550 bool cDevice::HasPid(int Pid) const
551 {
552  cMutexLock MutexLock(&mutexPids);
553  for (int i = 0; i < MAXPIDHANDLES; i++) {
554  if (pidHandles[i].pid == Pid)
555  return true;
556  }
557  return false;
558 }
559 
560 bool cDevice::AddPid(int Pid, ePidType PidType, int StreamType)
561 {
562  cMutexLock MutexLock(&mutexPids);
563  if (Pid || PidType == ptPcr) {
564  int n = -1;
565  int a = -1;
566  if (PidType != ptPcr) { // PPID always has to be explicit
567  for (int i = 0; i < MAXPIDHANDLES; i++) {
568  if (i != ptPcr) {
569  if (pidHandles[i].pid == Pid)
570  n = i;
571  else if (a < 0 && i >= ptOther && !pidHandles[i].used)
572  a = i;
573  }
574  }
575  }
576  if (n >= 0) {
577  // The Pid is already in use
578  if (++pidHandles[n].used == 2 && n <= ptTeletext) {
579  // It's a special PID that may have to be switched into "tap" mode
580  PRINTPIDS("A");
581  if (!SetPid(&pidHandles[n], n, true)) {
582  esyslog("ERROR: can't set PID %d on device %d", Pid, DeviceNumber() + 1);
583  if (PidType <= ptTeletext)
584  DetachAll(Pid);
585  DelPid(Pid, PidType);
586  return false;
587  }
588  if (camSlot)
589  camSlot->SetPid(Pid, true);
590  }
591  PRINTPIDS("a");
592  return true;
593  }
594  else if (PidType < ptOther) {
595  // The Pid is not yet in use and it is a special one
596  n = PidType;
597  }
598  else if (a >= 0) {
599  // The Pid is not yet in use and we have a free slot
600  n = a;
601  }
602  else {
603  esyslog("ERROR: no free slot for PID %d on device %d", Pid, DeviceNumber() + 1);
604  return false;
605  }
606  if (n >= 0) {
607  pidHandles[n].pid = Pid;
608  pidHandles[n].streamType = StreamType;
609  pidHandles[n].used = 1;
610  PRINTPIDS("C");
611  if (!SetPid(&pidHandles[n], n, true)) {
612  esyslog("ERROR: can't set PID %d on device %d", Pid, DeviceNumber() + 1);
613  if (PidType <= ptTeletext)
614  DetachAll(Pid);
615  DelPid(Pid, PidType);
616  return false;
617  }
618  if (camSlot)
619  camSlot->SetPid(Pid, true);
620  }
621  }
622  return true;
623 }
624 
625 void cDevice::DelPid(int Pid, ePidType PidType)
626 {
627  cMutexLock MutexLock(&mutexPids);
628  if (Pid || PidType == ptPcr) {
629  int n = -1;
630  if (PidType == ptPcr)
631  n = PidType; // PPID always has to be explicit
632  else {
633  for (int i = 0; i < MAXPIDHANDLES; i++) {
634  if (pidHandles[i].pid == Pid) {
635  n = i;
636  break;
637  }
638  }
639  }
640  if (n >= 0 && pidHandles[n].used) {
641  PRINTPIDS("D");
642  if (--pidHandles[n].used < 2) {
643  SetPid(&pidHandles[n], n, false);
644  if (pidHandles[n].used == 0) {
645  pidHandles[n].handle = -1;
646  pidHandles[n].pid = 0;
647  if (camSlot)
648  camSlot->SetPid(Pid, false);
649  }
650  }
651  PRINTPIDS("E");
652  }
653  }
654 }
655 
656 bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
657 {
658  return false;
659 }
660 
662 {
663  cMutexLock MutexLock(&mutexPids);
664  for (int i = ptAudio; i < ptOther; i++) {
665  if (pidHandles[i].pid)
666  DelPid(pidHandles[i].pid, ePidType(i));
667  }
668 }
669 
671 {
672  if (!sectionHandler) {
673  sectionHandler = new cSectionHandler(this);
678  }
679 }
680 
682 {
683  if (sectionHandler) {
684  delete sectionHandler; // automatically detaches filters
685  delete nitFilter;
686  delete sdtFilter;
687  delete patFilter;
688  delete eitFilter;
689  nitFilter = NULL;
690  sdtFilter = NULL;
691  patFilter = NULL;
692  eitFilter = NULL;
693  sectionHandler = NULL;
694  }
695 }
696 
697 int cDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
698 {
699  return -1;
700 }
701 
702 int cDevice::ReadFilter(int Handle, void *Buffer, size_t Length)
703 {
704  return safe_read(Handle, Buffer, Length);
705 }
706 
707 void cDevice::CloseFilter(int Handle)
708 {
709  close(Handle);
710 }
711 
713 {
714  if (sectionHandler)
715  sectionHandler->Attach(Filter);
716 }
717 
719 {
720  if (sectionHandler)
721  sectionHandler->Detach(Filter);
722 }
723 
724 bool cDevice::ProvidesSource(int Source) const
725 {
726  return false;
727 }
728 
730 {
731  cDeviceHook *Hook = deviceHooks.First();
732  while (Hook) {
733  if (!Hook->DeviceProvidesTransponder(this, Channel))
734  return false;
735  Hook = deviceHooks.Next(Hook);
736  }
737  return true;
738 }
739 
741 {
742  cDeviceHook *Hook = deviceHooks.First();
743  while (Hook) {
744  if (!Hook->DeviceProvidesEIT(this))
745  return false;
746  Hook = deviceHooks.Next(Hook);
747  }
748  return true;
749 }
750 
751 bool cDevice::ProvidesTransponder(const cChannel *Channel) const
752 {
753  return false;
754 }
755 
757 {
758  for (int i = 0; i < numDevices; i++) {
759  if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
760  return false;
761  }
762  return true;
763 }
764 
765 bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
766 {
767  return false;
768 }
769 
770 bool cDevice::ProvidesEIT(void) const
771 {
772  return false;
773 }
774 
776 {
777  return 0;
778 }
779 
781 {
782  return NULL;
783 }
784 
785 bool cDevice::SignalStats(int &Valid, double *Strength, double *Cnr, double *BerPre, double *BerPost, double *Per, int *Status) const
786 {
787  return false;
788 }
789 
790 int cDevice::SignalStrength(void) const
791 {
792  return -1;
793 }
794 
795 int cDevice::SignalQuality(void) const
796 {
797  return -1;
798 }
799 
801 {
802  return NULL;
803 }
804 
805 bool cDevice::IsTunedToTransponder(const cChannel *Channel) const
806 {
807  return false;
808 }
809 
810 bool cDevice::MaySwitchTransponder(const cChannel *Channel) const
811 {
813 }
814 
816 {
817 }
818 
820 {
821  if (!Occupied() && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid))
822  SetPowerSaveMode(true);
823 }
824 
825 bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
826 {
827  if (LiveView) {
828  isyslog("switching to channel %d %s (%s)", Channel->Number(), *Channel->GetChannelID().ToString(), Channel->Name());
829  cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
830  // and, if decrypted, this removes the now superfluous PIDs from the CAM, too
831  }
832  for (int i = 3; i--;) {
833  switch (SetChannel(Channel, LiveView)) {
834  case scrOk: return true;
835  case scrNotAvailable: Skins.QueueMessage(mtInfo, tr("Channel not available!"));
836  return false;
837  case scrNoTransfer: Skins.QueueMessage(mtError, tr("Can't start Transfer Mode!"));
838  return false;
839  case scrFailed: break; // loop will retry
840  default: esyslog("ERROR: invalid return value from SetChannel");
841  }
842  esyslog("retrying");
843  }
844  return false;
845 }
846 
847 bool cDevice::SwitchChannel(int Direction)
848 {
849  bool result = false;
850  Direction = sgn(Direction);
851  if (Direction) {
852  cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
853  // and, if decrypted, this removes the now superfluous PIDs from the CAM, too
854  int n = CurrentChannel() + Direction;
855  int first = n;
857  const cChannel *Channel;
858  while ((Channel = Channels->GetByNumber(n, Direction)) != NULL) {
859  // try only channels which are currently available
860  if (GetDevice(Channel, LIVEPRIORITY, true, true))
861  break;
862  n = Channel->Number() + Direction;
863  }
864  if (Channel) {
865  int d = n - first;
866  if (abs(d) == 1)
867  dsyslog("skipped channel %d", first);
868  else if (d)
869  dsyslog("skipped channels %d..%d", first, n - sgn(d));
870  if (PrimaryDevice()->SwitchChannel(Channel, true))
871  result = true;
872  }
873  else if (n != first)
874  Skins.QueueMessage(mtError, tr("Channel not available!"));
875  }
876  return result;
877 }
878 
879 eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
880 {
881  cMutexLock MutexLock(&mutexChannel); // to avoid a race between SVDRP CHAN and HasProgramme()
882  cStatus::MsgChannelSwitch(this, 0, LiveView);
883 
884  if (LiveView) {
885  if (IsPrimaryDevice() && !Replaying() && !Transferring()) { // this is only for FF DVB cards!
887  if (const cChannel *ch = Channels->GetByNumber(currentChannel)) {
888  if (patFilter)
889  patFilter->Release(ch->Sid());
890  }
891  }
892  StopReplay();
895  }
896 
897  cDevice *Device = (LiveView && IsPrimaryDevice(false)) ? GetDevice(Channel, LIVEPRIORITY, true) : this;
898 
899  bool NeedsTransferMode = LiveView && Device != PrimaryDevice();
900  // If the CAM slot wants the TS data, we need to switch to Transfer Mode:
901  if (!NeedsTransferMode && LiveView && IsPrimaryDevice() && CamSlot() && CamSlot()->WantsTsData())
902  NeedsTransferMode = true;
903 
904  eSetChannelResult Result = scrOk;
905 
906  // If this DVB card can't receive this channel, let's see if we can
907  // use the card that actually can receive it and transfer data from there:
908 
909  if (NeedsTransferMode) {
910  if (Device && PrimaryDevice()->CanReplay()) {
911  if (Device->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
912  cControl::Launch(new cTransferControl(Device, Channel));
913  else
914  Result = scrNoTransfer;
915  }
916  else
917  Result = scrNotAvailable;
918  }
919  else {
920  // Stop section handling:
921  if (sectionHandler) {
922  sectionHandler->SetStatus(false);
923  sectionHandler->SetChannel(NULL);
924  }
925  // Tell the camSlot about the channel switch and add all PIDs of this
926  // channel to it, for possible later decryption:
927  if (camSlot)
928  camSlot->AddChannel(Channel);
929  SetPowerSaveMode(false);
930  if (SetChannelDevice(Channel, LiveView)) {
931  // Start section handling:
932  if (sectionHandler) {
933  sectionHandler->SetChannel(Channel);
934  sectionHandler->SetStatus(true);
935  }
936  // Start decrypting any PIDs that might have been set in SetChannelDevice():
937  if (camSlot)
939  }
940  else
941  Result = scrFailed;
942  }
943 
944  if (Result == scrOk) {
945  if (LiveView) {
946  if (IsPrimaryDevice(false))
947  currentChannel = Channel->Number();
948  if (IsPrimaryDevice()) {
949  if (patFilter) // this is only for FF DVB cards!
950  patFilter->Request(Channel->Sid());
951  // Set the available audio tracks:
953  for (int i = 0; i < MAXAPIDS; i++)
954  SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
955  if (Setup.UseDolbyDigital) {
956  for (int i = 0; i < MAXDPIDS; i++)
957  SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
958  }
959  for (int i = 0; i < MAXSPIDS; i++)
960  SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
961  if (!NeedsTransferMode)
962  EnsureAudioTrack(true);
964  }
965  }
966  cStatus::MsgChannelSwitch(this, Channel->Number(), LiveView); // only report status if channel switch successful
967  }
968 
969  return Result;
970 }
971 
973 {
976  if (const cChannel *Channel = Channels->GetByNumber(CurrentChannel())) {
977  SetPowerSaveMode(false);
978  SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
979  }
980  }
981 }
982 
983 int cDevice::Occupied(int Priority) const
984 {
986  return 0;
987  int Seconds = occupiedTimeout - time(NULL);
988  return Seconds > 0 ? Seconds : 0;
989 }
990 
991 void cDevice::SetOccupied(int Seconds, int Priority, time_t From)
992 {
993  if (Seconds < 0)
994  return;
995  if (From == 0)
996  From = time(NULL);
997  if (From == occupiedFrom)
999  else {
1001  occupiedFrom = From;
1002  }
1003  occupiedTimeout = From + min(Seconds, MAXOCCUPIEDTIMEOUT);
1004 }
1005 
1006 bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
1007 {
1008  return false;
1009 }
1010 
1011 bool cDevice::HasLock(int TimeoutMs) const
1012 {
1013  return true;
1014 }
1015 
1016 bool cDevice::HasProgramme(void) const
1017 {
1018  cMutexLock MutexLock(&mutexChannel); // to avoid a race between SVDRP CHAN and HasProgramme()
1020 }
1021 
1023 {
1024  return 0;
1025 }
1026 
1027 void cDevice::SetAudioChannelDevice(int AudioChannel)
1028 {
1029 }
1030 
1032 {
1033 }
1034 
1036 {
1037 }
1038 
1040 {
1041 }
1042 
1044 {
1045 }
1046 
1048 {
1049  int OldVolume = volume;
1050  mute = !mute;
1051  //XXX why is it necessary to use different sequences???
1052  if (mute) {
1053  SetVolume(0, true);
1054  Audios.MuteAudio(mute); // Mute external audio after analog audio
1055  }
1056  else {
1057  Audios.MuteAudio(mute); // Enable external audio before analog audio
1058  SetVolume(OldVolume, true);
1059  }
1060  volume = OldVolume;
1061  return mute;
1062 }
1063 
1065 {
1066  int c = GetAudioChannelDevice();
1067  return (0 <= c && c <= 2) ? c : 0;
1068 }
1069 
1070 void cDevice::SetAudioChannel(int AudioChannel)
1071 {
1072  if (0 <= AudioChannel && AudioChannel <= 2)
1073  SetAudioChannelDevice(AudioChannel);
1074 }
1075 
1076 void cDevice::SetVolume(int Volume, bool Absolute)
1077 {
1078  int OldVolume = volume;
1079  double VolumeDelta = double(MAXVOLUME) / Setup.VolumeSteps;
1080  double VolumeLinearize = (Setup.VolumeLinearize >= 0) ? (Setup.VolumeLinearize / 10.0 + 1.0) : (1.0 / ((-Setup.VolumeLinearize / 10.0) + 1.0));
1081  volume = constrain(int(floor((Absolute ? Volume : volume + Volume) / VolumeDelta + 0.5) * VolumeDelta), 0, MAXVOLUME);
1082  SetVolumeDevice(MAXVOLUME - int(pow(1.0 - pow(double(volume) / MAXVOLUME, VolumeLinearize), 1.0 / VolumeLinearize) * MAXVOLUME));
1083  Absolute |= mute;
1084  cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute);
1085  if (volume > 0) {
1086  mute = false;
1088  }
1089 }
1090 
1091 void cDevice::ClrAvailableTracks(bool DescriptionsOnly, bool IdsOnly)
1092 {
1093  if (keepTracks)
1094  return;
1095  if (DescriptionsOnly) {
1096  for (int i = ttNone; i < ttMaxTrackTypes; i++)
1097  *availableTracks[i].description = 0;
1098  }
1099  else {
1100  if (IdsOnly) {
1101  for (int i = ttNone; i < ttMaxTrackTypes; i++)
1102  availableTracks[i].id = 0;
1103  }
1104  else
1105  memset(availableTracks, 0, sizeof(availableTracks));
1107  SetAudioChannel(0); // fall back to stereo
1111  }
1112 }
1113 
1114 bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description)
1115 {
1116  eTrackType t = eTrackType(Type + Index);
1117  if (Type == ttAudio && IS_AUDIO_TRACK(t) ||
1118  Type == ttDolby && IS_DOLBY_TRACK(t) ||
1119  Type == ttSubtitle && IS_SUBTITLE_TRACK(t)) {
1120  if (Language)
1121  strn0cpy(availableTracks[t].language, Language, sizeof(availableTracks[t].language));
1122  if (Description)
1124  if (Id) {
1125  availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking
1126  if (Type == ttAudio || Type == ttDolby) {
1127  int numAudioTracks = NumAudioTracks();
1128  if (!availableTracks[currentAudioTrack].id && numAudioTracks && currentAudioTrackMissingCount++ > numAudioTracks * 10)
1129  EnsureAudioTrack();
1130  else if (t == currentAudioTrack)
1132  }
1133  else if (Type == ttSubtitle && autoSelectPreferredSubtitleLanguage)
1135  }
1136  return true;
1137  }
1138  else
1139  esyslog("ERROR: SetAvailableTrack called with invalid Type/Index (%d/%d)", Type, Index);
1140  return false;
1141 }
1142 
1144 {
1145  return (ttNone < Type && Type < ttMaxTrackTypes) ? &availableTracks[Type] : NULL;
1146 }
1147 
1148 int cDevice::NumTracks(eTrackType FirstTrack, eTrackType LastTrack) const
1149 {
1150  int n = 0;
1151  for (int i = FirstTrack; i <= LastTrack; i++) {
1152  if (availableTracks[i].id)
1153  n++;
1154  }
1155  return n;
1156 }
1157 
1159 {
1161 }
1162 
1164 {
1166 }
1167 
1169 {
1170  if (ttNone < Type && Type <= ttDolbyLast) {
1171  cMutexLock MutexLock(&mutexCurrentAudioTrack);
1172  if (IS_DOLBY_TRACK(Type))
1173  SetDigitalAudioDevice(true);
1174  currentAudioTrack = Type;
1175  if (player)
1177  else
1179  if (IS_AUDIO_TRACK(Type))
1180  SetDigitalAudioDevice(false);
1181  return true;
1182  }
1183  return false;
1184 }
1185 
1187 {
1188  if (Type == ttNone || IS_SUBTITLE_TRACK(Type)) {
1189  currentSubtitleTrack = Type;
1191  if (dvbSubtitleConverter) {
1193  if (Type == ttNone) {
1196  else {
1199  }
1200  }
1201  else if (Replaying() && !Transferring() && Setup.DisplaySubtitles == SUBTITLES_REWIND && Manual)
1203  }
1205  if (player)
1207  else
1209  if (currentSubtitleTrack != ttNone && !Replaying() && !Transferring()) {
1210  const tTrackId *TrackId = GetTrack(currentSubtitleTrack);
1211  if (TrackId && TrackId->id) {
1212  liveSubtitle = new cLiveSubtitle(TrackId->id);
1214  }
1215  }
1216  return true;
1217  }
1218  return false;
1219 }
1220 
1222 {
1225 }
1226 
1228 {
1229  if (keepTracks)
1230  return;
1231  if (Force || !availableTracks[currentAudioTrack].id) {
1232  eTrackType PreferredTrack = ttAudioFirst;
1233  int PreferredAudioChannel = 0;
1234  int LanguagePreference = -1;
1235  int StartCheck = Setup.CurrentDolby ? ttDolbyFirst : ttAudioFirst;
1236  int EndCheck = ttDolbyLast;
1237  for (int i = StartCheck; i <= EndCheck; i++) {
1238  const tTrackId *TrackId = GetTrack(eTrackType(i));
1239  int pos = 0;
1240  if (TrackId && TrackId->id && I18nIsPreferredLanguage(Setup.AudioLanguages, TrackId->language, LanguagePreference, &pos)) {
1241  PreferredTrack = eTrackType(i);
1242  PreferredAudioChannel = pos;
1243  }
1244  if (Setup.CurrentDolby && i == ttDolbyLast) {
1245  i = ttAudioFirst - 1;
1246  EndCheck = ttAudioLast;
1247  }
1248  }
1249  // Make sure we're set to an available audio track:
1250  const tTrackId *Track = GetTrack(GetCurrentAudioTrack());
1251  if (Force || !Track || !Track->id || PreferredTrack != GetCurrentAudioTrack()) {
1252  if (!Force) // only log this for automatic changes
1253  dsyslog("setting audio track to %d (%d)", PreferredTrack, PreferredAudioChannel);
1254  SetCurrentAudioTrack(PreferredTrack);
1255  SetAudioChannel(PreferredAudioChannel);
1256  }
1257  }
1258 }
1259 
1261 {
1262  if (keepTracks)
1263  return;
1265  eTrackType PreferredTrack = ttNone;
1266  int LanguagePreference = INT_MAX; // higher than the maximum possible value
1267  for (int i = ttSubtitleFirst; i <= ttSubtitleLast; i++) {
1268  const tTrackId *TrackId = GetTrack(eTrackType(i));
1269  if (TrackId && TrackId->id && (I18nIsPreferredLanguage(Setup.SubtitleLanguages, TrackId->language, LanguagePreference) ||
1270  (i == ttSubtitleFirst + 8 && !*TrackId->language && LanguagePreference == INT_MAX))) // compatibility mode for old subtitles plugin
1271  PreferredTrack = eTrackType(i);
1272  }
1273  // Make sure we're set to an available subtitle track:
1274  const tTrackId *Track = GetTrack(GetCurrentSubtitleTrack());
1275  if (!Track || !Track->id || PreferredTrack != GetCurrentSubtitleTrack())
1276  SetCurrentSubtitleTrack(PreferredTrack);
1277  }
1278  else
1280 }
1281 
1282 bool cDevice::CanReplay(void) const
1283 {
1284  return HasDecoder();
1285 }
1286 
1288 {
1289  return false;
1290 }
1291 
1292 int64_t cDevice::GetSTC(void)
1293 {
1294  return -1;
1295 }
1296 
1297 void cDevice::TrickSpeed(int Speed, bool Forward)
1298 {
1299 }
1300 
1301 void cDevice::Clear(void)
1302 {
1303  Audios.ClearAudio();
1306 }
1307 
1308 void cDevice::Play(void)
1309 {
1312  dvbSubtitleConverter->Freeze(false);
1313 }
1314 
1316 {
1317  Audios.MuteAudio(true);
1320 }
1321 
1322 void cDevice::Mute(void)
1323 {
1324  Audios.MuteAudio(true);
1325 }
1326 
1327 void cDevice::StillPicture(const uchar *Data, int Length)
1328 {
1329  if (Data[0] == 0x47) {
1330  // TS data
1331  cTsToPes TsToPes;
1332  uchar *buf = NULL;
1333  int Size = 0;
1334  while (Length >= TS_SIZE) {
1335  int Pid = TsPid(Data);
1336  if (Pid == PATPID)
1337  patPmtParser.ParsePat(Data, TS_SIZE);
1338  else if (patPmtParser.IsPmtPid(Pid))
1339  patPmtParser.ParsePmt(Data, TS_SIZE);
1340  else if (Pid == patPmtParser.Vpid()) {
1341  if (TsPayloadStart(Data)) {
1342  int l;
1343  while (const uchar *p = TsToPes.GetPes(l)) {
1344  int Offset = Size;
1345  int NewSize = Size + l;
1346  if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) {
1347  Size = NewSize;
1348  buf = NewBuffer;
1349  memcpy(buf + Offset, p, l);
1350  }
1351  else {
1352  LOG_ERROR_STR("out of memory");
1353  free(buf);
1354  return;
1355  }
1356  }
1357  TsToPes.Reset();
1358  }
1359  TsToPes.PutTs(Data, TS_SIZE);
1360  }
1361  Length -= TS_SIZE;
1362  Data += TS_SIZE;
1363  }
1364  int l;
1365  while (const uchar *p = TsToPes.GetPes(l)) {
1366  int Offset = Size;
1367  int NewSize = Size + l;
1368  if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) {
1369  Size = NewSize;
1370  buf = NewBuffer;
1371  memcpy(buf + Offset, p, l);
1372  }
1373  else {
1374  esyslog("ERROR: out of memory");
1375  free(buf);
1376  return;
1377  }
1378  }
1379  if (buf) {
1380  StillPicture(buf, Size);
1381  free(buf);
1382  }
1383  }
1384 }
1385 
1386 bool cDevice::Replaying(void) const
1387 {
1388  return player != NULL;
1389 }
1390 
1391 bool cDevice::Transferring(void) const
1392 {
1393  return cTransferControl::ReceiverDevice() != NULL;
1394 }
1395 
1397 {
1398  if (CanReplay()) {
1399  if (player)
1400  Detach(player);
1403  patPmtParser.Reset();
1404  player = Player;
1405  if (!Transferring())
1406  ClrAvailableTracks(false, true);
1408  player->device = this;
1409  player->Activate(true);
1410  return true;
1411  }
1412  return false;
1413 }
1414 
1416 {
1417  if (Player && player == Player) {
1418  cPlayer *p = player;
1419  player = NULL; // avoids recursive calls to Detach()
1420  p->Activate(false);
1421  p->device = NULL;
1423  delete dvbSubtitleConverter;
1424  dvbSubtitleConverter = NULL;
1427  PlayTs(NULL, 0);
1428  patPmtParser.Reset();
1429  Audios.ClearAudio();
1430  isPlayingVideo = false;
1431  }
1432 }
1433 
1435 {
1436  if (player) {
1437  Detach(player);
1438  if (IsPrimaryDevice())
1440  }
1441 }
1442 
1443 bool cDevice::Poll(cPoller &Poller, int TimeoutMs)
1444 {
1445  return false;
1446 }
1447 
1448 bool cDevice::Flush(int TimeoutMs)
1449 {
1450  return true;
1451 }
1452 
1453 int cDevice::PlayVideo(const uchar *Data, int Length)
1454 {
1455  return -1;
1456 }
1457 
1458 int cDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
1459 {
1460  return -1;
1461 }
1462 
1463 int cDevice::PlaySubtitle(const uchar *Data, int Length)
1464 {
1465  if (!dvbSubtitleConverter) {
1467  if (Replaying() && !Transferring())
1469  }
1470  return dvbSubtitleConverter->ConvertFragments(Data, Length);
1471 }
1472 
1473 int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly)
1474 {
1475  bool FirstLoop = true;
1476  uchar c = Data[3];
1477  const uchar *Start = Data;
1478  const uchar *End = Start + Length;
1479  while (Start < End) {
1480  int d = End - Start;
1481  int w = d;
1482  switch (c) {
1483  case 0xBE: // padding stream, needed for MPEG1
1484  case 0xE0 ... 0xEF: // video
1485  isPlayingVideo = true;
1486  w = PlayVideo(Start, d);
1487  break;
1488  case 0xC0 ... 0xDF: // audio
1489  SetAvailableTrack(ttAudio, c - 0xC0, c);
1490  if ((!VideoOnly || HasIBPTrickSpeed()) && c == availableTracks[currentAudioTrack].id) {
1491  w = PlayAudio(Start, d, c);
1492  if (FirstLoop)
1493  Audios.PlayAudio(Data, Length, c);
1494  }
1495  break;
1496  case 0xBD: { // private stream 1
1497  int PayloadOffset = Data[8] + 9;
1498 
1499  // Compatibility mode for old subtitles plugin:
1500  if ((Data[7] & 0x01) && (Data[PayloadOffset - 3] & 0x81) == 0x01 && Data[PayloadOffset - 2] == 0x81)
1501  PayloadOffset--;
1502 
1503  uchar SubStreamId = Data[PayloadOffset];
1504  uchar SubStreamType = SubStreamId & 0xF0;
1505  uchar SubStreamIndex = SubStreamId & 0x1F;
1506 
1507  // Compatibility mode for old VDR recordings, where 0xBD was only AC3:
1508 pre_1_3_19_PrivateStreamDetected:
1510  SubStreamId = c;
1511  SubStreamType = 0x80;
1512  SubStreamIndex = 0;
1513  }
1514  else if (pre_1_3_19_PrivateStream)
1515  pre_1_3_19_PrivateStream--; // every known PS1 packet counts down towards 0 to recover from glitches...
1516  switch (SubStreamType) {
1517  case 0x20: // SPU
1518  case 0x30: // SPU
1519  SetAvailableTrack(ttSubtitle, SubStreamIndex, SubStreamId);
1520  if ((!VideoOnly || HasIBPTrickSpeed()) && currentSubtitleTrack != ttNone && SubStreamId == availableTracks[currentSubtitleTrack].id)
1521  w = PlaySubtitle(Start, d);
1522  break;
1523  case 0x80: // AC3 & DTS
1524  if (Setup.UseDolbyDigital) {
1525  SetAvailableTrack(ttDolby, SubStreamIndex, SubStreamId);
1526  if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) {
1527  w = PlayAudio(Start, d, SubStreamId);
1528  if (FirstLoop)
1529  Audios.PlayAudio(Data, Length, SubStreamId);
1530  }
1531  }
1532  break;
1533  case 0xA0: // LPCM
1534  SetAvailableTrack(ttAudio, SubStreamIndex, SubStreamId);
1535  if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) {
1536  w = PlayAudio(Start, d, SubStreamId);
1537  if (FirstLoop)
1538  Audios.PlayAudio(Data, Length, SubStreamId);
1539  }
1540  break;
1541  default:
1542  // Compatibility mode for old VDR recordings, where 0xBD was only AC3:
1544  dsyslog("unknown PS1 packet, substream id = %02X (counter is at %d)", SubStreamId, pre_1_3_19_PrivateStream);
1545  pre_1_3_19_PrivateStream += 2; // ...and every unknown PS1 packet counts up (the very first one counts twice, but that's ok)
1547  dsyslog("switching to pre 1.3.19 Dolby Digital compatibility mode - substream id = %02X", SubStreamId);
1550  goto pre_1_3_19_PrivateStreamDetected;
1551  }
1552  }
1553  }
1554  }
1555  break;
1556  default:
1557  ;//esyslog("ERROR: unexpected packet id %02X", c);
1558  }
1559  if (w > 0)
1560  Start += w;
1561  else {
1562  if (Start != Data)
1563  esyslog("ERROR: incomplete PES packet write!");
1564  return Start == Data ? w : Start - Data;
1565  }
1566  FirstLoop = false;
1567  }
1568  return Length;
1569 }
1570 
1571 int cDevice::PlayPes(const uchar *Data, int Length, bool VideoOnly)
1572 {
1573  if (!Data) {
1576  return 0;
1577  }
1578  int i = 0;
1579  while (i <= Length - 6) {
1580  if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
1581  int l = PesLength(Data + i);
1582  if (i + l > Length) {
1583  esyslog("ERROR: incomplete PES packet!");
1584  return Length;
1585  }
1586  int w = PlayPesPacket(Data + i, l, VideoOnly);
1587  if (w > 0)
1588  i += l;
1589  else
1590  return i == 0 ? w : i;
1591  }
1592  else
1593  i++;
1594  }
1595  if (i < Length)
1596  esyslog("ERROR: leftover PES data!");
1597  return Length;
1598 }
1599 
1600 int cDevice::PlayTsVideo(const uchar *Data, int Length)
1601 {
1602  // Video PES has no explicit length, so we can only determine the end of
1603  // a PES packet when the next TS packet that starts a payload comes in:
1604  if (TsPayloadStart(Data)) {
1605  int l;
1606  while (const uchar *p = tsToPesVideo.GetPes(l)) {
1607  int w = PlayVideo(p, l);
1608  if (w <= 0) {
1610  return w;
1611  }
1612  }
1613  tsToPesVideo.Reset();
1614  }
1615  tsToPesVideo.PutTs(Data, Length);
1616  return Length;
1617 }
1618 
1619 int cDevice::PlayTsAudio(const uchar *Data, int Length)
1620 {
1621  // Audio PES always has an explicit length and consists of single packets:
1622  int l;
1623  if (const uchar *p = tsToPesAudio.GetPes(l)) {
1624  int w = PlayAudio(p, l, p[3]);
1625  if (w <= 0) {
1627  return w;
1628  }
1629  tsToPesAudio.Reset();
1630  }
1631  tsToPesAudio.PutTs(Data, Length);
1632  return Length;
1633 }
1634 
1635 int cDevice::PlayTsSubtitle(const uchar *Data, int Length)
1636 {
1637  if (!dvbSubtitleConverter) {
1639  if (Replaying() && !Transferring())
1641  }
1642  tsToPesSubtitle.PutTs(Data, Length);
1643  int l;
1644  if (const uchar *p = tsToPesSubtitle.GetPes(l)) {
1647  }
1648  return Length;
1649 }
1650 
1651 int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
1652 {
1653  int Played = 0;
1654  if (!Data) {
1655  tsToPesVideo.Reset();
1656  tsToPesAudio.Reset();
1658  }
1659  else if (Length < TS_SIZE) {
1660  esyslog("ERROR: skipped %d bytes of TS fragment", Length);
1661  return Length;
1662  }
1663  else {
1664  while (Length >= TS_SIZE) {
1665  if (int Skipped = TS_SYNC(Data, Length))
1666  return Played + Skipped;
1667  int Pid = TsPid(Data);
1668  if (TsHasPayload(Data)) { // silently ignore TS packets w/o payload
1669  int PayloadOffset = TsPayloadOffset(Data);
1670  if (PayloadOffset < TS_SIZE) {
1671  if (Pid == PATPID)
1672  patPmtParser.ParsePat(Data, TS_SIZE);
1673  else if (patPmtParser.IsPmtPid(Pid))
1674  patPmtParser.ParsePmt(Data, TS_SIZE);
1675  else if (Pid == patPmtParser.Vpid()) {
1676  isPlayingVideo = true;
1677  int w = PlayTsVideo(Data, TS_SIZE);
1678  if (w < 0)
1679  return Played ? Played : w;
1680  if (w == 0)
1681  break;
1682  }
1683  else if (Pid == availableTracks[currentAudioTrack].id) {
1684  if (!VideoOnly || HasIBPTrickSpeed()) {
1685  int w = PlayTsAudio(Data, TS_SIZE);
1686  if (w < 0)
1687  return Played ? Played : w;
1688  if (w == 0)
1689  break;
1690  Audios.PlayTsAudio(Data, TS_SIZE);
1691  }
1692  }
1693  else if (Pid == availableTracks[currentSubtitleTrack].id) {
1694  if (!VideoOnly || HasIBPTrickSpeed())
1695  PlayTsSubtitle(Data, TS_SIZE);
1696  }
1697  }
1698  }
1699  else if (Pid == patPmtParser.Ppid()) {
1700  int w = PlayTsVideo(Data, TS_SIZE);
1701  if (w < 0)
1702  return Played ? Played : w;
1703  if (w == 0)
1704  break;
1705  }
1706  Played += TS_SIZE;
1707  Length -= TS_SIZE;
1708  Data += TS_SIZE;
1709  }
1710  }
1711  return Played;
1712 }
1713 
1714 int cDevice::Priority(bool IgnoreOccupied) const
1715 {
1716  int priority = IDLEPRIORITY;
1717  if (IsPrimaryDevice() && !Replaying() && HasProgramme())
1718  priority = TRANSFERPRIORITY; // we use the same value here, no matter whether it's actual Transfer Mode or real live viewing
1719  if (!IgnoreOccupied && time(NULL) <= occupiedTimeout && occupiedPriority > priority)
1720  priority = occupiedPriority - 1; // so timers with occupiedPriority can start
1721  cMutexLock MutexLock(&mutexReceiver);
1722  for (int i = 0; i < MAXRECEIVERS; i++) {
1723  if (receiver[i])
1724  priority = max(receiver[i]->priority, priority);
1725  }
1726  return priority;
1727 }
1728 
1729 bool cDevice::Ready(void)
1730 {
1731  return true;
1732 }
1733 
1734 bool cDevice::Receiving(bool Dummy) const
1735 {
1736  cMutexLock MutexLock(&mutexReceiver);
1737  for (int i = 0; i < MAXRECEIVERS; i++) {
1738  if (receiver[i])
1739  return true;
1740  }
1741  return false;
1742 }
1743 
1744 #define TS_SCRAMBLING_TIMEOUT 3 // seconds to wait until a TS becomes unscrambled
1745 #define TS_SCRAMBLING_TIME_OK 3 // seconds before a Channel/CAM combination is marked as known to decrypt
1746 #define EIT_INJECTION_TIME 10 // seconds for which to inject EIT event
1747 
1749 {
1750  if (Running() && OpenDvr()) {
1751  while (Running()) {
1752  // Read data from the DVR device:
1753  uchar *b = NULL;
1754  if (GetTSPacket(b)) {
1755  if (b) {
1756  // Distribute the packet to all attached receivers:
1757  Lock();
1758  cCamSlot *cs = CamSlot();
1759  if (cs)
1760  cs->TsPostProcess(b);
1761  int Pid = TsPid(b);
1762  bool IsScrambled = TsIsScrambled(b);
1763  for (int i = 0; i < MAXRECEIVERS; i++) {
1764  cMutexLock MutexLock(&mutexReceiver);
1765  cReceiver *Receiver = receiver[i];
1766  if (Receiver && Receiver->WantsPid(Pid)) {
1767  Receiver->Receive(b, TS_SIZE);
1768  // Check whether the TS packet is scrambled:
1769  if (Receiver->startScrambleDetection) {
1770  if (cs) {
1771  int CamSlotNumber = cs->MasterSlotNumber();
1772  if (Receiver->lastScrambledPacket < Receiver->startScrambleDetection)
1773  Receiver->lastScrambledPacket = Receiver->startScrambleDetection;
1774  time_t Now = time(NULL);
1775  if (IsScrambled) {
1776  Receiver->lastScrambledPacket = Now;
1777  if (Now - Receiver->startScrambleDetection > Receiver->scramblingTimeout) {
1778  if (!cs->IsActivating() || Receiver->Priority() >= LIVEPRIORITY) {
1779  if (Receiver->ChannelID().Valid()) {
1780  dsyslog("CAM %d: won't decrypt channel %s, detaching receiver", CamSlotNumber, *Receiver->ChannelID().ToString());
1781  ChannelCamRelations.SetChecked(Receiver->ChannelID(), CamSlotNumber);
1782  }
1783  Detach(Receiver);
1784  }
1785  }
1786  }
1787  else if (Now - Receiver->lastScrambledPacket > TS_SCRAMBLING_TIME_OK) {
1788  if (Receiver->ChannelID().Valid()) {
1789  dsyslog("CAM %d: decrypts channel %s", CamSlotNumber, *Receiver->ChannelID().ToString());
1790  ChannelCamRelations.SetDecrypt(Receiver->ChannelID(), CamSlotNumber);
1791  }
1792  Receiver->startScrambleDetection = 0;
1793  }
1794  }
1795  }
1796  // Inject EIT event to avoid the CAMs parental rating prompt:
1797  if (Receiver->startEitInjection) {
1798  time_t Now = time(NULL);
1799  if (cCamSlot *cs = CamSlot()) {
1800  if (Now != Receiver->lastEitInjection) { // once per second
1801  cs->InjectEit(Receiver->ChannelID().Sid());
1802  Receiver->lastEitInjection = Now;
1803  }
1804  }
1805  if (Now - Receiver->startEitInjection > EIT_INJECTION_TIME)
1806  Receiver->startEitInjection = 0;
1807  }
1808  }
1809  }
1810  Unlock();
1811  }
1812  }
1813  else
1814  break;
1815  }
1816  CloseDvr();
1817  }
1819 }
1820 
1822 {
1823  return false;
1824 }
1825 
1827 {
1828 }
1829 
1831 {
1832  return false;
1833 }
1834 
1836 {
1837  if (!Receiver)
1838  return false;
1839  if (Receiver->device == this)
1840  return true;
1841 // activate the following line if you need it - actually the driver should be fixed!
1842 //#define WAIT_FOR_TUNER_LOCK
1843 #ifdef WAIT_FOR_TUNER_LOCK
1844 #define TUNER_LOCK_TIMEOUT 5000 // ms
1845  if (!HasLock(TUNER_LOCK_TIMEOUT)) {
1846  esyslog("ERROR: device %d has no lock, can't attach receiver!", DeviceNumber() + 1);
1847  return false;
1848  }
1849 #endif
1850  cMutexLock MutexLock(&mutexReceiver);
1851  for (int i = 0; i < MAXRECEIVERS; i++) {
1852  if (!receiver[i]) {
1853  for (int n = 0; n < Receiver->numPids; n++) {
1854  if (!AddPid(Receiver->pids[n])) {
1855  for ( ; n-- > 0; )
1856  DelPid(Receiver->pids[n]);
1857  return false;
1858  }
1859  }
1860  Receiver->Activate(true);
1861  Receiver->device = this;
1862  receiver[i] = Receiver;
1863  if (camSlot && Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
1865  if (camSlot->WantsTsData()) {
1866  Receiver->lastEitInjection = 0;
1867  Receiver->startEitInjection = time(NULL);
1868  }
1869  if (CamSlots.NumReadyMasterSlots() > 1) { // don't try different CAMs if there is only one
1870  Receiver->startScrambleDetection = time(NULL);
1872  bool KnownToDecrypt = ChannelCamRelations.CamDecrypt(Receiver->ChannelID(), camSlot->MasterSlotNumber());
1873  if (KnownToDecrypt)
1874  Receiver->scramblingTimeout *= 9; // give it time to receive ECM/EMM (must be less than MAXBROKENTIMEOUT in recorder.c!)
1875  if (Receiver->ChannelID().Valid())
1876  dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->MasterSlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), Receiver->scramblingTimeout);
1877  }
1878  }
1879  if (patFilter && Receiver->ChannelID().Valid())
1880  patFilter->Request(Receiver->ChannelID().Sid());
1881  Start();
1882  return true;
1883  }
1884  }
1885  esyslog("ERROR: no free receiver slot!");
1886  return false;
1887 }
1888 
1889 void cDevice::Detach(cReceiver *Receiver, bool ReleaseCam)
1890 {
1891  if (!Receiver || Receiver->device != this)
1892  return;
1893  bool receiversLeft = false;
1894  mutexReceiver.Lock();
1895  for (int i = 0; i < MAXRECEIVERS; i++) {
1896  if (receiver[i] == Receiver)
1897  receiver[i] = NULL;
1898  else if (receiver[i])
1899  receiversLeft = true;
1900  }
1901  if (patFilter && Receiver->ChannelID().Valid())
1902  patFilter->Release(Receiver->ChannelID().Sid());
1904  Receiver->device = NULL;
1905  Receiver->Activate(false);
1906  for (int n = 0; n < Receiver->numPids; n++)
1907  DelPid(Receiver->pids[n]);
1908  if (camSlot) {
1909  if (Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
1911  if (ReleaseCam)
1912  ReleaseCamSlot();
1913  }
1914  }
1915  if (!receiversLeft)
1916  Cancel(-1);
1917 }
1918 
1919 void cDevice::DetachAll(int Pid)
1920 {
1921  if (Pid) {
1922  cMutexLock MutexLock(&mutexReceiver);
1923  for (int i = 0; i < MAXRECEIVERS; i++) {
1924  cReceiver *Receiver = receiver[i];
1925  if (Receiver && Receiver->WantsPid(Pid))
1926  Detach(Receiver, false);
1927  }
1928  ReleaseCamSlot();
1929  }
1930 }
1931 
1933 {
1934  cMutexLock MutexLock(&mutexReceiver);
1935  for (int i = 0; i < MAXRECEIVERS; i++)
1936  Detach(receiver[i], false);
1937  ReleaseCamSlot();
1938 }
1939 
1940 // --- cTSBuffer -------------------------------------------------------------
1941 
1942 cTSBuffer::cTSBuffer(int File, int Size, int DeviceNumber)
1943 {
1944  SetDescription("device %d TS buffer", DeviceNumber);
1945  f = File;
1946  deviceNumber = DeviceNumber;
1947  delivered = 0;
1948  ringBuffer = new cRingBufferLinear(Size, TS_SIZE, true, "TS");
1949  ringBuffer->SetTimeouts(100, 100);
1951  Start();
1952 }
1953 
1955 {
1956  Cancel(3);
1957  delete ringBuffer;
1958 }
1959 
1961 {
1962  if (ringBuffer) {
1963  bool firstRead = true;
1964  cPoller Poller(f);
1965  while (Running()) {
1966  if (firstRead || Poller.Poll(100)) {
1967  firstRead = false;
1968  int r = ringBuffer->Read(f);
1969  if (r < 0 && FATALERRNO) {
1970  if (errno == EOVERFLOW)
1971  esyslog("ERROR: driver buffer overflow on device %d", deviceNumber);
1972  else {
1973  LOG_ERROR;
1974  break;
1975  }
1976  }
1977  cCondWait::SleepMs(10); // avoids small chunks of data, which cause high CPU usage, esp. on ARM CPUs
1978  }
1979  }
1980  }
1981 }
1982 
1983 uchar *cTSBuffer::Get(int *Available, bool CheckAvailable)
1984 {
1985  int Count = 0;
1986  if (delivered) {
1988  delivered = 0;
1989  }
1990  if (CheckAvailable && ringBuffer->Available() < TS_SIZE)
1991  return NULL;
1992  uchar *p = ringBuffer->Get(Count);
1993  if (p && Count >= TS_SIZE) {
1994  if (*p != TS_SYNC_BYTE) {
1995  for (int i = 1; i < Count; i++) {
1996  if (p[i] == TS_SYNC_BYTE) {
1997  Count = i;
1998  break;
1999  }
2000  }
2001  ringBuffer->Del(Count);
2002  esyslog("ERROR: skipped %d bytes to sync on TS packet on device %d", Count, deviceNumber);
2003  return NULL;
2004  }
2005  delivered = TS_SIZE;
2006  if (Available)
2007  *Available = Count;
2008  return p;
2009  }
2010  return NULL;
2011 }
2012 
2013 void cTSBuffer::Skip(int Count)
2014 {
2015  delivered = Count;
2016 }
cAudios Audios
Definition: audio.c:27
#define CA_ENCRYPTED_MIN
Definition: channels.h:44
#define MAXDPIDS
Definition: channels.h:32
#define MAXAPIDS
Definition: channels.h:31
#define MAXSPIDS
Definition: channels.h:33
#define CA_DVB_MAX
Definition: channels.h:41
#define LOCK_CHANNELS_READ
Definition: channels.h:273
cChannelCamRelations ChannelCamRelations
Definition: ci.c:2947
cCamSlots CamSlots
Definition: ci.c:2838
@ msReady
Definition: ci.h:170
void PlayAudio(const uchar *Data, int Length, uchar Id)
Definition: audio.c:29
void PlayTsAudio(const uchar *Data, int Length)
Definition: audio.c:35
void ClearAudio(void)
Definition: audio.c:47
void MuteAudio(bool On)
Definition: audio.c:41
Definition: ci.h:232
bool MtdActive(void)
Returns true if MTD is currently active.
Definition: ci.h:288
virtual bool IsDecrypting(void)
Returns true if the CAM in this slot is currently used for decrypting.
Definition: ci.c:2795
virtual void InjectEit(int Sid)
Injects a generated EIT with a "present event" for the given Sid into the TS data stream sent to the ...
Definition: ci.c:2830
int Priority(void)
Returns the priority of the device this slot is currently assigned to, or IDLEPRIORITY if it is not a...
Definition: ci.c:2656
int MasterSlotNumber(void)
Returns the number of this CAM's master slot within the whole system.
Definition: ci.h:347
virtual eModuleStatus ModuleStatus(void)
Returns the status of the CAM in this slot.
Definition: ci.c:2431
virtual void AddChannel(const cChannel *Channel)
Adds all PIDs of the given Channel to the current list of PIDs.
Definition: ci.c:2720
bool WantsTsData(void) const
Returns true if this CAM slot wants to receive the TS data through its Decrypt() function.
Definition: ci.h:338
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this CAM slot to the given Device, if this is possible.
Definition: ci.c:2221
virtual void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active.
Definition: ci.c:2697
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function.
Definition: ci.c:2776
virtual bool IsActivating(void)
Returns true if this CAM slot is currently activating a smart card.
Definition: ci.c:2424
virtual bool TsPostProcess(uchar *Data)
If there is a cCiSession that needs to do additional processing on TS packets (after the CAM has done...
Definition: ci.c:2820
cDevice * Device(void)
Returns the device this CAM slot is currently assigned to.
Definition: ci.h:332
cCamSlot * MtdSpawn(void)
If this CAM slot can do MTD ("Multi Transponder Decryption"), a call to this function returns a cMtdC...
Definition: ci.c:2213
cCamSlot * MasterSlot(void)
Returns this CAM slot's master slot, or a pointer to itself if it is a master slot.
Definition: ci.h:309
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
Definition: ci.c:2664
int NumReadyMasterSlots(void)
Returns the number of master CAM slots in the system that are ready to decrypt.
Definition: ci.c:2840
void SetChecked(tChannelID ChannelID, int CamSlotNumber)
Definition: ci.c:3011
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
Definition: ci.c:3004
bool CamChecked(tChannelID ChannelID, int CamSlotNumber)
Definition: ci.c:2997
void SetDecrypt(tChannelID ChannelID, int CamSlotNumber)
Definition: ci.c:3019
const int * Caids(void) const
Definition: channels.h:174
const char * Alang(int i) const
Definition: channels.h:165
int Number(void) const
Definition: channels.h:181
const char * Name(void) const
Definition: channels.c:122
int Dpid(int i) const
Definition: channels.h:163
int Apid(int i) const
Definition: channels.h:162
tChannelID GetChannelID(void) const
Definition: channels.h:194
int Ca(int Index=0) const
Definition: channels.h:175
int Spid(int i) const
Definition: channels.h:164
int Sid(void) const
Definition: channels.h:178
const char * Slang(int i) const
Definition: channels.h:167
const char * Dlang(int i) const
Definition: channels.h:166
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
Definition: thread.c:73
static void Shutdown(void)
Definition: player.c:99
static void Launch(cControl *Control)
Definition: player.c:79
virtual bool DeviceProvidesEIT(const cDevice *Device) const
Returns true if the given Device can provide EIT data.
Definition: device.c:61
cDeviceHook(void)
Creates a new device hook object.
Definition: device.c:51
virtual bool DeviceProvidesTransponder(const cDevice *Device, const cChannel *Channel) const
Returns true if the given Device can provide the given Channel's transponder.
Definition: device.c:56
cCamSlot * camSlot
Definition: device.h:479
cPlayer * player
Definition: device.h:653
static int NextCardIndex(int n=0)
Calculates the next card index.
Definition: device.c:155
int Occupied(int Priority=MINPRIORITY) const
Returns the number of seconds this device is still occupied for with a priority >= Priority.
Definition: device.c:983
virtual cString DeviceName(void) const
Returns a string identifying the name of this device.
Definition: device.c:181
static cList< cDeviceHook > deviceHooks
Definition: device.h:246
bool Replaying(void) const
Returns true if we are currently replaying.
Definition: device.c:1386
virtual bool Poll(cPoller &Poller, int TimeoutMs=0)
Returns true if the device itself or any of the file handles in Poller is ready for further action.
Definition: device.c:1443
int currentAudioTrackMissingCount
Definition: device.h:559
void StopSectionHandler(void)
A device that has called StartSectionHandler() must call this function (typically in its destructor) ...
Definition: device.c:681
int Priority(bool IgnoreOccupied=false) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY),...
Definition: device.c:1714
virtual bool SignalStats(int &Valid, double *Strength=NULL, double *Cnr=NULL, double *BerPre=NULL, double *BerPost=NULL, double *Per=NULL, int *Status=NULL) const
Returns statistics about the currently received signal (if available).
Definition: device.c:785
virtual void SetSubtitleTrackDevice(eTrackType Type)
Sets the current subtitle track to the given value.
Definition: device.c:1043
virtual int GetAudioChannelDevice(void)
Gets the current audio channel, which is stereo (0), mono left (1) or mono right (2).
Definition: device.c:1022
virtual int PlayVideo(const uchar *Data, int Length)
Plays the given data block as video.
Definition: device.c:1453
cSectionHandler * sectionHandler
Definition: device.h:441
bool SetCurrentSubtitleTrack(eTrackType Type, bool Manual=false)
Sets the current subtitle track to the given Type.
Definition: device.c:1186
virtual bool HasInternalCam(void)
Returns true if this device handles encrypted channels itself without VDR assistance.
Definition: device.h:485
virtual uchar * GrabImage(int &Size, bool Jpeg=true, int Quality=-1, int SizeX=-1, int SizeY=-1)
Grabs the currently visible screen image.
Definition: device.c:474
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
Definition: device.c:533
bool GrabImageFile(const char *FileName, bool Jpeg=true, int Quality=-1, int SizeX=-1, int SizeY=-1)
Calls GrabImage() and stores the resulting image in a file with the given name.
Definition: device.c:479
eSetChannelResult SetChannel(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (general setup).
Definition: device.c:879
bool mute
Definition: device.h:621
virtual bool HasLock(int TimeoutMs=0) const
Returns true if the device has a lock on the requested transponder.
Definition: device.c:1011
void StartSectionHandler(void)
A derived device that provides section data must call this function (typically in its constructor) to...
Definition: device.c:670
ePidType
Definition: device.h:410
@ ptTeletext
Definition: device.h:410
@ ptPcr
Definition: device.h:410
@ ptOther
Definition: device.h:410
@ ptDolby
Definition: device.h:410
@ ptAudio
Definition: device.h:410
@ ptVideo
Definition: device.h:410
cMutex mutexCurrentAudioTrack
Definition: device.h:557
virtual const cPositioner * Positioner(void) const
Returns a pointer to the positioner (if any) this device has used to move the satellite dish to the r...
Definition: device.c:780
virtual int NumProvidedSystems(void) const
Returns the number of individual "delivery systems" this device provides.
Definition: device.c:775
int NumSubtitleTracks(void) const
Returns the number of subtitle tracks that are currently available.
Definition: device.c:1163
bool keepTracks
Definition: device.h:561
virtual int PlayPes(const uchar *Data, int Length, bool VideoOnly=false)
Plays all valid PES packets in Data with the given Length.
Definition: device.c:1571
cMutex mutexReceiver
Definition: device.h:847
virtual bool ProvidesSource(int Source) const
Returns true if this device can provide the given source.
Definition: device.c:724
void ReleaseCamSlot(void)
Releases the CAM slot if it is currently not used.
Definition: device.c:448
static int useDevice
Definition: device.h:125
cDvbSubtitleConverter * dvbSubtitleConverter
Definition: device.h:255
bool HasPid(int Pid) const
Returns true if this device is currently receiving the given PID.
Definition: device.c:550
virtual void SetAudioTrackDevice(eTrackType Type)
Sets the current audio track to the given value.
Definition: device.c:1039
virtual bool SetPid(cPidHandle *Handle, int Type, bool On)
Does the actual PID setting on this device.
Definition: device.c:656
static int nextCardIndex
Definition: device.h:188
cTsToPes tsToPesAudio
Definition: device.h:656
cNitFilter * nitFilter
Definition: device.h:445
bool autoSelectPreferredSubtitleLanguage
Definition: device.h:560
static bool WaitForAllDevicesReady(int Timeout=0)
Waits until all devices have become ready, or the given Timeout (seconds) has expired.
Definition: device.c:133
void SetCamSlot(cCamSlot *CamSlot)
Sets the given CamSlot to be used with this device.
Definition: device.c:459
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise.
Definition: device.c:222
static void SetUseDevice(int n)
Sets the 'useDevice' flag of the given device.
Definition: device.c:149
virtual bool MaySwitchTransponder(const cChannel *Channel) const
Returns true if it is ok to switch to the Channel's transponder on this device, without disturbing an...
Definition: device.c:810
eTrackType currentSubtitleTrack
Definition: device.h:556
eTrackType GetCurrentSubtitleTrack(void) const
Definition: device.h:597
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition: device.c:230
static void Shutdown(void)
Closes down all devices.
Definition: device.c:465
cPatFilter * patFilter
Definition: device.h:443
eTrackType GetCurrentAudioTrack(void) const
Definition: device.h:593
cDevice(void)
Definition: device.c:79
bool DeviceHooksProvidesEIT(void) const
Definition: device.c:740
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
Definition: device.c:825
virtual int PlayTsVideo(const uchar *Data, int Length)
Plays the given data block as video.
Definition: device.c:1600
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition: device.c:167
virtual void SetPowerSaveMode(bool On)
Puts the device into power save mode, if applicable.
Definition: device.c:815
cEitFilter * eitFilter
Definition: device.h:442
virtual bool ProvidesEIT(void) const
Returns true if this device provides EIT data and thus wants to be tuned to the channels it can recei...
Definition: device.c:770
virtual void SetAudioChannelDevice(int AudioChannel)
Sets the audio channel to stereo (0), mono left (1) or mono right (2).
Definition: device.c:1027
cReceiver * receiver[MAXRECEIVERS]
Definition: device.h:848
void DelPid(int Pid, ePidType PidType=ptOther)
Deletes a PID from the set of PIDs this device shall receive.
Definition: device.c:625
bool AttachReceiver(cReceiver *Receiver)
Attaches the given receiver to this device.
Definition: device.c:1835
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
Definition: device.h:371
bool IsPrimaryDevice(bool CheckDecoder=true) const
Definition: device.h:223
virtual bool AvoidRecording(void) const
Returns true if this device should only be used for recording if no other device is available.
Definition: device.h:239
static cDevice * primaryDevice
Definition: device.h:127
static bool SetPrimaryDevice(int n)
Sets the primary device to 'n'.
Definition: device.c:194
bool Receiving(bool Dummy=false) const
Returns true if we are currently receiving. The parameter has no meaning (for backwards compatibility...
Definition: device.c:1734
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
Definition: device.c:1391
virtual int PlayTsAudio(const uchar *Data, int Length)
Plays the given data block as audio.
Definition: device.c:1619
time_t occupiedTimeout
Definition: device.h:266
void StopReplay(void)
Stops the current replay session (if any).
Definition: device.c:1434
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
Definition: device.c:186
virtual bool ProvidesTransponderExclusively(const cChannel *Channel) const
Returns true if this is the only device that is able to provide the given channel's transponder.
Definition: device.c:756
void DetachAll(int Pid)
Detaches all receivers from this device for this pid.
Definition: device.c:1919
virtual bool ProvidesChannel(const cChannel *Channel, int Priority=IDLEPRIORITY, bool *NeedsDetachReceivers=NULL) const
Returns true if this device can provide the given channel.
Definition: device.c:765
int cardIndex
Definition: device.h:189
virtual int SignalQuality(void) const
Returns the "quality" of the currently received signal.
Definition: device.c:795
virtual int SignalStrength(void) const
Returns the "strength" of the currently received signal.
Definition: device.c:790
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
Definition: device.c:1308
int GetAudioChannel(void)
Gets the current audio channel, which is stereo (0), mono left (1) or mono right (2).
Definition: device.c:1064
cPidHandle pidHandles[MAXPIDHANDLES]
Definition: device.h:419
void EnsureAudioTrack(bool Force=false)
Makes sure an audio track is selected that is actually available.
Definition: device.c:1227
void Detach(cFilter *Filter)
Detaches the given filter from this device.
Definition: device.c:718
cTsToPes tsToPesVideo
Definition: device.h:655
eTrackType currentAudioTrack
Definition: device.h:555
virtual bool SetPlayMode(ePlayMode PlayMode)
Sets the device into the given play mode.
Definition: device.c:1287
virtual bool OpenDvr(void)
Opens the DVR of this device and prepares it to deliver a Transport Stream for use in a cReceiver.
Definition: device.c:1821
const tTrackId * GetTrack(eTrackType Type)
Returns a pointer to the given track id, or NULL if Type is not less than ttMaxTrackTypes.
Definition: device.c:1143
void SetVolume(int Volume, bool Absolute=false)
Sets the volume to the given value, either absolutely or relative to the current volume.
Definition: device.c:1076
virtual void TrickSpeed(int Speed, bool Forward)
Sets the device into a mode where replay is done slower.
Definition: device.c:1297
cLiveSubtitle * liveSubtitle
Definition: device.h:254
virtual void Mute(void)
Turns off audio while replaying.
Definition: device.c:1322
virtual bool HasCi(void)
Returns true if this device has a Common Interface.
Definition: device.c:454
virtual cString DeviceType(void) const
Returns a string identifying the type of this device (like "DVB-S").
Definition: device.c:176
virtual const cChannel * GetCurrentlyTunedTransponder(void) const
Returns a pointer to the currently tuned transponder.
Definition: device.c:800
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
Definition: device.c:1315
void SetAudioChannel(int AudioChannel)
Sets the audio channel to stereo (0), mono left (1) or mono right (2).
Definition: device.c:1070
static int NumDevices(void)
Returns the total number of devices.
Definition: device.h:129
virtual int64_t GetSTC(void)
Gets the current System Time Counter, which can be used to synchronize audio, video and subtitles.
Definition: device.c:1292
time_t occupiedFrom
Definition: device.h:265
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder).
Definition: device.c:506
bool isPlayingVideo
Definition: device.h:658
virtual bool Flush(int TimeoutMs=0)
Returns true if the device's output buffers are empty, i.
Definition: device.c:1448
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
Definition: device.c:212
virtual int PlayTsSubtitle(const uchar *Data, int Length)
Plays the given data block as a subtitle.
Definition: device.c:1635
virtual void SetVideoFormat(bool VideoFormat16_9)
Sets the output video format to either 16:9 or 4:3 (only useful if this device has an MPEG decoder).
Definition: device.c:529
virtual void CloseDvr(void)
Shuts down the DVR.
Definition: device.c:1826
virtual void CloseFilter(int Handle)
Closes a file handle that has previously been opened by OpenFilter().
Definition: device.c:707
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
Definition: device.c:1006
bool AttachPlayer(cPlayer *Player)
Attaches the given player to this device.
Definition: device.c:1396
void ClrAvailableTracks(bool DescriptionsOnly=false, bool IdsOnly=false)
Clears the list of currently available tracks.
Definition: device.c:1091
virtual bool HasProgramme(void) const
Returns true if the device is currently showing any programme to the user, either through replaying o...
Definition: device.c:1016
friend class cLiveSubtitle
Definition: device.h:120
int volume
Definition: device.h:622
void EnsureSubtitleTrack(void)
Makes sure one of the preferred language subtitle tracks is selected.
Definition: device.c:1260
virtual void DetachAllReceivers(void)
Detaches all receivers from this device.
Definition: device.c:1932
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel's transponder.
Definition: device.c:805
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
Definition: device.c:1282
int NumTracks(eTrackType FirstTrack, eTrackType LastTrack) const
Returns the number of tracks in the given range that are currently available.
Definition: device.c:1148
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:148
void AttachFilter(cFilter *Filter)
Attaches the given filter to this device.
Definition: device.c:712
virtual cSpuDecoder * GetSpuDecoder(void)
Returns a pointer to the device's SPU decoder (or NULL, if this device doesn't have an SPU decoder).
Definition: device.c:217
virtual bool HasIBPTrickSpeed(void)
Returns true if this device can handle all frames in 'fast forward' trick speeds.
Definition: device.h:763
virtual bool Ready(void)
Returns true if this device is ready.
Definition: device.c:1729
cMutex mutexChannel
Definition: device.h:264
static cDevice * GetDeviceForTransponder(const cChannel *Channel, int Priority)
Returns a device that is not currently "occupied" and can be tuned to the transponder of the given Ch...
Definition: device.c:427
virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect)
Returns the Width, Height and PixelAspect ratio the OSD should use to best fit the resolution of the ...
Definition: device.c:540
tTrackId availableTracks[ttMaxTrackTypes]
Definition: device.h:554
virtual bool GetTSPacket(uchar *&Data)
Gets exactly one TS packet from the DVR of this device and returns a pointer to it in Data.
Definition: device.c:1830
virtual void Clear(void)
Clears all video and audio data from the device.
Definition: device.c:1301
cTsToPes tsToPesSubtitle
Definition: device.h:657
int CardIndex(void) const
Returns the card index of this device (0 ... MAXDEVICES - 1).
Definition: device.h:224
bool SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language=NULL, const char *Description=NULL)
Sets the track of the given Type and Index to the given values.
Definition: device.c:1114
void SetOccupied(int Seconds, int Priority=MINPRIORITY, time_t From=0)
Sets the occupied timeout for this device to the given number of Seconds, This can be used to tune a ...
Definition: device.c:991
static int numDevices
Definition: device.h:124
int NumAudioTracks(void) const
Returns the number of audio tracks that are currently available.
Definition: device.c:1158
virtual int PlayPesPacket(const uchar *Data, int Length, bool VideoOnly=false)
Plays the single PES packet in Data with the given Length.
Definition: device.c:1473
bool ToggleMute(void)
Turns the volume off or on and returns the new mute state.
Definition: device.c:1047
void SetPowerSaveIfUnused(void)
Sets this device into a power save mode if it is not currently used and has implemented SetPowerSaveM...
Definition: device.c:819
void DelLivePids(void)
Deletes the live viewing PIDs.
Definition: device.c:661
static int currentChannel
Definition: device.h:269
virtual int PlayTs(const uchar *Data, int Length, bool VideoOnly=false)
Plays the given TS packet.
Definition: device.c:1651
cPatPmtParser patPmtParser
Definition: device.h:654
bool AddPid(int Pid, ePidType PidType=ptOther, int StreamType=0)
Adds a PID to the set of PIDs this device shall receive.
Definition: device.c:560
virtual ~cDevice() override
Definition: device.c:122
cMutex mutexCurrentSubtitleTrack
Definition: device.h:558
int pre_1_3_19_PrivateStream
Definition: device.h:562
bool DeviceHooksProvidesTransponder(const cChannel *Channel) const
Definition: device.c:729
virtual int ReadFilter(int Handle, void *Buffer, size_t Length)
Reads data from a handle for the given filter.
Definition: device.c:702
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask)
Opens a file handle for the given filter data.
Definition: device.c:697
cSdtFilter * sdtFilter
Definition: device.h:444
static cDevice * device[MAXDEVICES]
Definition: device.h:126
int occupiedPriority
Definition: device.h:267
void ForceTransferMode(void)
Forces the device into transfermode for the current channel.
Definition: device.c:972
virtual int PlayAudio(const uchar *Data, int Length, uchar Id)
Plays the given data block as audio.
Definition: device.c:1458
cMutex mutexPids
Definition: device.h:407
bool SetCurrentAudioTrack(eTrackType Type)
Sets the current audio track to the given Type.
Definition: device.c:1168
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
Definition: device.c:1748
void SetTempSubtitles(void)
Temporarily turn on subtitles after a fast rewind during reply.
Definition: device.c:1221
virtual bool ProvidesTransponder(const cChannel *Channel) const
Returns true if this device can provide the transponder of the given Channel (which implies that it c...
Definition: device.c:751
virtual void SetDigitalAudioDevice(bool On)
Tells the output device that the current audio track is Dolby Digital.
Definition: device.c:1035
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use.
Definition: device.h:493
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
Definition: device.c:1327
virtual int PlaySubtitle(const uchar *Data, int Length)
Plays the given data block as a subtitle.
Definition: device.c:1463
virtual void SetVolumeDevice(int Volume)
Sets the audio volume on this device (Volume = 0...255).
Definition: device.c:1031
int Convert(const uchar *Data, int Length)
Definition: dvbsubtitle.c:1472
void Freeze(bool Status)
Definition: dvbsubtitle.h:59
void SetTempVisible(void)
Definition: dvbsubtitle.c:1399
void SetVisible(bool Visible)
Definition: dvbsubtitle.c:1390
int ConvertFragments(const uchar *Data, int Length)
Definition: dvbsubtitle.c:1426
Definition: eit.h:48
Definition: filter.h:74
virtual void Clear(void)
Definition: tools.c:2254
int Count(void) const
Definition: tools.h:627
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2177
int Index(void) const
Definition: tools.c:2097
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
Definition: tools.h:650
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
Definition: tools.h:643
const T * Get(int Index) const
Returns the list element at the given Index, or NULL if no such element exists.
Definition: tools.h:640
virtual ~cLiveSubtitle() override
Definition: device.c:38
cLiveSubtitle(int SPid)
Definition: device.c:33
virtual void Receive(const uchar *Data, int Length) override
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
Definition: device.c:43
void Lock(void)
Definition: thread.c:223
void Unlock(void)
Definition: thread.c:229
Definition: nit.h:16
Definition: pat.h:21
void Request(int Sid)
Definition: pat.c:408
void Release(int Sid)
Definition: pat.c:431
void Reset(void)
Resets the parser.
Definition: remux.c:619
void ParsePat(const uchar *Data, int Length)
Parses the PAT data from the single TS packet in Data.
Definition: remux.c:629
void ParsePmt(const uchar *Data, int Length)
Parses the PMT data from the single TS packet in Data.
Definition: remux.c:661
bool IsPmtPid(int Pid) const
Returns true if Pid the one of the PMT pids as defined by the current PAT.
Definition: remux.h:400
int Ppid(void) const
Returns the PCR pid as defined by the current PMT, or 0 if no PCR pid has been detected,...
Definition: remux.h:406
int Vpid(void) const
Returns the video pid as defined by the current PMT, or 0 if no video pid has been detected,...
Definition: remux.h:403
Definition: player.h:16
virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId)
Definition: player.h:73
ePlayMode playMode
Definition: player.h:20
virtual void Activate(bool On)
Definition: player.h:40
virtual void SetSubtitleTrack(eTrackType Type, const tTrackId *TrackId)
Definition: player.h:77
cDevice * device
Definition: player.h:19
Definition: tools.h:434
bool Poll(int TimeoutMs=0)
Definition: tools.c:1585
A steerable satellite dish generally points to the south on the northern hemisphere,...
Definition: positioner.h:31
time_t lastEitInjection
Definition: receiver.h:29
int Priority(void)
Definition: receiver.h:57
bool WantsPid(int Pid)
Definition: receiver.c:114
time_t startEitInjection
Definition: receiver.h:28
int pids[MAXRECEIVEPIDS]
Definition: receiver.h:23
tChannelID ChannelID(void)
Definition: receiver.h:80
void Detach(void)
Definition: receiver.c:125
cDevice * device
Definition: receiver.h:20
int priority
Definition: receiver.h:22
virtual void Receive(const uchar *Data, int Length)=0
This function is called from the cDevice we are attached to, and delivers one TS packet from the set ...
int numPids
Definition: receiver.h:24
bool AddPid(int Pid)
Adds the given Pid to the list of PIDs of this receiver.
Definition: receiver.c:42
time_t startScrambleDetection
Definition: receiver.h:26
time_t lastScrambledPacket
Definition: receiver.h:25
int scramblingTimeout
Definition: receiver.h:27
virtual void Activate(bool On)
This function is called just before the cReceiver gets attached to (On == true) and right after it ge...
Definition: receiver.h:34
void Del(int Count)
Deletes at most Count bytes from the ring buffer.
Definition: ringbuffer.c:371
uchar * Get(int &Count)
Gets data from the ring buffer.
Definition: ringbuffer.c:346
int Read(int FileHandle, int Max=0)
Reads at most Max bytes from FileHandle and stores them in the ring buffer.
Definition: ringbuffer.c:230
virtual int Available(void) override
Definition: ringbuffer.c:211
void SetTimeouts(int PutTimeout, int GetTimeout)
Definition: ringbuffer.c:89
void SetIoThrottle(void)
Definition: ringbuffer.c:95
Definition: sdt.h:16
void SetChannel(const cChannel *Channel)
Definition: sections.c:140
void SetStatus(bool On)
Definition: sections.c:147
void Attach(cFilter *Filter)
Definition: sections.c:119
void Detach(cFilter *Filter)
Definition: sections.c:130
int VolumeSteps
Definition: config.h:376
int VideoDisplayFormat
Definition: config.h:333
int CurrentVolume
Definition: config.h:375
int SubtitleLanguages[I18N_MAX_LANGUAGES+1]
Definition: config.h:302
int DisplaySubtitles
Definition: config.h:301
int VolumeLinearize
Definition: config.h:377
int AudioLanguages[I18N_MAX_LANGUAGES+1]
Definition: config.h:300
int VideoFormat
Definition: config.h:334
int PrimaryDVB
Definition: config.h:276
int UseDolbyDigital
Definition: config.h:336
int CurrentDolby
Definition: config.h:378
int QueueMessage(eMessageType Type, const char *s, int Seconds=0, int Timeout=0)
Like Message(), but this function may be called from a background thread.
Definition: skins.c:330
@ eSpuPanAndScan
Definition: spu.h:21
@ eSpuNormal
Definition: spu.h:21
@ eSpuLetterBox
Definition: spu.h:21
virtual void setScaleMode(cSpuDecoder::eScaleMode ScaleMode)=0
static void MsgSetVolume(int Volume, bool Absolute)
Definition: status.c:69
static void MsgChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView)
Definition: status.c:45
Definition: tools.h:178
cTSBuffer(int File, int Size, int DeviceNumber)
Definition: device.c:1942
int delivered
Definition: device.h:895
uchar * Get(int *Available=NULL, bool CheckAvailable=false)
Returns a pointer to the first TS packet in the buffer.
Definition: device.c:1983
virtual ~cTSBuffer() override
Definition: device.c:1954
cRingBufferLinear * ringBuffer
Definition: device.h:896
void Skip(int Count)
If after a call to Get() more or less than TS_SIZE of the available data has been processed,...
Definition: device.c:2013
int deviceNumber
Definition: device.h:894
int f
Definition: device.h:893
virtual void Action(void) override
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
Definition: device.c:1960
void Unlock(void)
Definition: thread.h:95
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
Definition: thread.c:305
void SetDescription(const char *Description,...) __attribute__((format(printf
Definition: thread.c:268
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
Definition: thread.h:101
void Lock(void)
Definition: thread.h:94
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
Definition: thread.c:355
char * description
Definition: thread.h:87
static cDevice * ReceiverDevice(void)
Definition: transfer.h:38
void PutTs(const uchar *Data, int Length)
Puts the payload data of the single TS packet at Data into the converter.
Definition: remux.c:1048
void SetRepeatLast(void)
Makes the next call to GetPes() return exactly the same data as the last one (provided there was no c...
Definition: remux.c:1125
const uchar * GetPes(int &Length)
Gets a pointer to the complete PES packet, or NULL if the packet is not complete yet.
Definition: remux.c:1077
void Reset(void)
Resets the converter.
Definition: remux.c:1130
cSetup Setup
Definition: config.c:372
#define MINPRIORITY
Definition: config.h:46
#define TRANSFERPRIORITY
Definition: config.h:48
#define MAXPRIORITY
Definition: config.h:45
#define SUBTITLES_ALWAYS
Definition: config.h:86
#define IDLEPRIORITY
Definition: config.h:49
#define SUBTITLES_REWIND
Definition: config.h:87
#define LIVEPRIORITY
Definition: config.h:47
#define EIT_INJECTION_TIME
Definition: device.c:1746
static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device)
Definition: device.c:235
#define PRINTPIDS(s)
Definition: device.c:548
#define TS_SCRAMBLING_TIMEOUT
Definition: device.c:1744
#define MIN_PRE_1_3_19_PRIVATESTREAM
Definition: device.c:69
#define TS_SCRAMBLING_TIME_OK
Definition: device.c:1745
#define MAXVOLUME
Definition: device.h:32
#define MAXPIDHANDLES
Definition: device.h:30
eVideoDisplayFormat
Definition: device.h:58
@ vdfLetterBox
Definition: device.h:59
@ vdfCenterCutOut
Definition: device.h:60
@ vdfPanAndScan
Definition: device.h:58
ePlayMode
Definition: device.h:39
@ pmNone
Definition: device.h:39
#define MAXDEVICES
Definition: device.h:29
#define MAXOCCUPIEDTIMEOUT
Definition: device.h:34
#define IS_AUDIO_TRACK(t)
Definition: device.h:76
eTrackType
Definition: device.h:63
@ ttSubtitle
Definition: device.h:70
@ ttMaxTrackTypes
Definition: device.h:73
@ ttDolbyLast
Definition: device.h:69
@ ttAudioLast
Definition: device.h:66
@ ttDolby
Definition: device.h:67
@ ttAudioFirst
Definition: device.h:65
@ ttSubtitleLast
Definition: device.h:72
@ ttDolbyFirst
Definition: device.h:68
@ ttSubtitleFirst
Definition: device.h:71
@ ttAudio
Definition: device.h:64
@ ttNone
Definition: device.h:63
#define MAXRECEIVERS
Definition: device.h:31
#define IS_SUBTITLE_TRACK(t)
Definition: device.h:78
#define IS_DOLBY_TRACK(t)
Definition: device.h:77
eSetChannelResult
Definition: device.h:36
@ scrOk
Definition: device.h:36
@ scrNotAvailable
Definition: device.h:36
@ scrFailed
Definition: device.h:36
@ scrNoTransfer
Definition: device.h:36
bool I18nIsPreferredLanguage(int *PreferredLanguages, const char *LanguageCode, int &OldPreference, int *Position)
Checks the given LanguageCode (which may be something like "eng" or "eng+deu") against the PreferredL...
Definition: i18n.c:317
#define tr(s)
Definition: i18n.h:85
unsigned char u_char
Definition: headers.h:24
int TsPid(const uchar *p)
Definition: remux.h:82
bool TsHasPayload(const uchar *p)
Definition: remux.h:62
#define PATPID
Definition: remux.h:52
bool TsIsScrambled(const uchar *p)
Definition: remux.h:93
#define TS_SIZE
Definition: remux.h:34
bool TsPayloadStart(const uchar *p)
Definition: remux.h:72
#define TS_SYNC(Data, Length)
Definition: remux.h:149
int TsPayloadOffset(const uchar *p)
Definition: remux.h:108
#define TS_SYNC_BYTE
Definition: remux.h:33
int PesLength(const uchar *p)
Definition: remux.h:173
cSkins Skins
Definition: skins.c:253
@ mtInfo
Definition: skins.h:37
@ mtError
Definition: skins.h:37
int Sid(void) const
Definition: channels.h:66
bool Valid(void) const
Definition: channels.h:60
cString ToString(void) const
Definition: channels.c:41
char language[MAXLANGCODE2]
Definition: device.h:82
uint16_t id
Definition: device.h:81
#define LOCK_THREAD
Definition: thread.h:167
char * Utf8Strn0Cpy(char *Dest, const char *Src, int n)
Copies at most n character bytes from Src to Dest, making sure that the resulting copy ends with a co...
Definition: tools.c:915
ssize_t safe_read(int filedes, void *buffer, size_t size)
Definition: tools.c:53
ssize_t safe_write(int filedes, const void *buffer, size_t size)
Definition: tools.c:65
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
#define FATALERRNO
Definition: tools.h:52
T constrain(T v, T l, T h)
Definition: tools.h:70
#define LOG_ERROR_STR(s)
Definition: tools.h:40
unsigned char uchar
Definition: tools.h:31
#define dsyslog(a...)
Definition: tools.h:37
int sgn(T a)
Definition: tools.h:68
void DELETENULL(T *&p)
Definition: tools.h:49
T min(T a, T b)
Definition: tools.h:63
T max(T a, T b)
Definition: tools.h:64
#define esyslog(a...)
Definition: tools.h:35
#define LOG_ERROR
Definition: tools.h:39
#define isyslog(a...)
Definition: tools.h:36