00001
00002
00003
00004 #include <cerrno>
00005 #include <cstring>
00006
00007 #include <pthread.h>
00008 #include <fcntl.h>
00009 #include <unistd.h>
00010 #include <sys/select.h>
00011
00012 #include "mythcontext.h"
00013 #include "mythdbcon.h"
00014 #include "hdhrsignalmonitor.h"
00015 #include "atscstreamdata.h"
00016 #include "mpegtables.h"
00017 #include "atsctables.h"
00018
00019 #include "hdhrchannel.h"
00020 #include "hdhrrecorder.h"
00021
00022 #define LOC QString("HDHRSM(%1): ").arg(channel->GetDevice())
00023 #define LOC_ERR QString("HDHRSM(%1), Error: ").arg(channel->GetDevice())
00024
00040 HDHRSignalMonitor::HDHRSignalMonitor(int db_cardnum,
00041 HDHRChannel* _channel,
00042 uint64_t _flags, const char *_name)
00043 : DTVSignalMonitor(db_cardnum, _channel, _flags, _name),
00044 dtvMonitorRunning(false)
00045 {
00046 VERBOSE(VB_CHANNEL, LOC + "ctor");
00047
00048 _channel->DelAllPIDs();
00049
00050 signalStrength.SetThreshold(45);
00051
00052 AddFlags(kDTVSigMon_WaitForSig);
00053 }
00054
00058 HDHRSignalMonitor::~HDHRSignalMonitor()
00059 {
00060 VERBOSE(VB_CHANNEL, LOC + "dtor");
00061 Stop();
00062 }
00063
00064 void HDHRSignalMonitor::deleteLater(void)
00065 {
00066 disconnect();
00067 Stop();
00068 DTVSignalMonitor::deleteLater();
00069 }
00070
00074 void HDHRSignalMonitor::Stop(void)
00075 {
00076 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin");
00077 SignalMonitor::Stop();
00078 if (dtvMonitorRunning)
00079 {
00080 dtvMonitorRunning = false;
00081 pthread_join(table_monitor_thread, NULL);
00082 }
00083 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end");
00084 }
00085
00086 void *HDHRSignalMonitor::TableMonitorThread(void *param)
00087 {
00088 HDHRSignalMonitor *mon = (HDHRSignalMonitor*) param;
00089 mon->RunTableMonitor();
00090 return NULL;
00091 }
00092
00093 bool HDHRSignalMonitor::UpdateFiltersFromStreamData(void)
00094 {
00095 vector<int> add_pids;
00096 vector<int> del_pids;
00097
00098 if (!GetStreamData())
00099 return false;
00100
00101 UpdateListeningForEIT();
00102
00103 const pid_map_t &listening = GetStreamData()->ListeningPIDs();
00104
00105
00106 pid_map_t::const_iterator lit = listening.constBegin();
00107 for (; lit != listening.constEnd(); ++lit)
00108 if (lit.data() && (filters.find(lit.key()) == filters.end()))
00109 add_pids.push_back(lit.key());
00110
00111
00112 FilterMap::const_iterator fit = filters.constBegin();
00113 for (; fit != filters.constEnd(); ++fit)
00114 if (listening.find(fit.key()) == listening.end())
00115 del_pids.push_back(fit.key());
00116
00117 HDHRChannel *hdhr = dynamic_cast<HDHRChannel*>(channel);
00118
00119 bool ok = true;
00120 vector<int>::iterator dit = del_pids.begin();
00121 for (; dit != del_pids.end(); ++dit)
00122 {
00123 ok &= hdhr->DelPID(*dit);
00124 filters.erase(filters.find(*dit));
00125 }
00126
00127
00128 vector<int>::iterator ait = add_pids.begin();
00129 for (; ait != add_pids.end(); ++ait)
00130 {
00131 ok &= hdhr->AddPID(*ait);
00132 filters[*ait] = 1;
00133 }
00134
00135 return ok;
00136 }
00137
00138 void HDHRSignalMonitor::RunTableMonitor(void)
00139 {
00140 dtvMonitorRunning = true;
00141
00142 HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel);
00143 struct hdhomerun_device_t *_hdhomerun_device = hdrc->GetHDHRDevice();
00144
00145 if (!_hdhomerun_device)
00146 {
00147 VERBOSE(VB_IMPORTANT, "Failed to get HDHomeRun device handle");
00148 return;
00149 }
00150
00151 if (!hdhomerun_device_stream_start(_hdhomerun_device))
00152 {
00153 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set target");
00154 return;
00155 }
00156
00157 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): " +
00158 QString("begin (# of pids %1)")
00159 .arg(GetStreamData()->ListeningPIDs().size()));
00160
00161 while (dtvMonitorRunning && GetStreamData())
00162 {
00163 UpdateFiltersFromStreamData();
00164
00165 size_t data_length;
00166 unsigned char *data_buffer =
00167 hdhomerun_device_stream_recv(_hdhomerun_device,
00168 VIDEO_DATA_BUFFER_SIZE_1S / 5,
00169 &data_length);
00170
00171 if (data_buffer)
00172 {
00173 GetStreamData()->ProcessData(data_buffer, data_length);
00174 continue;
00175 }
00176
00177 usleep(2500);
00178 }
00179
00180 hdhomerun_device_stream_stop(_hdhomerun_device);
00181
00182 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown");
00183
00184
00185
00186 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end");
00187 }
00188
00199 void HDHRSignalMonitor::UpdateValues(void)
00200 {
00201 if (!running || exit)
00202 return;
00203
00204 if (dtvMonitorRunning)
00205 {
00206 EmitHDHRSignals();
00207 if (IsAllGood())
00208 emit AllGood();
00209
00210
00211 update_done = true;
00212 return;
00213 }
00214
00215 HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel);
00216 struct hdhomerun_device_t *_hdhomerun_device = hdrc->GetHDHRDevice();
00217 struct hdhomerun_tuner_status_t status;
00218 hdhomerun_device_get_tuner_status(_hdhomerun_device, NULL, &status);
00219
00220 uint sig = status.signal_strength;
00221 uint snq = status.signal_to_noise_quality;
00222 uint seq = status.symbol_error_quality;
00223
00224 (void) snq;
00225 (void) seq;
00226
00227
00228
00229
00230
00231
00232 bool isLocked = false;
00233 {
00234 QMutexLocker locker(&statusLock);
00235 signalStrength.SetValue(sig);
00236 signalLock.SetValue(status.lock_supported);
00237 isLocked = signalLock.IsGood();
00238 }
00239
00240 EmitHDHRSignals();
00241 if (IsAllGood())
00242 emit AllGood();
00243
00244
00245
00246 if (isLocked && GetStreamData() &&
00247 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT |
00248 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT |
00249 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT))
00250 {
00251 pthread_create(&table_monitor_thread, NULL,
00252 TableMonitorThread, this);
00253
00254 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- "
00255 "Waiting for table monitor to start");
00256
00257 while (!dtvMonitorRunning)
00258 usleep(50);
00259
00260 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- "
00261 "Table monitor started");
00262 }
00263
00264 update_done = true;
00265 }
00266
00267 #define EMIT(SIGNAL_FUNC, SIGNAL_VAL) \
00268 do { statusLock.lock(); \
00269 SignalMonitorValue val = SIGNAL_VAL; \
00270 statusLock.unlock(); \
00271 emit SIGNAL_FUNC(val); } while (false)
00272
00276 void HDHRSignalMonitor::EmitHDHRSignals(void)
00277 {
00278
00279 EMIT(StatusSignalLock, signalLock);
00280 if (HasFlags(kDTVSigMon_WaitForSig))
00281 EMIT(StatusSignalStrength, signalStrength);
00282 }
00283
00284 #undef EMIT