Ticket #6138: 133-hdhr.multirec.8.trunk.patch
File 133-hdhr.multirec.8.trunk.patch, 105.4 KB (added by , 16 years ago) |
---|
-
mythtv/libs/libmythtv/cardutil.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/cardutil.cpp myth.20018.0218b/mythtv/libs/libmythtv/cardutil.cpp
29 29 #include "videodev_myth.h" 30 30 #endif 31 31 32 #include "hdhomerun_includes.h" 33 32 34 #define LOC QString("CardUtil: ") 33 35 #define LOC_WARN QString("CardUtil, Warning: ") 34 36 #define LOC_ERR QString("CardUtil, Error: ") … … 210 212 devs.push_back(subit->filePath()); 211 213 } 212 214 } 215 else if (rawtype.toUpper() == "HDHOMERUN") 216 { 217 218 uint32_t target_ip = 0; 219 uint32_t device_type = HDHOMERUN_DEVICE_TYPE_TUNER; 220 uint32_t device_id = HDHOMERUN_DEVICE_ID_WILDCARD; 221 const int max_count = 50; 222 hdhomerun_discover_device_t result_list[max_count]; 223 224 int result = hdhomerun_discover_find_devices_custom( 225 target_ip, 226 device_type, 227 device_id, 228 result_list, 229 max_count); 230 231 if (result == -1) 232 { 233 VERBOSE(VB_IMPORTANT, "CardUtil::ProbeVideoDevices: Error finding HDHomerun devices"); 234 return devs; 235 } 236 237 if (result == 20) 238 VERBOSE(VB_IMPORTANT, "CardUtil::ProbeVideoDevices: Warning: may be > 20 HDHomerun devices"); 239 240 // Fixme -- figure out some way to return ip address as well 241 for (int i = 0; i < result; i++) 242 { 243 QString did = QString("%1").arg(result_list[i].device_id,0, 16); 244 did=did.toUpper(); 245 246 devs.push_back(did + "-0"); 247 devs.push_back(did + "-1"); 248 } 249 } 213 250 else 214 251 { 215 252 VERBOSE(VB_IMPORTANT, QString("CardUtil::ProbeVideoDevices: ") + … … 1146 1183 uint id = 0; 1147 1184 for (uint i = 0; !id && (i < 100); i++) 1148 1185 { 1149 name = QString("DVB%1").arg(dev.toUInt()); 1186 bool ok; 1187 name = QString("DVB%1").arg(dev.toUInt(&ok)); 1188 if (! ok) 1189 { 1190 name = QString("HDHR_%1").arg(dev); 1191 } 1150 1192 name += (i) ? QString(":%1").arg(i) : QString(""); 1151 1193 id = CardUtil::CreateInputGroup(name); 1152 1194 } … … 1749 1791 } 1750 1792 else if (cardtype == "HDHOMERUN") 1751 1793 { 1752 MSqlQuery query(MSqlQuery::InitCon()); 1753 query.prepare( 1754 "SELECT dbox2_port " 1755 "FROM capturecard " 1756 "WHERE cardid = :CARDID"); 1757 query.bindValue(":CARDID", cardid); 1758 1759 if (!query.exec() || !query.isActive() || !query.next()) 1760 label = "[ DB ERROR ]"; 1761 else 1762 label = QString("[ HDHomeRun : ID %1 Port %2 ]") 1763 .arg(videodevice).arg(query.value(0).toString()); 1794 label = QString("[ HDHomeRun : %1 ]").arg(videodevice); 1764 1795 } 1765 1796 else 1766 1797 { -
mythtv/libs/libmythtv/cardutil.h
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/cardutil.h myth.20018.0218b/mythtv/libs/libmythtv/cardutil.h
115 115 116 116 static bool IsTunerSharingCapable(const QString &rawtype) 117 117 { 118 return (rawtype == "DVB") ;118 return (rawtype == "DVB") || (rawtype == "HDHOMERUN"); 119 119 } 120 120 121 121 static bool IsTunerShared(uint cardidA, uint cardidB); -
mythtv/libs/libmythtv/hdhomerun_includes.h
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhomerun_includes.h myth.20018.0218b/mythtv/libs/libmythtv/hdhomerun_includes.h
1 #ifndef __HDHOMERUN_INCLUDES__ 2 #define __HDHOMERUN_INCLUDES__ 3 4 #include "hdhomerun.h" 5 6 #endif /* __HDHOMERUN_INCLUDES__ */ 7 -
mythtv/libs/libmythtv/hdhrchannel.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrchannel.cpp myth.20018.0218b/mythtv/libs/libmythtv/hdhrchannel.cpp
27 27 #include "channelutil.h" 28 28 #include "frequencytables.h" 29 29 30 #include "hdhrstreamhandler.h" 31 30 32 #define DEBUG_PID_FILTERS 31 33 32 34 #define LOC QString("HDHRChan(%1): ").arg(GetDevice()) 33 35 #define LOC_ERR QString("HDHRChan(%1), Error: ").arg(GetDevice()) 34 36 35 HDHRChannel::HDHRChannel(TVRec *parent, const QString &device, uint tuner) 36 : DTVChannel(parent), _control_socket(NULL), 37 _device_id(0), _device_ip(0), 38 _tuner(tuner), _lock(QMutex::Recursive) 39 { 40 bool valid; 41 _device_id = device.toUInt(&valid, 16); 42 43 if (valid && hdhomerun_discover_validate_device_id(_device_id)) 44 return; 45 46 /* Otherwise, is it a valid IP address? */ 47 struct in_addr address; 48 if (inet_aton(device.toLatin1().constData(), &address)) 49 { 50 _device_ip = ntohl(address.s_addr); 51 return; 52 } 53 54 /* Invalid, use wildcard device ID. */ 55 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Invalid DeviceID '%1'") 56 .arg(device)); 57 58 _device_id = HDHOMERUN_DEVICE_ID_WILDCARD; 37 HDHRChannel::HDHRChannel(TVRec *parent, const QString &device) 38 : DTVChannel(parent), _stream_handler(NULL), 39 _device_id(device), _lock(QMutex::Recursive), 40 tune_lock(QMutex::Recursive), 41 hw_lock(QMutex::Recursive) 42 { 59 43 } 60 44 61 45 HDHRChannel::~HDHRChannel(void) … … 65 49 66 50 bool HDHRChannel::Open(void) 67 51 { 52 VERBOSE(VB_CHANNEL, LOC + "Opening HDHR channel"); 53 54 QMutexLocker locker(&hw_lock); 55 68 56 if (IsOpen()) 69 57 return true; 70 58 71 if (!FindDevice()) 72 return false; 59 _stream_handler = HDHRStreamHandler::Get(_device_id); 73 60 74 61 if (!InitializeInputs()) 75 return false;76 77 return (_device_ip != 0) && Connect();78 }79 80 void HDHRChannel::Close(void)81 {82 if (_control_socket)83 {84 hdhomerun_control_destroy(_control_socket);85 _control_socket = NULL;86 }87 }88 89 bool HDHRChannel::EnterPowerSavingMode(void)90 {91 return QString::null != TunerSet("channel", "none", false);92 }93 94 bool HDHRChannel::FindDevice(void)95 {96 if (!_device_id)97 return _device_ip;98 99 _device_ip = 0;100 101 /* Discover. */102 struct hdhomerun_discover_device_t result;103 int ret = hdhomerun_discover_find_devices_custom(104 0, HDHOMERUN_DEVICE_TYPE_WILDCARD, _device_id, &result, 1);105 if (ret < 0)106 {107 VERBOSE(VB_IMPORTANT,108 LOC_ERR + "Unable to send discovery request" + ENO);109 return false;110 }111 if (ret == 0)112 {113 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("device not found"));114 return false;115 }116 117 /* Found. */118 _device_ip = result.ip_addr;119 120 VERBOSE(VB_IMPORTANT, LOC +121 QString("device found at address %1.%2.%3.%4")122 .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF)123 .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF));124 125 return true;126 }127 128 bool HDHRChannel::Connect(void)129 {130 _control_socket = hdhomerun_control_create(_device_id, _device_ip);131 if (!_control_socket)132 62 { 133 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create control socket");63 Close(); 134 64 return false; 135 65 } 136 66 137 if (hdhomerun_control_get_local_addr(_control_socket) == 0) 138 { 139 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to connect to device"); 140 return false; 141 } 142 143 VERBOSE(VB_CHANNEL, LOC + "Successfully connected to device"); 144 return true; 145 } 146 147 QString HDHRChannel::DeviceGet(const QString &name, bool report_error_return) 148 { 149 QMutexLocker locker(&_lock); 150 151 if (!_control_socket) 152 { 153 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (not connected)"); 154 return QString::null; 155 } 156 157 char *value = NULL; 158 char *error = NULL; 159 if (hdhomerun_control_get(_control_socket, name.toLatin1().constData(), 160 &value, &error) < 0) 161 { 162 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed" + ENO); 163 return QString::null; 164 } 165 166 if (report_error_return && error) 167 { 168 VERBOSE(VB_IMPORTANT, LOC_ERR + 169 QString("DeviceGet(%1): %2").arg(name).arg(error)); 170 171 return QString::null; 172 } 173 174 return QString(value); 67 return _stream_handler->Connected(); 175 68 } 176 69 177 QString HDHRChannel::DeviceSet(const QString &name, const QString &val, 178 bool report_error_return) 70 void HDHRChannel::Close(void) 179 71 { 180 QMutexLocker locker(&_lock); 181 182 if (!_control_socket) 183 { 184 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (not connected)"); 185 return QString::null; 186 } 187 188 char *value = NULL; 189 char *error = NULL; 190 if (hdhomerun_control_set(_control_socket, name.toLatin1().constData(), 191 val.toAscii().constData(), &value, &error) < 0) 192 { 193 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed" + ENO); 72 VERBOSE(VB_CHANNEL, LOC + "Closing HDHR channel"); 194 73 195 return QString::null; 196 } 197 198 if (report_error_return && error) 199 { 200 VERBOSE(VB_IMPORTANT, LOC_ERR + 201 QString("DeviceSet(%1 %2): %3").arg(name).arg(val).arg(error)); 202 203 return QString::null; 204 } 74 if (! IsOpen()) 75 return; // this caller didn't have it open in the first place.. 205 76 206 return QString(value);77 HDHRStreamHandler::Return(_stream_handler); 207 78 } 208 79 209 QString HDHRChannel::TunerGet(const QString &name, bool report_error_return)80 bool HDHRChannel::EnterPowerSavingMode(void) 210 81 { 211 return DeviceGet(QString("/tuner%1/%2").arg(_tuner).arg(name), 212 report_error_return); 82 if ( IsOpen()) 83 return _stream_handler->EnterPowerSavingMode(); 84 else 85 return true; 213 86 } 214 87 215 QString HDHRChannel::TunerSet(const QString &name, const QString &value, 216 bool report_error_return) 88 bool HDHRChannel::IsOpen(void) const 217 89 { 218 return DeviceSet(QString("/tuner%1/%2").arg(_tuner).arg(name), value, 219 report_error_return); 90 return (_stream_handler != NULL); 220 91 } 221 92 222 bool HDHRChannel:: DeviceSetTarget(unsigned short localPort)93 bool HDHRChannel::Init(QString &inputname, QString &startchannel, bool setchan) 223 94 { 224 if (localPort == 0) 225 { 226 return false; 227 } 228 229 unsigned long localIP = hdhomerun_control_get_local_addr(_control_socket); 230 if (localIP == 0) 231 { 232 return false; 233 } 234 235 QString configValue = QString("%1.%2.%3.%4:%5") 236 .arg((localIP >> 24) & 0xFF).arg((localIP >> 16) & 0xFF) 237 .arg((localIP >> 8) & 0xFF).arg((localIP >> 0) & 0xFF) 238 .arg(localPort); 239 240 if (TunerSet("target", configValue).isEmpty()) 241 { 242 return false; 243 } 95 if (setchan && !IsOpen()) 96 Open(); 244 97 245 return true; 246 } 247 248 bool HDHRChannel::DeviceClearTarget() 249 { 250 return !TunerSet("target", "0.0.0.0:0").isEmpty(); 98 return ChannelBase::Init(inputname, startchannel, setchan); 251 99 } 252 100 253 101 bool HDHRChannel::SetChannelByString(const QString &channum) … … 281 129 return SwitchToInput(inputName, channum); 282 130 283 131 ClearDTVInfo(); 284 _ignore_filters = false;285 132 286 133 InputMap::const_iterator it = inputs.find(currentInputID); 287 134 if (it == inputs.end()) … … 355 202 if (mpeg_prog_num && (GetTuningMode() == "mpeg")) 356 203 { 357 204 QString pnum = QString::number(mpeg_prog_num); 358 _ignore_filters = QString::null != TunerSet("program", pnum, false); 205 //_ignore_filters = _stream_handler->TuneProgram(pnum); 206 _stream_handler->TuneProgram(pnum); 359 207 } 360 208 361 209 return true; … … 417 265 418 266 name.append(':' + QString::number(frequency)); 419 267 420 ok = ! TunerSet("channel", name).isEmpty();268 ok = _stream_handler->TuneChannel(name); 421 269 422 270 if (ok) 423 271 SetSIStandard(si_std); … … 425 273 return ok; 426 274 } 427 275 428 bool HDHRChannel::AddPID(uint pid, bool do_update)429 {430 QMutexLocker locker(&_lock);431 432 vector<uint>::iterator it;433 it = lower_bound(_pids.begin(), _pids.end(), pid);434 if (it != _pids.end() && *it == pid)435 {436 #ifdef DEBUG_PID_FILTERS437 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<") NOOP");438 #endif // DEBUG_PID_FILTERS439 return true;440 }441 442 _pids.insert(it, pid);443 444 #ifdef DEBUG_PID_FILTERS445 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<")");446 #endif // DEBUG_PID_FILTERS447 448 if (do_update)449 return UpdateFilters();450 return true;451 }452 453 bool HDHRChannel::DelPID(uint pid, bool do_update)454 {455 QMutexLocker locker(&_lock);456 457 vector<uint>::iterator it;458 it = lower_bound(_pids.begin(), _pids.end(), pid);459 if (it == _pids.end())460 {461 #ifdef DEBUG_PID_FILTERS462 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") NOOP");463 #endif // DEBUG_PID_FILTERS464 465 return true;466 }467 468 if (*it == pid)469 {470 #ifdef DEBUG_PID_FILTERS471 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") -- found");472 #endif // DEBUG_PID_FILTERS473 _pids.erase(it);474 }475 else476 {477 #ifdef DEBUG_PID_FILTERS478 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") -- failed");479 #endif // DEBUG_PID_FILTERS480 }481 482 if (do_update)483 return UpdateFilters();484 return true;485 }486 487 bool HDHRChannel::DelAllPIDs(void)488 {489 QMutexLocker locker(&_lock);490 491 #ifdef DEBUG_PID_FILTERS492 VERBOSE(VB_CHANNEL, "DelAllPID()");493 #endif // DEBUG_PID_FILTERS494 495 _pids.clear();496 497 return UpdateFilters();498 }499 500 QString filt_str(uint pid)501 {502 uint pid0 = (pid / (16*16*16)) % 16;503 uint pid1 = (pid / (16*16)) % 16;504 uint pid2 = (pid / (16)) % 16;505 uint pid3 = pid % 16;506 return QString("0x%1%2%3%4")507 .arg(pid0,0,16).arg(pid1,0,16)508 .arg(pid2,0,16).arg(pid3,0,16);509 }510 511 bool HDHRChannel::UpdateFilters(void)512 {513 QMutexLocker locker(&_lock);514 515 QString filter = "";516 517 vector<uint> range_min;518 vector<uint> range_max;519 520 if (_ignore_filters)521 return true;522 523 for (uint i = 0; i < _pids.size(); i++)524 {525 uint pid_min = _pids[i];526 uint pid_max = pid_min;527 for (uint j = i + 1; j < _pids.size(); j++)528 {529 if (pid_max + 1 != _pids[j])530 break;531 pid_max++;532 i++;533 }534 range_min.push_back(pid_min);535 range_max.push_back(pid_max);536 }537 538 if (range_min.size() > 16)539 {540 range_min.resize(16);541 uint pid_max = range_max.back();542 range_max.resize(15);543 range_max.push_back(pid_max);544 }545 546 for (uint i = 0; i < range_min.size(); i++)547 {548 filter += filt_str(range_min[i]);549 if (range_min[i] != range_max[i])550 filter += QString("-%1").arg(filt_str(range_max[i]));551 filter += " ";552 }553 554 filter = filter.trimmed();555 556 QString new_filter = TunerSet("filter", filter);557 558 #ifdef DEBUG_PID_FILTERS559 QString msg = QString("Filter: '%1'").arg(filter);560 if (filter != new_filter)561 msg += QString("\n\t\t\t\t'%2'").arg(new_filter);562 563 VERBOSE(VB_CHANNEL, msg);564 #endif // DEBUG_PID_FILTERS565 566 return filter == new_filter;567 } -
mythtv/libs/libmythtv/hdhrchannel.cpp.rej.fixed
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrchannel.cpp.rej.fixed myth.20018.0218b/mythtv/libs/libmythtv/hdhrchannel.cpp.rej.fixed
1 *************** 2 *** 26,61 **** 3 #include "channelutil.h" 4 #include "frequencytables.h" 5 6 #define DEBUG_PID_FILTERS 7 8 #define LOC QString("HDHRChan(%1): ").arg(GetDevice()) 9 #define LOC_ERR QString("HDHRChan(%1), Error: ").arg(GetDevice()) 10 11 - HDHRChannel::HDHRChannel(TVRec *parent, const QString &device, uint tuner) 12 - : DTVChannel(parent), _control_socket(NULL), 13 - _device_id(0), _device_ip(0), 14 - _tuner(tuner), _lock(true) 15 - { 16 - bool valid; 17 - _device_id = device.toUInt(&valid, 16); 18 - 19 - if (valid && hdhomerun_discover_validate_device_id(_device_id)) 20 - return; 21 - 22 - _device_id = HDHOMERUN_DEVICE_ID_WILDCARD; 23 - /* Otherwise, is it a valid IP address? */ 24 - struct in_addr address; 25 - if (inet_aton(device, &address)) 26 - { 27 - _device_ip = ntohl(address.s_addr); 28 - return; 29 - } 30 - 31 - /* Invalid, use wildcard device ID. */ 32 - VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Invalid DeviceID '%1'") 33 - .arg(device)); 34 - 35 - _device_id = HDHOMERUN_DEVICE_ID_WILDCARD; 36 } 37 38 HDHRChannel::~HDHRChannel(void) 39 --- 26,43 ---- 40 #include "channelutil.h" 41 #include "frequencytables.h" 42 43 + #include "hdhrstreamhandler.h" 44 + 45 #define DEBUG_PID_FILTERS 46 47 #define LOC QString("HDHRChan(%1): ").arg(GetDevice()) 48 #define LOC_ERR QString("HDHRChan(%1), Error: ").arg(GetDevice()) 49 50 + HDHRChannel::HDHRChannel(TVRec *parent, const QString &device) 51 + : DTVChannel(parent), _stream_handler(NULL), 52 + _device_id(device), _lock(true), 53 + tune_lock(true), hw_lock(true) 54 + { 55 } 56 57 HDHRChannel::~HDHRChannel(void) 58 *************** 59 *** 65,249 **** 60 61 bool HDHRChannel::Open(void) 62 { 63 if (IsOpen()) 64 return true; 65 66 - if (!FindDevice()) 67 - return false; 68 69 if (!InitializeInputs()) 70 - return false; 71 - 72 - return (_device_ip != 0) && Connect(); 73 - } 74 - 75 - void HDHRChannel::Close(void) 76 - { 77 - if (_control_socket) 78 - { 79 - hdhomerun_control_destroy(_control_socket); 80 - _control_socket = NULL; 81 - } 82 - } 83 - 84 - bool HDHRChannel::EnterPowerSavingMode(void) 85 - { 86 - return QString::null != TunerSet("channel", "none", false); 87 - } 88 - 89 - bool HDHRChannel::FindDevice(void) 90 - { 91 - if (!_device_id) 92 - return _device_ip; 93 - 94 - _device_ip = 0; 95 - 96 - /* Discover. */ 97 - struct hdhomerun_discover_device_t result; 98 - int ret = hdhomerun_discover_find_devices_custom(0, HDHOMERUN_DEVICE_TYPE_WILDCARD, _device_id, &result, 1); 99 - if (ret < 0) 100 - { 101 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to send discovery request" + ENO); 102 - return false; 103 - } 104 - if (ret == 0) 105 { 106 - VERBOSE(VB_IMPORTANT, LOC_ERR + QString("device not found")); 107 return false; 108 } 109 110 - /* Found. */ 111 - _device_ip = result.ip_addr; 112 113 - VERBOSE(VB_IMPORTANT, LOC + 114 - QString("device found at address %1.%2.%3.%4") 115 - .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF) 116 - .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF)); 117 118 - return true; 119 } 120 121 - bool HDHRChannel::Connect(void) 122 { 123 - _control_socket = hdhomerun_control_create(_device_id, _device_ip); 124 - if (!_control_socket) 125 - { 126 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create control socket"); 127 - return false; 128 - } 129 130 - if (hdhomerun_control_get_local_addr(_control_socket) == 0) 131 - { 132 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to connect to device"); 133 - return false; 134 - } 135 136 - VERBOSE(VB_CHANNEL, LOC + "Successfully connected to device"); 137 - return true; 138 } 139 140 - QString HDHRChannel::DeviceGet(const QString &name, bool report_error_return) 141 - { 142 - QMutexLocker locker(&_lock); 143 - 144 - if (!_control_socket) 145 - { 146 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (not connected)"); 147 - return QString::null; 148 - } 149 - 150 - char *value = NULL; 151 - char *error = NULL; 152 - if (hdhomerun_control_get(_control_socket, name, &value, &error) < 0) 153 - { 154 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed" + ENO); 155 - return QString::null; 156 - } 157 - 158 - if (report_error_return && error) 159 - { 160 - VERBOSE(VB_IMPORTANT, LOC_ERR + 161 - QString("DeviceGet(%1): %2").arg(name).arg(error)); 162 - 163 - return QString::null; 164 - } 165 - 166 - return QString(value); 167 - } 168 - 169 - QString HDHRChannel::DeviceSet(const QString &name, const QString &val, 170 - bool report_error_return) 171 { 172 - QMutexLocker locker(&_lock); 173 - 174 - if (!_control_socket) 175 - { 176 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (not connected)"); 177 - return QString::null; 178 - } 179 - 180 - char *value = NULL; 181 - char *error = NULL; 182 - if (hdhomerun_control_set(_control_socket, name, val, &value, &error) < 0) 183 - { 184 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed" + ENO); 185 - 186 - return QString::null; 187 - } 188 - 189 - if (report_error_return && error) 190 - { 191 - VERBOSE(VB_IMPORTANT, LOC_ERR + 192 - QString("DeviceSet(%1 %2): %3").arg(name).arg(val).arg(error)); 193 - 194 - return QString::null; 195 - } 196 - 197 - return QString(value); 198 } 199 200 - QString HDHRChannel::TunerGet(const QString &name, bool report_error_return) 201 - { 202 - return DeviceGet(QString("/tuner%1/%2").arg(_tuner).arg(name), 203 - report_error_return); 204 - } 205 206 - QString HDHRChannel::TunerSet(const QString &name, const QString &value, 207 - bool report_error_return) 208 { 209 - return DeviceSet(QString("/tuner%1/%2").arg(_tuner).arg(name), value, 210 - report_error_return); 211 } 212 213 - bool HDHRChannel::DeviceSetTarget(unsigned short localPort) 214 { 215 - if (localPort == 0) 216 - { 217 - return false; 218 - } 219 220 - unsigned long localIP = hdhomerun_control_get_local_addr(_control_socket); 221 - if (localIP == 0) 222 - { 223 - return false; 224 - } 225 - 226 - QString configValue = QString("%1.%2.%3.%4:%5") 227 - .arg((localIP >> 24) & 0xFF).arg((localIP >> 16) & 0xFF) 228 - .arg((localIP >> 8) & 0xFF).arg((localIP >> 0) & 0xFF) 229 - .arg(localPort); 230 - 231 - if (!TunerSet("target", configValue)) 232 - { 233 - return false; 234 - } 235 - 236 - return true; 237 - } 238 - 239 - bool HDHRChannel::DeviceClearTarget() 240 - { 241 - return TunerSet("target", "0.0.0.0:0"); 242 } 243 244 bool HDHRChannel::SetChannelByString(const QString &channum) 245 --- 47,103 ---- 246 247 bool HDHRChannel::Open(void) 248 { 249 + VERBOSE(VB_CHANNEL, LOC + "Opening HDHR channel"); 250 + 251 + QMutexLocker locker(&hw_lock); 252 + 253 if (IsOpen()) 254 return true; 255 256 + _stream_handler = HDHRStreamHandler::Get(_device_id); 257 258 if (!InitializeInputs()) 259 { 260 + Close(); 261 return false; 262 } 263 264 + // nextInputID = currentInputID; 265 266 + return _stream_handler->Connected(); 267 268 } 269 270 + void HDHRChannel::Close() 271 { 272 + VERBOSE(VB_CHANNEL, LOC + "Closing HDHR channel"); 273 274 + if (! IsOpen()) 275 + return; // this caller didn't have it open in the first place.. 276 277 + HDHRStreamHandler::Return(_stream_handler); 278 } 279 280 + bool HDHRChannel::EnterPowerSavingMode(void) 281 { 282 + if ( IsOpen()) 283 + return _stream_handler->EnterPowerSavingMode(); 284 + else 285 + return true; 286 } 287 288 289 + bool HDHRChannel::IsOpen(void) const 290 { 291 + return (_stream_handler != NULL); 292 } 293 294 + bool HDHRChannel::Init(QString &inputname, QString &startchannel, bool setchan) 295 { 296 + if (setchan && !IsOpen()) 297 + Open(); 298 299 + return ChannelBase::Init(inputname, startchannel, setchan); 300 } 301 302 bool HDHRChannel::SetChannelByString(const QString &channum) 303 *************** 304 *** 400,554 **** 305 QString("TuneTo(%1,%2)").arg(frequency).arg(modulation)); 306 307 if (modulation == "8vsb") 308 - ok = TunerSet("channel", QString("8vsb:%1").arg(frequency)); 309 else if (modulation == "qam_64") 310 - ok = TunerSet("channel", QString("qam64:%1").arg(frequency)); 311 else if (modulation == "qam_256") 312 - ok = TunerSet("channel", QString("qam256:%1").arg(frequency)); 313 314 if (ok) 315 SetSIStandard(si_std); 316 317 return ok; 318 } 319 - 320 - bool HDHRChannel::AddPID(uint pid, bool do_update) 321 - { 322 - QMutexLocker locker(&_lock); 323 - 324 - vector<uint>::iterator it; 325 - it = lower_bound(_pids.begin(), _pids.end(), pid); 326 - if (it != _pids.end() && *it == pid) 327 - { 328 - #ifdef DEBUG_PID_FILTERS 329 - VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<") NOOP"); 330 - #endif // DEBUG_PID_FILTERS 331 - return true; 332 - } 333 - 334 - _pids.insert(it, pid); 335 - 336 - #ifdef DEBUG_PID_FILTERS 337 - VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<")"); 338 - #endif // DEBUG_PID_FILTERS 339 - 340 - if (do_update) 341 - return UpdateFilters(); 342 - return true; 343 - } 344 - 345 - bool HDHRChannel::DelPID(uint pid, bool do_update) 346 - { 347 - QMutexLocker locker(&_lock); 348 - 349 - vector<uint>::iterator it; 350 - it = lower_bound(_pids.begin(), _pids.end(), pid); 351 - if (it == _pids.end()) 352 - { 353 - #ifdef DEBUG_PID_FILTERS 354 - VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") NOOP"); 355 - #endif // DEBUG_PID_FILTERS 356 - 357 - return true; 358 - } 359 - 360 - if (*it == pid) 361 - { 362 - #ifdef DEBUG_PID_FILTERS 363 - VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") -- found"); 364 - #endif // DEBUG_PID_FILTERS 365 - _pids.erase(it); 366 - } 367 - else 368 - { 369 - #ifdef DEBUG_PID_FILTERS 370 - VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") -- failed"); 371 - #endif // DEBUG_PID_FILTERS 372 - } 373 - 374 - if (do_update) 375 - return UpdateFilters(); 376 - return true; 377 - } 378 - 379 - bool HDHRChannel::DelAllPIDs(void) 380 - { 381 - QMutexLocker locker(&_lock); 382 - 383 - #ifdef DEBUG_PID_FILTERS 384 - VERBOSE(VB_CHANNEL, "DelAllPID()"); 385 - #endif // DEBUG_PID_FILTERS 386 - 387 - _pids.clear(); 388 - 389 - return UpdateFilters(); 390 - } 391 - 392 - QString filt_str(uint pid) 393 - { 394 - uint pid0 = (pid / (16*16*16)) % 16; 395 - uint pid1 = (pid / (16*16)) % 16; 396 - uint pid2 = (pid / (16)) % 16; 397 - uint pid3 = pid % 16; 398 - return QString("0x%1%2%3%4") 399 - .arg(pid0,0,16).arg(pid1,0,16) 400 - .arg(pid2,0,16).arg(pid3,0,16); 401 - } 402 - 403 - bool HDHRChannel::UpdateFilters(void) 404 - { 405 - QMutexLocker locker(&_lock); 406 - 407 - QString filter = ""; 408 - 409 - vector<uint> range_min; 410 - vector<uint> range_max; 411 - 412 - if (_ignore_filters) 413 - return true; 414 - 415 - for (uint i = 0; i < _pids.size(); i++) 416 - { 417 - uint pid_min = _pids[i]; 418 - uint pid_max = pid_min; 419 - for (uint j = i + 1; j < _pids.size(); j++) 420 - { 421 - if (pid_max + 1 != _pids[j]) 422 - break; 423 - pid_max++; 424 - i++; 425 - } 426 - range_min.push_back(pid_min); 427 - range_max.push_back(pid_max); 428 - } 429 - 430 - if (range_min.size() > 16) 431 - { 432 - range_min.resize(16); 433 - uint pid_max = range_max.back(); 434 - range_max.resize(15); 435 - range_max.push_back(pid_max); 436 - } 437 - 438 - for (uint i = 0; i < range_min.size(); i++) 439 - { 440 - filter += filt_str(range_min[i]); 441 - if (range_min[i] != range_max[i]) 442 - filter += QString("-%1").arg(filt_str(range_max[i])); 443 - filter += " "; 444 - } 445 - 446 - filter = filter.stripWhiteSpace(); 447 - 448 - QString new_filter = TunerSet("filter", filter); 449 - 450 - #ifdef DEBUG_PID_FILTERS 451 - QString msg = QString("Filter: '%1'").arg(filter); 452 - if (filter != new_filter) 453 - msg += QString("\n\t\t\t\t'%2'").arg(new_filter); 454 - 455 - VERBOSE(VB_CHANNEL, msg); 456 - #endif // DEBUG_PID_FILTERS 457 - 458 - return filter == new_filter; 459 - } 460 --- 254,267 ---- 461 QString("TuneTo(%1,%2)").arg(frequency).arg(modulation)); 462 463 if (modulation == "8vsb") 464 + ok = _stream_handler->TuneChannel(QString("8vsb:%1").arg(frequency)); 465 else if (modulation == "qam_64") 466 + ok = _stream_handler->TuneChannel(QString("qam64:%1").arg(frequency)); 467 else if (modulation == "qam_256") 468 + ok = _stream_handler->TuneChannel(QString("qam256:%1").arg(frequency)); 469 470 if (ok) 471 SetSIStandard(si_std); 472 473 return ok; 474 } -
mythtv/libs/libmythtv/hdhrchannel.h
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrchannel.h myth.20018.0218b/mythtv/libs/libmythtv/hdhrchannel.h
15 15 16 16 // HDHomeRun headers 17 17 #ifdef USING_HDHOMERUN 18 #include "hdhomerun.h" 19 #else 20 struct hdhomerun_control_sock_t { int dummy; }; 18 #include "hdhomerun_includes.h" 21 19 #endif 22 20 23 typedef struct hdhomerun_control_sock_t hdhr_socket_t; 21 class HDHRChannel; 22 class HDHRStreamHandler; 23 class ProgramMapTable; 24 24 25 25 class HDHRChannel : public DTVChannel 26 26 { … … 28 28 friend class HDHRRecorder; 29 29 30 30 public: 31 HDHRChannel(TVRec *parent, const QString &device , uint tuner);31 HDHRChannel(TVRec *parent, const QString &device); 32 32 ~HDHRChannel(void); 33 33 34 34 bool Open(void); 35 35 void Close(void); 36 36 bool EnterPowerSavingMode(void); 37 37 38 bool Init(QString &inputname, QString &startchannel, bool setchan); 39 38 40 // Sets 41 void SetPMT(const ProgramMapTable*) {}; 39 42 bool SetChannelByString(const QString &chan); 40 43 41 44 // Gets 42 bool IsOpen(void) const { return (_control_socket != NULL); } 43 QString GetDevice(void) const 44 { return QString("%1/%2").arg(_device_id, 8, 16).arg(_tuner); } 45 bool IsOpen(void) const; 46 QString GetDevice(void) const { return _device_id; } 45 47 vector<uint> GetPIDs(void) const 46 48 { QMutexLocker locker(&_lock); return _pids; } 47 49 QString GetSIStandard(void) const { return "atsc"; } 48 50 49 // Commands50 bool AddPID(uint pid, bool do_update = true);51 bool DelPID(uint pid, bool do_update = true);52 bool DelAllPIDs(void);53 bool UpdateFilters(void);54 55 51 // ATSC scanning stuff 56 52 bool TuneMultiplex(uint mplexid, QString inputname); 57 53 bool Tune(const DTVMultiplex &tuning, QString inputname); 58 54 59 55 private: 60 bool FindDevice(void);61 bool Connect(void);62 56 bool Tune(uint frequency, QString inputname, 63 57 QString modulation, QString si_std); 64 58 65 bool DeviceSetTarget(unsigned short localPort);66 bool DeviceClearTarget(void);59 private: 60 HDHRStreamHandler *_stream_handler; 67 61 68 QString DeviceGet(const QString &name, bool report_error_return = true); 69 QString DeviceSet(const QString &name, const QString &value, 70 bool report_error_return = true); 71 72 QString TunerGet(const QString &name, bool report_error_return = true); 73 QString TunerSet(const QString &name, const QString &value, 74 bool report_error_return = true); 62 QString _device_id; 75 63 76 private:77 hdhr_socket_t *_control_socket;78 uint _device_id;79 uint _device_ip;80 uint _tuner;81 bool _ignore_filters;82 64 vector<uint> _pids; 83 65 mutable QMutex _lock; 66 mutable QMutex tune_lock; 67 mutable QMutex hw_lock; 84 68 }; 85 69 86 70 #endif -
mythtv/libs/libmythtv/hdhrchannel.h.rej.fixed
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrchannel.h.rej.fixed myth.20018.0218b/mythtv/libs/libmythtv/hdhrchannel.h.rej.fixed
1 *************** 2 *** 15,26 **** 3 4 // HDHomeRun headers 5 #ifdef USING_HDHOMERUN 6 - #include "hdhomerun/hdhomerun.h" 7 - #else 8 - struct hdhomerun_control_sock_t { int dummy; }; 9 #endif 10 11 - typedef struct hdhomerun_control_sock_t hdhr_socket_t; 12 13 class HDHRChannel : public DTVChannel 14 { 15 --- 15,26 ---- 16 17 // HDHomeRun headers 18 #ifdef USING_HDHOMERUN 19 + #include "hdhomerun_includes.h" 20 #endif 21 22 + class HDHRChannel; 23 + class HDHRStreamHandler; 24 + class ProgramMapTable; 25 26 class HDHRChannel : public DTVChannel 27 { -
mythtv/libs/libmythtv/hdhrrecorder.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrrecorder.cpp myth.20018.0218b/mythtv/libs/libmythtv/hdhrrecorder.cpp
23 23 24 24 // MythTV includes 25 25 #include "RingBuffer.h" 26 #include "hdhrchannel.h"27 #include "hdhrrecorder.h"28 26 #include "atsctables.h" 29 27 #include "atscstreamdata.h" 30 28 #include "eithelper.h" 31 29 #include "tv_rec.h" 32 30 31 // MythTV HDHR includes 32 #include "hdhrchannel.h" 33 #include "hdhrrecorder.h" 34 #include "hdhrstreamhandler.h" 35 33 36 #define LOC QString("HDHRRec(%1): ").arg(tvrec->GetCaptureCardNum()) 37 #define LOC_WARN QString("HDHRRec(%1), Warning: ") \ 38 .arg(tvrec->GetCaptureCardNum()) 34 39 #define LOC_ERR QString("HDHRRec(%1), Error: ") \ 35 40 .arg(tvrec->GetCaptureCardNum()) 36 41 37 42 HDHRRecorder::HDHRRecorder(TVRec *rec, HDHRChannel *channel) 38 43 : DTVRecorder(rec), 39 _channel(channel), _video_socket(NULL), 44 _channel(channel), 45 _stream_handler(NULL), 40 46 _stream_data(NULL), 41 _input_pat(NULL), _input_pmt(NULL), 42 _reset_pid_filters(false),_pid_lock(QMutex::Recursive) 47 _pid_lock(QMutex::Recursive), 48 _input_pat(NULL), 49 _input_pmt(NULL), 50 _has_no_av(false) 43 51 { 44 52 } 45 53 … … 90 98 // HACK -- end 91 99 } 92 100 101 bool HDHRRecorder::IsOpen(void) { 102 return (_stream_handler != NULL); 103 } 104 93 105 bool HDHRRecorder::Open(void) 94 106 { 95 107 VERBOSE(VB_RECORD, LOC + "Open()"); 96 if ( _video_socket)108 if (IsOpen()) 97 109 { 98 110 VERBOSE(VB_RECORD, LOC + "Card already open (recorder)"); 99 111 return true; 100 112 } 101 113 102 /* Calculate buffer size */ 103 uint buffersize = gContext->GetNumSetting( 104 "HDRingbufferSize", 50 * TSPacket::SIZE) * 1024; 105 buffersize /= VIDEO_DATA_PACKET_SIZE; 106 buffersize *= VIDEO_DATA_PACKET_SIZE; 114 bzero(_stream_id, sizeof(_stream_id)); 115 bzero(_pid_status, sizeof(_pid_status)); 116 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 107 117 108 // Buffer should be at least about 1MB.. 109 buffersize = max(49 * TSPacket::SIZE * 128, buffersize); 118 _stream_handler = HDHRStreamHandler::Get(_channel->GetDevice()); 110 119 111 /* Create TS socket. */ 112 _video_socket = hdhomerun_video_create(0, buffersize); 113 if (!_video_socket) 114 { 115 VERBOSE(VB_IMPORTANT, LOC + "Open() failed to open socket"); 116 return false; 117 } 120 VERBOSE(VB_RECORD, LOC + "HDHR opened successfully"); 118 121 119 /* Success. */120 122 return true; 121 123 } 122 124 123 /** \fn HDHRRecorder::StartData(void)124 * \brief Configure device to send video.125 */126 bool HDHRRecorder::StartData(void)127 {128 VERBOSE(VB_RECORD, LOC + "StartData()");129 uint localPort = hdhomerun_video_get_local_port(_video_socket);130 return _channel->DeviceSetTarget(localPort);131 }132 133 125 void HDHRRecorder::Close(void) 134 126 { 135 VERBOSE(VB_RECORD, LOC + "Close()"); 136 if (_video_socket) 137 { 138 hdhomerun_video_destroy(_video_socket); 139 _video_socket = NULL; 140 } 141 } 142 143 void HDHRRecorder::ProcessTSData(const uint8_t *buffer, int len) 144 { 145 QMutexLocker locker(&_pid_lock); 146 const uint8_t *data = buffer; 147 const uint8_t *end = buffer + len; 127 VERBOSE(VB_RECORD, LOC + "Close() - Begin"); 148 128 149 while (data + 188 <= end)129 if (IsOpen()) 150 130 { 151 if (data[0] != 0x47) 152 { 153 return; 154 } 155 156 const TSPacket *tspacket = reinterpret_cast<const TSPacket*>(data); 157 ProcessTSPacket(*tspacket); 158 159 data += 188; 131 HDHRStreamHandler::Return(_stream_handler); 160 132 } 133 134 VERBOSE(VB_RECORD, LOC + "Close() - End"); 161 135 } 162 136 163 137 void HDHRRecorder::SetStreamData(MPEGStreamData *data) … … 216 190 ProgramAssociationTable *oldpat = _input_pat; 217 191 _input_pat = new ProgramAssociationTable(*_pat); 218 192 delete oldpat; 219 220 _reset_pid_filters = true;221 193 } 222 194 223 195 void HDHRRecorder::HandlePMT(uint progNum, const ProgramMapTable *_pmt) … … 229 201 VERBOSE(VB_RECORD, LOC + "SetPMT("<<progNum<<")"); 230 202 ProgramMapTable *oldpmt = _input_pmt; 231 203 _input_pmt = new ProgramMapTable(*_pmt); 232 delete oldpmt;233 204 234 _reset_pid_filters = true; 205 QString sistandard = _channel->GetSIStandard(); 206 207 bool has_no_av = true; 208 for (uint i = 0; i < _input_pmt->StreamCount() && has_no_av; i++) 209 { 210 has_no_av &= !_input_pmt->IsVideo(i, sistandard); 211 has_no_av &= !_input_pmt->IsAudio(i, sistandard); 212 } 213 _has_no_av = has_no_av; 214 215 _channel->SetPMT(_input_pmt); 216 delete oldpmt; 235 217 } 236 218 } 237 219 … … 242 224 243 225 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 244 226 pat->tsheader()->SetContinuityCounter(next); 245 BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader())));227 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader()))); 246 228 } 247 229 248 230 void HDHRRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 249 231 { 250 232 if (!pmt) 233 { 234 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)"); 235 return; 236 } 237 238 // collect stream types for H.264 (MPEG-4 AVC) keyframe detection 239 for (uint i = 0; i < pmt->StreamCount(); i++) 240 _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i); 241 242 if (!ringBuffer) 251 243 return; 252 244 253 245 unsigned char buf[8 * 1024]; … … 255 247 pmt->tsheader()->SetContinuityCounter(next_cc); 256 248 uint size = pmt->WriteAsTSPackets(buf, next_cc); 257 249 250 uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 251 258 252 for (uint i = 0; i < size ; i += TSPacket::SIZE) 259 253 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 254 255 uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 256 257 if (posB[0] + posB[1] * TSPacket::SIZE > 258 posA[0] + posA[1] * TSPacket::SIZE) 259 { 260 VERBOSE(VB_RECORD, LOC + "Wrote PMT @" 261 << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 262 } 263 else 264 { 265 VERBOSE(VB_RECORD, LOC + "Saw PMT but did not write to disk yet"); 266 } 260 267 } 261 268 262 269 /** \fn HDHRRecorder::HandleMGT(const MasterGuideTable*) … … 276 283 } 277 284 */ 278 285 286 bool HDHRRecorder::ProcessVideoTSPacket(const TSPacket &tspacket) 287 { 288 uint streamType = _stream_id[tspacket.PID()]; 289 290 // Check for keyframes and count frames 291 if (streamType == StreamID::H264Video) 292 { 293 _buffer_packets = !FindH264Keyframes(&tspacket); 294 if (!_seen_sps) 295 return true; 296 } 297 else 298 { 299 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 300 } 301 302 return ProcessAVTSPacket(tspacket); 303 } 304 305 bool HDHRRecorder::ProcessAudioTSPacket(const TSPacket &tspacket) 306 { 307 _buffer_packets = !FindAudioKeyframes(&tspacket); 308 return ProcessAVTSPacket(tspacket); 309 } 310 311 /// Common code for processing either audio or video packets 312 bool HDHRRecorder::ProcessAVTSPacket(const TSPacket &tspacket) 313 { 314 const uint pid = tspacket.PID(); 315 // Sync recording start to first keyframe 316 if (_wait_for_keyframe_option && _first_keyframe < 0) 317 return true; 318 319 // Sync streams to the first Payload Unit Start Indicator 320 // _after_ first keyframe iff _wait_for_keyframe_option is true 321 if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload()) 322 { 323 if (!tspacket.PayloadStart()) 324 return true; // not payload start - drop packet 325 326 VERBOSE(VB_RECORD, 327 QString("PID 0x%1 Found Payload Start").arg(pid,0,16)); 328 329 _pid_status[pid] |= kPayloadStartSeen; 330 } 331 332 BufferedWrite(tspacket); 333 334 return true; 335 } 336 279 337 bool HDHRRecorder::ProcessTSPacket(const TSPacket& tspacket) 280 338 { 281 bool ok = !tspacket.TransportError();282 if ( ok && !tspacket.ScramplingControl())339 // Only create fake keyframe[s] if there are no audio/video streams 340 if (_input_pmt && _has_no_av) 283 341 { 284 if (tspacket.HasAdaptationField()) 285 GetStreamData()->HandleAdaptationFieldControl(&tspacket); 286 if (tspacket.HasPayload()) 287 { 288 const unsigned int lpid = tspacket.PID(); 342 _buffer_packets = !FindOtherKeyframes(&tspacket); 343 } 344 else 345 { 346 // There are audio/video streams. Only write the packet 347 // if audio/video key-frames have been found 348 if (_wait_for_keyframe_option && _first_keyframe < 0) 349 return true; 289 350 290 if ((GetStreamData()->VideoPIDSingleProgram() > 0x1fff) && 291 _wait_for_keyframe_option) 292 { 293 _wait_for_keyframe_option = false; 294 } 295 296 // Pass or reject frames based on PID, and parse info from them 297 if (lpid == GetStreamData()->VideoPIDSingleProgram()) 298 { 299 //cerr<<"v"; 300 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 301 BufferedWrite(tspacket); 302 } 303 else if (GetStreamData()->IsAudioPID(lpid)) 304 { 305 //cerr<<"a"; 306 _buffer_packets = !FindAudioKeyframes(&tspacket); 307 BufferedWrite(tspacket); 308 } 309 else if (GetStreamData()->IsListeningPID(lpid)) 310 { 311 //cerr<<"t"; 312 GetStreamData()->HandleTSTables(&tspacket); 313 } 314 else if (GetStreamData()->IsWritingPID(lpid)) 315 BufferedWrite(tspacket); 316 } 351 _buffer_packets = true; 317 352 } 318 return ok; 353 354 BufferedWrite(tspacket); 319 355 } 320 356 321 357 void HDHRRecorder::StartRecording(void) … … 333 369 _request_recording = true; 334 370 _recording = true; 335 371 336 if (!StartData())337 {338 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting recording "339 "(set target failed). Aborting.");340 Close();341 _error = true;342 VERBOSE(VB_RECORD, LOC + "StartRecording -- end 2"); 343 return;344 }345 346 hdhomerun_video_flush(_video_socket);372 // Make sure the first things in the file are a PAT & PMT 373 bool tmp = _wait_for_keyframe_option; 374 _wait_for_keyframe_option = false; 375 HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 376 HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 377 _wait_for_keyframe_option = tmp; 378 379 _stream_data->AddAVListener(this); 380 _stream_data->AddWritingListener(this); 381 _stream_handler->AddListener(_stream_data); 382 347 383 while (_request_recording && !_error) 348 384 { 385 usleep(50000); 386 349 387 if (PauseAndWait()) 350 388 continue; 351 389 352 if ( _stream_data)390 if (!_input_pmt) 353 391 { 354 QMutexLocker read_lock(&_pid_lock); 355 _reset_pid_filters |= _stream_data->HasEITPIDChanges(_eit_pids); 392 VERBOSE(VB_GENERAL, LOC_WARN + 393 "Recording will not commence until a PMT is set."); 394 usleep(5000); 395 continue; 356 396 } 357 397 358 if ( _reset_pid_filters)398 if (!_stream_handler->IsRunning()) 359 399 { 360 _reset_pid_filters = false; 361 VERBOSE(VB_RECORD, LOC + "Resetting Demux Filters"); 362 AdjustFilters(); 363 } 400 _error = true; 364 401 365 size_t read_size = 64 * 1024; // read about 64KB 366 read_size /= VIDEO_DATA_PACKET_SIZE; 367 read_size *= VIDEO_DATA_PACKET_SIZE; 368 369 size_t data_length; 370 unsigned char *data_buffer = 371 hdhomerun_video_recv(_video_socket, read_size, &data_length); 372 if (!data_buffer) 373 { 374 usleep(5000); 375 continue; 376 } 377 378 ProcessTSData(data_buffer, data_length); 402 VERBOSE(VB_IMPORTANT, LOC_ERR + 403 "Stream handler died unexpectedly."); 404 } 379 405 } 380 406 381 407 VERBOSE(VB_RECORD, LOC + "StartRecording -- ending..."); 382 408 383 _channel->DeviceClearTarget(); 409 _stream_handler->RemoveListener(_stream_data); 410 _stream_data->RemoveWritingListener(this); 411 _stream_data->RemoveAVListener(this); 412 384 413 Close(); 385 414 386 415 FinishRecording(); … … 389 418 VERBOSE(VB_RECORD, LOC + "StartRecording -- end"); 390 419 } 391 420 392 bool HDHRRecorder::AdjustFilters(void)421 void HDHRRecorder::ResetForNewFile(void) 393 422 { 394 QMutexLocker change_lock(&_pid_lock);423 DTVRecorder::ResetForNewFile(); 395 424 396 if (!_channel) 397 { 398 VERBOSE(VB_IMPORTANT, LOC_ERR + "AdjustFilters() no channel"); 399 return false; 400 } 425 bzero(_stream_id, sizeof(_stream_id)); 426 bzero(_pid_status, sizeof(_pid_status)); 427 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 401 428 402 if (!_input_pat || !_input_pmt) 403 { 404 VERBOSE(VB_IMPORTANT, LOC + "AdjustFilters() no pmt or no pat"); 405 return false; 406 } 407 408 uint_vec_t add_pid; 429 // FIXME 430 // Close and re-open ??? 431 //Close(); 432 //Open(); 433 } 409 434 410 add_pid.push_back(MPEG_PAT_PID); 411 _stream_data->AddListeningPID(MPEG_PAT_PID); 435 void HDHRRecorder::StopRecording(void) 436 { 437 _request_recording = false; 438 while (_recording) 439 usleep(2000); 440 } 412 441 413 for (uint i = 0; i < _input_pat->ProgramCount(); i++) 442 bool HDHRRecorder::PauseAndWait(int timeout) 443 { 444 if (request_pause) 414 445 { 415 add_pid.push_back(_input_pat->ProgramPID(i)); 416 _stream_data->AddListeningPID(_input_pat->ProgramPID(i)); 417 } 446 QMutex waitlock; 447 if (!paused) 448 { 449 assert(_stream_handler); 450 assert(_stream_data); 418 451 419 // Record the streams in the PMT... 420 bool need_pcr_pid = true; 421 for (uint i = 0; i < _input_pmt->StreamCount(); i++) 422 { 423 add_pid.push_back(_input_pmt->StreamPID(i)); 424 need_pcr_pid &= (_input_pmt->StreamPID(i) != _input_pmt->PCRPID()); 425 _stream_data->AddWritingPID(_input_pmt->StreamPID(i)); 426 } 452 _stream_handler->RemoveListener(_stream_data); 427 453 428 if (need_pcr_pid && (_input_pmt->PCRPID())) 429 { 430 add_pid.push_back(_input_pmt->PCRPID()); 431 _stream_data->AddWritingPID(_input_pmt->PCRPID()); 454 paused = true; 455 pauseWait.wakeAll(); 456 if (tvrec) 457 tvrec->RecorderPaused(); 458 } 459 waitlock.lock(); 460 unpauseWait.wait(&waitlock, timeout); 432 461 } 433 462 434 // Adjust for EIT 435 AdjustEITPIDs(); 436 for (uint i = 0; i < _eit_pids.size(); i++) 463 if (!request_pause && paused) 437 464 { 438 add_pid.push_back(_eit_pids[i]); 439 _stream_data->AddListeningPID(_eit_pids[i]); 440 } 465 paused = false; 441 466 442 // Delete filters for pids we no longer wish to monitor 443 vector<uint>::const_iterator it; 444 vector<uint> pids = _channel->GetPIDs(); 445 for (it = pids.begin(); it != pids.end(); ++it) 446 { 447 if (find(add_pid.begin(), add_pid.end(), *it) == add_pid.end()) 448 { 449 _stream_data->RemoveListeningPID(*it); 450 _stream_data->RemoveWritingPID(*it); 451 _channel->DelPID(*it, false); 452 } 453 } 467 assert(_stream_handler); 468 assert(_stream_data); 454 469 455 for (it = add_pid.begin(); it != add_pid.end(); ++it) 456 _channel->AddPID(*it, false); 457 458 _channel->UpdateFilters(); 470 _stream_handler->AddListener(_stream_data); 471 } 459 472 460 return add_pid.size();473 return paused; 461 474 } 462 475 463 /** \fn HDHRRecorder::AdjustEITPIDs(void) 464 * \brief Adjusts EIT PID monitoring to monitor the right number of EIT PIDs. 465 */ 466 bool HDHRRecorder::AdjustEITPIDs(void) 476 void HDHRRecorder::BufferedWrite(const TSPacket &tspacket) 467 477 { 468 bool changes = false; 469 uint_vec_t add, del; 470 471 QMutexLocker change_lock(&_pid_lock); 472 473 if (GetStreamData()->HasEITPIDChanges(_eit_pids)) 474 changes = GetStreamData()->GetEITPIDChanges(_eit_pids, add, del); 478 // Care must be taken to make sure that the packet actually gets written 479 // as the decision to actually write it has already been made 475 480 476 if (!changes) 477 return false; 478 479 for (uint i = 0; i < del.size(); i++) 481 // Do we have to buffer the packet for exact keyframe detection? 482 if (_buffer_packets) 480 483 { 481 uint_vec_t::iterator it;482 it = find(_eit_pids.begin(), _eit_pids.end(), del[i]);483 if (it != _eit_pids.end())484 _eit_pids.erase(it);484 int idx = _payload_buffer.size(); 485 _payload_buffer.resize(idx + TSPacket::SIZE); 486 memcpy(&_payload_buffer[idx], tspacket.data(), TSPacket::SIZE); 487 return; 485 488 } 486 489 487 for (uint i = 0; i < add.size(); i++) 488 _eit_pids.push_back(add[i]); 489 490 return true; 490 // We are free to write the packet, but if we have buffered packet[s] 491 // we have to write them first... 492 if (!_payload_buffer.empty()) 493 { 494 if (ringBuffer) 495 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 496 _payload_buffer.clear(); 497 } 498 if (ringBuffer) 499 ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 491 500 } 492 501 -
mythtv/libs/libmythtv/hdhrrecorder.cpp.rej.fixed
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrrecorder.cpp.rej.fixed myth.20018.0218b/mythtv/libs/libmythtv/hdhrrecorder.cpp.rej.fixed
1 *************** 2 *** 23,45 **** 3 4 // MythTV includes 5 #include "RingBuffer.h" 6 - #include "hdhrchannel.h" 7 - #include "hdhrrecorder.h" 8 #include "atsctables.h" 9 #include "atscstreamdata.h" 10 #include "eithelper.h" 11 #include "tv_rec.h" 12 13 #define LOC QString("HDHRRec(%1): ").arg(tvrec->GetCaptureCardNum()) 14 #define LOC_ERR QString("HDHRRec(%1), Error: ") \ 15 .arg(tvrec->GetCaptureCardNum()) 16 17 HDHRRecorder::HDHRRecorder(TVRec *rec, HDHRChannel *channel) 18 : DTVRecorder(rec), 19 - _channel(channel), _video_socket(NULL), 20 _stream_data(NULL), 21 - _input_pat(NULL), _input_pmt(NULL), 22 - _reset_pid_filters(false),_pid_lock(true) 23 { 24 } 25 26 --- 23,53 ---- 27 28 // MythTV includes 29 #include "RingBuffer.h" 30 #include "atsctables.h" 31 #include "atscstreamdata.h" 32 #include "eithelper.h" 33 #include "tv_rec.h" 34 35 + // MythTV HDHR includes 36 + #include "hdhrchannel.h" 37 + #include "hdhrrecorder.h" 38 + #include "hdhrstreamhandler.h" 39 + 40 #define LOC QString("HDHRRec(%1): ").arg(tvrec->GetCaptureCardNum()) 41 + #define LOC_WARN QString("HDHRRec(%1), Warning: ") \ 42 + .arg(tvrec->GetCaptureCardNum()) 43 #define LOC_ERR QString("HDHRRec(%1), Error: ") \ 44 .arg(tvrec->GetCaptureCardNum()) 45 46 HDHRRecorder::HDHRRecorder(TVRec *rec, HDHRChannel *channel) 47 : DTVRecorder(rec), 48 + _channel(channel), 49 + _stream_handler(NULL), 50 _stream_data(NULL), 51 + _pid_lock(true), 52 + _input_pat(NULL), 53 + _input_pmt(NULL), 54 + _has_no_av(false) 55 { 56 } 57 -
mythtv/libs/libmythtv/hdhrrecorder.h
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrrecorder.h myth.20018.0218b/mythtv/libs/libmythtv/hdhrrecorder.h
14 14 15 15 class HDHRChannel; 16 16 class ProgramMapTable; 17 class MPEGStreamData; 18 class HDHRStreamHandler; 19 17 20 18 21 typedef vector<uint> uint_vec_t; 19 22 20 23 class HDHRRecorder : public DTVRecorder, 21 24 public MPEGStreamListener, 22 public MPEGSingleProgramStreamListener 25 public MPEGSingleProgramStreamListener, 26 public TSPacketListener, 27 public TSPacketListenerAV 23 28 { 24 29 friend class ATSCStreamData; 25 30 … … 33 38 const QString &vbidev); 34 39 35 40 bool Open(void); 36 bool StartData(void);41 bool IsOpen(void); 37 42 void Close(void); 38 43 39 44 void StartRecording(void); 45 void ResetForNewFile(void); 46 void StopRecording(void); 40 47 41 48 void SetStreamData(MPEGStreamData*); 42 49 MPEGStreamData *GetStreamData(void) { return _stream_data; } … … 59 66 void HandleVCT(uint, const VirtualChannelTable*) {} 60 67 */ 61 68 62 private: 63 bool AdjustFilters(void); 64 bool AdjustEITPIDs(void); 69 // TSPacketListenerAV 70 bool ProcessVideoTSPacket(const TSPacket& tspacket); 71 bool ProcessAudioTSPacket(const TSPacket& tspacket); 72 73 // Common audio/visual processing 74 bool ProcessAVTSPacket(const TSPacket &tspacket); 65 75 66 void ProcessTSData(const unsigned char *buffer, int len);67 76 bool ProcessTSPacket(const TSPacket& tspacket); 77 78 void BufferedWrite(const TSPacket &tspacket); 79 private: 68 80 void TeardownAll(void); 81 82 void ReaderPaused(int fd); 83 bool PauseAndWait(int timeout = 100); 69 84 70 85 private: 71 86 HDHRChannel *_channel; 72 struct hdhomerun_video_sock_t *_video_socket;87 HDHRStreamHandler *_stream_handler; 73 88 MPEGStreamData *_stream_data; 74 89 90 mutable QMutex _pid_lock; 75 91 ProgramAssociationTable *_input_pat; 76 92 ProgramMapTable *_input_pmt; 77 bool _reset_pid_filters; 78 uint_vec_t _eit_pids; 79 mutable QMutex _pid_lock; 93 bool _has_no_av; 94 95 unsigned char _stream_id[0x1fff]; 96 unsigned char _pid_status[0x1fff]; 97 unsigned char _continuity_counter[0x1fff]; 98 99 // Constants 100 static const int TSPACKETS_BETWEEN_PSIP_SYNC; 101 static const int POLL_INTERVAL; 102 static const int POLL_WARNING_TIMEOUT; 103 104 static const unsigned char kPayloadStartSeen = 0x2; 80 105 }; 81 106 82 107 #endif -
mythtv/libs/libmythtv/hdhrsignalmonitor.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrsignalmonitor.cpp myth.20018.0218b/mythtv/libs/libmythtv/hdhrsignalmonitor.cpp
18 18 19 19 #include "hdhrchannel.h" 20 20 #include "hdhrrecorder.h" 21 #include "hdhrstreamhandler.h" 21 22 22 23 #define LOC QString("HDHRSM(%1): ").arg(channel->GetDevice()) 23 24 #define LOC_ERR QString("HDHRSM(%1), Error: ").arg(channel->GetDevice()) … … 39 40 HDHRSignalMonitor::HDHRSignalMonitor( 40 41 int db_cardnum, HDHRChannel* _channel, uint64_t _flags) : 41 42 DTVSignalMonitor(db_cardnum, _channel, _flags), 42 dtvMonitorRunning(false) 43 streamHandlerStarted(false), 44 streamHandler(NULL) 45 43 46 { 44 47 VERBOSE(VB_CHANNEL, LOC + "ctor"); 45 48 46 _channel->DelAllPIDs();47 48 49 signalStrength.SetThreshold(45); 49 50 50 51 AddFlags(kSigMon_WaitForSig); 52 53 streamHandler = HDHRStreamHandler::Get(_channel->GetDevice()); 51 54 } 52 55 53 56 /** \fn HDHRSignalMonitor::~HDHRSignalMonitor() … … 57 60 { 58 61 VERBOSE(VB_CHANNEL, LOC + "dtor"); 59 62 Stop(); 63 HDHRStreamHandler::Return(streamHandler); 60 64 } 61 65 62 66 /** \fn HDHRSignalMonitor::Stop(void) … … 66 70 { 67 71 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 68 72 SignalMonitor::Stop(); 69 if (dtvMonitorRunning) 70 { 71 dtvMonitorRunning = false; 72 pthread_join(table_monitor_thread, NULL); 73 } 74 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 75 } 76 77 void *HDHRSignalMonitor::TableMonitorThread(void *param) 78 { 79 HDHRSignalMonitor *mon = (HDHRSignalMonitor*) param; 80 mon->RunTableMonitor(); 81 return NULL; 82 } 83 84 bool HDHRSignalMonitor::UpdateFiltersFromStreamData(void) 85 { 86 vector<int> add_pids; 87 vector<int> del_pids; 88 89 if (!GetStreamData()) 90 return false; 91 92 UpdateListeningForEIT(); 93 94 const pid_map_t &listening = GetStreamData()->ListeningPIDs(); 95 96 // PIDs that need to be added.. 97 pid_map_t::const_iterator lit = listening.constBegin(); 98 for (; lit != listening.constEnd(); ++lit) 99 if (*lit && (filters.find(lit.key()) == filters.end())) 100 add_pids.push_back(lit.key()); 101 102 // PIDs that need to be removed.. 103 FilterMap::const_iterator fit = filters.constBegin(); 104 for (; fit != filters.constEnd(); ++fit) 105 if (listening.find(fit.key()) == listening.end()) 106 del_pids.push_back(fit.key()); 107 108 HDHRChannel *hdhr = dynamic_cast<HDHRChannel*>(channel); 109 if (!hdhr) 110 return false; 111 112 // Remove PIDs 113 bool ok = true; 114 vector<int>::iterator dit = del_pids.begin(); 115 for (; dit != del_pids.end(); ++dit) 116 { 117 ok &= hdhr->DelPID(*dit); 118 filters.erase(filters.find(*dit)); 119 } 73 if (GetStreamData()) 74 streamHandler->RemoveListener(GetStreamData()); 75 streamHandlerStarted = false; 76 streamHandler->SetRetuneAllowed(false, NULL, NULL); 120 77 121 // Add PIDs 122 vector<int>::iterator ait = add_pids.begin(); 123 for (; ait != add_pids.end(); ++ait) 124 { 125 ok &= hdhr->AddPID(*ait); 126 filters[*ait] = 1; 127 } 128 129 return ok; 78 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 130 79 } 131 80 132 void HDHRSignalMonitor::RunTableMonitor(void)81 HDHRChannel *HDHRSignalMonitor::GetHDHRChannel(void) 133 82 { 134 dtvMonitorRunning = true; 135 136 struct hdhomerun_video_sock_t *_video_socket; 137 _video_socket = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 138 if (!_video_socket) 139 { 140 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get video socket"); 141 return; 142 } 143 144 HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); 145 if (!hdrc) 146 return; 147 148 uint localPort = hdhomerun_video_get_local_port(_video_socket); 149 if (!hdrc->DeviceSetTarget(localPort)) 150 { 151 hdhomerun_video_destroy(_video_socket); 152 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set target"); 153 return; 154 } 155 156 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): " + 157 QString("begin (# of pids %1)") 158 .arg(GetStreamData()->ListeningPIDs().size())); 159 160 while (dtvMonitorRunning && GetStreamData()) 161 { 162 UpdateFiltersFromStreamData(); 163 164 size_t data_length; 165 unsigned char *data_buffer = 166 hdhomerun_video_recv(_video_socket, 167 VIDEO_DATA_BUFFER_SIZE_1S / 5, 168 &data_length); 169 170 if (data_buffer) 171 { 172 GetStreamData()->ProcessData(data_buffer, data_length); 173 continue; 174 } 175 176 usleep(2500); 177 } 178 179 hdrc->DeviceClearTarget(); 180 hdhomerun_video_destroy(_video_socket); 181 182 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown"); 183 184 // TODO teardown PID filters here 185 186 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 83 return dynamic_cast<HDHRChannel*>(channel); 187 84 } 188 85 189 86 /** \fn HDHRSignalMonitor::UpdateValues() … … 201 98 if (!running || exit) 202 99 return; 203 100 204 if ( dtvMonitorRunning)101 if (streamHandlerStarted) 205 102 { 206 103 EmitStatus(); 207 104 if (IsAllGood()) … … 212 109 return; 213 110 } 214 111 215 QString msg = ((HDHRChannel*)channel)->TunerGet("status");112 QString msg = streamHandler->GetTunerStatus(); 216 113 //ss = signal strength, [0,100] 217 114 //snq = signal to noise quality [0,100] 218 115 //seq = signal error quality [0,100] … … 250 147 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 251 148 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 252 149 { 253 pthread_create(&table_monitor_thread, NULL, 254 TableMonitorThread, this); 255 256 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 257 "Waiting for table monitor to start"); 258 259 while (!dtvMonitorRunning) 260 usleep(50); 261 262 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 263 "Table monitor started"); 150 streamHandler->AddListener(GetStreamData()); 151 streamHandlerStarted = true; 264 152 } 265 153 266 154 update_done = true; -
mythtv/libs/libmythtv/hdhrsignalmonitor.cpp.rej.fixed
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrsignalmonitor.cpp.rej.fixed myth.20018.0218b/mythtv/libs/libmythtv/hdhrsignalmonitor.cpp.rej.fixed
1 *************** 2 *** 41,55 **** 3 HDHRChannel* _channel, 4 uint64_t _flags, const char *_name) 5 : DTVSignalMonitor(db_cardnum, _channel, _flags, _name), 6 - dtvMonitorRunning(false) 7 { 8 VERBOSE(VB_CHANNEL, LOC + "ctor"); 9 10 - _channel->DelAllPIDs(); 11 - 12 signalStrength.SetThreshold(45); 13 14 AddFlags(kDTVSigMon_WaitForSig); 15 } 16 17 /** \fn HDHRSignalMonitor::~HDHRSignalMonitor() 18 --- 42,58 ---- 19 HDHRChannel* _channel, 20 uint64_t _flags, const char *_name) 21 : DTVSignalMonitor(db_cardnum, _channel, _flags, _name), 22 + streamHandlerStarted(false), 23 + streamHandler(NULL) 24 + 25 { 26 VERBOSE(VB_CHANNEL, LOC + "ctor"); 27 28 signalStrength.SetThreshold(45); 29 30 AddFlags(kDTVSigMon_WaitForSig); 31 + 32 + streamHandler = HDHRStreamHandler::Get(_channel->GetDevice()); 33 } 34 35 /** \fn HDHRSignalMonitor::~HDHRSignalMonitor() 36 *************** 37 *** 73,190 **** 38 { 39 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 40 SignalMonitor::Stop(); 41 - if (dtvMonitorRunning) 42 - { 43 - dtvMonitorRunning = false; 44 - pthread_join(table_monitor_thread, NULL); 45 - } 46 - VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 47 - } 48 49 - void *HDHRSignalMonitor::TableMonitorThread(void *param) 50 - { 51 - HDHRSignalMonitor *mon = (HDHRSignalMonitor*) param; 52 - mon->RunTableMonitor(); 53 - return NULL; 54 - } 55 - 56 - bool HDHRSignalMonitor::UpdateFiltersFromStreamData(void) 57 - { 58 - vector<int> add_pids; 59 - vector<int> del_pids; 60 - 61 - if (!GetStreamData()) 62 - return false; 63 - 64 - UpdateListeningForEIT(); 65 - 66 - const pid_map_t &listening = GetStreamData()->ListeningPIDs(); 67 - 68 - // PIDs that need to be added.. 69 - pid_map_t::const_iterator lit = listening.constBegin(); 70 - for (; lit != listening.constEnd(); ++lit) 71 - if (lit.data() && (filters.find(lit.key()) == filters.end())) 72 - add_pids.push_back(lit.key()); 73 - 74 - // PIDs that need to be removed.. 75 - FilterMap::const_iterator fit = filters.constBegin(); 76 - for (; fit != filters.constEnd(); ++fit) 77 - if (listening.find(fit.key()) == listening.end()) 78 - del_pids.push_back(fit.key()); 79 - 80 - HDHRChannel *hdhr = dynamic_cast<HDHRChannel*>(channel); 81 - // Remove PIDs 82 - bool ok = true; 83 - vector<int>::iterator dit = del_pids.begin(); 84 - for (; dit != del_pids.end(); ++dit) 85 - { 86 - ok &= hdhr->DelPID(*dit); 87 - filters.erase(filters.find(*dit)); 88 - } 89 - 90 - // Add PIDs 91 - vector<int>::iterator ait = add_pids.begin(); 92 - for (; ait != add_pids.end(); ++ait) 93 - { 94 - ok &= hdhr->AddPID(*ait); 95 - filters[*ait] = 1; 96 - } 97 - 98 - return ok; 99 } 100 101 - void HDHRSignalMonitor::RunTableMonitor(void) 102 { 103 - dtvMonitorRunning = true; 104 - 105 - struct hdhomerun_video_sock_t *_video_socket; 106 - _video_socket = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 107 - if (!_video_socket) 108 - { 109 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get video socket"); 110 - return; 111 - } 112 - 113 - HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); 114 - uint localPort = hdhomerun_video_get_local_port(_video_socket); 115 - if (!hdrc->DeviceSetTarget(localPort)) 116 - { 117 - hdhomerun_video_destroy(_video_socket); 118 - VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set target"); 119 - return; 120 - } 121 - 122 - VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): " + 123 - QString("begin (# of pids %1)") 124 - .arg(GetStreamData()->ListeningPIDs().size())); 125 - 126 - while (dtvMonitorRunning && GetStreamData()) 127 - { 128 - UpdateFiltersFromStreamData(); 129 - 130 - size_t data_length; 131 - unsigned char *data_buffer = 132 - hdhomerun_video_recv(_video_socket, 133 - VIDEO_DATA_BUFFER_SIZE_1S / 5, 134 - &data_length); 135 - 136 - if (data_buffer) 137 - { 138 - GetStreamData()->ProcessData(data_buffer, data_length); 139 - continue; 140 - } 141 - 142 - usleep(2500); 143 - } 144 - 145 - hdrc->DeviceClearTarget(); 146 - hdhomerun_video_destroy(_video_socket); 147 - 148 - VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown"); 149 - 150 - // TODO teardown PID filters here 151 - 152 - VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 153 } 154 155 /** \fn HDHRSignalMonitor::UpdateValues() 156 --- 77,93 ---- 157 { 158 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 159 SignalMonitor::Stop(); 160 + if (GetStreamData()) 161 + streamHandler->RemoveListener(GetStreamData()); 162 + streamHandlerStarted = false; 163 + streamHandler->SetRetuneAllowed(false, NULL, NULL); 164 165 + VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 166 } 167 168 + HDHRChannel *HDHRSignalMonitor::GetHDHRChannel(void) 169 { 170 + return dynamic_cast<HDHRChannel*>(channel); 171 } 172 173 /** \fn HDHRSignalMonitor::UpdateValues() -
mythtv/libs/libmythtv/hdhrsignalmonitor.h
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrsignalmonitor.h myth.20018.0218b/mythtv/libs/libmythtv/hdhrsignalmonitor.h
7 7 #include "qstringlist.h" 8 8 9 9 class HDHRChannel; 10 class HDHRStreamHandler; 10 11 11 12 typedef QMap<uint,int> FilterMap; 12 13 … … 19 20 20 21 void Stop(void); 21 22 22 bool UpdateFiltersFromStreamData(void);23 24 23 protected: 25 24 HDHRSignalMonitor(void); 26 25 HDHRSignalMonitor(const HDHRSignalMonitor&); 27 26 28 27 virtual void UpdateValues(void); 29 28 30 static void *TableMonitorThread(void *param);31 void RunTableMonitor(void);32 33 29 bool SupportsTSMonitoring(void); 34 30 31 HDHRChannel *GetHDHRChannel(void); 32 35 33 protected: 36 bool dtvMonitorRunning;37 pthread_t table_monitor_thread;38 34 39 FilterMap filters; ///< PID filters for table monitoring 35 bool streamHandlerStarted; 36 HDHRStreamHandler *streamHandler; 37 40 38 }; 41 39 42 40 #endif // HDHRSIGNALMONITOR_H -
mythtv/libs/libmythtv/hdhrsignalmonitor.h.rej.fixed
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrsignalmonitor.h.rej.fixed myth.20018.0218b/mythtv/libs/libmythtv/hdhrsignalmonitor.h.rej.fixed
1 *************** 2 *** 21,28 **** 3 4 void Stop(void); 5 6 - bool UpdateFiltersFromStreamData(void); 7 - 8 public slots: 9 void deleteLater(void); 10 11 --- 22,27 ---- 12 13 void Stop(void); 14 15 public slots: 16 void deleteLater(void); 17 -
mythtv/libs/libmythtv/hdhrstreamhandler.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrstreamhandler.cpp myth.20018.0218b/mythtv/libs/libmythtv/hdhrstreamhandler.cpp
1 // -*- Mode: c++ -*- 2 3 #include <cassert> // remove when everything is filled in... 4 5 // POSIX headers 6 #include <pthread.h> 7 #include <fcntl.h> 8 #include <unistd.h> 9 #include <sys/select.h> 10 #include <sys/ioctl.h> 11 12 // Qt headers 13 #include <qstring.h> 14 #include <qdeepcopy.h> 15 16 // MythTV headers 17 #include "hdhrstreamhandler.h" 18 #include "hdhrchannel.h" 19 #include "dtvsignalmonitor.h" 20 #include "streamlisteners.h" 21 #include "mpegstreamdata.h" 22 #include "cardutil.h" 23 24 #define LOC QString("HDHRSH( %1 ): ").arg(_devicename) 25 #define LOC_WARN QString("HDHRSH( %1 ) Warning: ").arg(_devicename) 26 #define LOC_ERR QString("HDHRSH( %1 ) Error: ").arg(_devicename) 27 28 QMap<uint,bool> HDHRStreamHandler::_rec_supports_ts_monitoring; 29 QMutex HDHRStreamHandler::_rec_supports_ts_monitoring_lock; 30 31 QMap<QString,HDHRStreamHandler*> HDHRStreamHandler::_handlers; 32 QMap<QString,uint> HDHRStreamHandler::_handlers_refcnt; 33 QMutex HDHRStreamHandler::_handlers_lock; 34 35 36 #define DEBUG_PID_FILTERS 37 38 HDHRStreamHandler *HDHRStreamHandler::Get(QString devicename) 39 { 40 QMutexLocker locker(&_handlers_lock); 41 42 QMap<QString,HDHRStreamHandler*>::iterator it = 43 _handlers.find(devicename); 44 45 if (it == _handlers.end()) 46 { 47 HDHRStreamHandler *newhandler = new HDHRStreamHandler(devicename); 48 newhandler->Open(); 49 _handlers[devicename] = newhandler; 50 _handlers_refcnt[devicename] = 1; 51 VERBOSE(VB_RECORD, QString("HDHRSH: Creating new stream handler for %1") 52 .arg(devicename)); 53 } 54 else 55 { 56 _handlers_refcnt[devicename]++; 57 uint rcount=_handlers_refcnt[devicename]; 58 VERBOSE(VB_RECORD, QString("HDHRSH: Using existing stream handler for %1 (%2 in use)") 59 .arg(devicename).arg(rcount)); 60 } 61 62 return _handlers[devicename]; 63 } 64 65 void HDHRStreamHandler::Return(HDHRStreamHandler * & ref) 66 { 67 QMutexLocker locker(&_handlers_lock); 68 69 QMap<QString,uint>::iterator rit = _handlers_refcnt.find(ref->_devicename); 70 if (rit == _handlers_refcnt.end()) 71 return; 72 73 uint rcount = *rit; 74 VERBOSE(VB_RECORD, QString("HDHRSH: %1 streams left for %2") 75 .arg(rcount-1).arg(ref->_devicename)); 76 77 if (*rit > 1) 78 { 79 (*rit)--; 80 ref=NULL; 81 return; 82 } 83 84 QMap<QString, HDHRStreamHandler*>::iterator it = _handlers.find(ref->_devicename); 85 if ((it != _handlers.end()) && (*it == ref)) 86 { 87 VERBOSE(VB_RECORD, QString("HDHRSH: Closing handler for %1").arg(ref->_devicename)); 88 ref->Close(); 89 delete *it; 90 _handlers.erase(it); 91 } else { 92 VERBOSE(VB_IMPORTANT, QString("HDHRSH: Couldn't find handler for %1").arg(ref->_devicename)); 93 } 94 95 _handlers_refcnt.erase(rit); 96 ref=NULL; 97 } 98 99 HDHRStreamHandler::HDHRStreamHandler(QString devicename) : 100 _control_socket(NULL), 101 _video_socket(NULL), 102 _devicename(devicename), 103 _allow_retune(false), 104 105 _start_stop_lock(QMutex::Recursive), 106 _running(false), 107 108 _sigmon(NULL), 109 _channel(NULL), 110 111 _pid_lock(QMutex::Recursive), 112 _listener_lock(QMutex::Recursive), 113 _hdhr_lock(QMutex::Recursive) 114 { 115 } 116 117 HDHRStreamHandler::~HDHRStreamHandler() 118 { 119 assert(_stream_data_list.empty()); 120 } 121 122 bool HDHRStreamHandler::Open() 123 { 124 if (!FindDevice()) 125 return false; 126 127 return Connect(); 128 } 129 130 void HDHRStreamHandler::Close() 131 { 132 if (_control_socket) 133 { 134 TuneChannel("none"); 135 hdhomerun_control_destroy(_control_socket); 136 _control_socket=NULL; 137 } 138 } 139 140 bool HDHRStreamHandler::Connect() 141 { 142 _control_socket = hdhomerun_control_create(_device_id, _device_ip); 143 144 if (!_control_socket) 145 { 146 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create control socket"); 147 return false; 148 } 149 150 if (hdhomerun_control_get_local_addr(_control_socket) == 0) 151 { 152 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to connect to device"); 153 return false; 154 } 155 156 VERBOSE(VB_CHANNEL, LOC + "Successfully connected to device"); 157 return true; 158 } 159 160 bool HDHRStreamHandler::FindDevice(void) 161 { 162 hdhomerun_device_t* thisdevice = hdhomerun_device_create_from_str(_devicename.toLocal8Bit().constData()); 163 164 if (thisdevice) 165 { 166 _device_id = hdhomerun_device_get_device_id(thisdevice); 167 _device_ip = hdhomerun_device_get_device_ip(thisdevice); 168 _tuner = hdhomerun_device_get_tuner(thisdevice); 169 hdhomerun_device_destroy(thisdevice); 170 171 VERBOSE(VB_IMPORTANT, LOC + 172 QString("device %5 found at address %1.%2.%3.%4 tuner %6") 173 .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF) 174 .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF) 175 .arg(_devicename).arg(_tuner)); 176 177 return true; 178 } 179 return false; 180 } 181 182 183 bool HDHRStreamHandler::EnterPowerSavingMode(void) 184 { 185 if (_video_socket) 186 { 187 VERBOSE(VB_CHANNEL, LOC + "Ignoring request - video streaming active"); 188 return false; 189 } 190 else 191 { 192 return TuneChannel("none"); 193 /* QString::null != TunerSet("channel", "none", false); */ 194 } 195 } 196 197 QString HDHRStreamHandler::DeviceGet(const QString &name, bool report_error_return) 198 { 199 QMutexLocker locker(&_hdhr_lock); 200 201 if (!_control_socket) 202 { 203 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (not connected)"); 204 return QString::null; 205 } 206 207 char *value = NULL; 208 char *error = NULL; 209 if (hdhomerun_control_get(_control_socket, name.toLocal8Bit().constData(), &value, &error) < 0) 210 { 211 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed" + ENO); 212 return QString::null; 213 } 214 215 if (report_error_return && error) 216 { 217 VERBOSE(VB_IMPORTANT, LOC_ERR + 218 QString("DeviceGet(%1): %2").arg(name).arg(error)); 219 220 return QString::null; 221 } 222 223 return QString(value); 224 } 225 226 227 QString HDHRStreamHandler::DeviceSet(const QString &name, const QString &val, 228 bool report_error_return) 229 { 230 QMutexLocker locker(&_hdhr_lock); 231 232 if (!_control_socket) 233 { 234 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (not connected)"); 235 return QString::null; 236 } 237 238 char *value = NULL; 239 char *error = NULL; 240 if (hdhomerun_control_set(_control_socket, name.toLocal8Bit().constData(), val.toLocal8Bit().constData(), &value, &error) < 0) 241 { 242 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed" + ENO); 243 244 return QString::null; 245 } 246 247 if (report_error_return && error) 248 { 249 VERBOSE(VB_IMPORTANT, LOC_ERR + 250 QString("DeviceSet(%1 %2): %3").arg(name).arg(val).arg(error)); 251 252 return QString::null; 253 } 254 255 return QString(value); 256 } 257 258 QString HDHRStreamHandler::TunerGet(const QString &name, bool report_error_return) 259 { 260 return DeviceGet(QString("/tuner%1/%2").arg(_tuner).arg(name), 261 report_error_return); 262 } 263 264 QString HDHRStreamHandler::TunerSet(const QString &name, const QString &value, 265 bool report_error_return) 266 { 267 return DeviceSet(QString("/tuner%1/%2").arg(_tuner).arg(name), value, 268 report_error_return); 269 } 270 271 bool HDHRStreamHandler::DeviceSetTarget(unsigned short localPort) 272 { 273 if (localPort == 0) 274 { 275 return false; 276 } 277 278 unsigned long localIP = hdhomerun_control_get_local_addr(_control_socket); 279 if (localIP == 0) 280 { 281 return false; 282 } 283 284 QString configValue = QString("rtp://%1.%2.%3.%4:%5") 285 .arg((localIP >> 24) & 0xFF).arg((localIP >> 16) & 0xFF) 286 .arg((localIP >> 8) & 0xFF).arg((localIP >> 0) & 0xFF) 287 .arg(localPort); 288 289 return (QString::null != TunerSet("target", configValue)); 290 } 291 292 bool HDHRStreamHandler::DeviceClearTarget() 293 { 294 return (QString::null != TunerSet("target", "0.0.0.0:0")); 295 } 296 297 QString HDHRStreamHandler::GetTunerStatus() { 298 return TunerGet("status"); 299 } 300 301 bool HDHRStreamHandler::Connected() { 302 // FIXME 303 return (_control_socket != NULL); 304 } 305 306 bool HDHRStreamHandler::TuneChannel(QString chn) { 307 QString current = TunerGet("channel"); 308 if (current == chn) 309 { 310 VERBOSE(VB_RECORD, QString(LOC + "Not Re-Tuning channel %1").arg(chn)); 311 return true; 312 } 313 VERBOSE(VB_RECORD, QString(LOC + "Tuning channel %1 (was %2)").arg(chn).arg(current)); 314 return (QString::null != TunerSet("channel", chn)); 315 } 316 317 bool HDHRStreamHandler::TuneProgram(QString pnum) { 318 VERBOSE(VB_RECORD, QString(LOC + "Tuning program %1").arg(pnum)); 319 return (QString::null != TunerSet("program", pnum, false)); 320 } 321 322 void HDHRStreamHandler::AddListener(MPEGStreamData *data) 323 { 324 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- begin"); 325 assert(data); 326 327 _listener_lock.lock(); 328 329 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- locked"); 330 331 _stream_data_list.push_back(data); 332 333 _listener_lock.unlock(); 334 335 Start(); 336 337 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- end"); 338 } 339 340 void HDHRStreamHandler::RemoveListener(MPEGStreamData *data) 341 { 342 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- begin"); 343 assert(data); 344 345 _listener_lock.lock(); 346 347 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- locked"); 348 349 vector<MPEGStreamData*>::iterator it = 350 find(_stream_data_list.begin(), _stream_data_list.end(), data); 351 352 if (it != _stream_data_list.end()) 353 _stream_data_list.erase(it); 354 355 if (_stream_data_list.empty()) 356 { 357 _listener_lock.unlock(); 358 Stop(); 359 } 360 else 361 { 362 _listener_lock.unlock(); 363 } 364 365 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- end"); 366 } 367 368 void *run_hdhr_stream_handler_thunk(void *param) 369 { 370 HDHRStreamHandler *mon = (HDHRStreamHandler*) param; 371 mon->Run(); 372 return NULL; 373 } 374 375 void HDHRStreamHandler::Start(void) 376 { 377 QMutexLocker locker(&_start_stop_lock); 378 379 _eit_pids.clear(); 380 381 if (!IsRunning()) 382 { 383 QMutex is_running_lock; 384 int rval = pthread_create(&_reader_thread, NULL, 385 run_hdhr_stream_handler_thunk, this); 386 387 if (0 != rval) 388 { 389 VERBOSE(VB_IMPORTANT, LOC_ERR + 390 "Start: Failed to create thread." + ENO); 391 return; 392 } 393 394 while (!IsRunning()) 395 { 396 is_running_lock.lock(); 397 _running_state_changed.wait(&is_running_lock, 100); 398 } 399 } 400 } 401 402 void HDHRStreamHandler::Stop(void) 403 { 404 QMutexLocker locker(&_start_stop_lock); 405 406 if (IsRunning()) 407 { 408 SetRunning(false); 409 pthread_join(_reader_thread, NULL); 410 } 411 } 412 413 void HDHRStreamHandler::Run(void) 414 { 415 SetRunning(true); 416 RunTS(); 417 } 418 419 /** \fn HDHRStreamHandler::RunTS(void) 420 * \brief Uses TS filtering devices to read a DVB device for tables & data 421 * 422 * This supports all types of MPEG based stream data, but is extreemely 423 * slow with DVB over USB 1.0 devices which for efficiency reasons buffer 424 * a stream until a full block transfer buffer full of the requested 425 * tables is available. This takes a very long time when you are just 426 * waiting for a PAT or PMT table, and the buffer is hundreds of packets 427 * in size. 428 */ 429 void HDHRStreamHandler::RunTS(void) 430 { 431 int remainder = 0; 432 VERBOSE(VB_RECORD, LOC + "RunTS()"); 433 434 /* Calculate buffer size */ 435 uint buffersize = gContext->GetNumSetting( 436 "HDRingbufferSize", 50 * TSPacket::SIZE) * 1024; 437 buffersize /= VIDEO_DATA_PACKET_SIZE; 438 buffersize *= VIDEO_DATA_PACKET_SIZE; 439 440 // Buffer should be at least about 1MB.. 441 buffersize = max(49 * TSPacket::SIZE * 128, buffersize); 442 443 VERBOSE(VB_GENERAL, QString(LOC + "HD Ringbuffer size = %1 KB").arg(buffersize / 1024)); 444 445 /* Create TS socket. */ 446 _video_socket = hdhomerun_video_create(0, buffersize); 447 if (!_video_socket) 448 { 449 VERBOSE(VB_IMPORTANT, LOC + "Open() failed to open socket"); 450 return; 451 } 452 453 uint localPort = hdhomerun_video_get_local_port(_video_socket); 454 if (!DeviceSetTarget(localPort)) 455 { 456 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting recording (set target failed). Aborting."); 457 return; 458 } 459 hdhomerun_video_flush(_video_socket); 460 461 bool _error = false; 462 463 VERBOSE(VB_RECORD, LOC + "RunTS(): begin"); 464 465 while (IsRunning() && !_error) 466 { 467 UpdateFiltersFromStreamData(); 468 469 size_t read_size = 64 * 1024; // read about 64KB 470 read_size /= VIDEO_DATA_PACKET_SIZE; 471 read_size *= VIDEO_DATA_PACKET_SIZE; 472 473 size_t data_length; 474 unsigned char *data_buffer = 475 hdhomerun_video_recv(_video_socket, read_size, &data_length); 476 477 if (! data_buffer) 478 { 479 usleep(5000); 480 continue; 481 } 482 483 // Assume data_length is a multiple of 188 (packet size) 484 // ASSERT(0 == ( data_length % 188) ); 485 486 _listener_lock.lock(); 487 488 if (_stream_data_list.empty()) 489 { 490 _listener_lock.unlock(); 491 continue; 492 } 493 494 for (uint i = 0; i < _stream_data_list.size(); i++) 495 { 496 remainder = _stream_data_list[i]->ProcessData(data_buffer, data_length); 497 } 498 499 _listener_lock.unlock(); 500 if (remainder != 0) 501 VERBOSE(VB_GENERAL, QString(LOC + "RunTS(): data_length = %1 remainder = %2") 502 .arg(data_length).arg(remainder)); 503 } 504 VERBOSE(VB_RECORD, LOC + "RunTS(): " + "shutdown"); 505 506 DelAllPIDs(); 507 508 DeviceClearTarget(); 509 VERBOSE(VB_RECORD, LOC + "RunTS(): " + "end"); 510 511 hdhomerun_video_sock_t* tmp_video_socket; 512 { 513 QMutexLocker locker(&_hdhr_lock); 514 tmp_video_socket = _video_socket; 515 _video_socket=NULL; 516 } 517 518 hdhomerun_video_destroy(tmp_video_socket); 519 520 SetRunning(false); 521 } 522 523 bool HDHRStreamHandler::AddPID(uint pid, bool do_update) 524 { 525 QMutexLocker locker(&_pid_lock); 526 527 vector<uint>::iterator it; 528 it = lower_bound(_pid_info.begin(), _pid_info.end(), pid); 529 if (it != _pid_info.end() && *it == pid) 530 { 531 #ifdef DEBUG_PID_FILTERS 532 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<", " << do_update << ") NOOP"); 533 #endif // DEBUG_PID_FILTERS 534 return true; 535 } 536 537 _pid_info.insert(it, pid); 538 539 #ifdef DEBUG_PID_FILTERS 540 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<")", " << do_update << "); 541 #endif // DEBUG_PID_FILTERS 542 543 if (do_update) 544 return UpdateFilters(); 545 return true; 546 } 547 548 bool HDHRStreamHandler::DelPID(uint pid, bool do_update) 549 { 550 QMutexLocker locker(&_pid_lock); 551 552 vector<uint>::iterator it; 553 it = lower_bound(_pid_info.begin(), _pid_info.end(), pid); 554 if (it == _pid_info.end()) 555 { 556 #ifdef DEBUG_PID_FILTERS 557 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<", " << do_update << ") NOOP"); 558 #endif // DEBUG_PID_FILTERS 559 560 return true; 561 } 562 563 if (*it == pid) 564 { 565 #ifdef DEBUG_PID_FILTERS 566 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<", " << do_update << ") -- found"); 567 #endif // DEBUG_PID_FILTERS 568 _pid_info.erase(it); 569 } 570 else 571 { 572 #ifdef DEBUG_PID_FILTERS 573 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<", " << do_update << ") -- failed"); 574 #endif // DEBUG_PID_FILTERS 575 } 576 577 if (do_update) 578 return UpdateFilters(); 579 return true; 580 } 581 582 bool HDHRStreamHandler::DelAllPIDs(void) 583 { 584 QMutexLocker locker(&_pid_lock); 585 586 #ifdef DEBUG_PID_FILTERS 587 VERBOSE(VB_CHANNEL, "DelAllPID()"); 588 #endif // DEBUG_PID_FILTERS 589 590 _pid_info.clear(); 591 592 return UpdateFilters(); 593 } 594 595 QString filt_str(uint pid) 596 { 597 uint pid0 = (pid / (16*16*16)) % 16; 598 uint pid1 = (pid / (16*16)) % 16; 599 uint pid2 = (pid / (16)) % 16; 600 uint pid3 = pid % 16; 601 return QString("0x%1%2%3%4") 602 .arg(pid0,0,16).arg(pid1,0,16) 603 .arg(pid2,0,16).arg(pid3,0,16); 604 } 605 606 bool HDHRStreamHandler::UpdateFilters(void) 607 { 608 #ifdef DEBUG_PID_FILTERS 609 VERBOSE(VB_CHANNEL, LOC + "UpdateFilters()"); 610 #endif // DEBUG_PID_FILTERS 611 QMutexLocker locker(&_pid_lock); 612 613 QString filter = ""; 614 615 vector<uint> range_min; 616 vector<uint> range_max; 617 618 // FIXME 619 // if (_ignore_filters) 620 // return true; 621 622 for (uint i = 0; i < _pid_info.size(); i++) 623 { 624 uint pid_min = _pid_info[i]; 625 uint pid_max = pid_min; 626 for (uint j = i + 1; j < _pid_info.size(); j++) 627 { 628 if (pid_max + 1 != _pid_info[j]) 629 break; 630 pid_max++; 631 i++; 632 } 633 range_min.push_back(pid_min); 634 range_max.push_back(pid_max); 635 } 636 if (range_min.size() > 16) 637 { 638 range_min.resize(16); 639 uint pid_max = range_max.back(); 640 range_max.resize(15); 641 range_max.push_back(pid_max); 642 } 643 644 for (uint i = 0; i < range_min.size(); i++) 645 { 646 filter += filt_str(range_min[i]); 647 if (range_min[i] != range_max[i]) 648 filter += QString("-%1").arg(filt_str(range_max[i])); 649 filter += " "; 650 } 651 652 filter = filter.trimmed(); 653 654 QString new_filter = TunerSet("filter", filter); 655 656 #ifdef DEBUG_PID_FILTERS 657 QString msg = QString("Filter: '%1'").arg(filter); 658 if (filter != new_filter) 659 msg += QString("\n\t\t\t\t'%2'").arg(new_filter); 660 661 VERBOSE(VB_CHANNEL, LOC + msg); 662 #endif // DEBUG_PID_FILTERS 663 664 return filter == new_filter; 665 } 666 667 void HDHRStreamHandler::UpdateListeningForEIT(void) 668 { 669 vector<uint> add_eit, del_eit; 670 671 QMutexLocker read_locker(&_listener_lock); 672 673 for (uint i = 0; i < _stream_data_list.size(); i++) 674 { 675 MPEGStreamData *sd = _stream_data_list[i]; 676 if (sd->HasEITPIDChanges(_eit_pids) && 677 sd->GetEITPIDChanges(_eit_pids, add_eit, del_eit)) 678 { 679 for (uint i = 0; i < del_eit.size(); i++) 680 { 681 uint_vec_t::iterator it; 682 it = find(_eit_pids.begin(), _eit_pids.end(), del_eit[i]); 683 if (it != _eit_pids.end()) 684 _eit_pids.erase(it); 685 sd->RemoveListeningPID(del_eit[i]); 686 } 687 688 for (uint i = 0; i < add_eit.size(); i++) 689 { 690 _eit_pids.push_back(add_eit[i]); 691 sd->AddListeningPID(add_eit[i]); 692 } 693 } 694 } 695 } 696 697 bool HDHRStreamHandler::UpdateFiltersFromStreamData(void) 698 { 699 700 UpdateListeningForEIT(); 701 702 pid_map_t pids; 703 704 { 705 QMutexLocker read_locker(&_listener_lock); 706 707 for (uint i = 0; i < _stream_data_list.size(); i++) 708 _stream_data_list[i]->GetPIDs(pids); 709 } 710 711 uint_vec_t add_pids; 712 vector<uint> del_pids; 713 714 { 715 QMutexLocker read_locker(&_pid_lock); 716 717 // PIDs that need to be added.. 718 pid_map_t::const_iterator lit = pids.constBegin(); 719 for (; lit != pids.constEnd(); ++lit) 720 { 721 vector<uint>::iterator it; 722 it = lower_bound(_pid_info.begin(), _pid_info.end(), lit.key()); 723 if (! (it != _pid_info.end() && *it == lit.key())) { 724 add_pids.push_back(lit.key()); 725 } 726 } 727 728 // PIDs that need to be removed.. 729 vector<uint>::iterator fit = _pid_info.begin(); 730 for (; fit != _pid_info.end(); ++fit) 731 { 732 pid_map_t::const_iterator it = pids.find(*fit); 733 if(it == pids.end()) 734 del_pids.push_back(*fit); 735 } 736 } 737 738 bool need_update = false; 739 740 // Remove PIDs 741 bool ok = true; 742 vector<uint>::iterator dit = del_pids.begin(); 743 for (; dit != del_pids.end(); ++dit) 744 { 745 need_update = true; 746 ok &= DelPID(*dit, false); 747 } 748 749 // Add PIDs 750 vector<uint>::iterator ait = add_pids.begin(); 751 for (; ait != add_pids.end(); ++ait) 752 { 753 need_update = true; 754 ok &= AddPID(*ait, false); 755 } 756 757 if (need_update) 758 return UpdateFilters(); 759 760 return ok; 761 } 762 763 void HDHRStreamHandler::SetRetuneAllowed( 764 bool allow, 765 DTVSignalMonitor *sigmon, 766 HDHRChannel *hdhrchan) 767 { 768 if (allow && sigmon && hdhrchan) 769 { 770 _allow_retune = true; 771 _sigmon = sigmon; 772 _channel = hdhrchan; 773 } 774 else 775 { 776 _allow_retune = false; 777 _sigmon = NULL; 778 _channel = NULL; 779 } 780 } 781 782 /** \fn HDHRStreamHandler::SupportsTSMonitoring(void) 783 * \brief Returns true if TS monitoring is supported. 784 * 785 * NOTE: If you are using a DEC2000-t device you need to 786 * apply the patches provided by Peter Beutner for it, see 787 * http://www.gossamer-threads.com/lists/mythtv/dev/166172 788 * These patches should make it in to Linux 2.6.15 or 2.6.16. 789 */ 790 bool HDHRStreamHandler::SupportsTSMonitoring(void) 791 { 792 return false; 793 794 // FIXME 795 #if 0 796 const uint pat_pid = 0x0; 797 798 { 799 QMutexLocker locker(&_rec_supports_ts_monitoring_lock); 800 QMap<uint,bool>::const_iterator it; 801 it = _rec_supports_ts_monitoring.find(_dvb_dev_num); 802 if (it != _rec_supports_ts_monitoring.end()) 803 return *it; 804 } 805 806 int dvr_fd = open(_dvr_dev_path.ascii(), O_RDONLY | O_NONBLOCK); 807 if (dvr_fd < 0) 808 { 809 QMutexLocker locker(&_rec_supports_ts_monitoring_lock); 810 _rec_supports_ts_monitoring[_dvb_dev_num] = false; 811 return false; 812 } 813 814 bool supports_ts = false; 815 if (AddPIDFilter(new PIDInfoHDHR(pat_pid))) 816 { 817 supports_ts = true; 818 RemovePIDFilter(pat_pid); 819 } 820 821 close(dvr_fd); 822 823 QMutexLocker locker(&_rec_supports_ts_monitoring_lock); 824 _rec_supports_ts_monitoring[_dvb_dev_num] = supports_ts; 825 826 return supports_ts; 827 #endif 828 } 829 830 void HDHRStreamHandler::SetRunning(bool is_running) 831 { 832 _running = is_running; 833 _running_state_changed.wakeAll(); 834 } 835 836 PIDPriority HDHRStreamHandler::GetPIDPriority(uint pid) const 837 { 838 QMutexLocker reading_locker(&_listener_lock); 839 840 PIDPriority tmp = kPIDPriorityNone; 841 842 for (uint i = 0; i < _stream_data_list.size(); i++) 843 tmp = max(tmp, _stream_data_list[i]->GetPIDPriority(pid)); 844 845 return tmp; 846 } -
mythtv/libs/libmythtv/hdhrstreamhandler.h
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/hdhrstreamhandler.h myth.20018.0218b/mythtv/libs/libmythtv/hdhrstreamhandler.h
1 // -*- Mode: c++ -*- 2 3 #ifndef _HDHRSTREAMHANDLER_H_ 4 #define _HDHRSTREAMHANDLER_H_ 5 6 #include <vector> 7 using namespace std; 8 9 #include <qmap.h> 10 #include <qmutex.h> 11 12 #include "util.h" 13 #include "DeviceReadBuffer.h" 14 #include "mpegstreamdata.h" 15 16 class QString; 17 class HDHRStreamHandler; 18 class DTVSignalMonitor; 19 class HDHRChannel; 20 class DeviceReadBuffer; 21 22 // HDHomeRun headers 23 #ifdef USING_HDHOMERUN 24 #include "hdhomerun_includes.h" 25 #else 26 struct hdhomerun_control_sock_t { int dummy; }; 27 #endif 28 29 typedef QMap<uint,int> FilterMap; 30 31 //#define RETUNE_TIMEOUT 5000 32 33 class HDHRStreamHandler : public ReaderPausedCB 34 { 35 friend void *run_hdhr_stream_handler_thunk(void *param); 36 37 public: 38 static HDHRStreamHandler *Get(QString devicename); 39 static void Return(HDHRStreamHandler * & ref); 40 41 void AddListener(MPEGStreamData *data); 42 void RemoveListener(MPEGStreamData *data); 43 44 void RetuneMonitor(void); 45 46 bool IsRunning(void) const { return _running; } 47 bool IsRetuneAllowed(void) const { return _allow_retune; } 48 49 void SetRetuneAllowed(bool allow, 50 DTVSignalMonitor *sigmon, 51 HDHRChannel *dvbchan); 52 53 // ReaderPausedCB 54 virtual void ReaderPaused(int fd) { (void) fd; } 55 56 QString GetTunerStatus(void); 57 58 bool Connected(); 59 bool TuneChannel(QString ); 60 bool TuneProgram(QString ); 61 62 bool EnterPowerSavingMode(); 63 64 private: 65 66 bool FindDevice(); 67 bool Connect(void); 68 69 QString DeviceGet(const QString &name, bool report_error_return = true); 70 QString DeviceSet(const QString &name, const QString &value, 71 bool report_error_return = true); 72 73 QString TunerGet(const QString &name, bool report_error_return = true); 74 QString TunerSet(const QString &name, const QString &value, 75 bool report_error_return = true); 76 77 bool DeviceSetTarget(short unsigned int); 78 bool DeviceClearTarget(); 79 80 HDHRStreamHandler(QString); 81 ~HDHRStreamHandler(); 82 83 bool Open(void); 84 void Close(); 85 86 void Start(void); 87 void Stop(void); 88 89 void Run(void); 90 void RunTS(void); 91 92 void UpdateListeningForEIT(void); 93 bool UpdateFiltersFromStreamData(void); 94 95 // Commands 96 bool AddPID(uint pid, bool do_update = true); 97 bool DelPID(uint pid, bool do_update = true); 98 bool DelAllPIDs(void); 99 bool UpdateFilters(void); 100 101 void SetRunning(bool); 102 103 PIDPriority GetPIDPriority(uint pid) const; 104 bool SupportsTSMonitoring(void); 105 106 private: 107 hdhomerun_control_sock_t *_control_socket; 108 hdhomerun_video_sock_t *_video_socket; 109 uint _device_id; 110 uint _device_ip; 111 uint _tuner; 112 QString _devicename; 113 114 bool _allow_retune; 115 116 mutable QMutex _start_stop_lock; 117 bool _running; 118 QWaitCondition _running_state_changed; 119 pthread_t _reader_thread; 120 DTVSignalMonitor *_sigmon; 121 HDHRChannel *_channel; 122 123 mutable QMutex _pid_lock; 124 vector<uint> _eit_pids; 125 vector<uint> _pid_info; 126 uint _open_pid_filters; 127 MythTimer _cycle_timer; 128 129 mutable QMutex _listener_lock; 130 vector<MPEGStreamData*> _stream_data_list; 131 132 mutable QMutex _hdhr_lock; 133 134 // for caching TS monitoring supported value. 135 static QMutex _rec_supports_ts_monitoring_lock; 136 static QMap<uint,bool> _rec_supports_ts_monitoring; 137 138 // for implementing Get & Return 139 static QMutex _handlers_lock; 140 static QMap<QString, HDHRStreamHandler*> _handlers; 141 static QMap<QString, uint> _handlers_refcnt; 142 }; 143 144 #endif // _HDHRSTREAMHANDLER_H_ -
mythtv/libs/libmythtv/libmythtv.pro
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/libmythtv.pro myth.20018.0218b/mythtv/libs/libmythtv/libmythtv.pro
494 494 using_hdhomerun { 495 495 # MythTV HDHomeRun glue 496 496 HEADERS += hdhrsignalmonitor.h hdhrchannel.h 497 HEADERS += hdhrrecorder.h 497 HEADERS += hdhrrecorder.h hdhrstreamhandler.h 498 498 499 499 SOURCES += hdhrsignalmonitor.cpp hdhrchannel.cpp 500 SOURCES += hdhrrecorder.cpp 500 SOURCES += hdhrrecorder.cpp hdhrstreamhandler.cpp 501 501 502 502 DEFINES += USING_HDHOMERUN 503 503 } -
mythtv/libs/libmythtv/scanwizardscanner.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/scanwizardscanner.cpp myth.20018.0218b/mythtv/libs/libmythtv/scanwizardscanner.cpp
523 523 #ifdef USING_HDHOMERUN 524 524 if ("HDHOMERUN" == card_type) 525 525 { 526 uint tuner = CardUtil::GetHDHRTuner(cardid); 527 channel = new HDHRChannel(NULL, device, tuner); 526 channel = new HDHRChannel(NULL, device); 528 527 } 529 528 #endif // USING_HDHOMERUN 530 529 -
mythtv/libs/libmythtv/tv_rec.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/tv_rec.cpp myth.20018.0218b/mythtv/libs/libmythtv/tv_rec.cpp
177 177 else if (genOpt.cardtype == "HDHOMERUN") 178 178 { 179 179 #ifdef USING_HDHOMERUN 180 channel = new HDHRChannel(this, genOpt.videodev , dboxOpt.port);180 channel = new HDHRChannel(this, genOpt.videodev); 181 181 if (!channel->Open()) 182 182 return false; 183 183 InitChannel(genOpt.defaultinput, startchannel); … … 3504 3504 return; 3505 3505 3506 3506 ClearFlags(kFlagWaitingForRecPause); 3507 #ifdef USING_HDHOMERUN3508 if (GetHDHRRecorder())3509 {3510 // We currently need to close the file descriptor for3511 // HDHomeRun signal monitoring to work.3512 GetHDHRRecorder()->Close();3513 GetHDHRRecorder()->SetRingBuffer(NULL);3514 }3515 #endif // USING_HDHOMERUN3516 3507 VERBOSE(VB_RECORD, LOC + "Recorder paused, calling TuningFrequency"); 3517 3508 TuningFrequency(lastTuningRequest); 3518 3509 } … … 4151 4142 } 4152 4143 recorder->Reset(); 4153 4144 4154 #ifdef USING_HDHOMERUN4155 if (GetHDHRRecorder())4156 {4157 pauseNotify = false;4158 GetHDHRRecorder()->Close();4159 pauseNotify = true;4160 GetHDHRRecorder()->Open();4161 GetHDHRRecorder()->StartData();4162 }4163 #endif // USING_HDHOMERUN4164 4165 4145 // Set file descriptor of channel from recorder for V4L 4166 4146 channel->SetFd(recorder->GetVideoFd()); 4167 4147 -
mythtv/libs/libmythtv/videosource.cpp
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/videosource.cpp myth.20018.0218b/mythtv/libs/libmythtv/videosource.cpp
50 50 51 51 QMutex XMLTVFindGrabbers::list_lock; 52 52 53 #include "hdhomerun_includes.h" 54 53 55 VideoSourceSelector::VideoSourceSelector(uint _initial_sourceid, 54 56 const QString &_card_types, 55 57 bool _must_have_mplexid) : … … 1406 1408 CaptureCard &parent; 1407 1409 }; 1408 1410 1409 class HDHomeRunDeviceID : public LineEditSetting, public CaptureCardDBStorage 1411 class HDHomeRunIP : public TransLabelSetting 1412 { 1413 public: 1414 HDHomeRunIP() 1415 { 1416 setLabel(QObject::tr("IP Address")); 1417 }; 1418 }; 1419 1420 class HDHomeRunTuner : public TransLabelSetting 1421 { 1422 public: 1423 HDHomeRunTuner() 1424 { 1425 setLabel(QObject::tr("Tuner")); 1426 }; 1427 }; 1428 1429 class HDHomeRunDeviceID : public ComboBoxSetting, public CaptureCardDBStorage 1410 1430 { 1411 1431 public: 1412 1432 HDHomeRunDeviceID(const CaptureCard &parent) : 1413 LineEditSetting(this),1433 ComboBoxSetting(this), 1414 1434 CaptureCardDBStorage(this, parent, "videodevice") 1415 1435 { 1416 setValue("FFFFFFFF");1417 1436 setLabel(QObject::tr("Device ID")); 1418 setHelpText(QObject::tr("IP address or Device ID from the bottom of " 1419 "the HDHomeRun. You may use " 1420 "'FFFFFFFF' if there is only one unit " 1421 "on your your network.")); 1437 setHelpText( 1438 QObject::tr("DevicedID and Tuner Number of available HDHomeRun " 1439 "devices. ")); 1440 fillSelections(""); 1441 }; 1442 1443 /// \brief Adds all available device-tuner combinations to list 1444 /// If current is >= 0 it will be considered available even 1445 /// if no device exists for it on the network 1446 void fillSelections(QString current) 1447 { 1448 clearSelections(); 1449 1450 // Get devices from filesystem 1451 vector<QString> devs = CardUtil::ProbeVideoDevices("HDHOMERUN"); 1452 1453 // Add current if needed 1454 if ((current != "") && 1455 (find(devs.begin(), devs.end(), current) == devs.end())) 1456 { 1457 devs.push_back(current); 1458 stable_sort(devs.begin(), devs.end()); 1459 } 1460 1461 vector<QString> db = CardUtil::GetVideoDevices("HDHOMERUN"); 1462 1463 QMap<QString, bool> in_use; 1464 QString sel = current; 1465 for (uint i = 0; i < devs.size(); i++) 1466 { 1467 const QString dev = devs[i]; 1468 in_use[devs[i]] = find(db.begin(), db.end(), dev) != db.end(); 1469 if (sel == "" && !in_use[devs[i]]) 1470 sel = dev; 1471 } 1472 1473 if (sel == "" && devs.size()) 1474 sel = devs[0]; 1475 1476 QString usestr = QString(" -- "); 1477 usestr += QObject::tr("Warning: already in use"); 1478 1479 for (uint i = 0; i < devs.size(); i++) 1480 { 1481 const QString dev = devs[i]; 1482 QString desc = dev + (in_use[devs[i]] ? usestr : ""); 1483 desc = (current == devs[i]) ? dev : desc; 1484 addSelection(desc, dev, dev == sel); 1485 } 1486 } 1487 1488 virtual void Load(void) 1489 { 1490 clearSelections(); 1491 addSelection(""); 1492 1493 CaptureCardDBStorage::Load(); 1494 1495 fillSelections(getValue()); 1422 1496 } 1423 1497 }; 1424 1498 … … 1452 1526 CaptureCard &parent; 1453 1527 }; 1454 1528 1455 class HDHomeRun TunerIndex : public ComboBoxSetting, public CaptureCardDBStorage1529 class HDHomeRunExtra : public ConfigurationWizard 1456 1530 { 1457 1531 public: 1458 HDHomeRunTunerIndex(const CaptureCard &parent) : 1459 ComboBoxSetting(this), 1460 CaptureCardDBStorage(this, parent, "dbox2_port") 1532 HDHomeRunExtra(HDHomeRunConfigurationGroup &parent); 1533 uint GetInstanceCount(void) const 1461 1534 { 1462 setLabel(QObject::tr("Tuner")); 1463 addSelection("0"); 1464 addSelection("1"); 1535 return (uint) count->intValue(); 1465 1536 } 1537 1538 private: 1539 InstanceCount *count; 1466 1540 }; 1467 1541 1468 class HDHomeRunConfigurationGroup : public VerticalConfigurationGroup 1542 HDHomeRunExtra::HDHomeRunExtra(HDHomeRunConfigurationGroup &parent) 1543 : count(new InstanceCount(parent.parent)) 1469 1544 { 1470 public: 1471 HDHomeRunConfigurationGroup(CaptureCard& a_parent) : 1472 VerticalConfigurationGroup(false, true, false, false), 1473 parent(a_parent) 1474 { 1475 setUseLabel(false); 1476 addChild(new HDHomeRunDeviceID(parent)); 1477 addChild(new HDHomeRunTunerIndex(parent)); 1478 addChild(new SignalTimeout(parent, 1000, 250)); 1479 addChild(new ChannelTimeout(parent, 3000, 1750)); 1480 addChild(new SingleCardInput(parent)); 1481 }; 1545 VerticalConfigurationGroup* rec = new VerticalConfigurationGroup(false); 1546 rec->setLabel(QObject::tr("Recorder Options")); 1547 rec->setUseLabel(false); 1548 1549 rec->addChild(count); 1550 1551 addChild(rec); 1552 } 1553 1554 HDHomeRunConfigurationGroup::HDHomeRunConfigurationGroup(CaptureCard& a_parent) : 1555 VerticalConfigurationGroup(false, true, false, false), 1556 parent(a_parent) 1557 { 1558 setUseLabel(false); 1559 deviceid = new HDHomeRunDeviceID(parent); 1560 addChild(deviceid); 1561 cardip = new HDHomeRunIP(); 1562 cardtuner = new HDHomeRunTuner(); 1563 1564 addChild(cardip); 1565 addChild(cardtuner); 1566 1567 addChild(new SignalTimeout(parent, 1000, 250)); 1568 addChild(new ChannelTimeout(parent, 3000, 1750)); 1569 addChild(new SingleCardInput(parent)); 1570 1571 TransButtonSetting *buttonRecOpt = new TransButtonSetting(); 1572 buttonRecOpt->setLabel(tr("Recording Options")); 1573 addChild(buttonRecOpt); 1574 1575 connect(deviceid, SIGNAL(valueChanged(const QString&)), 1576 this, SLOT( probeCard (const QString&))); 1577 connect(buttonRecOpt, SIGNAL(pressed()), 1578 this, SLOT( HDHomeRunExtraPanel())); 1579 1482 1580 1483 private:1484 CaptureCard &parent;1485 1581 }; 1486 1582 1583 void HDHomeRunConfigurationGroup::probeCard(const QString& deviceid) 1584 { 1585 hdhomerun_device_t* thisdevice = hdhomerun_device_create_from_str(deviceid.toLocal8Bit().constData()); 1586 1587 if (thisdevice) 1588 { 1589 uint device_ip = hdhomerun_device_get_device_ip(thisdevice); 1590 uint tuner = hdhomerun_device_get_tuner(thisdevice); 1591 hdhomerun_device_destroy(thisdevice); 1592 1593 QString ip = QString("%1.%2.%3.%4") 1594 .arg((device_ip>>24) & 0xFF).arg((device_ip>>16) & 0xFF) 1595 .arg((device_ip>> 8) & 0xFF).arg((device_ip>> 0) & 0xFF); 1596 1597 cardip->setValue(ip); 1598 cardtuner->setValue(QString("%1").arg(tuner)); 1599 } 1600 else 1601 { 1602 cardip->setValue("Unknown"); 1603 cardtuner->setValue("Unknown"); 1604 } 1605 } 1606 1607 void HDHomeRunConfigurationGroup::HDHomeRunExtraPanel(void) 1608 { 1609 parent.reload(); // ensure card id is valid 1610 1611 HDHomeRunExtra acw(*this); 1612 acw.exec(); 1613 parent.SetInstanceCount(acw.GetInstanceCount()); 1614 } 1615 1616 1487 1617 V4LConfigurationGroup::V4LConfigurationGroup(CaptureCard& a_parent) : 1488 1618 VerticalConfigurationGroup(false, true, false, false), 1489 1619 parent(a_parent), … … 1697 1827 if ((cardtype.toLower() == "dvb") && (1 != ++device_refs[videodevice])) 1698 1828 continue; 1699 1829 1830 if ((cardtype.toLower() == "hdhomerun") && (1 != ++device_refs[videodevice])) 1831 continue; 1832 1700 1833 QString label = CardUtil::GetDeviceLabel( 1701 1834 cardid, cardtype, videodevice); 1702 1835 … … 2839 2972 if ((cardtype.toLower() == "dvb") && (1 != ++device_refs[videodevice])) 2840 2973 continue; 2841 2974 2975 if ((cardtype.toLower() == "hdhomerun") && (1 != ++device_refs[videodevice])) 2976 continue; 2977 2842 2978 QStringList inputLabels; 2843 2979 vector<CardInput*> cardInputs; 2844 2980 -
mythtv/libs/libmythtv/videosource.h
diff -r -u -N -X diff.exclude -x myth.20018.0218a -x myth.20018.0218b myth.20018.0218a/mythtv/libs/libmythtv/videosource.h myth.20018.0218b/mythtv/libs/libmythtv/videosource.h
530 530 DiSEqCDevTree *diseqc_tree; 531 531 }; 532 532 533 class HDHomeRunDeviceID; 534 class HDHomeRunIP; 535 class HDHomeRunTuner; 536 class HDHomeRunConfigurationGroup : public VerticalConfigurationGroup 537 { 538 friend class HDHomeRunExtra; 539 540 Q_OBJECT 541 public: 542 HDHomeRunConfigurationGroup(CaptureCard& a_parent); 543 544 public slots: 545 void probeCard(const QString& deviceid); 546 void HDHomeRunExtraPanel(void); 547 548 private: 549 HDHomeRunDeviceID *deviceid; 550 HDHomeRunIP *cardip; 551 HDHomeRunTuner *cardtuner; 552 553 CaptureCard &parent; 554 }; 555 556 533 557 class FirewireGUID; 534 558 class FirewireModel : public ComboBoxSetting, public CaptureCardDBStorage 535 559 {