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