00001
00002
00003
00004 #include <fcntl.h>
00005 #include <unistd.h>
00006 #include <sys/select.h>
00007
00008 #include "mythdbcon.h"
00009 #include "atscstreamdata.h"
00010 #include "mpegtables.h"
00011 #include "atsctables.h"
00012 #include "firewirechannel.h"
00013 #include "firewiresignalmonitor.h"
00014 #include "mythlogging.h"
00015
00016 #define LOC QString("FireSM(%1): ").arg(channel->GetDevice())
00017
00018 void FirewireTableMonitorThread::run(void)
00019 {
00020 RunProlog();
00021 m_parent->RunTableMonitor();
00022 RunEpilog();
00023 }
00024
00025 const uint FirewireSignalMonitor::kPowerTimeout = 3000;
00026 const uint FirewireSignalMonitor::kBufferTimeout = 5000;
00027
00028 QMap<void*,uint> FirewireSignalMonitor::pat_keys;
00029 QMutex FirewireSignalMonitor::pat_keys_lock;
00030
00045 FirewireSignalMonitor::FirewireSignalMonitor(
00046 int db_cardnum,
00047 FirewireChannel *_channel,
00048 uint64_t _flags) :
00049 DTVSignalMonitor(db_cardnum, _channel, _flags),
00050 dtvMonitorRunning(false),
00051 tableMonitorThread(NULL),
00052 stb_needs_retune(true),
00053 stb_needs_to_wait_for_pat(false),
00054 stb_needs_to_wait_for_power(false)
00055 {
00056 LOG(VB_CHANNEL, LOG_INFO, LOC + "ctor");
00057
00058 signalStrength.SetThreshold(65);
00059
00060 AddFlags(kSigMon_WaitForSig);
00061
00062 stb_needs_retune =
00063 (FirewireDevice::kAVCPowerOff == _channel->GetPowerState());
00064 }
00065
00069 FirewireSignalMonitor::~FirewireSignalMonitor()
00070 {
00071 LOG(VB_CHANNEL, LOG_INFO, LOC + "dtor");
00072 Stop();
00073 }
00074
00078 void FirewireSignalMonitor::Stop(void)
00079 {
00080 LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- begin");
00081 SignalMonitor::Stop();
00082 if (tableMonitorThread)
00083 {
00084 dtvMonitorRunning = false;
00085 tableMonitorThread->wait();
00086 delete tableMonitorThread;
00087 tableMonitorThread = NULL;
00088 }
00089 LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- end");
00090 }
00091
00092 void FirewireSignalMonitor::HandlePAT(const ProgramAssociationTable *pat)
00093 {
00094 AddFlags(kDTVSigMon_PATSeen);
00095
00096 FirewireChannel *fwchan = dynamic_cast<FirewireChannel*>(channel);
00097 if (!fwchan)
00098 return;
00099
00100 bool crc_bogus = !fwchan->GetFirewireDevice()->IsSTBBufferCleared();
00101 if (crc_bogus && stb_needs_to_wait_for_pat &&
00102 (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout))
00103 {
00104 LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePAT() ignoring PAT");
00105 uint tsid = pat->TransportStreamID();
00106 GetStreamData()->SetVersionPAT(tsid, -1,0);
00107 return;
00108 }
00109
00110 if (crc_bogus && stb_needs_to_wait_for_pat)
00111 {
00112 LOG(VB_GENERAL, LOG_WARNING, LOC + "Wait for valid PAT timed out");
00113 stb_needs_to_wait_for_pat = false;
00114 }
00115
00116 DTVSignalMonitor::HandlePAT(pat);
00117 }
00118
00119 void FirewireSignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt)
00120 {
00121 LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePMT()");
00122
00123 AddFlags(kDTVSigMon_PMTSeen);
00124
00125 if (!HasFlags(kDTVSigMon_PATMatch))
00126 {
00127 GetStreamData()->SetVersionPMT(pnum, -1,0);
00128 LOG(VB_CHANNEL, LOG_INFO, LOC + "HandlePMT() ignoring PMT");
00129 return;
00130 }
00131
00132 DTVSignalMonitor::HandlePMT(pnum, pmt);
00133 }
00134
00135 void FirewireSignalMonitor::RunTableMonitor(void)
00136 {
00137 stb_needs_to_wait_for_pat = true;
00138 stb_wait_for_pat_timer.start();
00139 dtvMonitorRunning = true;
00140
00141 LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- begin");
00142
00143 FirewireChannel *lchan = dynamic_cast<FirewireChannel*>(channel);
00144 if (!lchan)
00145 {
00146 LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- err");
00147 while (dtvMonitorRunning)
00148 usleep(10000);
00149 LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- err end");
00150 return;
00151 }
00152
00153 FirewireDevice *dev = lchan->GetFirewireDevice();
00154
00155 dev->OpenPort();
00156 dev->AddListener(this);
00157
00158 while (dtvMonitorRunning && GetStreamData())
00159 usleep(10000);
00160
00161 LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- shutdown ");
00162
00163 dev->RemoveListener(this);
00164 dev->ClosePort();
00165
00166 while (dtvMonitorRunning)
00167 usleep(10000);
00168
00169 LOG(VB_CHANNEL, LOG_INFO, LOC + "RunTableMonitor(): -- end");
00170 }
00171
00172 void FirewireSignalMonitor::AddData(const unsigned char *data, uint len)
00173 {
00174 if (!dtvMonitorRunning)
00175 return;
00176
00177 if (GetStreamData())
00178 GetStreamData()->ProcessData((unsigned char *)data, len);
00179 }
00180
00191 void FirewireSignalMonitor::UpdateValues(void)
00192 {
00193 if (!running || exit)
00194 return;
00195
00196 if (dtvMonitorRunning)
00197 {
00198 EmitStatus();
00199 if (IsAllGood())
00200 SendMessageAllGood();
00201
00202
00203 update_done = true;
00204 return;
00205 }
00206
00207 if (stb_needs_to_wait_for_power &&
00208 (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout))
00209 {
00210 return;
00211 }
00212 stb_needs_to_wait_for_power = false;
00213
00214 FirewireChannel *fwchan = dynamic_cast<FirewireChannel*>(channel);
00215 if (!fwchan)
00216 return;
00217
00218 if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch))
00219 {
00220 bool retried = false;
00221 while (true)
00222 {
00223 FirewireDevice::PowerState power = fwchan->GetPowerState();
00224 if (FirewireDevice::kAVCPowerOn == power)
00225 {
00226 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
00227 }
00228 else if (FirewireDevice::kAVCPowerOff == power)
00229 {
00230 AddFlags(kFWSigMon_PowerSeen);
00231 fwchan->SetPowerState(true);
00232 stb_wait_for_power_timer.start();
00233 stb_needs_to_wait_for_power = true;
00234 }
00235 else
00236 {
00237 bool qfailed = (FirewireDevice::kAVCPowerQueryFailed == power);
00238 if (qfailed && !retried)
00239 {
00240 retried = true;
00241 continue;
00242 }
00243
00244 LOG(VB_RECORD, LOG_WARNING,
00245 "Can't determine if STB is power on, assuming it is...");
00246 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch);
00247 }
00248 break;
00249 }
00250 }
00251
00252 bool isLocked = !HasFlags(kFWSigMon_WaitForPower) ||
00253 HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch);
00254
00255 if (isLocked && stb_needs_retune)
00256 {
00257 fwchan->Retune();
00258 isLocked = stb_needs_retune = false;
00259 }
00260
00261 SignalMonitor::UpdateValues();
00262
00263 {
00264 QMutexLocker locker(&statusLock);
00265 if (!scriptStatus.IsGood())
00266 return;
00267 }
00268
00269
00270 {
00271 QMutexLocker locker(&statusLock);
00272 signalStrength.SetValue(isLocked ? 100 : 0);
00273 signalLock.SetValue(isLocked ? 1 : 0);
00274 }
00275
00276 EmitStatus();
00277 if (IsAllGood())
00278 SendMessageAllGood();
00279
00280
00281
00282 if (isLocked && GetStreamData() &&
00283 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT |
00284 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT |
00285 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT))
00286 {
00287 tableMonitorThread = new FirewireTableMonitorThread(this);
00288
00289 LOG(VB_CHANNEL, LOG_INFO, LOC + "UpdateValues() -- "
00290 "Waiting for table monitor to start");
00291
00292 while (!dtvMonitorRunning)
00293 usleep(5000);
00294
00295 LOG(VB_CHANNEL, LOG_INFO, LOC + "UpdateValues() -- "
00296 "Table monitor started");
00297 }
00298
00299 update_done = true;
00300 }