vdr
1.7.27
|
00001 /* 00002 * device.c: The basic device interface 00003 * 00004 * See the main source file 'vdr.c' for copyright information and 00005 * how to reach the author. 00006 * 00007 * $Id: device.c 2.58 2012/03/13 09:48:14 kls Exp $ 00008 */ 00009 00010 #include "device.h" 00011 #include <errno.h> 00012 #include <sys/ioctl.h> 00013 #include <sys/mman.h> 00014 #include "audio.h" 00015 #include "channels.h" 00016 #include "i18n.h" 00017 #include "player.h" 00018 #include "receiver.h" 00019 #include "status.h" 00020 #include "transfer.h" 00021 #include "vdrttxtsubshooks.h" 00022 00023 // --- cLiveSubtitle --------------------------------------------------------- 00024 00025 class cLiveSubtitle : public cReceiver { 00026 protected: 00027 virtual void Receive(uchar *Data, int Length); 00028 public: 00029 cLiveSubtitle(int SPid); 00030 virtual ~cLiveSubtitle(); 00031 }; 00032 00033 cLiveSubtitle::cLiveSubtitle(int SPid) 00034 { 00035 AddPid(SPid); 00036 } 00037 00038 cLiveSubtitle::~cLiveSubtitle() 00039 { 00040 cReceiver::Detach(); 00041 } 00042 00043 void cLiveSubtitle::Receive(uchar *Data, int Length) 00044 { 00045 if (cDevice::PrimaryDevice()) 00046 cDevice::PrimaryDevice()->PlayTs(Data, Length); 00047 } 00048 00049 // --- cDeviceHook ----------------------------------------------------------- 00050 00051 cDeviceHook::cDeviceHook(void) 00052 { 00053 cDevice::deviceHooks.Add(this); 00054 } 00055 00056 bool cDeviceHook::DeviceProvidesTransponder(const cDevice *Device, const cChannel *Channel) const 00057 { 00058 return true; 00059 } 00060 00061 // --- cDevice --------------------------------------------------------------- 00062 00063 // The minimum number of unknown PS1 packets to consider this a "pre 1.3.19 private stream": 00064 #define MIN_PRE_1_3_19_PRIVATESTREAM 10 00065 00066 int cDevice::numDevices = 0; 00067 int cDevice::useDevice = 0; 00068 int cDevice::nextCardIndex = 0; 00069 int cDevice::currentChannel = 1; 00070 cDevice *cDevice::device[MAXDEVICES] = { NULL }; 00071 cDevice *cDevice::primaryDevice = NULL; 00072 cList<cDeviceHook> cDevice::deviceHooks; 00073 00074 cDevice::cDevice(void) 00075 :patPmtParser(true) 00076 { 00077 cardIndex = nextCardIndex++; 00078 dsyslog("new device number %d", CardIndex() + 1); 00079 00080 SetDescription("receiver on device %d", CardIndex() + 1); 00081 00082 mute = false; 00083 volume = Setup.CurrentVolume; 00084 00085 sectionHandler = NULL; 00086 eitFilter = NULL; 00087 patFilter = NULL; 00088 sdtFilter = NULL; 00089 nitFilter = NULL; 00090 00091 camSlot = NULL; 00092 startScrambleDetection = 0; 00093 00094 occupiedTimeout = 0; 00095 00096 player = NULL; 00097 isPlayingVideo = false; 00098 ClrAvailableTracks(); 00099 currentAudioTrack = ttNone; 00100 currentAudioTrackMissingCount = 0; 00101 currentSubtitleTrack = ttNone; 00102 liveSubtitle = NULL; 00103 dvbSubtitleConverter = NULL; 00104 autoSelectPreferredSubtitleLanguage = true; 00105 00106 for (int i = 0; i < MAXRECEIVERS; i++) 00107 receiver[i] = NULL; 00108 00109 if (numDevices < MAXDEVICES) 00110 device[numDevices++] = this; 00111 else 00112 esyslog("ERROR: too many devices!"); 00113 } 00114 00115 cDevice::~cDevice() 00116 { 00117 Detach(player); 00118 DetachAllReceivers(); 00119 delete liveSubtitle; 00120 delete dvbSubtitleConverter; 00121 } 00122 00123 bool cDevice::WaitForAllDevicesReady(int Timeout) 00124 { 00125 for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) { 00126 bool ready = true; 00127 for (int i = 0; i < numDevices; i++) { 00128 if (device[i] && !device[i]->Ready()) { 00129 ready = false; 00130 cCondWait::SleepMs(100); 00131 } 00132 } 00133 if (ready) 00134 return true; 00135 } 00136 return false; 00137 } 00138 00139 void cDevice::SetUseDevice(int n) 00140 { 00141 if (n < MAXDEVICES) 00142 useDevice |= (1 << n); 00143 } 00144 00145 int cDevice::NextCardIndex(int n) 00146 { 00147 if (n > 0) { 00148 nextCardIndex += n; 00149 if (nextCardIndex >= MAXDEVICES) 00150 esyslog("ERROR: nextCardIndex too big (%d)", nextCardIndex); 00151 } 00152 else if (n < 0) 00153 esyslog("ERROR: invalid value in nextCardIndex(%d)", n); 00154 return nextCardIndex; 00155 } 00156 00157 int cDevice::DeviceNumber(void) const 00158 { 00159 for (int i = 0; i < numDevices; i++) { 00160 if (device[i] == this) 00161 return i; 00162 } 00163 return -1; 00164 } 00165 00166 cString cDevice::DeviceName(void) const 00167 { 00168 return ""; 00169 } 00170 00171 void cDevice::MakePrimaryDevice(bool On) 00172 { 00173 if (!On) { 00174 DELETENULL(liveSubtitle); 00175 DELETENULL(dvbSubtitleConverter); 00176 } 00177 } 00178 00179 bool cDevice::SetPrimaryDevice(int n) 00180 { 00181 n--; 00182 if (0 <= n && n < numDevices && device[n]) { 00183 isyslog("setting primary device to %d", n + 1); 00184 if (primaryDevice) 00185 primaryDevice->MakePrimaryDevice(false); 00186 primaryDevice = device[n]; 00187 primaryDevice->MakePrimaryDevice(true); 00188 primaryDevice->SetVideoFormat(Setup.VideoFormat); 00189 primaryDevice->SetVolumeDevice(Setup.CurrentVolume); 00190 return true; 00191 } 00192 esyslog("ERROR: invalid primary device number: %d", n + 1); 00193 return false; 00194 } 00195 00196 bool cDevice::HasDecoder(void) const 00197 { 00198 return false; 00199 } 00200 00201 cSpuDecoder *cDevice::GetSpuDecoder(void) 00202 { 00203 return NULL; 00204 } 00205 00206 cDevice *cDevice::ActualDevice(void) 00207 { 00208 cDevice *d = cTransferControl::ReceiverDevice(); 00209 if (!d) 00210 d = PrimaryDevice(); 00211 return d; 00212 } 00213 00214 cDevice *cDevice::GetDevice(int Index) 00215 { 00216 return (0 <= Index && Index < numDevices) ? device[Index] : NULL; 00217 } 00218 00219 static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device) 00220 { 00221 int MaxNumProvidedSystems = (1 << AvailableBits) - 1; 00222 int NumProvidedSystems = Device->NumProvidedSystems(); 00223 if (NumProvidedSystems > MaxNumProvidedSystems) { 00224 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); 00225 NumProvidedSystems = MaxNumProvidedSystems; 00226 } 00227 else if (NumProvidedSystems <= 0) { 00228 esyslog("ERROR: device %d reported an invalid number (%d) of supported delivery systems - assuming 1", Device->CardIndex() + 1, NumProvidedSystems); 00229 NumProvidedSystems = 1; 00230 } 00231 return NumProvidedSystems; 00232 } 00233 00234 cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool Query) 00235 { 00236 // Collect the current priorities of all CAM slots that can decrypt the channel: 00237 int NumCamSlots = CamSlots.Count(); 00238 int SlotPriority[NumCamSlots]; 00239 int NumUsableSlots = 0; 00240 if (Channel->Ca() >= CA_ENCRYPTED_MIN) { 00241 for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) { 00242 SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used 00243 if (CamSlot->ModuleStatus() == msReady) { 00244 if (CamSlot->ProvidesCa(Channel->Caids())) { 00245 if (!ChannelCamRelations.CamChecked(Channel->GetChannelID(), CamSlot->SlotNumber())) { 00246 SlotPriority[CamSlot->Index()] = CamSlot->Priority(); 00247 NumUsableSlots++; 00248 } 00249 } 00250 } 00251 } 00252 if (!NumUsableSlots) 00253 return NULL; // no CAM is able to decrypt this channel 00254 } 00255 00256 bool NeedsDetachReceivers = false; 00257 cDevice *d = NULL; 00258 cCamSlot *s = NULL; 00259 00260 uint32_t Impact = 0xFFFFFFFF; // we're looking for a device with the least impact 00261 for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) { 00262 if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY) 00263 continue; // there is no CAM available in this slot 00264 for (int i = 0; i < numDevices; i++) { 00265 if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != device[i]->CardIndex() + 1) 00266 continue; // a specific card was requested, but not this one 00267 if (NumUsableSlots && !CamSlots.Get(j)->Assign(device[i], true)) 00268 continue; // CAM slot can't be used with this device 00269 bool ndr; 00270 if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job 00271 if (NumUsableSlots && device[i]->CamSlot() && device[i]->CamSlot() != CamSlots.Get(j)) 00272 ndr = true; // using a different CAM slot requires detaching receivers 00273 // Put together an integer number that reflects the "impact" using 00274 // this device would have on the overall system. Each condition is represented 00275 // by one bit in the number (or several bits, if the condition is actually 00276 // a numeric value). The sequence in which the conditions are listed corresponds 00277 // to their individual severity, where the one listed first will make the most 00278 // difference, because it results in the most significant bit of the result. 00279 uint32_t imp = 0; 00280 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 00281 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 00282 imp <<= 1; imp |= device[i]->Receiving(); // avoid devices that are receiving 00283 imp <<= 4; imp |= GetClippedNumProvidedSystems(4, device[i]) - 1; // avoid cards which support multiple delivery systems 00284 imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device 00285 imp <<= 8; imp |= device[i]->Priority() - IDLEPRIORITY; // use the device with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used) 00286 imp <<= 8; imp |= (NumUsableSlots ? SlotPriority[j] : IDLEPRIORITY) - IDLEPRIORITY; // use the CAM slot with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used) 00287 imp <<= 1; imp |= ndr; // avoid devices if we need to detach existing receivers 00288 imp <<= 1; imp |= NumUsableSlots ? 0 : device[i]->HasCi(); // avoid cards with Common Interface for FTA channels 00289 imp <<= 1; imp |= device[i]->AvoidRecording(); // avoid SD full featured cards 00290 imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel 00291 imp <<= 1; imp |= device[i]->IsPrimaryDevice(); // avoid the primary device 00292 if (imp < Impact) { 00293 // This device has less impact than any previous one, so we take it. 00294 Impact = imp; 00295 d = device[i]; 00296 NeedsDetachReceivers = ndr; 00297 if (NumUsableSlots) 00298 s = CamSlots.Get(j); 00299 } 00300 } 00301 } 00302 if (!NumUsableSlots) 00303 break; // no CAM necessary, so just one loop over the devices 00304 } 00305 if (d && !Query) { 00306 if (NeedsDetachReceivers) 00307 d->DetachAllReceivers(); 00308 if (s) { 00309 if (s->Device() != d) { 00310 if (s->Device()) 00311 s->Device()->DetachAllReceivers(); 00312 if (d->CamSlot()) 00313 d->CamSlot()->Assign(NULL); 00314 s->Assign(d); 00315 } 00316 } 00317 else if (d->CamSlot() && !d->CamSlot()->IsDecrypting()) 00318 d->CamSlot()->Assign(NULL); 00319 } 00320 return d; 00321 } 00322 00323 cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority) 00324 { 00325 cDevice *Device = NULL; 00326 for (int i = 0; i < cDevice::NumDevices(); i++) { 00327 if (cDevice *d = cDevice::GetDevice(i)) { 00328 if (d->IsTunedToTransponder(Channel)) 00329 return d; // if any device is tuned to the transponder, we're done 00330 if (d->ProvidesTransponder(Channel)) { 00331 if (d->MaySwitchTransponder(Channel)) 00332 Device = d; // this device may switch to the transponder without disturbing any receiver or live view 00333 else if (!d->Occupied()) { 00334 if (d->Priority() < Priority && (!Device || d->Priority() < Device->Priority())) 00335 Device = d; // use this one only if no other with less impact can be found 00336 } 00337 } 00338 } 00339 } 00340 return Device; 00341 } 00342 00343 bool cDevice::HasCi(void) 00344 { 00345 return false; 00346 } 00347 00348 void cDevice::SetCamSlot(cCamSlot *CamSlot) 00349 { 00350 camSlot = CamSlot; 00351 } 00352 00353 void cDevice::Shutdown(void) 00354 { 00355 deviceHooks.Clear(); 00356 primaryDevice = NULL; 00357 for (int i = 0; i < numDevices; i++) { 00358 delete device[i]; 00359 device[i] = NULL; 00360 } 00361 } 00362 00363 uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY) 00364 { 00365 return NULL; 00366 } 00367 00368 bool cDevice::GrabImageFile(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY) 00369 { 00370 int result = 0; 00371 int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE); 00372 if (fd >= 0) { 00373 int ImageSize; 00374 uchar *Image = GrabImage(ImageSize, Jpeg, Quality, SizeX, SizeY); 00375 if (Image) { 00376 if (safe_write(fd, Image, ImageSize) == ImageSize) 00377 isyslog("grabbed image to %s", FileName); 00378 else { 00379 LOG_ERROR_STR(FileName); 00380 result |= 1; 00381 } 00382 free(Image); 00383 } 00384 else 00385 result |= 1; 00386 close(fd); 00387 } 00388 else { 00389 LOG_ERROR_STR(FileName); 00390 result |= 1; 00391 } 00392 return result == 0; 00393 } 00394 00395 void cDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat) 00396 { 00397 cSpuDecoder *spuDecoder = GetSpuDecoder(); 00398 if (spuDecoder) { 00399 if (Setup.VideoFormat) 00400 spuDecoder->setScaleMode(cSpuDecoder::eSpuNormal); 00401 else { 00402 switch (VideoDisplayFormat) { 00403 case vdfPanAndScan: 00404 spuDecoder->setScaleMode(cSpuDecoder::eSpuPanAndScan); 00405 break; 00406 case vdfLetterBox: 00407 spuDecoder->setScaleMode(cSpuDecoder::eSpuLetterBox); 00408 break; 00409 case vdfCenterCutOut: 00410 spuDecoder->setScaleMode(cSpuDecoder::eSpuNormal); 00411 break; 00412 default: esyslog("ERROR: invalid value for VideoDisplayFormat '%d'", VideoDisplayFormat); 00413 } 00414 } 00415 } 00416 } 00417 00418 void cDevice::SetVideoFormat(bool VideoFormat16_9) 00419 { 00420 } 00421 00422 eVideoSystem cDevice::GetVideoSystem(void) 00423 { 00424 return vsPAL; 00425 } 00426 00427 void cDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect) 00428 { 00429 Width = 0; 00430 Height = 0; 00431 VideoAspect = 1.0; 00432 } 00433 00434 void cDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect) 00435 { 00436 Width = 720; 00437 Height = 480; 00438 PixelAspect = 1.0; 00439 } 00440 00441 //#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); } 00442 #define PRINTPIDS(s) 00443 00444 bool cDevice::HasPid(int Pid) const 00445 { 00446 for (int i = 0; i < MAXPIDHANDLES; i++) { 00447 if (pidHandles[i].pid == Pid) 00448 return true; 00449 } 00450 return false; 00451 } 00452 00453 bool cDevice::AddPid(int Pid, ePidType PidType, int StreamType) 00454 { 00455 if (Pid || PidType == ptPcr) { 00456 int n = -1; 00457 int a = -1; 00458 if (PidType != ptPcr) { // PPID always has to be explicit 00459 for (int i = 0; i < MAXPIDHANDLES; i++) { 00460 if (i != ptPcr) { 00461 if (pidHandles[i].pid == Pid) 00462 n = i; 00463 else if (a < 0 && i >= ptOther && !pidHandles[i].used) 00464 a = i; 00465 } 00466 } 00467 } 00468 if (n >= 0) { 00469 // The Pid is already in use 00470 if (++pidHandles[n].used == 2 && n <= ptTeletext) { 00471 // It's a special PID that may have to be switched into "tap" mode 00472 PRINTPIDS("A"); 00473 if (!SetPid(&pidHandles[n], n, true)) { 00474 esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1); 00475 if (PidType <= ptTeletext) 00476 DetachAll(Pid); 00477 DelPid(Pid, PidType); 00478 return false; 00479 } 00480 if (camSlot) 00481 camSlot->SetPid(Pid, true); 00482 } 00483 PRINTPIDS("a"); 00484 return true; 00485 } 00486 else if (PidType < ptOther) { 00487 // The Pid is not yet in use and it is a special one 00488 n = PidType; 00489 } 00490 else if (a >= 0) { 00491 // The Pid is not yet in use and we have a free slot 00492 n = a; 00493 } 00494 else { 00495 esyslog("ERROR: no free slot for PID %d on device %d", Pid, CardIndex() + 1); 00496 return false; 00497 } 00498 if (n >= 0) { 00499 pidHandles[n].pid = Pid; 00500 pidHandles[n].streamType = StreamType; 00501 pidHandles[n].used = 1; 00502 PRINTPIDS("C"); 00503 if (!SetPid(&pidHandles[n], n, true)) { 00504 esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1); 00505 if (PidType <= ptTeletext) 00506 DetachAll(Pid); 00507 DelPid(Pid, PidType); 00508 return false; 00509 } 00510 if (camSlot) 00511 camSlot->SetPid(Pid, true); 00512 } 00513 } 00514 return true; 00515 } 00516 00517 void cDevice::DelPid(int Pid, ePidType PidType) 00518 { 00519 if (Pid || PidType == ptPcr) { 00520 int n = -1; 00521 if (PidType == ptPcr) 00522 n = PidType; // PPID always has to be explicit 00523 else { 00524 for (int i = 0; i < MAXPIDHANDLES; i++) { 00525 if (pidHandles[i].pid == Pid) { 00526 n = i; 00527 break; 00528 } 00529 } 00530 } 00531 if (n >= 0 && pidHandles[n].used) { 00532 PRINTPIDS("D"); 00533 if (--pidHandles[n].used < 2) { 00534 SetPid(&pidHandles[n], n, false); 00535 if (pidHandles[n].used == 0) { 00536 pidHandles[n].handle = -1; 00537 pidHandles[n].pid = 0; 00538 if (camSlot) 00539 camSlot->SetPid(Pid, false); 00540 } 00541 } 00542 PRINTPIDS("E"); 00543 } 00544 } 00545 } 00546 00547 bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On) 00548 { 00549 return false; 00550 } 00551 00552 void cDevice::DelLivePids(void) 00553 { 00554 for (int i = ptAudio; i < ptOther; i++) { 00555 if (pidHandles[i].pid) 00556 DelPid(pidHandles[i].pid, ePidType(i)); 00557 } 00558 } 00559 00560 void cDevice::StartSectionHandler(void) 00561 { 00562 if (!sectionHandler) { 00563 sectionHandler = new cSectionHandler(this); 00564 AttachFilter(eitFilter = new cEitFilter); 00565 AttachFilter(patFilter = new cPatFilter); 00566 AttachFilter(sdtFilter = new cSdtFilter(patFilter)); 00567 AttachFilter(nitFilter = new cNitFilter); 00568 } 00569 } 00570 00571 void cDevice::StopSectionHandler(void) 00572 { 00573 if (sectionHandler) { 00574 delete nitFilter; 00575 delete sdtFilter; 00576 delete patFilter; 00577 delete eitFilter; 00578 delete sectionHandler; 00579 nitFilter = NULL; 00580 sdtFilter = NULL; 00581 patFilter = NULL; 00582 eitFilter = NULL; 00583 sectionHandler = NULL; 00584 } 00585 } 00586 00587 int cDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) 00588 { 00589 return -1; 00590 } 00591 00592 void cDevice::CloseFilter(int Handle) 00593 { 00594 close(Handle); 00595 } 00596 00597 void cDevice::AttachFilter(cFilter *Filter) 00598 { 00599 if (sectionHandler) 00600 sectionHandler->Attach(Filter); 00601 } 00602 00603 void cDevice::Detach(cFilter *Filter) 00604 { 00605 if (sectionHandler) 00606 sectionHandler->Detach(Filter); 00607 } 00608 00609 bool cDevice::ProvidesSource(int Source) const 00610 { 00611 return false; 00612 } 00613 00614 bool cDevice::DeviceHooksProvidesTransponder(const cChannel *Channel) const 00615 { 00616 cDeviceHook *Hook = deviceHooks.First(); 00617 while (Hook) { 00618 if (!Hook->DeviceProvidesTransponder(this, Channel)) 00619 return false; 00620 Hook = deviceHooks.Next(Hook); 00621 } 00622 return true; 00623 } 00624 00625 bool cDevice::ProvidesTransponder(const cChannel *Channel) const 00626 { 00627 return false; 00628 } 00629 00630 bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const 00631 { 00632 for (int i = 0; i < numDevices; i++) { 00633 if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel)) 00634 return false; 00635 } 00636 return true; 00637 } 00638 00639 bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const 00640 { 00641 return false; 00642 } 00643 00644 bool cDevice::ProvidesEIT(void) const 00645 { 00646 return false; 00647 } 00648 00649 int cDevice::NumProvidedSystems(void) const 00650 { 00651 return 0; 00652 } 00653 00654 int cDevice::SignalStrength(void) const 00655 { 00656 return -1; 00657 } 00658 00659 int cDevice::SignalQuality(void) const 00660 { 00661 return -1; 00662 } 00663 00664 const cChannel *cDevice::GetCurrentlyTunedTransponder(void) const 00665 { 00666 return NULL; 00667 } 00668 00669 bool cDevice::IsTunedToTransponder(const cChannel *Channel) const 00670 { 00671 return false; 00672 } 00673 00674 bool cDevice::MaySwitchTransponder(const cChannel *Channel) const 00675 { 00676 return time(NULL) > occupiedTimeout && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid); 00677 } 00678 00679 bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView) 00680 { 00681 if (LiveView) { 00682 isyslog("switching to channel %d", Channel->Number()); 00683 cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer 00684 } 00685 for (int i = 3; i--;) { 00686 switch (SetChannel(Channel, LiveView)) { 00687 case scrOk: return true; 00688 case scrNotAvailable: Skins.Message(mtInfo, tr("Channel not available!")); 00689 return false; 00690 case scrNoTransfer: Skins.Message(mtError, tr("Can't start Transfer Mode!")); 00691 return false; 00692 case scrFailed: break; // loop will retry 00693 default: esyslog("ERROR: invalid return value from SetChannel"); 00694 } 00695 esyslog("retrying"); 00696 } 00697 return false; 00698 } 00699 00700 bool cDevice::SwitchChannel(int Direction) 00701 { 00702 bool result = false; 00703 Direction = sgn(Direction); 00704 if (Direction) { 00705 cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer 00706 int n = CurrentChannel() + Direction; 00707 int first = n; 00708 cChannel *channel; 00709 while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { 00710 // try only channels which are currently available 00711 if (GetDevice(channel, LIVEPRIORITY, true, true)) 00712 break; 00713 n = channel->Number() + Direction; 00714 } 00715 if (channel) { 00716 int d = n - first; 00717 if (abs(d) == 1) 00718 dsyslog("skipped channel %d", first); 00719 else if (d) 00720 dsyslog("skipped channels %d..%d", first, n - sgn(d)); 00721 if (PrimaryDevice()->SwitchChannel(channel, true)) 00722 result = true; 00723 } 00724 else if (n != first) 00725 Skins.Message(mtError, tr("Channel not available!")); 00726 } 00727 return result; 00728 } 00729 00730 eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) 00731 { 00732 cStatus::MsgChannelSwitch(this, 0, LiveView); 00733 00734 if (LiveView) { 00735 StopReplay(); 00736 DELETENULL(liveSubtitle); 00737 DELETENULL(dvbSubtitleConverter); 00738 } 00739 00740 cDevice *Device = (LiveView && IsPrimaryDevice()) ? GetDevice(Channel, LIVEPRIORITY, true) : this; 00741 00742 bool NeedsTransferMode = Device != this; 00743 00744 eSetChannelResult Result = scrOk; 00745 00746 // If this DVB card can't receive this channel, let's see if we can 00747 // use the card that actually can receive it and transfer data from there: 00748 00749 if (NeedsTransferMode) { 00750 if (Device && CanReplay()) { 00751 if (Device->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()! 00752 cControl::Launch(new cTransferControl(Device, Channel)); 00753 else 00754 Result = scrNoTransfer; 00755 } 00756 else 00757 Result = scrNotAvailable; 00758 } 00759 else { 00760 Channels.Lock(false); 00761 // Stop section handling: 00762 if (sectionHandler) { 00763 sectionHandler->SetStatus(false); 00764 sectionHandler->SetChannel(NULL); 00765 } 00766 // Tell the camSlot about the channel switch and add all PIDs of this 00767 // channel to it, for possible later decryption: 00768 if (camSlot) 00769 camSlot->AddChannel(Channel); 00770 if (SetChannelDevice(Channel, LiveView)) { 00771 // Start section handling: 00772 if (sectionHandler) { 00773 sectionHandler->SetChannel(Channel); 00774 sectionHandler->SetStatus(true); 00775 } 00776 // Start decrypting any PIDs that might have been set in SetChannelDevice(): 00777 if (camSlot) 00778 camSlot->StartDecrypting(); 00779 } 00780 else 00781 Result = scrFailed; 00782 Channels.Unlock(); 00783 } 00784 00785 if (Result == scrOk) { 00786 if (LiveView && IsPrimaryDevice()) { 00787 currentChannel = Channel->Number(); 00788 // Set the available audio tracks: 00789 ClrAvailableTracks(); 00790 for (int i = 0; i < MAXAPIDS; i++) 00791 SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i)); 00792 if (Setup.UseDolbyDigital) { 00793 for (int i = 0; i < MAXDPIDS; i++) 00794 SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i)); 00795 } 00796 for (int i = 0; i < MAXSPIDS; i++) 00797 SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i)); 00798 if (!NeedsTransferMode) 00799 EnsureAudioTrack(true); 00800 EnsureSubtitleTrack(); 00801 } 00802 cStatus::MsgChannelSwitch(this, Channel->Number(), LiveView); // only report status if channel switch successfull 00803 } 00804 00805 return Result; 00806 } 00807 00808 void cDevice::ForceTransferMode(void) 00809 { 00810 if (!cTransferControl::ReceiverDevice()) { 00811 cChannel *Channel = Channels.GetByNumber(CurrentChannel()); 00812 if (Channel) 00813 SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode 00814 } 00815 } 00816 00817 int cDevice::Occupied(void) const 00818 { 00819 int Seconds = occupiedTimeout - time(NULL); 00820 return Seconds > 0 ? Seconds : 0; 00821 } 00822 00823 void cDevice::SetOccupied(int Seconds) 00824 { 00825 if (Seconds >= 0) 00826 occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT); 00827 } 00828 00829 bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) 00830 { 00831 return false; 00832 } 00833 00834 bool cDevice::HasLock(int TimeoutMs) 00835 { 00836 return true; 00837 } 00838 00839 bool cDevice::HasProgramme(void) 00840 { 00841 return Replaying() || pidHandles[ptAudio].pid || pidHandles[ptVideo].pid; 00842 } 00843 00844 int cDevice::GetAudioChannelDevice(void) 00845 { 00846 return 0; 00847 } 00848 00849 void cDevice::SetAudioChannelDevice(int AudioChannel) 00850 { 00851 } 00852 00853 void cDevice::SetVolumeDevice(int Volume) 00854 { 00855 } 00856 00857 void cDevice::SetDigitalAudioDevice(bool On) 00858 { 00859 } 00860 00861 void cDevice::SetAudioTrackDevice(eTrackType Type) 00862 { 00863 } 00864 00865 void cDevice::SetSubtitleTrackDevice(eTrackType Type) 00866 { 00867 } 00868 00869 bool cDevice::ToggleMute(void) 00870 { 00871 int OldVolume = volume; 00872 mute = !mute; 00873 //XXX why is it necessary to use different sequences??? 00874 if (mute) { 00875 SetVolume(0, true); 00876 Audios.MuteAudio(mute); // Mute external audio after analog audio 00877 } 00878 else { 00879 Audios.MuteAudio(mute); // Enable external audio before analog audio 00880 SetVolume(OldVolume, true); 00881 } 00882 volume = OldVolume; 00883 return mute; 00884 } 00885 00886 int cDevice::GetAudioChannel(void) 00887 { 00888 int c = GetAudioChannelDevice(); 00889 return (0 <= c && c <= 2) ? c : 0; 00890 } 00891 00892 void cDevice::SetAudioChannel(int AudioChannel) 00893 { 00894 if (0 <= AudioChannel && AudioChannel <= 2) 00895 SetAudioChannelDevice(AudioChannel); 00896 } 00897 00898 void cDevice::SetVolume(int Volume, bool Absolute) 00899 { 00900 int OldVolume = volume; 00901 volume = constrain(Absolute ? Volume : volume + Volume, 0, MAXVOLUME); 00902 SetVolumeDevice(volume); 00903 Absolute |= mute; 00904 cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute); 00905 if (volume > 0) { 00906 mute = false; 00907 Audios.MuteAudio(mute); 00908 } 00909 } 00910 00911 void cDevice::ClrAvailableTracks(bool DescriptionsOnly, bool IdsOnly) 00912 { 00913 if (DescriptionsOnly) { 00914 for (int i = ttNone; i < ttMaxTrackTypes; i++) 00915 *availableTracks[i].description = 0; 00916 } 00917 else { 00918 if (IdsOnly) { 00919 for (int i = ttNone; i < ttMaxTrackTypes; i++) 00920 availableTracks[i].id = 0; 00921 } 00922 else 00923 memset(availableTracks, 0, sizeof(availableTracks)); 00924 pre_1_3_19_PrivateStream = 0; 00925 SetAudioChannel(0); // fall back to stereo 00926 currentAudioTrackMissingCount = 0; 00927 currentAudioTrack = ttNone; 00928 currentSubtitleTrack = ttNone; 00929 } 00930 } 00931 00932 bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description) 00933 { 00934 eTrackType t = eTrackType(Type + Index); 00935 if (Type == ttAudio && IS_AUDIO_TRACK(t) || 00936 Type == ttDolby && IS_DOLBY_TRACK(t) || 00937 Type == ttSubtitle && IS_SUBTITLE_TRACK(t)) { 00938 if (Language) 00939 strn0cpy(availableTracks[t].language, Language, sizeof(availableTracks[t].language)); 00940 if (Description) 00941 Utf8Strn0Cpy(availableTracks[t].description, Description, sizeof(availableTracks[t].description)); 00942 if (Id) { 00943 availableTracks[t].id = Id; // setting 'id' last to avoid the need for extensive locking 00944 if (Type == ttAudio || Type == ttDolby) { 00945 int numAudioTracks = NumAudioTracks(); 00946 if (!availableTracks[currentAudioTrack].id && numAudioTracks && currentAudioTrackMissingCount++ > numAudioTracks * 10) 00947 EnsureAudioTrack(); 00948 else if (t == currentAudioTrack) 00949 currentAudioTrackMissingCount = 0; 00950 } 00951 else if (Type == ttSubtitle && autoSelectPreferredSubtitleLanguage) 00952 EnsureSubtitleTrack(); 00953 } 00954 return true; 00955 } 00956 else 00957 esyslog("ERROR: SetAvailableTrack called with invalid Type/Index (%d/%d)", Type, Index); 00958 return false; 00959 } 00960 00961 const tTrackId *cDevice::GetTrack(eTrackType Type) 00962 { 00963 return (ttNone < Type && Type < ttMaxTrackTypes) ? &availableTracks[Type] : NULL; 00964 } 00965 00966 int cDevice::NumTracks(eTrackType FirstTrack, eTrackType LastTrack) const 00967 { 00968 int n = 0; 00969 for (int i = FirstTrack; i <= LastTrack; i++) { 00970 if (availableTracks[i].id) 00971 n++; 00972 } 00973 return n; 00974 } 00975 00976 int cDevice::NumAudioTracks(void) const 00977 { 00978 return NumTracks(ttAudioFirst, ttDolbyLast); 00979 } 00980 00981 int cDevice::NumSubtitleTracks(void) const 00982 { 00983 return NumTracks(ttSubtitleFirst, ttSubtitleLast); 00984 } 00985 00986 bool cDevice::SetCurrentAudioTrack(eTrackType Type) 00987 { 00988 if (ttNone < Type && Type <= ttDolbyLast) { 00989 cMutexLock MutexLock(&mutexCurrentAudioTrack); 00990 if (IS_DOLBY_TRACK(Type)) 00991 SetDigitalAudioDevice(true); 00992 currentAudioTrack = Type; 00993 if (player) 00994 player->SetAudioTrack(currentAudioTrack, GetTrack(currentAudioTrack)); 00995 else 00996 SetAudioTrackDevice(currentAudioTrack); 00997 if (IS_AUDIO_TRACK(Type)) 00998 SetDigitalAudioDevice(false); 00999 return true; 01000 } 01001 return false; 01002 } 01003 01004 bool cDevice::SetCurrentSubtitleTrack(eTrackType Type, bool Manual) 01005 { 01006 if (Type == ttNone || IS_SUBTITLE_TRACK(Type)) { 01007 currentSubtitleTrack = Type; 01008 autoSelectPreferredSubtitleLanguage = !Manual; 01009 if (dvbSubtitleConverter) 01010 dvbSubtitleConverter->Reset(); 01011 if (Type == ttNone && dvbSubtitleConverter) { 01012 cMutexLock MutexLock(&mutexCurrentSubtitleTrack); 01013 DELETENULL(dvbSubtitleConverter); 01014 } 01015 DELETENULL(liveSubtitle); 01016 if (player) 01017 player->SetSubtitleTrack(currentSubtitleTrack, GetTrack(currentSubtitleTrack)); 01018 else 01019 SetSubtitleTrackDevice(currentSubtitleTrack); 01020 if (currentSubtitleTrack != ttNone && !Replaying() && !Transferring()) { 01021 const tTrackId *TrackId = GetTrack(currentSubtitleTrack); 01022 if (TrackId && TrackId->id) { 01023 liveSubtitle = new cLiveSubtitle(TrackId->id); 01024 AttachReceiver(liveSubtitle); 01025 } 01026 } 01027 return true; 01028 } 01029 return false; 01030 } 01031 01032 void cDevice::EnsureAudioTrack(bool Force) 01033 { 01034 if (Force || !availableTracks[currentAudioTrack].id) { 01035 eTrackType PreferredTrack = ttAudioFirst; 01036 int PreferredAudioChannel = 0; 01037 int LanguagePreference = -1; 01038 int StartCheck = Setup.CurrentDolby ? ttDolbyFirst : ttAudioFirst; 01039 int EndCheck = ttDolbyLast; 01040 for (int i = StartCheck; i <= EndCheck; i++) { 01041 const tTrackId *TrackId = GetTrack(eTrackType(i)); 01042 int pos = 0; 01043 if (TrackId && TrackId->id && I18nIsPreferredLanguage(Setup.AudioLanguages, TrackId->language, LanguagePreference, &pos)) { 01044 PreferredTrack = eTrackType(i); 01045 PreferredAudioChannel = pos; 01046 } 01047 if (Setup.CurrentDolby && i == ttDolbyLast) { 01048 i = ttAudioFirst - 1; 01049 EndCheck = ttAudioLast; 01050 } 01051 } 01052 // Make sure we're set to an available audio track: 01053 const tTrackId *Track = GetTrack(GetCurrentAudioTrack()); 01054 if (Force || !Track || !Track->id || PreferredTrack != GetCurrentAudioTrack()) { 01055 if (!Force) // only log this for automatic changes 01056 dsyslog("setting audio track to %d (%d)", PreferredTrack, PreferredAudioChannel); 01057 SetCurrentAudioTrack(PreferredTrack); 01058 SetAudioChannel(PreferredAudioChannel); 01059 } 01060 } 01061 } 01062 01063 void cDevice::EnsureSubtitleTrack(void) 01064 { 01065 if (Setup.DisplaySubtitles) { 01066 eTrackType PreferredTrack = ttNone; 01067 int LanguagePreference = INT_MAX; // higher than the maximum possible value 01068 for (int i = ttSubtitleFirst; i <= ttSubtitleLast; i++) { 01069 const tTrackId *TrackId = GetTrack(eTrackType(i)); 01070 if (TrackId && TrackId->id && (I18nIsPreferredLanguage(Setup.SubtitleLanguages, TrackId->language, LanguagePreference) || 01071 (i == ttSubtitleFirst + 8 && !*TrackId->language && LanguagePreference == INT_MAX))) // compatibility mode for old subtitles plugin 01072 PreferredTrack = eTrackType(i); 01073 } 01074 // Make sure we're set to an available subtitle track: 01075 const tTrackId *Track = GetTrack(GetCurrentSubtitleTrack()); 01076 if (!Track || !Track->id || PreferredTrack != GetCurrentSubtitleTrack()) 01077 SetCurrentSubtitleTrack(PreferredTrack); 01078 } 01079 else 01080 SetCurrentSubtitleTrack(ttNone); 01081 } 01082 01083 bool cDevice::CanReplay(void) const 01084 { 01085 return HasDecoder(); 01086 } 01087 01088 bool cDevice::SetPlayMode(ePlayMode PlayMode) 01089 { 01090 return false; 01091 } 01092 01093 int64_t cDevice::GetSTC(void) 01094 { 01095 return -1; 01096 } 01097 01098 void cDevice::TrickSpeed(int Speed) 01099 { 01100 } 01101 01102 void cDevice::Clear(void) 01103 { 01104 Audios.ClearAudio(); 01105 if (dvbSubtitleConverter) 01106 dvbSubtitleConverter->Reset(); 01107 } 01108 01109 void cDevice::Play(void) 01110 { 01111 Audios.MuteAudio(mute); 01112 if (dvbSubtitleConverter) 01113 dvbSubtitleConverter->Freeze(false); 01114 } 01115 01116 void cDevice::Freeze(void) 01117 { 01118 Audios.MuteAudio(true); 01119 if (dvbSubtitleConverter) 01120 dvbSubtitleConverter->Freeze(true); 01121 } 01122 01123 void cDevice::Mute(void) 01124 { 01125 Audios.MuteAudio(true); 01126 } 01127 01128 void cDevice::StillPicture(const uchar *Data, int Length) 01129 { 01130 if (Data[0] == 0x47) { 01131 // TS data 01132 cTsToPes TsToPes; 01133 uchar *buf = NULL; 01134 int Size = 0; 01135 while (Length >= TS_SIZE) { 01136 int Pid = TsPid(Data); 01137 if (Pid == 0) 01138 patPmtParser.ParsePat(Data, TS_SIZE); 01139 else if (Pid == patPmtParser.PmtPid()) 01140 patPmtParser.ParsePmt(Data, TS_SIZE); 01141 else if (Pid == patPmtParser.Vpid()) { 01142 if (TsPayloadStart(Data)) { 01143 int l; 01144 while (const uchar *p = TsToPes.GetPes(l)) { 01145 int Offset = Size; 01146 int NewSize = Size + l; 01147 if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) { 01148 Size = NewSize; 01149 buf = NewBuffer; 01150 memcpy(buf + Offset, p, l); 01151 } 01152 else { 01153 LOG_ERROR_STR("out of memory"); 01154 free(buf); 01155 return; 01156 } 01157 } 01158 TsToPes.Reset(); 01159 } 01160 TsToPes.PutTs(Data, TS_SIZE); 01161 } 01162 Length -= TS_SIZE; 01163 Data += TS_SIZE; 01164 } 01165 int l; 01166 while (const uchar *p = TsToPes.GetPes(l)) { 01167 int Offset = Size; 01168 int NewSize = Size + l; 01169 if (uchar *NewBuffer = (uchar *)realloc(buf, NewSize)) { 01170 Size = NewSize; 01171 buf = NewBuffer; 01172 memcpy(buf + Offset, p, l); 01173 } 01174 else { 01175 esyslog("ERROR: out of memory"); 01176 free(buf); 01177 return; 01178 } 01179 } 01180 StillPicture(buf, Size); 01181 free(buf); 01182 } 01183 } 01184 01185 bool cDevice::Replaying(void) const 01186 { 01187 return player != NULL; 01188 } 01189 01190 bool cDevice::Transferring(void) const 01191 { 01192 return ActualDevice() != PrimaryDevice(); 01193 } 01194 01195 bool cDevice::AttachPlayer(cPlayer *Player) 01196 { 01197 if (CanReplay()) { 01198 if (player) 01199 Detach(player); 01200 DELETENULL(liveSubtitle); 01201 DELETENULL(dvbSubtitleConverter); 01202 patPmtParser.Reset(); 01203 player = Player; 01204 if (!Transferring()) 01205 ClrAvailableTracks(false, true); 01206 SetPlayMode(player->playMode); 01207 player->device = this; 01208 player->Activate(true); 01209 return true; 01210 } 01211 return false; 01212 } 01213 01214 void cDevice::Detach(cPlayer *Player) 01215 { 01216 if (Player && player == Player) { 01217 cPlayer *p = player; 01218 player = NULL; // avoids recursive calls to Detach() 01219 p->Activate(false); 01220 p->device = NULL; 01221 cMutexLock MutexLock(&mutexCurrentSubtitleTrack); 01222 delete dvbSubtitleConverter; 01223 dvbSubtitleConverter = NULL; 01224 SetPlayMode(pmNone); 01225 SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat)); 01226 PlayTs(NULL, 0); 01227 patPmtParser.Reset(); 01228 Audios.ClearAudio(); 01229 isPlayingVideo = false; 01230 } 01231 } 01232 01233 void cDevice::StopReplay(void) 01234 { 01235 if (player) { 01236 Detach(player); 01237 if (IsPrimaryDevice()) 01238 cControl::Shutdown(); 01239 } 01240 } 01241 01242 bool cDevice::Poll(cPoller &Poller, int TimeoutMs) 01243 { 01244 return false; 01245 } 01246 01247 bool cDevice::Flush(int TimeoutMs) 01248 { 01249 return true; 01250 } 01251 01252 int cDevice::PlayVideo(const uchar *Data, int Length) 01253 { 01254 return -1; 01255 } 01256 01257 int cDevice::PlayAudio(const uchar *Data, int Length, uchar Id) 01258 { 01259 return -1; 01260 } 01261 01262 int cDevice::PlaySubtitle(const uchar *Data, int Length) 01263 { 01264 if (!dvbSubtitleConverter) 01265 dvbSubtitleConverter = new cDvbSubtitleConverter; 01266 return dvbSubtitleConverter->ConvertFragments(Data, Length); 01267 } 01268 01269 int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) 01270 { 01271 cMutexLock MutexLock(&mutexCurrentAudioTrack); 01272 bool FirstLoop = true; 01273 uchar c = Data[3]; 01274 const uchar *Start = Data; 01275 const uchar *End = Start + Length; 01276 while (Start < End) { 01277 int d = End - Start; 01278 int w = d; 01279 switch (c) { 01280 case 0xBE: // padding stream, needed for MPEG1 01281 case 0xE0 ... 0xEF: // video 01282 isPlayingVideo = true; 01283 w = PlayVideo(Start, d); 01284 break; 01285 case 0xC0 ... 0xDF: // audio 01286 SetAvailableTrack(ttAudio, c - 0xC0, c); 01287 if ((!VideoOnly || HasIBPTrickSpeed()) && c == availableTracks[currentAudioTrack].id) { 01288 w = PlayAudio(Start, d, c); 01289 if (FirstLoop) 01290 Audios.PlayAudio(Data, Length, c); 01291 } 01292 break; 01293 case 0xBD: { // private stream 1 01294 // EBU Teletext data, ETSI EN 300 472 01295 // if PES data header length = 24 and data_identifier = 0x10..0x1F (EBU Data) 01296 if (Data[8] == 0x24 && Data[45] >= 0x10 && Data[45] < 0x20) { 01297 cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uint8_t*)Data, Length); 01298 break; 01299 } 01300 01301 int PayloadOffset = Data[8] + 9; 01302 01303 // Compatibility mode for old subtitles plugin: 01304 if ((Data[7] & 0x01) && (Data[PayloadOffset - 3] & 0x81) == 0x01 && Data[PayloadOffset - 2] == 0x81) 01305 PayloadOffset--; 01306 01307 uchar SubStreamId = Data[PayloadOffset]; 01308 uchar SubStreamType = SubStreamId & 0xF0; 01309 uchar SubStreamIndex = SubStreamId & 0x1F; 01310 01311 // Compatibility mode for old VDR recordings, where 0xBD was only AC3: 01312 pre_1_3_19_PrivateStreamDetected: 01313 if (pre_1_3_19_PrivateStream > MIN_PRE_1_3_19_PRIVATESTREAM) { 01314 SubStreamId = c; 01315 SubStreamType = 0x80; 01316 SubStreamIndex = 0; 01317 } 01318 else if (pre_1_3_19_PrivateStream) 01319 pre_1_3_19_PrivateStream--; // every known PS1 packet counts down towards 0 to recover from glitches... 01320 switch (SubStreamType) { 01321 case 0x20: // SPU 01322 case 0x30: // SPU 01323 SetAvailableTrack(ttSubtitle, SubStreamIndex, SubStreamId); 01324 if ((!VideoOnly || HasIBPTrickSpeed()) && currentSubtitleTrack != ttNone && SubStreamId == availableTracks[currentSubtitleTrack].id) 01325 w = PlaySubtitle(Start, d); 01326 break; 01327 case 0x80: // AC3 & DTS 01328 if (Setup.UseDolbyDigital) { 01329 SetAvailableTrack(ttDolby, SubStreamIndex, SubStreamId); 01330 if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) { 01331 w = PlayAudio(Start, d, SubStreamId); 01332 if (FirstLoop) 01333 Audios.PlayAudio(Data, Length, SubStreamId); 01334 } 01335 } 01336 break; 01337 case 0xA0: // LPCM 01338 SetAvailableTrack(ttAudio, SubStreamIndex, SubStreamId); 01339 if ((!VideoOnly || HasIBPTrickSpeed()) && SubStreamId == availableTracks[currentAudioTrack].id) { 01340 w = PlayAudio(Start, d, SubStreamId); 01341 if (FirstLoop) 01342 Audios.PlayAudio(Data, Length, SubStreamId); 01343 } 01344 break; 01345 default: 01346 // Compatibility mode for old VDR recordings, where 0xBD was only AC3: 01347 if (pre_1_3_19_PrivateStream <= MIN_PRE_1_3_19_PRIVATESTREAM) { 01348 dsyslog("unknown PS1 packet, substream id = %02X (counter is at %d)", SubStreamId, pre_1_3_19_PrivateStream); 01349 pre_1_3_19_PrivateStream += 2; // ...and every unknown PS1 packet counts up (the very first one counts twice, but that's ok) 01350 if (pre_1_3_19_PrivateStream > MIN_PRE_1_3_19_PRIVATESTREAM) { 01351 dsyslog("switching to pre 1.3.19 Dolby Digital compatibility mode - substream id = %02X", SubStreamId); 01352 ClrAvailableTracks(); 01353 pre_1_3_19_PrivateStream = MIN_PRE_1_3_19_PRIVATESTREAM + 1; 01354 goto pre_1_3_19_PrivateStreamDetected; 01355 } 01356 } 01357 } 01358 } 01359 break; 01360 default: 01361 ;//esyslog("ERROR: unexpected packet id %02X", c); 01362 } 01363 if (w > 0) 01364 Start += w; 01365 else { 01366 if (Start != Data) 01367 esyslog("ERROR: incomplete PES packet write!"); 01368 return Start == Data ? w : Start - Data; 01369 } 01370 FirstLoop = false; 01371 } 01372 return Length; 01373 } 01374 01375 int cDevice::PlayPes(const uchar *Data, int Length, bool VideoOnly) 01376 { 01377 if (!Data) { 01378 if (dvbSubtitleConverter) 01379 dvbSubtitleConverter->Reset(); 01380 return 0; 01381 } 01382 int i = 0; 01383 while (i <= Length - 6) { 01384 if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) { 01385 int l = PesLength(Data + i); 01386 if (i + l > Length) { 01387 esyslog("ERROR: incomplete PES packet!"); 01388 return Length; 01389 } 01390 int w = PlayPesPacket(Data + i, l, VideoOnly); 01391 if (w > 0) 01392 i += l; 01393 else 01394 return i == 0 ? w : i; 01395 } 01396 else 01397 i++; 01398 } 01399 if (i < Length) 01400 esyslog("ERROR: leftover PES data!"); 01401 return Length; 01402 } 01403 01404 int cDevice::PlayTsVideo(const uchar *Data, int Length) 01405 { 01406 // Video PES has no explicit length, so we can only determine the end of 01407 // a PES packet when the next TS packet that starts a payload comes in: 01408 if (TsPayloadStart(Data)) { 01409 int l; 01410 while (const uchar *p = tsToPesVideo.GetPes(l)) { 01411 int w = PlayVideo(p, l); 01412 if (w <= 0) { 01413 tsToPesVideo.SetRepeatLast(); 01414 return w; 01415 } 01416 } 01417 tsToPesVideo.Reset(); 01418 } 01419 tsToPesVideo.PutTs(Data, Length); 01420 return Length; 01421 } 01422 01423 int cDevice::PlayTsAudio(const uchar *Data, int Length) 01424 { 01425 // Audio PES always has an explicit length and consists of single packets: 01426 int l; 01427 if (const uchar *p = tsToPesAudio.GetPes(l)) { 01428 int w = PlayAudio(p, l, p[3]); 01429 if (w <= 0) { 01430 tsToPesAudio.SetRepeatLast(); 01431 return w; 01432 } 01433 tsToPesAudio.Reset(); 01434 } 01435 tsToPesAudio.PutTs(Data, Length); 01436 return Length; 01437 } 01438 01439 int cDevice::PlayTsSubtitle(const uchar *Data, int Length) 01440 { 01441 if (!dvbSubtitleConverter) 01442 dvbSubtitleConverter = new cDvbSubtitleConverter; 01443 tsToPesSubtitle.PutTs(Data, Length); 01444 int l; 01445 if (const uchar *p = tsToPesSubtitle.GetPes(l)) { 01446 dvbSubtitleConverter->Convert(p, l); 01447 tsToPesSubtitle.Reset(); 01448 } 01449 return Length; 01450 } 01451 01452 //TODO detect and report continuity errors? 01453 int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly) 01454 { 01455 int Played = 0; 01456 if (Data == NULL) { 01457 tsToPesVideo.Reset(); 01458 tsToPesAudio.Reset(); 01459 tsToPesSubtitle.Reset(); 01460 tsToPesTeletext.Reset(); 01461 } 01462 else if (Length < TS_SIZE) { 01463 esyslog("ERROR: skipped %d bytes of TS fragment", Length); 01464 return Length; 01465 } 01466 else { 01467 cMutexLock MutexLock(&mutexCurrentAudioTrack); 01468 while (Length >= TS_SIZE) { 01469 if (Data[0] != TS_SYNC_BYTE) { 01470 int Skipped = 1; 01471 while (Skipped < Length && (Data[Skipped] != TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] != TS_SYNC_BYTE)) 01472 Skipped++; 01473 esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped); 01474 return Played + Skipped; 01475 } 01476 int Pid = TsPid(Data); 01477 if (TsHasPayload(Data)) { // silently ignore TS packets w/o payload 01478 int PayloadOffset = TsPayloadOffset(Data); 01479 if (PayloadOffset < TS_SIZE) { 01480 if (Pid == 0) 01481 patPmtParser.ParsePat(Data, TS_SIZE); 01482 else if (Pid == patPmtParser.PmtPid()) 01483 patPmtParser.ParsePmt(Data, TS_SIZE); 01484 else if (Pid == patPmtParser.Vpid()) { 01485 isPlayingVideo = true; 01486 int w = PlayTsVideo(Data, TS_SIZE); 01487 if (w < 0) 01488 return Played ? Played : w; 01489 if (w == 0) 01490 break; 01491 } 01492 else if (Pid == availableTracks[currentAudioTrack].id) { 01493 if (!VideoOnly || HasIBPTrickSpeed()) { 01494 int w = PlayTsAudio(Data, TS_SIZE); 01495 if (w < 0) 01496 return Played ? Played : w; 01497 if (w == 0) 01498 break; 01499 Audios.PlayTsAudio(Data, TS_SIZE); 01500 } 01501 } 01502 else if (Pid == availableTracks[currentSubtitleTrack].id) { 01503 if (!VideoOnly || HasIBPTrickSpeed()) 01504 PlayTsSubtitle(Data, TS_SIZE); 01505 } 01506 else if (Pid == patPmtParser.Tpid()) { 01507 if (!VideoOnly || HasIBPTrickSpeed()) { 01508 int l; 01509 tsToPesTeletext.PutTs(Data, Length); 01510 if (const uchar *p = tsToPesTeletext.GetPes(l)) { 01511 if ((l > 45) && (p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xbd) && (p[8] == 0x24) && (p[45] >= 0x10) && (p[45] < 0x20)) 01512 cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uchar *)p, l, false, patPmtParser.TeletextSubtitlePages(), patPmtParser.TotalTeletextSubtitlePages()); 01513 tsToPesTeletext.Reset(); 01514 } 01515 } 01516 } 01517 } 01518 } 01519 else if (Pid == patPmtParser.Ppid()) { 01520 int w = PlayTsVideo(Data, TS_SIZE); 01521 if (w < 0) 01522 return Played ? Played : w; 01523 if (w == 0) 01524 break; 01525 } 01526 Played += TS_SIZE; 01527 Length -= TS_SIZE; 01528 Data += TS_SIZE; 01529 } 01530 } 01531 return Played; 01532 } 01533 01534 int cDevice::Priority(void) const 01535 { 01536 int priority = IDLEPRIORITY; 01537 if (IsPrimaryDevice() && !Replaying() && ActualDevice() == PrimaryDevice()) 01538 priority = TRANSFERPRIORITY; // we use the same value here, no matter whether it's actual Transfer Mode or real live viewing 01539 cMutexLock MutexLock(&mutexReceiver); 01540 for (int i = 0; i < MAXRECEIVERS; i++) { 01541 if (receiver[i]) 01542 priority = max(receiver[i]->priority, priority); 01543 } 01544 return priority; 01545 } 01546 01547 bool cDevice::Ready(void) 01548 { 01549 return true; 01550 } 01551 01552 bool cDevice::Receiving(bool Dummy) const 01553 { 01554 cMutexLock MutexLock(&mutexReceiver); 01555 for (int i = 0; i < MAXRECEIVERS; i++) { 01556 if (receiver[i]) 01557 return true; 01558 } 01559 return false; 01560 } 01561 01562 #define TS_SCRAMBLING_TIMEOUT 3 // seconds to wait until a TS becomes unscrambled 01563 #define TS_SCRAMBLING_TIME_OK 10 // seconds before a Channel/CAM combination is marked as known to decrypt 01564 01565 void cDevice::Action(void) 01566 { 01567 if (Running() && OpenDvr()) { 01568 while (Running()) { 01569 // Read data from the DVR device: 01570 uchar *b = NULL; 01571 if (GetTSPacket(b)) { 01572 if (b) { 01573 int Pid = TsPid(b); 01574 // Check whether the TS packets are scrambled: 01575 bool DetachReceivers = false; 01576 bool DescramblingOk = false; 01577 int CamSlotNumber = 0; 01578 if (startScrambleDetection) { 01579 cCamSlot *cs = CamSlot(); 01580 CamSlotNumber = cs ? cs->SlotNumber() : 0; 01581 if (CamSlotNumber) { 01582 bool Scrambled = b[3] & TS_SCRAMBLING_CONTROL; 01583 int t = time(NULL) - startScrambleDetection; 01584 if (Scrambled) { 01585 if (t > TS_SCRAMBLING_TIMEOUT) 01586 DetachReceivers = true; 01587 } 01588 else if (t > TS_SCRAMBLING_TIME_OK) { 01589 DescramblingOk = true; 01590 startScrambleDetection = 0; 01591 } 01592 } 01593 } 01594 // Distribute the packet to all attached receivers: 01595 Lock(); 01596 for (int i = 0; i < MAXRECEIVERS; i++) { 01597 if (receiver[i] && receiver[i]->WantsPid(Pid)) { 01598 if (DetachReceivers) { 01599 ChannelCamRelations.SetChecked(receiver[i]->ChannelID(), CamSlotNumber); 01600 Detach(receiver[i]); 01601 } 01602 else 01603 receiver[i]->Receive(b, TS_SIZE); 01604 if (DescramblingOk) 01605 ChannelCamRelations.SetDecrypt(receiver[i]->ChannelID(), CamSlotNumber); 01606 } 01607 } 01608 Unlock(); 01609 } 01610 } 01611 else 01612 break; 01613 } 01614 CloseDvr(); 01615 } 01616 } 01617 01618 bool cDevice::OpenDvr(void) 01619 { 01620 return false; 01621 } 01622 01623 void cDevice::CloseDvr(void) 01624 { 01625 } 01626 01627 bool cDevice::GetTSPacket(uchar *&Data) 01628 { 01629 return false; 01630 } 01631 01632 bool cDevice::AttachReceiver(cReceiver *Receiver) 01633 { 01634 if (!Receiver) 01635 return false; 01636 if (Receiver->device == this) 01637 return true; 01638 // activate the following line if you need it - actually the driver should be fixed! 01639 //#define WAIT_FOR_TUNER_LOCK 01640 #ifdef WAIT_FOR_TUNER_LOCK 01641 #define TUNER_LOCK_TIMEOUT 5000 // ms 01642 if (!HasLock(TUNER_LOCK_TIMEOUT)) { 01643 esyslog("ERROR: device %d has no lock, can't attach receiver!", CardIndex() + 1); 01644 return false; 01645 } 01646 #endif 01647 cMutexLock MutexLock(&mutexReceiver); 01648 for (int i = 0; i < MAXRECEIVERS; i++) { 01649 if (!receiver[i]) { 01650 for (int n = 0; n < Receiver->numPids; n++) { 01651 if (!AddPid(Receiver->pids[n])) { 01652 for ( ; n-- > 0; ) 01653 DelPid(Receiver->pids[n]); 01654 return false; 01655 } 01656 } 01657 Receiver->Activate(true); 01658 Lock(); 01659 Receiver->device = this; 01660 receiver[i] = Receiver; 01661 Unlock(); 01662 if (camSlot) { 01663 camSlot->StartDecrypting(); 01664 startScrambleDetection = time(NULL); 01665 } 01666 Start(); 01667 return true; 01668 } 01669 } 01670 esyslog("ERROR: no free receiver slot!"); 01671 return false; 01672 } 01673 01674 void cDevice::Detach(cReceiver *Receiver) 01675 { 01676 if (!Receiver || Receiver->device != this) 01677 return; 01678 bool receiversLeft = false; 01679 cMutexLock MutexLock(&mutexReceiver); 01680 for (int i = 0; i < MAXRECEIVERS; i++) { 01681 if (receiver[i] == Receiver) { 01682 Receiver->Activate(false); 01683 Lock(); 01684 receiver[i] = NULL; 01685 Receiver->device = NULL; 01686 Unlock(); 01687 for (int n = 0; n < Receiver->numPids; n++) 01688 DelPid(Receiver->pids[n]); 01689 } 01690 else if (receiver[i]) 01691 receiversLeft = true; 01692 } 01693 if (camSlot) 01694 camSlot->StartDecrypting(); 01695 if (!receiversLeft) 01696 Cancel(-1); 01697 } 01698 01699 void cDevice::DetachAll(int Pid) 01700 { 01701 if (Pid) { 01702 cMutexLock MutexLock(&mutexReceiver); 01703 for (int i = 0; i < MAXRECEIVERS; i++) { 01704 cReceiver *Receiver = receiver[i]; 01705 if (Receiver && Receiver->WantsPid(Pid)) 01706 Detach(Receiver); 01707 } 01708 } 01709 } 01710 01711 void cDevice::DetachAllReceivers(void) 01712 { 01713 cMutexLock MutexLock(&mutexReceiver); 01714 for (int i = 0; i < MAXRECEIVERS; i++) 01715 Detach(receiver[i]); 01716 } 01717 01718 // --- cTSBuffer ------------------------------------------------------------- 01719 01720 cTSBuffer::cTSBuffer(int File, int Size, int CardIndex) 01721 { 01722 SetDescription("TS buffer on device %d", CardIndex); 01723 f = File; 01724 cardIndex = CardIndex; 01725 delivered = false; 01726 ringBuffer = new cRingBufferLinear(Size, TS_SIZE, true, "TS"); 01727 ringBuffer->SetTimeouts(100, 100); 01728 Start(); 01729 } 01730 01731 cTSBuffer::~cTSBuffer() 01732 { 01733 Cancel(3); 01734 delete ringBuffer; 01735 } 01736 01737 void cTSBuffer::Action(void) 01738 { 01739 if (ringBuffer) { 01740 bool firstRead = true; 01741 cPoller Poller(f); 01742 while (Running()) { 01743 if (firstRead || Poller.Poll(100)) { 01744 firstRead = false; 01745 int r = ringBuffer->Read(f); 01746 if (r < 0 && FATALERRNO) { 01747 if (errno == EOVERFLOW) 01748 esyslog("ERROR: driver buffer overflow on device %d", cardIndex); 01749 else { 01750 LOG_ERROR; 01751 break; 01752 } 01753 } 01754 } 01755 } 01756 } 01757 } 01758 01759 uchar *cTSBuffer::Get(void) 01760 { 01761 int Count = 0; 01762 if (delivered) { 01763 ringBuffer->Del(TS_SIZE); 01764 delivered = false; 01765 } 01766 uchar *p = ringBuffer->Get(Count); 01767 if (p && Count >= TS_SIZE) { 01768 if (*p != TS_SYNC_BYTE) { 01769 for (int i = 1; i < Count; i++) { 01770 if (p[i] == TS_SYNC_BYTE) { 01771 Count = i; 01772 break; 01773 } 01774 } 01775 ringBuffer->Del(Count); 01776 esyslog("ERROR: skipped %d bytes to sync on TS packet on device %d", Count, cardIndex); 01777 return NULL; 01778 } 01779 delivered = true; 01780 return p; 01781 } 01782 return NULL; 01783 }