vdr  2.0.2
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 2.74.1.1 2013/04/05 10:47:38 kls Exp $
8  */
9 
10 #include "device.h"
11 #include <errno.h>
12 #include <sys/ioctl.h>
13 #include <sys/mman.h>
14 #include "audio.h"
15 #include "channels.h"
16 #include "i18n.h"
17 #include "player.h"
18 #include "receiver.h"
19 #include "status.h"
20 #include "transfer.h"
21 #include "vdrttxtsubshooks.h"
22 
23 // --- cLiveSubtitle ---------------------------------------------------------
24 
25 class cLiveSubtitle : public cReceiver {
26 protected:
27  virtual void Receive(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(uchar *Data, int Length)
44 {
46  cDevice::PrimaryDevice()->PlayTs(Data, Length);
47 }
48 
49 // --- cDeviceHook -----------------------------------------------------------
50 
52 {
54 }
55 
56 bool cDeviceHook::DeviceProvidesTransponder(const cDevice *Device, const cChannel *Channel) const
57 {
58  return true;
59 }
60 
61 // --- 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", CardIndex() + 1);
79 
80  SetDescription("receiver on device %d", CardIndex() + 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;
93 
94  occupiedTimeout = 0;
95 
96  player = NULL;
97  isPlayingVideo = false;
98  keepTracks = false; // used in ClrAvailableTracks()!
103  liveSubtitle = NULL;
104  dvbSubtitleConverter = NULL;
106 
107  for (int i = 0; i < MAXRECEIVERS; i++)
108  receiver[i] = NULL;
109 
110  if (numDevices < MAXDEVICES)
111  device[numDevices++] = this;
112  else
113  esyslog("ERROR: too many devices!");
114 }
115 
117 {
118  Detach(player);
120  delete liveSubtitle;
121  delete dvbSubtitleConverter;
122 }
123 
125 {
126  for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
127  bool ready = true;
128  for (int i = 0; i < numDevices; i++) {
129  if (device[i] && !device[i]->Ready()) {
130  ready = false;
131  cCondWait::SleepMs(100);
132  }
133  }
134  if (ready)
135  return true;
136  }
137  return false;
138 }
139 
141 {
142  if (n < MAXDEVICES)
143  useDevice |= (1 << n);
144 }
145 
147 {
148  if (n > 0) {
149  nextCardIndex += n;
150  if (nextCardIndex >= MAXDEVICES)
151  esyslog("ERROR: nextCardIndex too big (%d)", nextCardIndex);
152  }
153  else if (n < 0)
154  esyslog("ERROR: invalid value in nextCardIndex(%d)", n);
155  return nextCardIndex;
156 }
157 
158 int cDevice::DeviceNumber(void) const
159 {
160  for (int i = 0; i < numDevices; i++) {
161  if (device[i] == this)
162  return i;
163  }
164  return -1;
165 }
166 
168 {
169  return "";
170 }
171 
173 {
174  return "";
175 }
176 
178 {
179  if (!On) {
182  }
183 }
184 
186 {
187  n--;
188  if (0 <= n && n < numDevices && device[n]) {
189  isyslog("setting primary device to %d", n + 1);
190  if (primaryDevice)
192  primaryDevice = device[n];
196  return true;
197  }
198  esyslog("ERROR: invalid primary device number: %d", n + 1);
199  return false;
200 }
201 
202 bool cDevice::HasDecoder(void) const
203 {
204  return false;
205 }
206 
208 {
209  return NULL;
210 }
211 
213 {
215  if (!d)
216  d = PrimaryDevice();
217  return d;
218 }
219 
221 {
222  return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
223 }
224 
225 static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device)
226 {
227  int MaxNumProvidedSystems = (1 << AvailableBits) - 1;
228  int NumProvidedSystems = Device->NumProvidedSystems();
229  if (NumProvidedSystems > MaxNumProvidedSystems) {
230  esyslog("ERROR: device %d supports %d modulation systems but cDevice::GetDevice() currently only supports %d delivery systems which should be fixed", Device->CardIndex() + 1, NumProvidedSystems, MaxNumProvidedSystems);
231  NumProvidedSystems = MaxNumProvidedSystems;
232  }
233  else if (NumProvidedSystems <= 0) {
234  esyslog("ERROR: device %d reported an invalid number (%d) of supported delivery systems - assuming 1", Device->CardIndex() + 1, NumProvidedSystems);
235  NumProvidedSystems = 1;
236  }
237  return NumProvidedSystems;
238 }
239 
240 cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool Query)
241 {
242  // Collect the current priorities of all CAM slots that can decrypt the channel:
243  int NumCamSlots = CamSlots.Count();
244  int SlotPriority[NumCamSlots];
245  int NumUsableSlots = 0;
246  bool InternalCamNeeded = false;
247  if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
249  SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used
250  if (CamSlot->ModuleStatus() == msReady) {
251  if (CamSlot->ProvidesCa(Channel->Caids())) {
253  SlotPriority[CamSlot->Index()] = CamSlot->Priority();
254  NumUsableSlots++;
255  }
256  }
257  }
258  }
259  if (!NumUsableSlots)
260  InternalCamNeeded = true; // no CAM is able to decrypt this channel
261  }
262 
263  bool NeedsDetachReceivers = false;
264  cDevice *d = NULL;
265  cCamSlot *s = NULL;
266 
267  uint32_t Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
268  for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) {
269  if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY)
270  continue; // there is no CAM available in this slot
271  for (int i = 0; i < numDevices; i++) {
272  if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != device[i]->CardIndex() + 1)
273  continue; // a specific card was requested, but not this one
274  bool HasInternalCam = device[i]->HasInternalCam();
275  if (InternalCamNeeded && !HasInternalCam)
276  continue; // no CAM is able to decrypt this channel and the device uses vdr handled CAMs
277  if (NumUsableSlots && !HasInternalCam && !CamSlots.Get(j)->Assign(device[i], true))
278  continue; // CAM slot can't be used with this device
279  bool ndr;
280  if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job
281  if (NumUsableSlots && !HasInternalCam && device[i]->CamSlot() && device[i]->CamSlot() != CamSlots.Get(j))
282  ndr = true; // using a different CAM slot requires detaching receivers
283  // Put together an integer number that reflects the "impact" using
284  // this device would have on the overall system. Each condition is represented
285  // by one bit in the number (or several bits, if the condition is actually
286  // a numeric value). The sequence in which the conditions are listed corresponds
287  // to their individual severity, where the one listed first will make the most
288  // difference, because it results in the most significant bit of the result.
289  uint32_t imp = 0;
290  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
291  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
292  imp <<= 1; imp |= device[i]->Receiving(); // avoid devices that are receiving
293  imp <<= 4; imp |= GetClippedNumProvidedSystems(4, device[i]) - 1; // avoid cards which support multiple delivery systems
294  imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device
295  imp <<= 8; imp |= device[i]->Priority() - IDLEPRIORITY; // use the device with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
296  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)
297  imp <<= 1; imp |= ndr; // avoid devices if we need to detach existing receivers
298  imp <<= 1; imp |= (NumUsableSlots || InternalCamNeeded) ? 0 : device[i]->HasCi(); // avoid cards with Common Interface for FTA channels
299  imp <<= 1; imp |= device[i]->AvoidRecording(); // avoid SD full featured cards
300  imp <<= 1; imp |= (NumUsableSlots && !HasInternalCam) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
301  imp <<= 1; imp |= device[i]->IsPrimaryDevice(); // avoid the primary device
302  if (imp < Impact) {
303  // This device has less impact than any previous one, so we take it.
304  Impact = imp;
305  d = device[i];
306  NeedsDetachReceivers = ndr;
307  if (NumUsableSlots && !HasInternalCam)
308  s = CamSlots.Get(j);
309  }
310  }
311  }
312  if (!NumUsableSlots)
313  break; // no CAM necessary, so just one loop over the devices
314  }
315  if (d && !Query) {
316  if (NeedsDetachReceivers)
317  d->DetachAllReceivers();
318  if (s) {
319  if (s->Device() != d) {
320  if (s->Device())
321  s->Device()->DetachAllReceivers();
322  if (d->CamSlot())
323  d->CamSlot()->Assign(NULL);
324  s->Assign(d);
325  }
326  }
327  else if (d->CamSlot() && !d->CamSlot()->IsDecrypting())
328  d->CamSlot()->Assign(NULL);
329  }
330  return d;
331 }
332 
333 cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority)
334 {
335  cDevice *Device = NULL;
336  for (int i = 0; i < cDevice::NumDevices(); i++) {
337  if (cDevice *d = cDevice::GetDevice(i)) {
338  if (d->IsTunedToTransponder(Channel))
339  return d; // if any device is tuned to the transponder, we're done
340  if (d->ProvidesTransponder(Channel)) {
341  if (d->MaySwitchTransponder(Channel))
342  Device = d; // this device may switch to the transponder without disturbing any receiver or live view
343  else if (!d->Occupied() && d->MaySwitchTransponder(Channel)) { // MaySwitchTransponder() implicitly calls Occupied()
344  if (d->Priority() < Priority && (!Device || d->Priority() < Device->Priority()))
345  Device = d; // use this one only if no other with less impact can be found
346  }
347  }
348  }
349  }
350  return Device;
351 }
352 
353 bool cDevice::HasCi(void)
354 {
355  return false;
356 }
357 
359 {
360  camSlot = CamSlot;
361 }
362 
364 {
365  deviceHooks.Clear();
366  primaryDevice = NULL;
367  for (int i = 0; i < numDevices; i++) {
368  delete device[i];
369  device[i] = NULL;
370  }
371 }
372 
373 uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
374 {
375  return NULL;
376 }
377 
378 bool cDevice::GrabImageFile(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
379 {
380  int result = 0;
381  int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE);
382  if (fd >= 0) {
383  int ImageSize;
384  uchar *Image = GrabImage(ImageSize, Jpeg, Quality, SizeX, SizeY);
385  if (Image) {
386  if (safe_write(fd, Image, ImageSize) == ImageSize)
387  isyslog("grabbed image to %s", FileName);
388  else {
389  LOG_ERROR_STR(FileName);
390  result |= 1;
391  }
392  free(Image);
393  }
394  else
395  result |= 1;
396  close(fd);
397  }
398  else {
399  LOG_ERROR_STR(FileName);
400  result |= 1;
401  }
402  return result == 0;
403 }
404 
406 {
407  cSpuDecoder *spuDecoder = GetSpuDecoder();
408  if (spuDecoder) {
409  if (Setup.VideoFormat)
411  else {
412  switch (VideoDisplayFormat) {
413  case vdfPanAndScan:
415  break;
416  case vdfLetterBox:
418  break;
419  case vdfCenterCutOut:
421  break;
422  default: esyslog("ERROR: invalid value for VideoDisplayFormat '%d'", VideoDisplayFormat);
423  }
424  }
425  }
426 }
427 
428 void cDevice::SetVideoFormat(bool VideoFormat16_9)
429 {
430 }
431 
433 {
434  return vsPAL;
435 }
436 
437 void cDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
438 {
439  Width = 0;
440  Height = 0;
441  VideoAspect = 1.0;
442 }
443 
444 void cDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
445 {
446  Width = 720;
447  Height = 480;
448  PixelAspect = 1.0;
449 }
450 
451 //#define PRINTPIDS(s) { char b[500]; char *q = b; q += sprintf(q, "%d %s ", CardIndex(), s); for (int i = 0; i < MAXPIDHANDLES; i++) q += sprintf(q, " %s%4d %d", i == ptOther ? "* " : "", pidHandles[i].pid, pidHandles[i].used); dsyslog("%s", b); }
452 #define PRINTPIDS(s)
453 
454 bool cDevice::HasPid(int Pid) const
455 {
456  for (int i = 0; i < MAXPIDHANDLES; i++) {
457  if (pidHandles[i].pid == Pid)
458  return true;
459  }
460  return false;
461 }
462 
463 bool cDevice::AddPid(int Pid, ePidType PidType, int StreamType)
464 {
465  if (Pid || PidType == ptPcr) {
466  int n = -1;
467  int a = -1;
468  if (PidType != ptPcr) { // PPID always has to be explicit
469  for (int i = 0; i < MAXPIDHANDLES; i++) {
470  if (i != ptPcr) {
471  if (pidHandles[i].pid == Pid)
472  n = i;
473  else if (a < 0 && i >= ptOther && !pidHandles[i].used)
474  a = i;
475  }
476  }
477  }
478  if (n >= 0) {
479  // The Pid is already in use
480  if (++pidHandles[n].used == 2 && n <= ptTeletext) {
481  // It's a special PID that may have to be switched into "tap" mode
482  PRINTPIDS("A");
483  if (!SetPid(&pidHandles[n], n, true)) {
484  esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1);
485  if (PidType <= ptTeletext)
486  DetachAll(Pid);
487  DelPid(Pid, PidType);
488  return false;
489  }
490  if (camSlot)
491  camSlot->SetPid(Pid, true);
492  }
493  PRINTPIDS("a");
494  return true;
495  }
496  else if (PidType < ptOther) {
497  // The Pid is not yet in use and it is a special one
498  n = PidType;
499  }
500  else if (a >= 0) {
501  // The Pid is not yet in use and we have a free slot
502  n = a;
503  }
504  else {
505  esyslog("ERROR: no free slot for PID %d on device %d", Pid, CardIndex() + 1);
506  return false;
507  }
508  if (n >= 0) {
509  pidHandles[n].pid = Pid;
510  pidHandles[n].streamType = StreamType;
511  pidHandles[n].used = 1;
512  PRINTPIDS("C");
513  if (!SetPid(&pidHandles[n], n, true)) {
514  esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1);
515  if (PidType <= ptTeletext)
516  DetachAll(Pid);
517  DelPid(Pid, PidType);
518  return false;
519  }
520  if (camSlot)
521  camSlot->SetPid(Pid, true);
522  }
523  }
524  return true;
525 }
526 
527 void cDevice::DelPid(int Pid, ePidType PidType)
528 {
529  if (Pid || PidType == ptPcr) {
530  int n = -1;
531  if (PidType == ptPcr)
532  n = PidType; // PPID always has to be explicit
533  else {
534  for (int i = 0; i < MAXPIDHANDLES; i++) {
535  if (pidHandles[i].pid == Pid) {
536  n = i;
537  break;
538  }
539  }
540  }
541  if (n >= 0 && pidHandles[n].used) {
542  PRINTPIDS("D");
543  if (--pidHandles[n].used < 2) {
544  SetPid(&pidHandles[n], n, false);
545  if (pidHandles[n].used == 0) {
546  pidHandles[n].handle = -1;
547  pidHandles[n].pid = 0;
548  if (camSlot)
549  camSlot->SetPid(Pid, false);
550  }
551  }
552  PRINTPIDS("E");
553  }
554  }
555 }
556 
557 bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
558 {
559  return false;
560 }
561 
563 {
564  for (int i = ptAudio; i < ptOther; i++) {
565  if (pidHandles[i].pid)
566  DelPid(pidHandles[i].pid, ePidType(i));
567  }
568 }
569 
571 {
572  if (!sectionHandler) {
573  sectionHandler = new cSectionHandler(this);
578  }
579 }
580 
582 {
583  if (sectionHandler) {
584  delete nitFilter;
585  delete sdtFilter;
586  delete patFilter;
587  delete eitFilter;
588  delete sectionHandler;
589  nitFilter = NULL;
590  sdtFilter = NULL;
591  patFilter = NULL;
592  eitFilter = NULL;
593  sectionHandler = NULL;
594  }
595 }
596 
597 int cDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
598 {
599  return -1;
600 }
601 
602 int cDevice::ReadFilter(int Handle, void *Buffer, size_t Length)
603 {
604  return safe_read(Handle, Buffer, Length);
605 }
606 
607 void cDevice::CloseFilter(int Handle)
608 {
609  close(Handle);
610 }
611 
613 {
614  if (sectionHandler)
615  sectionHandler->Attach(Filter);
616 }
617 
619 {
620  if (sectionHandler)
621  sectionHandler->Detach(Filter);
622 }
623 
624 bool cDevice::ProvidesSource(int Source) const
625 {
626  return false;
627 }
628 
630 {
631  cDeviceHook *Hook = deviceHooks.First();
632  while (Hook) {
633  if (!Hook->DeviceProvidesTransponder(this, Channel))
634  return false;
635  Hook = deviceHooks.Next(Hook);
636  }
637  return true;
638 }
639 
640 bool cDevice::ProvidesTransponder(const cChannel *Channel) const
641 {
642  return false;
643 }
644 
646 {
647  for (int i = 0; i < numDevices; i++) {
648  if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
649  return false;
650  }
651  return true;
652 }
653 
654 bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
655 {
656  return false;
657 }
658 
659 bool cDevice::ProvidesEIT(void) const
660 {
661  return false;
662 }
663 
665 {
666  return 0;
667 }
668 
669 int cDevice::SignalStrength(void) const
670 {
671  return -1;
672 }
673 
674 int cDevice::SignalQuality(void) const
675 {
676  return -1;
677 }
678 
680 {
681  return NULL;
682 }
683 
684 bool cDevice::IsTunedToTransponder(const cChannel *Channel) const
685 {
686  return false;
687 }
688 
689 bool cDevice::MaySwitchTransponder(const cChannel *Channel) const
690 {
691  return time(NULL) > occupiedTimeout && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid);
692 }
693 
694 bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
695 {
696  if (LiveView) {
697  isyslog("switching to channel %d", Channel->Number());
698  cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
699  }
700  for (int i = 3; i--;) {
701  switch (SetChannel(Channel, LiveView)) {
702  case scrOk: return true;
703  case scrNotAvailable: Skins.Message(mtInfo, tr("Channel not available!"));
704  return false;
705  case scrNoTransfer: Skins.Message(mtError, tr("Can't start Transfer Mode!"));
706  return false;
707  case scrFailed: break; // loop will retry
708  default: esyslog("ERROR: invalid return value from SetChannel");
709  }
710  esyslog("retrying");
711  }
712  return false;
713 }
714 
715 bool cDevice::SwitchChannel(int Direction)
716 {
717  bool result = false;
718  Direction = sgn(Direction);
719  if (Direction) {
720  cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
721  int n = CurrentChannel() + Direction;
722  int first = n;
723  cChannel *channel;
724  while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
725  // try only channels which are currently available
726  if (GetDevice(channel, LIVEPRIORITY, true, true))
727  break;
728  n = channel->Number() + Direction;
729  }
730  if (channel) {
731  int d = n - first;
732  if (abs(d) == 1)
733  dsyslog("skipped channel %d", first);
734  else if (d)
735  dsyslog("skipped channels %d..%d", first, n - sgn(d));
736  if (PrimaryDevice()->SwitchChannel(channel, true))
737  result = true;
738  }
739  else if (n != first)
740  Skins.Message(mtError, tr("Channel not available!"));
741  }
742  return result;
743 }
744 
745 eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
746 {
747  cStatus::MsgChannelSwitch(this, 0, LiveView);
748 
749  if (LiveView) {
750  StopReplay();
753  }
754 
755  cDevice *Device = (LiveView && IsPrimaryDevice()) ? GetDevice(Channel, LIVEPRIORITY, true) : this;
756 
757  bool NeedsTransferMode = Device != this;
758 
759  eSetChannelResult Result = scrOk;
760 
761  // If this DVB card can't receive this channel, let's see if we can
762  // use the card that actually can receive it and transfer data from there:
763 
764  if (NeedsTransferMode) {
765  if (Device && CanReplay()) {
766  if (Device->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
767  cControl::Launch(new cTransferControl(Device, Channel));
768  else
769  Result = scrNoTransfer;
770  }
771  else
772  Result = scrNotAvailable;
773  }
774  else {
775  Channels.Lock(false);
776  // Stop section handling:
777  if (sectionHandler) {
778  sectionHandler->SetStatus(false);
779  sectionHandler->SetChannel(NULL);
780  }
781  // Tell the camSlot about the channel switch and add all PIDs of this
782  // channel to it, for possible later decryption:
783  if (camSlot)
784  camSlot->AddChannel(Channel);
785  if (SetChannelDevice(Channel, LiveView)) {
786  // Start section handling:
787  if (sectionHandler) {
788  sectionHandler->SetChannel(Channel);
789  sectionHandler->SetStatus(true);
790  }
791  // Start decrypting any PIDs that might have been set in SetChannelDevice():
792  if (camSlot)
794  }
795  else
796  Result = scrFailed;
797  Channels.Unlock();
798  }
799 
800  if (Result == scrOk) {
801  if (LiveView && IsPrimaryDevice()) {
802  currentChannel = Channel->Number();
803  // Set the available audio tracks:
805  for (int i = 0; i < MAXAPIDS; i++)
806  SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
807  if (Setup.UseDolbyDigital) {
808  for (int i = 0; i < MAXDPIDS; i++)
809  SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
810  }
811  for (int i = 0; i < MAXSPIDS; i++)
812  SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
813  if (!NeedsTransferMode)
814  EnsureAudioTrack(true);
816  }
817  cStatus::MsgChannelSwitch(this, Channel->Number(), LiveView); // only report status if channel switch successful
818  }
819 
820  return Result;
821 }
822 
824 {
827  if (Channel)
828  SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
829  }
830 }
831 
832 int cDevice::Occupied(void) const
833 {
834  int Seconds = occupiedTimeout - time(NULL);
835  return Seconds > 0 ? Seconds : 0;
836 }
837 
838 void cDevice::SetOccupied(int Seconds)
839 {
840  if (Seconds >= 0)
841  occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
842 }
843 
844 bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
845 {
846  return false;
847 }
848 
849 bool cDevice::HasLock(int TimeoutMs) const
850 {
851  return true;
852 }
853 
854 bool cDevice::HasProgramme(void) const
855 {
857 }
858 
860 {
861  return 0;
862 }
863 
864 void cDevice::SetAudioChannelDevice(int AudioChannel)
865 {
866 }
867 
868 void cDevice::SetVolumeDevice(int Volume)
869 {
870 }
871 
873 {
874 }
875 
877 {
878 }
879 
881 {
882 }
883 
885 {
886  int OldVolume = volume;
887  mute = !mute;
888  //XXX why is it necessary to use different sequences???
889  if (mute) {
890  SetVolume(0, true);
891  Audios.MuteAudio(mute); // Mute external audio after analog audio
892  }
893  else {
894  Audios.MuteAudio(mute); // Enable external audio before analog audio
895  SetVolume(OldVolume, true);
896  }
897  volume = OldVolume;
898  return mute;
899 }
900 
902 {
903  int c = GetAudioChannelDevice();
904  return (0 <= c && c <= 2) ? c : 0;
905 }
906 
907 void cDevice::SetAudioChannel(int AudioChannel)
908 {
909  if (0 <= AudioChannel && AudioChannel <= 2)
910  SetAudioChannelDevice(AudioChannel);
911 }
912 
913 void cDevice::SetVolume(int Volume, bool Absolute)
914 {
915  int OldVolume = volume;
916  volume = constrain(Absolute ? Volume : volume + Volume, 0, MAXVOLUME);
918  Absolute |= mute;
919  cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute);
920  if (volume > 0) {
921  mute = false;
923  }
924 }
925 
926 void cDevice::ClrAvailableTracks(bool DescriptionsOnly, bool IdsOnly)
927 {
928  if (keepTracks)
929  return;
930  if (DescriptionsOnly) {
931  for (int i = ttNone; i < ttMaxTrackTypes; i++)
933  }
934  else {
935  if (IdsOnly) {
936  for (int i = ttNone; i < ttMaxTrackTypes; i++)
937  availableTracks[i].id = 0;
938  }
939  else
940  memset(availableTracks, 0, sizeof(availableTracks));
942  SetAudioChannel(0); // fall back to stereo
946  }
947 }
948 
949 bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description)
950 {
951  eTrackType t = eTrackType(Type + Index);
952  if (Type == ttAudio && IS_AUDIO_TRACK(t) ||
953  Type == ttDolby && IS_DOLBY_TRACK(t) ||
954  Type == ttSubtitle && IS_SUBTITLE_TRACK(t)) {
955  if (Language)
956  strn0cpy(availableTracks[t].language, Language, sizeof(availableTracks[t].language));
957  if (Description)
958  Utf8Strn0Cpy(availableTracks[t].description, Description, sizeof(availableTracks[t].description));
959  if (Id) {
960  availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking
961  if (Type == ttAudio || Type == ttDolby) {
962  int numAudioTracks = NumAudioTracks();
963  if (!availableTracks[currentAudioTrack].id && numAudioTracks && currentAudioTrackMissingCount++ > numAudioTracks * 10)
965  else if (t == currentAudioTrack)
967  }
970  }
971  return true;
972  }
973  else
974  esyslog("ERROR: SetAvailableTrack called with invalid Type/Index (%d/%d)", Type, Index);
975  return false;
976 }
977 
979 {
980  return (ttNone < Type && Type < ttMaxTrackTypes) ? &availableTracks[Type] : NULL;
981 }
982 
983 int cDevice::NumTracks(eTrackType FirstTrack, eTrackType LastTrack) const
984 {
985  int n = 0;
986  for (int i = FirstTrack; i <= LastTrack; i++) {
987  if (availableTracks[i].id)
988  n++;
989  }
990  return n;
991 }
992 
993 int cDevice::NumAudioTracks(void) const
994 {
996 }
997 
999 {
1001 }
1002 
1004 {
1005  if (ttNone < Type && Type <= ttDolbyLast) {
1006  cMutexLock MutexLock(&mutexCurrentAudioTrack);
1007  if (IS_DOLBY_TRACK(Type))
1008  SetDigitalAudioDevice(true);
1009  currentAudioTrack = Type;
1010  if (player)
1012  else
1014  if (IS_AUDIO_TRACK(Type))
1015  SetDigitalAudioDevice(false);
1016  return true;
1017  }
1018  return false;
1019 }
1020 
1022 {
1023  if (Type == ttNone || IS_SUBTITLE_TRACK(Type)) {
1024  currentSubtitleTrack = Type;
1028  if (Type == ttNone && dvbSubtitleConverter) {
1031  }
1033  if (player)
1035  else
1037  if (currentSubtitleTrack != ttNone && !Replaying() && !Transferring()) {
1038  const tTrackId *TrackId = GetTrack(currentSubtitleTrack);
1039  if (TrackId && TrackId->id) {
1040  liveSubtitle = new cLiveSubtitle(TrackId->id);
1042  }
1043  }
1044  return true;
1045  }
1046  return false;
1047 }
1048 
1050 {
1051  if (keepTracks)
1052  return;
1053  if (Force || !availableTracks[currentAudioTrack].id) {
1054  eTrackType PreferredTrack = ttAudioFirst;
1055  int PreferredAudioChannel = 0;
1056  int LanguagePreference = -1;
1057  int StartCheck = Setup.CurrentDolby ? ttDolbyFirst : ttAudioFirst;
1058  int EndCheck = ttDolbyLast;
1059  for (int i = StartCheck; i <= EndCheck; i++) {
1060  const tTrackId *TrackId = GetTrack(eTrackType(i));
1061  int pos = 0;
1062  if (TrackId && TrackId->id && I18nIsPreferredLanguage(Setup.AudioLanguages, TrackId->language, LanguagePreference, &pos)) {
1063  PreferredTrack = eTrackType(i);
1064  PreferredAudioChannel = pos;
1065  }
1066  if (Setup.CurrentDolby && i == ttDolbyLast) {
1067  i = ttAudioFirst - 1;
1068  EndCheck = ttAudioLast;
1069  }
1070  }
1071  // Make sure we're set to an available audio track:
1072  const tTrackId *Track = GetTrack(GetCurrentAudioTrack());
1073  if (Force || !Track || !Track->id || PreferredTrack != GetCurrentAudioTrack()) {
1074  if (!Force) // only log this for automatic changes
1075  dsyslog("setting audio track to %d (%d)", PreferredTrack, PreferredAudioChannel);
1076  SetCurrentAudioTrack(PreferredTrack);
1077  SetAudioChannel(PreferredAudioChannel);
1078  }
1079  }
1080 }
1081 
1083 {
1084  if (keepTracks)
1085  return;
1086  if (Setup.DisplaySubtitles) {
1087  eTrackType PreferredTrack = ttNone;
1088  int LanguagePreference = INT_MAX; // higher than the maximum possible value
1089  for (int i = ttSubtitleFirst; i <= ttSubtitleLast; i++) {
1090  const tTrackId *TrackId = GetTrack(eTrackType(i));
1091  if (TrackId && TrackId->id && (I18nIsPreferredLanguage(Setup.SubtitleLanguages, TrackId->language, LanguagePreference) ||
1092  (i == ttSubtitleFirst + 8 && !*TrackId->language && LanguagePreference == INT_MAX))) // compatibility mode for old subtitles plugin
1093  PreferredTrack = eTrackType(i);
1094  }
1095  // Make sure we're set to an available subtitle track:
1096  const tTrackId *Track = GetTrack(GetCurrentSubtitleTrack());
1097  if (!Track || !Track->id || PreferredTrack != GetCurrentSubtitleTrack())
1098  SetCurrentSubtitleTrack(PreferredTrack);
1099  }
1100  else
1102 }
1103 
1104 bool cDevice::CanReplay(void) const
1105 {
1106  return HasDecoder();
1107 }
1108 
1110 {
1111  return false;
1112 }
1113 
1114 int64_t cDevice::GetSTC(void)
1115 {
1116  return -1;
1117 }
1118 
1119 void cDevice::TrickSpeed(int Speed)
1120 {
1121 }
1122 
1123 void cDevice::Clear(void)
1124 {
1125  Audios.ClearAudio();
1128 }
1129 
1130 void cDevice::Play(void)
1131 {
1134  dvbSubtitleConverter->Freeze(false);
1135 }
1136 
1138 {
1139  Audios.MuteAudio(true);
1142 }
1143 
1144 void cDevice::Mute(void)
1145 {
1146  Audios.MuteAudio(true);
1147 }
1148 
1149 void cDevice::StillPicture(const uchar *Data, int Length)
1150 {
1151  if (Data[0] == 0x47) {
1152  // TS data
1153  cTsToPes TsToPes;
1154  uchar *buf = NULL;
1155  int Size = 0;
1156  while (Length >= TS_SIZE) {
1157  int Pid = TsPid(Data);
1158  if (Pid == PATPID)
1159  patPmtParser.ParsePat(Data, TS_SIZE);
1160  else if (patPmtParser.IsPmtPid(Pid))
1161  patPmtParser.ParsePmt(Data, TS_SIZE);
1162  else if (Pid == patPmtParser.Vpid()) {
1163  if (TsPayloadStart(Data)) {
1164  int l;
1165  while (const uchar *p = TsToPes.GetPes(l)) {
1166  int Offset = Size;
1167  int NewSize = Size + l;
1168  if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) {
1169  Size = NewSize;
1170  buf = NewBuffer;
1171  memcpy(buf + Offset, p, l);
1172  }
1173  else {
1174  LOG_ERROR_STR("out of memory");
1175  free(buf);
1176  return;
1177  }
1178  }
1179  TsToPes.Reset();
1180  }
1181  TsToPes.PutTs(Data, TS_SIZE);
1182  }
1183  Length -= TS_SIZE;
1184  Data += TS_SIZE;
1185  }
1186  int l;
1187  while (const uchar *p = TsToPes.GetPes(l)) {
1188  int Offset = Size;
1189  int NewSize = Size + l;
1190  if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) {
1191  Size = NewSize;
1192  buf = NewBuffer;
1193  memcpy(buf + Offset, p, l);
1194  }
1195  else {
1196  esyslog("ERROR: out of memory");
1197  free(buf);
1198  return;
1199  }
1200  }
1201  if (buf) {
1202  StillPicture(buf, Size);
1203  free(buf);
1204  }
1205  }
1206 }
1207 
1208 bool cDevice::Replaying(void) const
1209 {
1210  return player != NULL;
1211 }
1212 
1213 bool cDevice::Transferring(void) const
1214 {
1215  return cTransferControl::ReceiverDevice() != NULL;
1216 }
1217 
1219 {
1220  if (CanReplay()) {
1221  if (player)
1222  Detach(player);
1225  patPmtParser.Reset();
1226  player = Player;
1227  if (!Transferring())
1228  ClrAvailableTracks(false, true);
1230  player->device = this;
1231  player->Activate(true);
1232  return true;
1233  }
1234  return false;
1235 }
1236 
1238 {
1239  if (Player && player == Player) {
1240  cPlayer *p = player;
1241  player = NULL; // avoids recursive calls to Detach()
1242  p->Activate(false);
1243  p->device = NULL;
1245  delete dvbSubtitleConverter;
1246  dvbSubtitleConverter = NULL;
1249  PlayTs(NULL, 0);
1250  patPmtParser.Reset();
1251  Audios.ClearAudio();
1252  isPlayingVideo = false;
1253  }
1254 }
1255 
1257 {
1258  if (player) {
1259  Detach(player);
1260  if (IsPrimaryDevice())
1262  }
1263 }
1264 
1265 bool cDevice::Poll(cPoller &Poller, int TimeoutMs)
1266 {
1267  return false;
1268 }
1269 
1270 bool cDevice::Flush(int TimeoutMs)
1271 {
1272  return true;
1273 }
1274 
1275 int cDevice::PlayVideo(const uchar *Data, int Length)
1276 {
1277  return -1;
1278 }
1279 
1280 int cDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
1281 {
1282  return -1;
1283 }
1284 
1285 int cDevice::PlaySubtitle(const uchar *Data, int Length)
1286 {
1287  if (!dvbSubtitleConverter)
1289  return dvbSubtitleConverter->ConvertFragments(Data, Length);
1290 }
1291 
1292 int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly)
1293 {
1294  bool FirstLoop = true;
1295  uchar c = Data[3];
1296  const uchar *Start = Data;
1297  const uchar *End = Start + Length;
1298  while (Start < End) {
1299  int d = End - Start;
1300  int w = d;
1301  switch (c) {
1302  case 0xBE: // padding stream, needed for MPEG1
1303  case 0xE0 ... 0xEF: // video
1304  isPlayingVideo = true;
1305  w = PlayVideo(Start, d);
1306  break;
1307  case 0xC0 ... 0xDF: // audio
1308  SetAvailableTrack(ttAudio, c - 0xC0, c);
1309  if ((!VideoOnly || HasIBPTrickSpeed()) && c == availableTracks[currentAudioTrack].id) {
1310  w = PlayAudio(Start, d, c);
1311  if (FirstLoop)
1312  Audios.PlayAudio(Data, Length, c);
1313  }
1314  break;
1315  case 0xBD: { // private stream 1
1316  // EBU Teletext data, ETSI EN 300 472
1317  // if PES data header length = 24 and data_identifier = 0x10..0x1F (EBU Data)
1318  if (Data[8] == 0x24 && Data[45] >= 0x10 && Data[45] < 0x20) {
1319  cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uint8_t*)Data, Length);
1320  break;
1321  }
1322 
1323  int PayloadOffset = Data[8] + 9;
1324 
1325  // Compatibility mode for old subtitles plugin:
1326  if ((Data[7] & 0x01) && (Data[PayloadOffset - 3] & 0x81) == 0x01 && Data[PayloadOffset - 2] == 0x81)
1327  PayloadOffset--;
1328 
1329  uchar SubStreamId = Data[PayloadOffset];
1330  uchar SubStreamType = SubStreamId & 0xF0;
1331  uchar SubStreamIndex = SubStreamId & 0x1F;
1332 
1333  // Compatibility mode for old VDR recordings, where 0xBD was only AC3:
1334 pre_1_3_19_PrivateStreamDetected:
1336  SubStreamId = c;
1337  SubStreamType = 0x80;
1338  SubStreamIndex = 0;
1339  }
1340  else if (pre_1_3_19_PrivateStream)
1341  pre_1_3_19_PrivateStream--; // every known PS1 packet counts down towards 0 to recover from glitches...
1342  switch (SubStreamType) {
1343  case 0x20: // SPU
1344  case 0x30: // SPU
1345  SetAvailableTrack(ttSubtitle, SubStreamIndex, SubStreamId);
1346  if ((!VideoOnly || HasIBPTrickSpeed()) && currentSubtitleTrack != ttNone && SubStreamId == availableTracks[currentSubtitleTrack].id)
1347  w = PlaySubtitle(Start, d);
1348  break;
1349  case 0x80: // AC3 & DTS
1350  if (Setup.UseDolbyDigital) {
1351  SetAvailableTrack(ttDolby, SubStreamIndex, SubStreamId);
1352  if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) {
1353  w = PlayAudio(Start, d, SubStreamId);
1354  if (FirstLoop)
1355  Audios.PlayAudio(Data, Length, SubStreamId);
1356  }
1357  }
1358  break;
1359  case 0xA0: // LPCM
1360  SetAvailableTrack(ttAudio, SubStreamIndex, SubStreamId);
1361  if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) {
1362  w = PlayAudio(Start, d, SubStreamId);
1363  if (FirstLoop)
1364  Audios.PlayAudio(Data, Length, SubStreamId);
1365  }
1366  break;
1367  default:
1368  // Compatibility mode for old VDR recordings, where 0xBD was only AC3:
1370  dsyslog("unknown PS1 packet, substream id = %02X (counter is at %d)", SubStreamId, pre_1_3_19_PrivateStream);
1371  pre_1_3_19_PrivateStream += 2; // ...and every unknown PS1 packet counts up (the very first one counts twice, but that's ok)
1373  dsyslog("switching to pre 1.3.19 Dolby Digital compatibility mode - substream id = %02X", SubStreamId);
1376  goto pre_1_3_19_PrivateStreamDetected;
1377  }
1378  }
1379  }
1380  }
1381  break;
1382  default:
1383  ;//esyslog("ERROR: unexpected packet id %02X", c);
1384  }
1385  if (w > 0)
1386  Start += w;
1387  else {
1388  if (Start != Data)
1389  esyslog("ERROR: incomplete PES packet write!");
1390  return Start == Data ? w : Start - Data;
1391  }
1392  FirstLoop = false;
1393  }
1394  return Length;
1395 }
1396 
1397 int cDevice::PlayPes(const uchar *Data, int Length, bool VideoOnly)
1398 {
1399  if (!Data) {
1402  return 0;
1403  }
1404  int i = 0;
1405  while (i <= Length - 6) {
1406  if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
1407  int l = PesLength(Data + i);
1408  if (i + l > Length) {
1409  esyslog("ERROR: incomplete PES packet!");
1410  return Length;
1411  }
1412  int w = PlayPesPacket(Data + i, l, VideoOnly);
1413  if (w > 0)
1414  i += l;
1415  else
1416  return i == 0 ? w : i;
1417  }
1418  else
1419  i++;
1420  }
1421  if (i < Length)
1422  esyslog("ERROR: leftover PES data!");
1423  return Length;
1424 }
1425 
1426 int cDevice::PlayTsVideo(const uchar *Data, int Length)
1427 {
1428  // Video PES has no explicit length, so we can only determine the end of
1429  // a PES packet when the next TS packet that starts a payload comes in:
1430  if (TsPayloadStart(Data)) {
1431  int l;
1432  while (const uchar *p = tsToPesVideo.GetPes(l)) {
1433  int w = PlayVideo(p, l);
1434  if (w <= 0) {
1436  return w;
1437  }
1438  }
1439  tsToPesVideo.Reset();
1440  }
1441  tsToPesVideo.PutTs(Data, Length);
1442  return Length;
1443 }
1444 
1445 int cDevice::PlayTsAudio(const uchar *Data, int Length)
1446 {
1447  // Audio PES always has an explicit length and consists of single packets:
1448  int l;
1449  if (const uchar *p = tsToPesAudio.GetPes(l)) {
1450  int w = PlayAudio(p, l, p[3]);
1451  if (w <= 0) {
1453  return w;
1454  }
1455  tsToPesAudio.Reset();
1456  }
1457  tsToPesAudio.PutTs(Data, Length);
1458  return Length;
1459 }
1460 
1461 int cDevice::PlayTsSubtitle(const uchar *Data, int Length)
1462 {
1463  if (!dvbSubtitleConverter)
1465  tsToPesSubtitle.PutTs(Data, Length);
1466  int l;
1467  if (const uchar *p = tsToPesSubtitle.GetPes(l)) {
1470  }
1471  return Length;
1472 }
1473 
1474 //TODO detect and report continuity errors?
1475 int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
1476 {
1477  int Played = 0;
1478  if (!Data) {
1479  tsToPesVideo.Reset();
1480  tsToPesAudio.Reset();
1483  }
1484  else if (Length < TS_SIZE) {
1485  esyslog("ERROR: skipped %d bytes of TS fragment", Length);
1486  return Length;
1487  }
1488  else {
1489  while (Length >= TS_SIZE) {
1490  if (Data[0] != TS_SYNC_BYTE) {
1491  int Skipped = 1;
1492  while (Skipped < Length && (Data[Skipped] != TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] != TS_SYNC_BYTE))
1493  Skipped++;
1494  esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1495  return Played + Skipped;
1496  }
1497  int Pid = TsPid(Data);
1498  if (TsHasPayload(Data)) { // silently ignore TS packets w/o payload
1499  int PayloadOffset = TsPayloadOffset(Data);
1500  if (PayloadOffset < TS_SIZE) {
1501  if (Pid == PATPID)
1502  patPmtParser.ParsePat(Data, TS_SIZE);
1503  else if (patPmtParser.IsPmtPid(Pid))
1504  patPmtParser.ParsePmt(Data, TS_SIZE);
1505  else if (Pid == patPmtParser.Vpid()) {
1506  isPlayingVideo = true;
1507  int w = PlayTsVideo(Data, TS_SIZE);
1508  if (w < 0)
1509  return Played ? Played : w;
1510  if (w == 0)
1511  break;
1512  }
1513  else if (Pid == availableTracks[currentAudioTrack].id) {
1514  if (!VideoOnly || HasIBPTrickSpeed()) {
1515  int w = PlayTsAudio(Data, TS_SIZE);
1516  if (w < 0)
1517  return Played ? Played : w;
1518  if (w == 0)
1519  break;
1520  Audios.PlayTsAudio(Data, TS_SIZE);
1521  }
1522  }
1523  else if (Pid == availableTracks[currentSubtitleTrack].id) {
1524  if (!VideoOnly || HasIBPTrickSpeed())
1525  PlayTsSubtitle(Data, TS_SIZE);
1526  }
1527  else if (Pid == patPmtParser.Tpid()) {
1528  if (!VideoOnly || HasIBPTrickSpeed()) {
1529  int l;
1530  tsToPesTeletext.PutTs(Data, Length);
1531  if (const uchar *p = tsToPesTeletext.GetPes(l)) {
1532  if ((l > 45) && (p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xbd) && (p[8] == 0x24) && (p[45] >= 0x10) && (p[45] < 0x20))
1535  }
1536  }
1537  }
1538  }
1539  }
1540  else if (Pid == patPmtParser.Ppid()) {
1541  int w = PlayTsVideo(Data, TS_SIZE);
1542  if (w < 0)
1543  return Played ? Played : w;
1544  if (w == 0)
1545  break;
1546  }
1547  Played += TS_SIZE;
1548  Length -= TS_SIZE;
1549  Data += TS_SIZE;
1550  }
1551  }
1552  return Played;
1553 }
1554 
1555 int cDevice::Priority(void) const
1556 {
1557  int priority = IDLEPRIORITY;
1558  if (IsPrimaryDevice() && !Replaying() && HasProgramme())
1559  priority = TRANSFERPRIORITY; // we use the same value here, no matter whether it's actual Transfer Mode or real live viewing
1560  cMutexLock MutexLock(&mutexReceiver);
1561  for (int i = 0; i < MAXRECEIVERS; i++) {
1562  if (receiver[i])
1563  priority = max(receiver[i]->priority, priority);
1564  }
1565  return priority;
1566 }
1567 
1568 bool cDevice::Ready(void)
1569 {
1570  return true;
1571 }
1572 
1573 bool cDevice::Receiving(bool Dummy) const
1574 {
1575  cMutexLock MutexLock(&mutexReceiver);
1576  for (int i = 0; i < MAXRECEIVERS; i++) {
1577  if (receiver[i])
1578  return true;
1579  }
1580  return false;
1581 }
1582 
1583 #define TS_SCRAMBLING_TIMEOUT 3 // seconds to wait until a TS becomes unscrambled
1584 #define TS_SCRAMBLING_TIME_OK 10 // seconds before a Channel/CAM combination is marked as known to decrypt
1585 
1587 {
1588  if (Running() && OpenDvr()) {
1589  while (Running()) {
1590  // Read data from the DVR device:
1591  uchar *b = NULL;
1592  if (GetTSPacket(b)) {
1593  if (b) {
1594  int Pid = TsPid(b);
1595  // Check whether the TS packets are scrambled:
1596  bool DetachReceivers = false;
1597  bool DescramblingOk = false;
1598  int CamSlotNumber = 0;
1599  if (startScrambleDetection) {
1600  cCamSlot *cs = CamSlot();
1601  CamSlotNumber = cs ? cs->SlotNumber() : 0;
1602  if (CamSlotNumber) {
1603  bool Scrambled = b[3] & TS_SCRAMBLING_CONTROL;
1604  int t = time(NULL) - startScrambleDetection;
1605  if (Scrambled) {
1606  if (t > TS_SCRAMBLING_TIMEOUT)
1607  DetachReceivers = true;
1608  }
1609  else if (t > TS_SCRAMBLING_TIME_OK) {
1610  DescramblingOk = true;
1612  }
1613  }
1614  }
1615  // Distribute the packet to all attached receivers:
1616  Lock();
1617  for (int i = 0; i < MAXRECEIVERS; i++) {
1618  if (receiver[i] && receiver[i]->WantsPid(Pid)) {
1619  if (DetachReceivers) {
1620  ChannelCamRelations.SetChecked(receiver[i]->ChannelID(), CamSlotNumber);
1621  Detach(receiver[i]);
1622  }
1623  else
1624  receiver[i]->Receive(b, TS_SIZE);
1625  if (DescramblingOk)
1626  ChannelCamRelations.SetDecrypt(receiver[i]->ChannelID(), CamSlotNumber);
1627  }
1628  }
1629  Unlock();
1630  }
1631  }
1632  else
1633  break;
1634  }
1635  CloseDvr();
1636  }
1637 }
1638 
1640 {
1641  return false;
1642 }
1643 
1645 {
1646 }
1647 
1649 {
1650  return false;
1651 }
1652 
1654 {
1655  if (!Receiver)
1656  return false;
1657  if (Receiver->device == this)
1658  return true;
1659 // activate the following line if you need it - actually the driver should be fixed!
1660 //#define WAIT_FOR_TUNER_LOCK
1661 #ifdef WAIT_FOR_TUNER_LOCK
1662 #define TUNER_LOCK_TIMEOUT 5000 // ms
1663  if (!HasLock(TUNER_LOCK_TIMEOUT)) {
1664  esyslog("ERROR: device %d has no lock, can't attach receiver!", CardIndex() + 1);
1665  return false;
1666  }
1667 #endif
1668  cMutexLock MutexLock(&mutexReceiver);
1669  for (int i = 0; i < MAXRECEIVERS; i++) {
1670  if (!receiver[i]) {
1671  for (int n = 0; n < Receiver->numPids; n++) {
1672  if (!AddPid(Receiver->pids[n])) {
1673  for ( ; n-- > 0; )
1674  DelPid(Receiver->pids[n]);
1675  return false;
1676  }
1677  }
1678  Receiver->Activate(true);
1679  Lock();
1680  Receiver->device = this;
1681  receiver[i] = Receiver;
1682  Unlock();
1683  if (camSlot) {
1685  startScrambleDetection = time(NULL);
1686  }
1687  Start();
1688  return true;
1689  }
1690  }
1691  esyslog("ERROR: no free receiver slot!");
1692  return false;
1693 }
1694 
1696 {
1697  if (!Receiver || Receiver->device != this)
1698  return;
1699  bool receiversLeft = false;
1700  cMutexLock MutexLock(&mutexReceiver);
1701  for (int i = 0; i < MAXRECEIVERS; i++) {
1702  if (receiver[i] == Receiver) {
1703  Lock();
1704  receiver[i] = NULL;
1705  Receiver->device = NULL;
1706  Unlock();
1707  Receiver->Activate(false);
1708  for (int n = 0; n < Receiver->numPids; n++)
1709  DelPid(Receiver->pids[n]);
1710  }
1711  else if (receiver[i])
1712  receiversLeft = true;
1713  }
1714  if (camSlot)
1716  if (!receiversLeft)
1717  Cancel(-1);
1718 }
1719 
1720 void cDevice::DetachAll(int Pid)
1721 {
1722  if (Pid) {
1723  cMutexLock MutexLock(&mutexReceiver);
1724  for (int i = 0; i < MAXRECEIVERS; i++) {
1725  cReceiver *Receiver = receiver[i];
1726  if (Receiver && Receiver->WantsPid(Pid))
1727  Detach(Receiver);
1728  }
1729  }
1730 }
1731 
1733 {
1734  cMutexLock MutexLock(&mutexReceiver);
1735  for (int i = 0; i < MAXRECEIVERS; i++)
1736  Detach(receiver[i]);
1737 }
1738 
1739 // --- cTSBuffer -------------------------------------------------------------
1740 
1741 cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
1742 {
1743  SetDescription("TS buffer on device %d", CardIndex);
1744  f = File;
1745  cardIndex = CardIndex;
1746  delivered = false;
1747  ringBuffer = new cRingBufferLinear(Size, TS_SIZE, true, "TS");
1748  ringBuffer->SetTimeouts(100, 100);
1750  Start();
1751 }
1752 
1754 {
1755  Cancel(3);
1756  delete ringBuffer;
1757 }
1758 
1760 {
1761  if (ringBuffer) {
1762  bool firstRead = true;
1763  cPoller Poller(f);
1764  while (Running()) {
1765  if (firstRead || Poller.Poll(100)) {
1766  firstRead = false;
1767  int r = ringBuffer->Read(f);
1768  if (r < 0 && FATALERRNO) {
1769  if (errno == EOVERFLOW)
1770  esyslog("ERROR: driver buffer overflow on device %d", cardIndex);
1771  else {
1772  LOG_ERROR;
1773  break;
1774  }
1775  }
1776  }
1777  }
1778  }
1779 }
1780 
1782 {
1783  int Count = 0;
1784  if (delivered) {
1786  delivered = false;
1787  }
1788  uchar *p = ringBuffer->Get(Count);
1789  if (p && Count >= TS_SIZE) {
1790  if (*p != TS_SYNC_BYTE) {
1791  for (int i = 1; i < Count; i++) {
1792  if (p[i] == TS_SYNC_BYTE) {
1793  Count = i;
1794  break;
1795  }
1796  }
1797  ringBuffer->Del(Count);
1798  esyslog("ERROR: skipped %d bytes to sync on TS packet on device %d", Count, cardIndex);
1799  return NULL;
1800  }
1801  delivered = true;
1802  return p;
1803  }
1804  return NULL;
1805 }
1806