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