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