Ticket #6138: 133-hdhr.multirec.9.patch
File 133-hdhr.multirec.9.patch, 84.4 KB (added by , 17 years ago) |
---|
-
mythtv/libs/libmythtv/cardutil.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/cardutil.cpp release.20085.0302a/mythtv/libs/libmythtv/cardutil.cpp
28 28 #include "videodev_myth.h" 29 29 #endif 30 30 31 #include "hdhomerun_includes.h" 32 31 33 #define LOC QString("CardUtil: ") 32 34 #define LOC_WARN QString("CardUtil, Warning: ") 33 35 #define LOC_ERR QString("CardUtil, Error: ") … … 197 199 for (uint i = 0; i < list.size(); i++) 198 200 devs.push_back(QString::number(list[i])); 199 201 } 202 else if (rawtype.upper() == "HDHOMERUN") 203 { 204 205 uint32_t target_ip = 0; 206 uint32_t device_type = HDHOMERUN_DEVICE_TYPE_TUNER; 207 uint32_t device_id = HDHOMERUN_DEVICE_ID_WILDCARD; 208 const int max_count = 50; 209 hdhomerun_discover_device_t result_list[max_count]; 210 211 int result = hdhomerun_discover_find_devices_custom( 212 target_ip, 213 device_type, 214 device_id, 215 result_list, 216 max_count); 217 218 if (result == -1) 219 { 220 VERBOSE(VB_IMPORTANT, "CardUtil::ProbeVideoDevices: Error finding HDHomerun devices"); 221 return devs; 222 } 223 224 if (result == 20) 225 VERBOSE(VB_IMPORTANT, "CardUtil::ProbeVideoDevices: Warning: may be > 20 HDHomerun devices"); 226 227 // Fixme -- figure out some way to return ip address as well 228 for (int i = 0; i < result; i++) 229 { 230 QString did = QString("%1").arg(result_list[i].device_id,0, 16); 231 did=did.upper(); 232 233 devs.push_back(did + "-0"); 234 devs.push_back(did + "-1"); 235 } 236 } 200 237 else 201 238 { 202 239 VERBOSE(VB_IMPORTANT, QString("CardUtil::ProbeVideoDevices: ") + … … 1023 1060 uint id = 0; 1024 1061 for (uint i = 0; !id && (i < 100); i++) 1025 1062 { 1026 name = QString("DVB%1").arg(dev.toUInt()); 1063 bool ok; 1064 name = QString("DVB%1").arg(dev.toUInt(&ok)); 1065 if (! ok) 1066 { 1067 name = QString("HDHR_%1").arg(dev); 1068 } 1027 1069 name += (i) ? QString(":%1").arg(i) : QString(""); 1028 1070 id = CardUtil::CreateInputGroup(name); 1029 1071 } … … 1548 1590 } 1549 1591 else if (cardtype == "HDHOMERUN") 1550 1592 { 1551 MSqlQuery query(MSqlQuery::InitCon()); 1552 query.prepare( 1553 "SELECT dbox2_port " 1554 "FROM capturecard " 1555 "WHERE cardid = :CARDID"); 1556 query.bindValue(":CARDID", cardid); 1557 1558 if (!query.exec() || !query.isActive() || !query.next()) 1559 label = "[ DB ERROR ]"; 1560 else 1561 label = QString("[ HDHomeRun : ID %1 Port %2 ]") 1562 .arg(videodevice).arg(query.value(0).toString()); 1593 label = QString("[ HDHomeRun : %1 ]").arg(videodevice); 1563 1594 } 1564 1595 else 1565 1596 { -
mythtv/libs/libmythtv/cardutil.h
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/cardutil.h release.20085.0302a/mythtv/libs/libmythtv/cardutil.h
106 106 107 107 static bool IsTunerSharingCapable(const QString &rawtype) 108 108 { 109 return (rawtype == "DVB") ;109 return (rawtype == "DVB") || (rawtype == "HDHOMERUN"); 110 110 } 111 111 112 112 static bool IsTunerShared(uint cardidA, uint cardidB); -
mythtv/libs/libmythtv/hdhomerun_includes.h
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhomerun_includes.h release.20085.0302a/mythtv/libs/libmythtv/hdhomerun_includes.h
1 #ifndef __HDHOMERUN_INCLUDES__ 2 #define __HDHOMERUN_INCLUDES__ 3 4 #include "hdhomerun/hdhomerun.h" 5 6 #endif /* __HDHOMERUN_INCLUDES__ */ 7 -
mythtv/libs/libmythtv/hdhrchannel.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrchannel.cpp release.20085.0302a/mythtv/libs/libmythtv/hdhrchannel.cpp
25 25 #include "videosource.h" 26 26 #include "channelutil.h" 27 27 28 #include "hdhrstreamhandler.h" 29 28 30 #define DEBUG_PID_FILTERS 29 31 30 32 #define LOC QString("HDHRChan(%1): ").arg(GetDevice()) 31 33 #define LOC_ERR QString("HDHRChan(%1), Error: ").arg(GetDevice()) 32 34 33 HDHRChannel::HDHRChannel(TVRec *parent, const QString &device, uint tuner) 34 : DTVChannel(parent), _control_socket(NULL), 35 _device_id(0), _device_ip(0), 36 _tuner(tuner), _lock(true) 37 { 38 bool valid; 39 _device_id = device.toUInt(&valid, 16); 40 41 if (valid && hdhomerun_discover_validate_device_id(_device_id)) 42 return; 43 44 _device_id = HDHOMERUN_DEVICE_ID_WILDCARD; 45 /* Otherwise, is it a valid IP address? */ 46 struct in_addr address; 47 if (inet_aton(device, &address)) 48 { 49 _device_ip = ntohl(address.s_addr); 50 return; 51 } 52 53 /* Invalid, use wildcard device ID. */ 54 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Invalid DeviceID '%1'") 55 .arg(device)); 56 57 _device_id = HDHOMERUN_DEVICE_ID_WILDCARD; 35 HDHRChannel::HDHRChannel(TVRec *parent, const QString &device) 36 : DTVChannel(parent), _stream_handler(NULL), 37 _device_id(device), _lock(true), 38 tune_lock(true), hw_lock(true) 39 { 58 40 } 59 41 60 42 HDHRChannel::~HDHRChannel(void) … … 64 46 65 47 bool HDHRChannel::Open(void) 66 48 { 49 VERBOSE(VB_CHANNEL, LOC + "Opening HDHR channel"); 50 51 QMutexLocker locker(&hw_lock); 52 67 53 if (IsOpen()) 68 54 return true; 69 55 70 if (!FindDevice()) 71 return false; 56 _stream_handler = HDHRStreamHandler::Get(_device_id); 72 57 73 58 if (!InitializeInputs()) 74 return false;75 76 return (_device_ip != 0) && Connect();77 }78 79 void HDHRChannel::Close(void)80 {81 if (_control_socket)82 {83 hdhomerun_control_destroy(_control_socket);84 _control_socket = NULL;85 }86 }87 88 bool HDHRChannel::EnterPowerSavingMode(void)89 {90 return QString::null != TunerSet("channel", "none", false);91 }92 93 bool HDHRChannel::FindDevice(void)94 {95 if (!_device_id)96 return _device_ip;97 98 _device_ip = 0;99 100 /* Discover. */101 struct hdhomerun_discover_device_t result;102 int ret = hdhomerun_discover_find_devices_custom(0, HDHOMERUN_DEVICE_TYPE_WILDCARD, _device_id, &result, 1);103 if (ret < 0)104 {105 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to send discovery request" + ENO);106 return false;107 }108 if (ret == 0)109 59 { 110 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("device not found"));60 Close(); 111 61 return false; 112 62 } 113 63 114 /* Found. */ 115 _device_ip = result.ip_addr; 64 // nextInputID = currentInputID; 116 65 117 VERBOSE(VB_IMPORTANT, LOC + 118 QString("device found at address %1.%2.%3.%4") 119 .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF) 120 .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF)); 66 return _stream_handler->Connected(); 121 67 122 return true;123 68 } 124 69 125 bool HDHRChannel::Connect(void)70 void HDHRChannel::Close() 126 71 { 127 _control_socket = hdhomerun_control_create(_device_id, _device_ip); 128 if (!_control_socket) 129 { 130 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create control socket"); 131 return false; 132 } 72 VERBOSE(VB_CHANNEL, LOC + "Closing HDHR channel"); 133 73 134 if (hdhomerun_control_get_local_addr(_control_socket) == 0) 135 { 136 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to connect to device"); 137 return false; 138 } 74 if (! IsOpen()) 75 return; // this caller didn't have it open in the first place.. 139 76 140 VERBOSE(VB_CHANNEL, LOC + "Successfully connected to device"); 141 return true; 77 HDHRStreamHandler::Return(_stream_handler); 142 78 } 143 79 144 QString HDHRChannel::DeviceGet(const QString &name, bool report_error_return) 145 { 146 QMutexLocker locker(&_lock); 147 148 if (!_control_socket) 149 { 150 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (not connected)"); 151 return QString::null; 152 } 153 154 char *value = NULL; 155 char *error = NULL; 156 if (hdhomerun_control_get(_control_socket, name, &value, &error) < 0) 157 { 158 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed" + ENO); 159 return QString::null; 160 } 161 162 if (report_error_return && error) 163 { 164 VERBOSE(VB_IMPORTANT, LOC_ERR + 165 QString("DeviceGet(%1): %2").arg(name).arg(error)); 166 167 return QString::null; 168 } 169 170 return QString(value); 171 } 172 173 QString HDHRChannel::DeviceSet(const QString &name, const QString &val, 174 bool report_error_return) 80 bool HDHRChannel::EnterPowerSavingMode(void) 175 81 { 176 QMutexLocker locker(&_lock); 177 178 if (!_control_socket) 179 { 180 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (not connected)"); 181 return QString::null; 182 } 183 184 char *value = NULL; 185 char *error = NULL; 186 if (hdhomerun_control_set(_control_socket, name, val, &value, &error) < 0) 187 { 188 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed" + ENO); 189 190 return QString::null; 191 } 192 193 if (report_error_return && error) 194 { 195 VERBOSE(VB_IMPORTANT, LOC_ERR + 196 QString("DeviceSet(%1 %2): %3").arg(name).arg(val).arg(error)); 197 198 return QString::null; 199 } 200 201 return QString(value); 82 if ( IsOpen()) 83 return _stream_handler->EnterPowerSavingMode(); 84 else 85 return true; 202 86 } 203 87 204 QString HDHRChannel::TunerGet(const QString &name, bool report_error_return)205 {206 return DeviceGet(QString("/tuner%1/%2").arg(_tuner).arg(name),207 report_error_return);208 }209 88 210 QString HDHRChannel::TunerSet(const QString &name, const QString &value, 211 bool report_error_return) 89 bool HDHRChannel::IsOpen(void) const 212 90 { 213 return DeviceSet(QString("/tuner%1/%2").arg(_tuner).arg(name), value, 214 report_error_return); 91 return (_stream_handler != NULL); 215 92 } 216 93 217 bool HDHRChannel:: DeviceSetTarget(unsigned short localPort)94 bool HDHRChannel::Init(QString &inputname, QString &startchannel, bool setchan) 218 95 { 219 if (localPort == 0) 220 { 221 return false; 222 } 96 if (setchan && !IsOpen()) 97 Open(); 223 98 224 unsigned long localIP = hdhomerun_control_get_local_addr(_control_socket); 225 if (localIP == 0) 226 { 227 return false; 228 } 229 230 QString configValue = QString("%1.%2.%3.%4:%5") 231 .arg((localIP >> 24) & 0xFF).arg((localIP >> 16) & 0xFF) 232 .arg((localIP >> 8) & 0xFF).arg((localIP >> 0) & 0xFF) 233 .arg(localPort); 234 235 if (!TunerSet("target", configValue)) 236 { 237 return false; 238 } 239 240 return true; 241 } 242 243 bool HDHRChannel::DeviceClearTarget() 244 { 245 return TunerSet("target", "0.0.0.0:0"); 99 return ChannelBase::Init(inputname, startchannel, setchan); 246 100 } 247 101 248 102 bool HDHRChannel::SetChannelByString(const QString &channum) … … 276 130 return SwitchToInput(inputName, channum); 277 131 278 132 ClearDTVInfo(); 279 _ignore_filters = false;280 133 281 134 InputMap::const_iterator it = inputs.find(currentInputID); 282 135 if (it == inputs.end()) … … 348 201 if (mpeg_prog_num && (GetTuningMode() == "mpeg")) 349 202 { 350 203 QString pnum = QString::number(mpeg_prog_num); 351 _ignore_filters = QString::null != TunerSet("program", pnum, false); 204 //_ignore_filters = _stream_handler->TuneProgram(pnum); 205 _stream_handler->TuneProgram(pnum); 352 206 } 353 207 354 208 return true; … … 402 256 403 257 VERBOSE(VB_CHANNEL, LOC + "Tune()ing to " + chan); 404 258 405 if ( TunerSet("channel", chan).length())259 if (_stream_handler->TuneChannel(chan)) 406 260 { 407 261 SetSIStandard(si_std); 408 262 return true; … … 410 264 411 265 return false; 412 266 } 413 414 bool HDHRChannel::AddPID(uint pid, bool do_update)415 {416 QMutexLocker locker(&_lock);417 418 vector<uint>::iterator it;419 it = lower_bound(_pids.begin(), _pids.end(), pid);420 if (it != _pids.end() && *it == pid)421 {422 #ifdef DEBUG_PID_FILTERS423 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<") NOOP");424 #endif // DEBUG_PID_FILTERS425 return true;426 }427 428 _pids.insert(it, pid);429 430 #ifdef DEBUG_PID_FILTERS431 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<")");432 #endif // DEBUG_PID_FILTERS433 434 if (do_update)435 return UpdateFilters();436 return true;437 }438 439 bool HDHRChannel::DelPID(uint pid, bool do_update)440 {441 QMutexLocker locker(&_lock);442 443 vector<uint>::iterator it;444 it = lower_bound(_pids.begin(), _pids.end(), pid);445 if (it == _pids.end())446 {447 #ifdef DEBUG_PID_FILTERS448 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") NOOP");449 #endif // DEBUG_PID_FILTERS450 451 return true;452 }453 454 if (*it == pid)455 {456 #ifdef DEBUG_PID_FILTERS457 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") -- found");458 #endif // DEBUG_PID_FILTERS459 _pids.erase(it);460 }461 else462 {463 #ifdef DEBUG_PID_FILTERS464 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<") -- failed");465 #endif // DEBUG_PID_FILTERS466 }467 468 if (do_update)469 return UpdateFilters();470 return true;471 }472 473 bool HDHRChannel::DelAllPIDs(void)474 {475 QMutexLocker locker(&_lock);476 477 #ifdef DEBUG_PID_FILTERS478 VERBOSE(VB_CHANNEL, "DelAllPID()");479 #endif // DEBUG_PID_FILTERS480 481 _pids.clear();482 483 return UpdateFilters();484 }485 486 QString filt_str(uint pid)487 {488 uint pid0 = (pid / (16*16*16)) % 16;489 uint pid1 = (pid / (16*16)) % 16;490 uint pid2 = (pid / (16)) % 16;491 uint pid3 = pid % 16;492 return QString("0x%1%2%3%4")493 .arg(pid0,0,16).arg(pid1,0,16)494 .arg(pid2,0,16).arg(pid3,0,16);495 }496 497 bool HDHRChannel::UpdateFilters(void)498 {499 QMutexLocker locker(&_lock);500 501 QString filter = "";502 503 vector<uint> range_min;504 vector<uint> range_max;505 506 if (_ignore_filters)507 return true;508 509 for (uint i = 0; i < _pids.size(); i++)510 {511 uint pid_min = _pids[i];512 uint pid_max = pid_min;513 for (uint j = i + 1; j < _pids.size(); j++)514 {515 if (pid_max + 1 != _pids[j])516 break;517 pid_max++;518 i++;519 }520 range_min.push_back(pid_min);521 range_max.push_back(pid_max);522 }523 524 if (range_min.size() > 16)525 {526 range_min.resize(16);527 uint pid_max = range_max.back();528 range_max.resize(15);529 range_max.push_back(pid_max);530 }531 532 for (uint i = 0; i < range_min.size(); i++)533 {534 filter += filt_str(range_min[i]);535 if (range_min[i] != range_max[i])536 filter += QString("-%1").arg(filt_str(range_max[i]));537 filter += " ";538 }539 540 filter = filter.stripWhiteSpace();541 542 QString new_filter = TunerSet("filter", filter);543 544 #ifdef DEBUG_PID_FILTERS545 QString msg = QString("Filter: '%1'").arg(filter);546 if (filter != new_filter)547 msg += QString("\n\t\t\t\t'%2'").arg(new_filter);548 549 VERBOSE(VB_CHANNEL, msg);550 #endif // DEBUG_PID_FILTERS551 552 return filter == new_filter;553 } -
mythtv/libs/libmythtv/hdhrchannel.h
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrchannel.h release.20085.0302a/mythtv/libs/libmythtv/hdhrchannel.h
15 15 16 16 // HDHomeRun headers 17 17 #ifdef USING_HDHOMERUN 18 #include "hdhomerun/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/hdhrrecorder.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrrecorder.cpp release.20085.0302a/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 "dvbstreamdata.h" 31 29 #include "eithelper.h" 32 30 #include "tv_rec.h" 33 31 32 // MythTV HDHR includes 33 #include "hdhrchannel.h" 34 #include "hdhrrecorder.h" 35 #include "hdhrstreamhandler.h" 36 34 37 #define LOC QString("HDHRRec(%1): ").arg(tvrec->GetCaptureCardNum()) 38 #define LOC_WARN QString("HDHRRec(%1), Warning: ") \ 39 .arg(tvrec->GetCaptureCardNum()) 35 40 #define LOC_ERR QString("HDHRRec(%1), Error: ") \ 36 41 .arg(tvrec->GetCaptureCardNum()) 37 42 38 43 HDHRRecorder::HDHRRecorder(TVRec *rec, HDHRChannel *channel) 39 44 : DTVRecorder(rec), 40 _channel(channel), _video_socket(NULL), 45 _channel(channel), 46 _stream_handler(NULL), 41 47 _stream_data(NULL), 42 _input_pat(NULL), _input_pmt(NULL), 43 _reset_pid_filters(false),_pid_lock(true) 48 _pid_lock(true), 49 _input_pat(NULL), 50 _input_pmt(NULL), 51 _has_no_av(false) 44 52 { 45 53 } 46 54 … … 91 99 // HACK -- end 92 100 } 93 101 102 bool HDHRRecorder::IsOpen(void) { 103 return (_stream_handler != NULL); 104 } 105 94 106 bool HDHRRecorder::Open(void) 95 107 { 96 108 VERBOSE(VB_RECORD, LOC + "Open()"); 97 if ( _video_socket)109 if (IsOpen()) 98 110 { 99 111 VERBOSE(VB_RECORD, LOC + "Card already open (recorder)"); 100 112 return true; 101 113 } 102 114 103 /* Calculate buffer size */ 104 uint buffersize = gContext->GetNumSetting( 105 "HDRingbufferSize", 50 * TSPacket::SIZE) * 1024; 106 buffersize /= VIDEO_DATA_PACKET_SIZE; 107 buffersize *= VIDEO_DATA_PACKET_SIZE; 115 bzero(_stream_id, sizeof(_stream_id)); 116 bzero(_pid_status, sizeof(_pid_status)); 117 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 108 118 109 // Buffer should be at least about 1MB.. 110 buffersize = max(49 * TSPacket::SIZE * 128, buffersize); 119 _stream_handler = HDHRStreamHandler::Get(_channel->GetDevice()); 111 120 112 /* Create TS socket. */ 113 _video_socket = hdhomerun_video_create(0, buffersize); 114 if (!_video_socket) 115 { 116 VERBOSE(VB_IMPORTANT, LOC + "Open() failed to open socket"); 117 return false; 118 } 121 VERBOSE(VB_RECORD, LOC + "HDHR opened successfully"); 119 122 120 /* Success. */121 123 return true; 122 124 } 123 125 124 /** \fn HDHRRecorder::StartData(void)125 * \brief Configure device to send video.126 */127 bool HDHRRecorder::StartData(void)128 {129 VERBOSE(VB_RECORD, LOC + "StartData()");130 uint localPort = hdhomerun_video_get_local_port(_video_socket);131 return _channel->DeviceSetTarget(localPort);132 }133 134 126 void HDHRRecorder::Close(void) 135 127 { 136 VERBOSE(VB_RECORD, LOC + "Close()"); 137 if (_video_socket) 138 { 139 hdhomerun_video_destroy(_video_socket); 140 _video_socket = NULL; 141 } 142 } 143 144 void HDHRRecorder::ProcessTSData(const uint8_t *buffer, int len) 145 { 146 QMutexLocker locker(&_pid_lock); 147 const uint8_t *data = buffer; 148 const uint8_t *end = buffer + len; 128 VERBOSE(VB_RECORD, LOC + "Close() - Begin"); 149 129 150 while (data + 188 <= end)130 if (IsOpen()) 151 131 { 152 if (data[0] != 0x47) 153 { 154 return; 155 } 156 157 const TSPacket *tspacket = reinterpret_cast<const TSPacket*>(data); 158 ProcessTSPacket(*tspacket); 159 160 data += 188; 132 HDHRStreamHandler::Return(_stream_handler); 161 133 } 134 135 VERBOSE(VB_RECORD, LOC + "Close() - End"); 162 136 } 163 137 164 138 void HDHRRecorder::SetStreamData(MPEGStreamData *data) … … 220 194 ProgramAssociationTable *oldpat = _input_pat; 221 195 _input_pat = new ProgramAssociationTable(*_pat); 222 196 delete oldpat; 223 224 _reset_pid_filters = true;225 197 } 226 198 227 199 void HDHRRecorder::HandlePMT(uint progNum, const ProgramMapTable *_pmt) … … 233 205 VERBOSE(VB_RECORD, LOC + "SetPMT("<<progNum<<")"); 234 206 ProgramMapTable *oldpmt = _input_pmt; 235 207 _input_pmt = new ProgramMapTable(*_pmt); 236 delete oldpmt;237 208 238 _reset_pid_filters = true; 209 QString sistandard = _channel->GetSIStandard(); 210 211 bool has_no_av = true; 212 for (uint i = 0; i < _input_pmt->StreamCount() && has_no_av; i++) 213 { 214 has_no_av &= !_input_pmt->IsVideo(i, sistandard); 215 has_no_av &= !_input_pmt->IsAudio(i, sistandard); 216 } 217 _has_no_av = has_no_av; 218 219 _channel->SetPMT(_input_pmt); 220 delete oldpmt; 239 221 } 240 222 } 241 223 … … 246 228 247 229 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 248 230 pat->tsheader()->SetContinuityCounter(next); 249 BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader())));231 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader()))); 250 232 } 251 233 252 234 void HDHRRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 253 235 { 254 236 if (!pmt) 237 { 238 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)"); 239 return; 240 } 241 242 // collect stream types for H.264 (MPEG-4 AVC) keyframe detection 243 for (uint i = 0; i < pmt->StreamCount(); i++) 244 _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i); 245 246 if (!ringBuffer) 255 247 return; 256 248 257 249 unsigned char buf[8 * 1024]; … … 259 251 pmt->tsheader()->SetContinuityCounter(next_cc); 260 252 uint size = pmt->WriteAsTSPackets(buf, next_cc); 261 253 254 uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 255 262 256 for (uint i = 0; i < size ; i += TSPacket::SIZE) 263 257 DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 258 259 uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 260 261 if (posB[0] + posB[1] * TSPacket::SIZE > 262 posA[0] + posA[1] * TSPacket::SIZE) 263 { 264 VERBOSE(VB_RECORD, LOC + "Wrote PMT @" 265 << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 266 } 267 else 268 { 269 VERBOSE(VB_RECORD, LOC + "Saw PMT but did not write to disk yet"); 270 } 264 271 } 265 272 266 273 /** \fn HDHRRecorder::HandleMGT(const MasterGuideTable*) … … 280 287 } 281 288 */ 282 289 290 bool HDHRRecorder::ProcessVideoTSPacket(const TSPacket &tspacket) 291 { 292 uint streamType = _stream_id[tspacket.PID()]; 293 294 // Check for keyframes and count frames 295 if (streamType == StreamID::H264Video) 296 { 297 _buffer_packets = !FindH264Keyframes(&tspacket); 298 if (!_seen_sps) 299 return true; 300 } 301 else 302 { 303 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 304 } 305 306 return ProcessAVTSPacket(tspacket); 307 } 308 309 bool HDHRRecorder::ProcessAudioTSPacket(const TSPacket &tspacket) 310 { 311 _buffer_packets = !FindAudioKeyframes(&tspacket); 312 return ProcessAVTSPacket(tspacket); 313 } 314 315 /// Common code for processing either audio or video packets 316 bool HDHRRecorder::ProcessAVTSPacket(const TSPacket &tspacket) 317 { 318 const uint pid = tspacket.PID(); 319 // Sync recording start to first keyframe 320 if (_wait_for_keyframe_option && _first_keyframe < 0) 321 return true; 322 323 // Sync streams to the first Payload Unit Start Indicator 324 // _after_ first keyframe iff _wait_for_keyframe_option is true 325 if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload()) 326 { 327 if (!tspacket.PayloadStart()) 328 return true; // not payload start - drop packet 329 330 VERBOSE(VB_RECORD, 331 QString("PID 0x%1 Found Payload Start").arg(pid,0,16)); 332 333 _pid_status[pid] |= kPayloadStartSeen; 334 } 335 336 BufferedWrite(tspacket); 337 338 return true; 339 } 340 283 341 bool HDHRRecorder::ProcessTSPacket(const TSPacket& tspacket) 284 342 { 285 bool ok = !tspacket.TransportError();286 if ( ok && !tspacket.ScramplingControl())343 // Only create fake keyframe[s] if there are no audio/video streams 344 if (_input_pmt && _has_no_av) 287 345 { 288 if (tspacket.HasAdaptationField()) 289 GetStreamData()->HandleAdaptationFieldControl(&tspacket); 290 if (tspacket.HasPayload()) 291 { 292 const unsigned int lpid = tspacket.PID(); 346 _buffer_packets = !FindOtherKeyframes(&tspacket); 347 } 348 else 349 { 350 // There are audio/video streams. Only write the packet 351 // if audio/video key-frames have been found 352 if (_wait_for_keyframe_option && _first_keyframe < 0) 353 return true; 293 354 294 if ((GetStreamData()->VideoPIDSingleProgram() > 0x1fff) && 295 _wait_for_keyframe_option) 296 { 297 _wait_for_keyframe_option = false; 298 } 299 300 // Pass or reject frames based on PID, and parse info from them 301 if (lpid == GetStreamData()->VideoPIDSingleProgram()) 302 { 303 //cerr<<"v"; 304 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 305 BufferedWrite(tspacket); 306 } 307 else if (GetStreamData()->IsAudioPID(lpid)) 308 { 309 //cerr<<"a"; 310 _buffer_packets = !FindAudioKeyframes(&tspacket); 311 BufferedWrite(tspacket); 312 } 313 else if (GetStreamData()->IsListeningPID(lpid)) 314 { 315 //cerr<<"t"; 316 GetStreamData()->HandleTSTables(&tspacket); 317 } 318 else if (GetStreamData()->IsWritingPID(lpid)) 319 BufferedWrite(tspacket); 320 } 355 _buffer_packets = true; 321 356 } 322 return ok; 357 358 BufferedWrite(tspacket); 323 359 } 324 360 325 361 void HDHRRecorder::StartRecording(void) … … 337 373 _request_recording = true; 338 374 _recording = true; 339 375 340 if (!StartData())341 {342 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting recording "343 "(set target failed). Aborting.");344 Close();345 _error = true;346 VERBOSE(VB_RECORD, LOC + "StartRecording -- end 2"); 347 return;348 }349 350 hdhomerun_video_flush(_video_socket);376 // Make sure the first things in the file are a PAT & PMT 377 bool tmp = _wait_for_keyframe_option; 378 _wait_for_keyframe_option = false; 379 HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 380 HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 381 _wait_for_keyframe_option = tmp; 382 383 _stream_data->AddAVListener(this); 384 _stream_data->AddWritingListener(this); 385 _stream_handler->AddListener(_stream_data); 386 351 387 while (_request_recording && !_error) 352 388 { 389 usleep(50000); 390 353 391 if (PauseAndWait()) 354 392 continue; 355 393 356 if ( _stream_data)394 if (!_input_pmt) 357 395 { 358 QMutexLocker read_lock(&_pid_lock); 359 _reset_pid_filters |= _stream_data->HasEITPIDChanges(_eit_pids); 396 VERBOSE(VB_GENERAL, LOC_WARN + 397 "Recording will not commence until a PMT is set."); 398 usleep(5000); 399 continue; 360 400 } 361 401 362 if ( _reset_pid_filters)402 if (!_stream_handler->IsRunning()) 363 403 { 364 _reset_pid_filters = false; 365 VERBOSE(VB_RECORD, LOC + "Resetting Demux Filters"); 366 AdjustFilters(); 367 } 404 _error = true; 368 405 369 size_t read_size = 64 * 1024; // read about 64KB 370 read_size /= VIDEO_DATA_PACKET_SIZE; 371 read_size *= VIDEO_DATA_PACKET_SIZE; 372 373 size_t data_length; 374 unsigned char *data_buffer = 375 hdhomerun_video_recv(_video_socket, read_size, &data_length); 376 if (!data_buffer) 377 { 378 usleep(5000); 379 continue; 380 } 381 382 ProcessTSData(data_buffer, data_length); 406 VERBOSE(VB_IMPORTANT, LOC_ERR + 407 "Stream handler died unexpectedly."); 408 } 383 409 } 384 410 385 411 VERBOSE(VB_RECORD, LOC + "StartRecording -- ending..."); 386 412 387 _channel->DeviceClearTarget(); 413 _stream_handler->RemoveListener(_stream_data); 414 _stream_data->RemoveWritingListener(this); 415 _stream_data->RemoveAVListener(this); 416 388 417 Close(); 389 418 390 419 FinishRecording(); … … 393 422 VERBOSE(VB_RECORD, LOC + "StartRecording -- end"); 394 423 } 395 424 396 bool HDHRRecorder::AdjustFilters(void)425 void HDHRRecorder::ResetForNewFile(void) 397 426 { 398 QMutexLocker change_lock(&_pid_lock);427 DTVRecorder::ResetForNewFile(); 399 428 400 if (!_channel) 401 { 402 VERBOSE(VB_IMPORTANT, LOC_ERR + "AdjustFilters() no channel"); 403 return false; 404 } 429 bzero(_stream_id, sizeof(_stream_id)); 430 bzero(_pid_status, sizeof(_pid_status)); 431 memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 405 432 406 if (!_input_pat || !_input_pmt) 407 { 408 VERBOSE(VB_IMPORTANT, LOC + "AdjustFilters() no pmt or no pat"); 409 return false; 410 } 411 412 uint_vec_t add_pid; 433 // FIXME 434 // Close and re-open ??? 435 //Close(); 436 //Open(); 437 } 413 438 414 add_pid.push_back(MPEG_PAT_PID); 415 _stream_data->AddListeningPID(MPEG_PAT_PID); 439 void HDHRRecorder::StopRecording(void) 440 { 441 _request_recording = false; 442 while (_recording) 443 usleep(2000); 444 } 416 445 417 for (uint i = 0; i < _input_pat->ProgramCount(); i++) 446 bool HDHRRecorder::PauseAndWait(int timeout) 447 { 448 if (request_pause) 418 449 { 419 add_pid.push_back(_input_pat->ProgramPID(i)); 420 _stream_data->AddListeningPID(_input_pat->ProgramPID(i)); 421 } 450 if (!paused) 451 { 452 assert(_stream_handler); 453 assert(_stream_data); 422 454 423 // Record the streams in the PMT... 424 bool need_pcr_pid = true; 425 for (uint i = 0; i < _input_pmt->StreamCount(); i++) 426 { 427 add_pid.push_back(_input_pmt->StreamPID(i)); 428 need_pcr_pid &= (_input_pmt->StreamPID(i) != _input_pmt->PCRPID()); 429 _stream_data->AddWritingPID(_input_pmt->StreamPID(i)); 430 } 455 _stream_handler->RemoveListener(_stream_data); 431 456 432 if (need_pcr_pid && (_input_pmt->PCRPID())) 433 { 434 add_pid.push_back(_input_pmt->PCRPID()); 435 _stream_data->AddWritingPID(_input_pmt->PCRPID()); 457 paused = true; 458 pauseWait.wakeAll(); 459 if (tvrec) 460 tvrec->RecorderPaused(); 461 } 462 unpauseWait.wait(timeout); 436 463 } 437 464 438 // Adjust for EIT 439 AdjustEITPIDs(); 440 for (uint i = 0; i < _eit_pids.size(); i++) 465 if (!request_pause && paused) 441 466 { 442 add_pid.push_back(_eit_pids[i]); 443 _stream_data->AddListeningPID(_eit_pids[i]); 444 } 467 paused = false; 445 468 446 // Delete filters for pids we no longer wish to monitor 447 vector<uint>::const_iterator it; 448 vector<uint> pids = _channel->GetPIDs(); 449 for (it = pids.begin(); it != pids.end(); ++it) 450 { 451 if (find(add_pid.begin(), add_pid.end(), *it) == add_pid.end()) 452 { 453 _stream_data->RemoveListeningPID(*it); 454 _stream_data->RemoveWritingPID(*it); 455 _channel->DelPID(*it, false); 456 } 457 } 469 assert(_stream_handler); 470 assert(_stream_data); 458 471 459 for (it = add_pid.begin(); it != add_pid.end(); ++it) 460 _channel->AddPID(*it, false); 461 462 _channel->UpdateFilters(); 472 _stream_handler->AddListener(_stream_data); 473 } 463 474 464 return add_pid.size();475 return paused; 465 476 } 466 477 467 /** \fn HDHRRecorder::AdjustEITPIDs(void) 468 * \brief Adjusts EIT PID monitoring to monitor the right number of EIT PIDs. 469 */ 470 bool HDHRRecorder::AdjustEITPIDs(void) 478 void HDHRRecorder::BufferedWrite(const TSPacket &tspacket) 471 479 { 472 bool changes = false; 473 uint_vec_t add, del; 474 475 QMutexLocker change_lock(&_pid_lock); 476 477 if (GetStreamData()->HasEITPIDChanges(_eit_pids)) 478 changes = GetStreamData()->GetEITPIDChanges(_eit_pids, add, del); 480 // Care must be taken to make sure that the packet actually gets written 481 // as the decision to actually write it has already been made 479 482 480 if (!changes) 481 return false; 482 483 for (uint i = 0; i < del.size(); i++) 483 // Do we have to buffer the packet for exact keyframe detection? 484 if (_buffer_packets) 484 485 { 485 uint_vec_t::iterator it;486 it = find(_eit_pids.begin(), _eit_pids.end(), del[i]);487 if (it != _eit_pids.end())488 _eit_pids.erase(it);486 int idx = _payload_buffer.size(); 487 _payload_buffer.resize(idx + TSPacket::SIZE); 488 memcpy(&_payload_buffer[idx], tspacket.data(), TSPacket::SIZE); 489 return; 489 490 } 490 491 491 for (uint i = 0; i < add.size(); i++) 492 _eit_pids.push_back(add[i]); 493 494 return true; 492 // We are free to write the packet, but if we have buffered packet[s] 493 // we have to write them first... 494 if (!_payload_buffer.empty()) 495 { 496 if (ringBuffer) 497 ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 498 _payload_buffer.clear(); 499 } 500 if (ringBuffer) 501 ringBuffer->Write(tspacket.data(), TSPacket::SIZE); 495 502 } 496 503 -
mythtv/libs/libmythtv/hdhrrecorder.h
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrrecorder.h release.20085.0302a/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 … … 21 24 public DVBMainStreamListener, 22 25 public ATSCMainStreamListener, 23 26 public MPEGStreamListener, 24 public MPEGSingleProgramStreamListener 27 public MPEGSingleProgramStreamListener, 28 public TSPacketListener, 29 public TSPacketListenerAV 25 30 { 26 31 public: 27 32 HDHRRecorder(TVRec *rec, HDHRChannel *channel); … … 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; } … … 62 69 void HandleNIT(const NetworkInformationTable*) {} 63 70 void HandleSDT(uint /*tsid*/, const ServiceDescriptionTable*) {} 64 71 65 private: 66 bool AdjustFilters(void); 67 bool AdjustEITPIDs(void); 72 // TSPacketListenerAV 73 bool ProcessVideoTSPacket(const TSPacket& tspacket); 74 bool ProcessAudioTSPacket(const TSPacket& tspacket); 75 76 // Common audio/visual processing 77 bool ProcessAVTSPacket(const TSPacket &tspacket); 68 78 69 void ProcessTSData(const unsigned char *buffer, int len);70 79 bool ProcessTSPacket(const TSPacket& tspacket); 80 81 void BufferedWrite(const TSPacket &tspacket); 82 private: 71 83 void TeardownAll(void); 84 85 void ReaderPaused(int fd); 86 bool PauseAndWait(int timeout = 100); 72 87 73 88 private: 74 89 HDHRChannel *_channel; 75 struct hdhomerun_video_sock_t *_video_socket;90 HDHRStreamHandler *_stream_handler; 76 91 MPEGStreamData *_stream_data; 77 92 93 mutable QMutex _pid_lock; 78 94 ProgramAssociationTable *_input_pat; 79 95 ProgramMapTable *_input_pmt; 80 bool _reset_pid_filters; 81 uint_vec_t _eit_pids; 82 mutable QMutex _pid_lock; 96 bool _has_no_av; 97 98 unsigned char _stream_id[0x1fff]; 99 unsigned char _pid_status[0x1fff]; 100 unsigned char _continuity_counter[0x1fff]; 101 102 // Constants 103 static const int TSPACKETS_BETWEEN_PSIP_SYNC; 104 static const int POLL_INTERVAL; 105 static const int POLL_WARNING_TIMEOUT; 106 107 static const unsigned char kPayloadStartSeen = 0x2; 83 108 }; 84 109 85 110 #endif -
mythtv/libs/libmythtv/hdhrsignalmonitor.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrsignalmonitor.cpp release.20085.0302a/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()) … … 41 42 HDHRChannel* _channel, 42 43 uint64_t _flags, const char *_name) 43 44 : DTVSignalMonitor(db_cardnum, _channel, _flags, _name), 44 dtvMonitorRunning(false) 45 streamHandlerStarted(false), 46 streamHandler(NULL) 47 45 48 { 46 49 VERBOSE(VB_CHANNEL, LOC + "ctor"); 47 50 48 _channel->DelAllPIDs();49 50 51 signalStrength.SetThreshold(45); 51 52 52 53 AddFlags(kDTVSigMon_WaitForSig); 54 55 streamHandler = HDHRStreamHandler::Get(_channel->GetDevice()); 53 56 } 54 57 55 58 /** \fn HDHRSignalMonitor::~HDHRSignalMonitor() … … 59 62 { 60 63 VERBOSE(VB_CHANNEL, LOC + "dtor"); 61 64 Stop(); 65 HDHRStreamHandler::Return(streamHandler); 62 66 } 63 67 64 68 void HDHRSignalMonitor::deleteLater(void) … … 75 79 { 76 80 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 77 81 SignalMonitor::Stop(); 78 if (dtvMonitorRunning) 79 { 80 dtvMonitorRunning = false; 81 pthread_join(table_monitor_thread, NULL); 82 } 83 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 84 } 82 if (GetStreamData()) 83 streamHandler->RemoveListener(GetStreamData()); 84 streamHandlerStarted = false; 85 streamHandler->SetRetuneAllowed(false, NULL, NULL); 85 86 86 void *HDHRSignalMonitor::TableMonitorThread(void *param) 87 { 88 HDHRSignalMonitor *mon = (HDHRSignalMonitor*) param; 89 mon->RunTableMonitor(); 90 return NULL; 91 } 92 93 bool HDHRSignalMonitor::UpdateFiltersFromStreamData(void) 94 { 95 vector<int> add_pids; 96 vector<int> del_pids; 97 98 if (!GetStreamData()) 99 return false; 100 101 UpdateListeningForEIT(); 102 103 const pid_map_t &listening = GetStreamData()->ListeningPIDs(); 104 105 // PIDs that need to be added.. 106 pid_map_t::const_iterator lit = listening.constBegin(); 107 for (; lit != listening.constEnd(); ++lit) 108 if (lit.data() && (filters.find(lit.key()) == filters.end())) 109 add_pids.push_back(lit.key()); 110 111 // PIDs that need to be removed.. 112 FilterMap::const_iterator fit = filters.constBegin(); 113 for (; fit != filters.constEnd(); ++fit) 114 if (listening.find(fit.key()) == listening.end()) 115 del_pids.push_back(fit.key()); 116 117 HDHRChannel *hdhr = dynamic_cast<HDHRChannel*>(channel); 118 // Remove PIDs 119 bool ok = true; 120 vector<int>::iterator dit = del_pids.begin(); 121 for (; dit != del_pids.end(); ++dit) 122 { 123 ok &= hdhr->DelPID(*dit); 124 filters.erase(filters.find(*dit)); 125 } 126 127 // Add PIDs 128 vector<int>::iterator ait = add_pids.begin(); 129 for (; ait != add_pids.end(); ++ait) 130 { 131 ok &= hdhr->AddPID(*ait); 132 filters[*ait] = 1; 133 } 134 135 return ok; 87 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 136 88 } 137 89 138 void HDHRSignalMonitor::RunTableMonitor(void)90 HDHRChannel *HDHRSignalMonitor::GetHDHRChannel(void) 139 91 { 140 dtvMonitorRunning = true; 141 142 struct hdhomerun_video_sock_t *_video_socket; 143 _video_socket = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 144 if (!_video_socket) 145 { 146 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get video socket"); 147 return; 148 } 149 150 HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); 151 uint localPort = hdhomerun_video_get_local_port(_video_socket); 152 if (!hdrc->DeviceSetTarget(localPort)) 153 { 154 hdhomerun_video_destroy(_video_socket); 155 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set target"); 156 return; 157 } 158 159 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): " + 160 QString("begin (# of pids %1)") 161 .arg(GetStreamData()->ListeningPIDs().size())); 162 163 while (dtvMonitorRunning && GetStreamData()) 164 { 165 UpdateFiltersFromStreamData(); 166 167 size_t data_length; 168 unsigned char *data_buffer = 169 hdhomerun_video_recv(_video_socket, 170 VIDEO_DATA_BUFFER_SIZE_1S / 5, 171 &data_length); 172 173 if (data_buffer) 174 { 175 GetStreamData()->ProcessData(data_buffer, data_length); 176 continue; 177 } 178 179 usleep(2500); 180 } 181 182 hdrc->DeviceClearTarget(); 183 hdhomerun_video_destroy(_video_socket); 184 185 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown"); 186 187 // TODO teardown PID filters here 188 189 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 92 return dynamic_cast<HDHRChannel*>(channel); 190 93 } 191 94 192 95 /** \fn HDHRSignalMonitor::UpdateValues() … … 204 107 if (!running || exit) 205 108 return; 206 109 207 if ( dtvMonitorRunning)110 if (streamHandlerStarted) 208 111 { 209 112 EmitHDHRSignals(); 210 113 if (IsAllGood()) … … 215 118 return; 216 119 } 217 120 218 QString msg = ((HDHRChannel*)channel)->TunerGet("status");121 QString msg = streamHandler->GetTunerStatus(); 219 122 //ss = signal strength, [0,100] 220 123 //snq = signal to noise quality [0,100] 221 124 //seq = signal error quality [0,100] … … 253 156 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 254 157 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 255 158 { 256 pthread_create(&table_monitor_thread, NULL, 257 TableMonitorThread, this); 258 259 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 260 "Waiting for table monitor to start"); 261 262 while (!dtvMonitorRunning) 263 usleep(50); 264 265 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 266 "Table monitor started"); 159 streamHandler->AddListener(GetStreamData()); 160 streamHandlerStarted = true; 267 161 } 268 162 269 163 update_done = true; -
mythtv/libs/libmythtv/hdhrsignalmonitor.h
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrsignalmonitor.h release.20085.0302a/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 … … 21 22 22 23 void Stop(void); 23 24 24 bool UpdateFiltersFromStreamData(void);25 26 25 public slots: 27 26 void deleteLater(void); 28 27 … … 33 32 virtual void UpdateValues(void); 34 33 void EmitHDHRSignals(void); 35 34 36 static void *TableMonitorThread(void *param);37 void RunTableMonitor(void);38 39 35 bool SupportsTSMonitoring(void); 40 36 37 HDHRChannel *GetHDHRChannel(void); 38 41 39 protected: 42 bool dtvMonitorRunning;43 pthread_t table_monitor_thread;44 40 45 FilterMap filters; ///< PID filters for table monitoring 41 bool streamHandlerStarted; 42 HDHRStreamHandler *streamHandler; 43 46 44 }; 47 45 48 46 #endif // HDHRSIGNALMONITOR_H -
mythtv/libs/libmythtv/hdhrstreamhandler.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrstreamhandler.cpp release.20085.0302a/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(true), 106 _running(false), 107 108 _sigmon(NULL), 109 _channel(NULL), 110 111 _pid_lock(true), 112 _listener_lock(true), 113 _hdhr_lock(true) 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); 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, &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, val, &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 if (!TunerSet("target", configValue)) 290 { 291 return false; 292 } 293 294 return true; 295 } 296 297 bool HDHRStreamHandler::DeviceClearTarget() 298 { 299 return (QString::null != TunerSet("target", "0.0.0.0:0")); 300 } 301 302 QString HDHRStreamHandler::GetTunerStatus() { 303 return TunerGet("status"); 304 } 305 306 bool HDHRStreamHandler::Connected() { 307 // FIXME 308 return (_control_socket != NULL); 309 } 310 311 bool HDHRStreamHandler::TuneChannel(QString chn) { 312 QString current = TunerGet("channel"); 313 if (current == chn) 314 { 315 VERBOSE(VB_RECORD, QString(LOC + "Not Re-Tuning channel %1").arg(chn)); 316 return true; 317 } 318 VERBOSE(VB_RECORD, QString(LOC + "Tuning channel %1 (was %2)").arg(chn).arg(current)); 319 return (QString::null != TunerSet("channel", chn)); 320 } 321 322 bool HDHRStreamHandler::TuneProgram(QString pnum) { 323 VERBOSE(VB_RECORD, QString(LOC + "Tuning program %1").arg(pnum)); 324 return (QString::null != TunerSet("program", pnum, false)); 325 } 326 327 void HDHRStreamHandler::AddListener(MPEGStreamData *data) 328 { 329 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- begin"); 330 assert(data); 331 332 _listener_lock.lock(); 333 334 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- locked"); 335 336 _stream_data_list.push_back(data); 337 338 _listener_lock.unlock(); 339 340 Start(); 341 342 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- end"); 343 } 344 345 void HDHRStreamHandler::RemoveListener(MPEGStreamData *data) 346 { 347 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- begin"); 348 assert(data); 349 350 _listener_lock.lock(); 351 352 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- locked"); 353 354 vector<MPEGStreamData*>::iterator it = 355 find(_stream_data_list.begin(), _stream_data_list.end(), data); 356 357 if (it != _stream_data_list.end()) 358 _stream_data_list.erase(it); 359 360 if (_stream_data_list.empty()) 361 { 362 _listener_lock.unlock(); 363 Stop(); 364 } 365 else 366 { 367 _listener_lock.unlock(); 368 } 369 370 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- end"); 371 } 372 373 void *run_hdhr_stream_handler_thunk(void *param) 374 { 375 HDHRStreamHandler *mon = (HDHRStreamHandler*) param; 376 mon->Run(); 377 return NULL; 378 } 379 380 void HDHRStreamHandler::Start(void) 381 { 382 QMutexLocker locker(&_start_stop_lock); 383 384 _eit_pids.clear(); 385 386 if (!IsRunning()) 387 { 388 pthread_create(&_reader_thread, NULL, 389 run_hdhr_stream_handler_thunk, this); 390 391 while (!IsRunning()) 392 _running_state_changed.wait(100); 393 } 394 } 395 396 void HDHRStreamHandler::Stop(void) 397 { 398 QMutexLocker locker(&_start_stop_lock); 399 400 if (IsRunning()) 401 { 402 SetRunning(false); 403 pthread_join(_reader_thread, NULL); 404 } 405 } 406 407 void HDHRStreamHandler::Run(void) 408 { 409 SetRunning(true); 410 RunTS(); 411 } 412 413 /** \fn HDHRStreamHandler::RunTS(void) 414 * \brief Uses TS filtering devices to read a DVB device for tables & data 415 * 416 * This supports all types of MPEG based stream data, but is extreemely 417 * slow with DVB over USB 1.0 devices which for efficiency reasons buffer 418 * a stream until a full block transfer buffer full of the requested 419 * tables is available. This takes a very long time when you are just 420 * waiting for a PAT or PMT table, and the buffer is hundreds of packets 421 * in size. 422 */ 423 void HDHRStreamHandler::RunTS(void) 424 { 425 int remainder = 0; 426 VERBOSE(VB_RECORD, LOC + "RunTS()"); 427 428 /* Calculate buffer size */ 429 uint buffersize = gContext->GetNumSetting( 430 "HDRingbufferSize", 50 * TSPacket::SIZE) * 1024; 431 buffersize /= VIDEO_DATA_PACKET_SIZE; 432 buffersize *= VIDEO_DATA_PACKET_SIZE; 433 434 // Buffer should be at least about 1MB.. 435 buffersize = max(49 * TSPacket::SIZE * 128, buffersize); 436 437 VERBOSE(VB_GENERAL, QString(LOC + "HD Ringbuffer size = %1 KB").arg(buffersize / 1024)); 438 439 /* Create TS socket. */ 440 _video_socket = hdhomerun_video_create(0, buffersize); 441 if (!_video_socket) 442 { 443 VERBOSE(VB_IMPORTANT, LOC + "Open() failed to open socket"); 444 return; 445 } 446 447 uint localPort = hdhomerun_video_get_local_port(_video_socket); 448 if (!DeviceSetTarget(localPort)) 449 { 450 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting recording (set target failed). Aborting."); 451 return; 452 } 453 hdhomerun_video_flush(_video_socket); 454 455 bool _error = false; 456 457 VERBOSE(VB_RECORD, LOC + "RunTS(): begin"); 458 459 while (IsRunning() && !_error) 460 { 461 UpdateFiltersFromStreamData(); 462 463 size_t read_size = 64 * 1024; // read about 64KB 464 read_size /= VIDEO_DATA_PACKET_SIZE; 465 read_size *= VIDEO_DATA_PACKET_SIZE; 466 467 size_t data_length; 468 unsigned char *data_buffer = 469 hdhomerun_video_recv(_video_socket, read_size, &data_length); 470 471 if (! data_buffer) 472 { 473 usleep(5000); 474 continue; 475 } 476 477 // Assume data_length is a multiple of 188 (packet size) 478 ASSERT(0 == ( data_length % 188) ); 479 480 _listener_lock.lock(); 481 482 if (_stream_data_list.empty()) 483 { 484 _listener_lock.unlock(); 485 continue; 486 } 487 488 for (uint i = 0; i < _stream_data_list.size(); i++) 489 { 490 remainder = _stream_data_list[i]->ProcessData(data_buffer, data_length); 491 } 492 493 _listener_lock.unlock(); 494 if (remainder != 0) 495 VERBOSE(VB_GENERAL, QString(LOC + "RunTS(): data_length = %1 remainder = %2") 496 .arg(data_length).arg(remainder)); 497 } 498 VERBOSE(VB_RECORD, LOC + "RunTS(): " + "shutdown"); 499 500 DelAllPIDs(); 501 502 DeviceClearTarget(); 503 VERBOSE(VB_RECORD, LOC + "RunTS(): " + "end"); 504 505 hdhomerun_video_sock_t* tmp_video_socket; 506 { 507 QMutexLocker locker(&_hdhr_lock); 508 tmp_video_socket = _video_socket; 509 _video_socket=NULL; 510 } 511 512 hdhomerun_video_destroy(tmp_video_socket); 513 514 SetRunning(false); 515 } 516 517 bool HDHRStreamHandler::AddPID(uint pid, bool do_update) 518 { 519 QMutexLocker locker(&_pid_lock); 520 521 vector<uint>::iterator it; 522 it = lower_bound(_pid_info.begin(), _pid_info.end(), pid); 523 if (it != _pid_info.end() && *it == pid) 524 { 525 #ifdef DEBUG_PID_FILTERS 526 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<", " << do_update << ") NOOP"); 527 #endif // DEBUG_PID_FILTERS 528 return true; 529 } 530 531 _pid_info.insert(it, pid); 532 533 #ifdef DEBUG_PID_FILTERS 534 VERBOSE(VB_CHANNEL, "AddPID(0x"<<hex<<pid<<dec<<")", " << do_update << "); 535 #endif // DEBUG_PID_FILTERS 536 537 if (do_update) 538 return UpdateFilters(); 539 return true; 540 } 541 542 bool HDHRStreamHandler::DelPID(uint pid, bool do_update) 543 { 544 QMutexLocker locker(&_pid_lock); 545 546 vector<uint>::iterator it; 547 it = lower_bound(_pid_info.begin(), _pid_info.end(), pid); 548 if (it == _pid_info.end()) 549 { 550 #ifdef DEBUG_PID_FILTERS 551 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<", " << do_update << ") NOOP"); 552 #endif // DEBUG_PID_FILTERS 553 554 return true; 555 } 556 557 if (*it == pid) 558 { 559 #ifdef DEBUG_PID_FILTERS 560 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<", " << do_update << ") -- found"); 561 #endif // DEBUG_PID_FILTERS 562 _pid_info.erase(it); 563 } 564 else 565 { 566 #ifdef DEBUG_PID_FILTERS 567 VERBOSE(VB_CHANNEL, "DelPID(0x"<<hex<<pid<<dec<<", " << do_update << ") -- failed"); 568 #endif // DEBUG_PID_FILTERS 569 } 570 571 if (do_update) 572 return UpdateFilters(); 573 return true; 574 } 575 576 bool HDHRStreamHandler::DelAllPIDs(void) 577 { 578 QMutexLocker locker(&_pid_lock); 579 580 #ifdef DEBUG_PID_FILTERS 581 VERBOSE(VB_CHANNEL, "DelAllPID()"); 582 #endif // DEBUG_PID_FILTERS 583 584 _pid_info.clear(); 585 586 return UpdateFilters(); 587 } 588 589 QString filt_str(uint pid) 590 { 591 uint pid0 = (pid / (16*16*16)) % 16; 592 uint pid1 = (pid / (16*16)) % 16; 593 uint pid2 = (pid / (16)) % 16; 594 uint pid3 = pid % 16; 595 return QString("0x%1%2%3%4") 596 .arg(pid0,0,16).arg(pid1,0,16) 597 .arg(pid2,0,16).arg(pid3,0,16); 598 } 599 600 bool HDHRStreamHandler::UpdateFilters(void) 601 { 602 #ifdef DEBUG_PID_FILTERS 603 VERBOSE(VB_CHANNEL, LOC + "UpdateFilters()"); 604 #endif // DEBUG_PID_FILTERS 605 QMutexLocker locker(&_pid_lock); 606 607 QString filter = ""; 608 609 vector<uint> range_min; 610 vector<uint> range_max; 611 612 // FIXME 613 // if (_ignore_filters) 614 // return true; 615 616 for (uint i = 0; i < _pid_info.size(); i++) 617 { 618 uint pid_min = _pid_info[i]; 619 uint pid_max = pid_min; 620 for (uint j = i + 1; j < _pid_info.size(); j++) 621 { 622 if (pid_max + 1 != _pid_info[j]) 623 break; 624 pid_max++; 625 i++; 626 } 627 range_min.push_back(pid_min); 628 range_max.push_back(pid_max); 629 } 630 if (range_min.size() > 16) 631 { 632 range_min.resize(16); 633 uint pid_max = range_max.back(); 634 range_max.resize(15); 635 range_max.push_back(pid_max); 636 } 637 638 for (uint i = 0; i < range_min.size(); i++) 639 { 640 filter += filt_str(range_min[i]); 641 if (range_min[i] != range_max[i]) 642 filter += QString("-%1").arg(filt_str(range_max[i])); 643 filter += " "; 644 } 645 646 filter = filter.stripWhiteSpace(); 647 648 QString new_filter = TunerSet("filter", filter); 649 650 #ifdef DEBUG_PID_FILTERS 651 QString msg = QString("Filter: '%1'").arg(filter); 652 if (filter != new_filter) 653 msg += QString("\n\t\t\t\t'%2'").arg(new_filter); 654 655 VERBOSE(VB_CHANNEL, LOC + msg); 656 #endif // DEBUG_PID_FILTERS 657 658 return filter == new_filter; 659 } 660 661 void HDHRStreamHandler::UpdateListeningForEIT(void) 662 { 663 vector<uint> add_eit, del_eit; 664 665 QMutexLocker read_locker(&_listener_lock); 666 667 for (uint i = 0; i < _stream_data_list.size(); i++) 668 { 669 MPEGStreamData *sd = _stream_data_list[i]; 670 if (sd->HasEITPIDChanges(_eit_pids) && 671 sd->GetEITPIDChanges(_eit_pids, add_eit, del_eit)) 672 { 673 for (uint i = 0; i < del_eit.size(); i++) 674 { 675 uint_vec_t::iterator it; 676 it = find(_eit_pids.begin(), _eit_pids.end(), del_eit[i]); 677 if (it != _eit_pids.end()) 678 _eit_pids.erase(it); 679 sd->RemoveListeningPID(del_eit[i]); 680 } 681 682 for (uint i = 0; i < add_eit.size(); i++) 683 { 684 _eit_pids.push_back(add_eit[i]); 685 sd->AddListeningPID(add_eit[i]); 686 } 687 } 688 } 689 } 690 691 bool HDHRStreamHandler::UpdateFiltersFromStreamData(void) 692 { 693 694 UpdateListeningForEIT(); 695 696 pid_map_t pids; 697 698 { 699 QMutexLocker read_locker(&_listener_lock); 700 701 for (uint i = 0; i < _stream_data_list.size(); i++) 702 _stream_data_list[i]->GetPIDs(pids); 703 } 704 705 uint_vec_t add_pids; 706 vector<uint> del_pids; 707 708 { 709 QMutexLocker read_locker(&_pid_lock); 710 711 // PIDs that need to be added.. 712 pid_map_t::const_iterator lit = pids.constBegin(); 713 for (; lit != pids.constEnd(); ++lit) 714 { 715 vector<uint>::iterator it; 716 it = lower_bound(_pid_info.begin(), _pid_info.end(), lit.key()); 717 if (! (it != _pid_info.end() && *it == lit.key())) { 718 add_pids.push_back(lit.key()); 719 } 720 } 721 722 // PIDs that need to be removed.. 723 vector<uint>::iterator fit = _pid_info.begin(); 724 for (; fit != _pid_info.end(); ++fit) 725 { 726 pid_map_t::const_iterator it = pids.find(*fit); 727 if(it == pids.end()) 728 del_pids.push_back(*fit); 729 } 730 } 731 732 bool need_update = false; 733 734 // Remove PIDs 735 bool ok = true; 736 vector<uint>::iterator dit = del_pids.begin(); 737 for (; dit != del_pids.end(); ++dit) 738 { 739 need_update = true; 740 ok &= DelPID(*dit, false); 741 } 742 743 // Add PIDs 744 vector<uint>::iterator ait = add_pids.begin(); 745 for (; ait != add_pids.end(); ++ait) 746 { 747 need_update = true; 748 ok &= AddPID(*ait, false); 749 } 750 751 if (need_update) 752 return UpdateFilters(); 753 754 return ok; 755 } 756 757 void HDHRStreamHandler::SetRetuneAllowed( 758 bool allow, 759 DTVSignalMonitor *sigmon, 760 HDHRChannel *hdhrchan) 761 { 762 if (allow && sigmon && hdhrchan) 763 { 764 _allow_retune = true; 765 _sigmon = sigmon; 766 _channel = hdhrchan; 767 } 768 else 769 { 770 _allow_retune = false; 771 _sigmon = NULL; 772 _channel = NULL; 773 } 774 } 775 776 /** \fn HDHRStreamHandler::SupportsTSMonitoring(void) 777 * \brief Returns true if TS monitoring is supported. 778 * 779 * NOTE: If you are using a DEC2000-t device you need to 780 * apply the patches provided by Peter Beutner for it, see 781 * http://www.gossamer-threads.com/lists/mythtv/dev/166172 782 * These patches should make it in to Linux 2.6.15 or 2.6.16. 783 */ 784 bool HDHRStreamHandler::SupportsTSMonitoring(void) 785 { 786 return false; 787 788 // FIXME 789 #if 0 790 const uint pat_pid = 0x0; 791 792 { 793 QMutexLocker locker(&_rec_supports_ts_monitoring_lock); 794 QMap<uint,bool>::const_iterator it; 795 it = _rec_supports_ts_monitoring.find(_dvb_dev_num); 796 if (it != _rec_supports_ts_monitoring.end()) 797 return *it; 798 } 799 800 int dvr_fd = open(_dvr_dev_path.ascii(), O_RDONLY | O_NONBLOCK); 801 if (dvr_fd < 0) 802 { 803 QMutexLocker locker(&_rec_supports_ts_monitoring_lock); 804 _rec_supports_ts_monitoring[_dvb_dev_num] = false; 805 return false; 806 } 807 808 bool supports_ts = false; 809 if (AddPIDFilter(new PIDInfoHDHR(pat_pid))) 810 { 811 supports_ts = true; 812 RemovePIDFilter(pat_pid); 813 } 814 815 close(dvr_fd); 816 817 QMutexLocker locker(&_rec_supports_ts_monitoring_lock); 818 _rec_supports_ts_monitoring[_dvb_dev_num] = supports_ts; 819 820 return supports_ts; 821 #endif 822 } 823 824 void HDHRStreamHandler::SetRunning(bool is_running) 825 { 826 _running = is_running; 827 _running_state_changed.wakeAll(); 828 } 829 830 PIDPriority HDHRStreamHandler::GetPIDPriority(uint pid) const 831 { 832 QMutexLocker reading_locker(&_listener_lock); 833 834 PIDPriority tmp = kPIDPriorityNone; 835 836 for (uint i = 0; i < _stream_data_list.size(); i++) 837 tmp = max(tmp, _stream_data_list[i]->GetPIDPriority(pid)); 838 839 return tmp; 840 } -
mythtv/libs/libmythtv/hdhrstreamhandler.h
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/hdhrstreamhandler.h release.20085.0302a/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 release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/libmythtv.pro release.20085.0302a/mythtv/libs/libmythtv/libmythtv.pro
451 451 using_hdhomerun { 452 452 # MythTV HDHomeRun glue 453 453 HEADERS += hdhrsignalmonitor.h hdhrchannel.h 454 HEADERS += hdhrrecorder.h 454 HEADERS += hdhrrecorder.h hdhrstreamhandler.h 455 455 456 456 SOURCES += hdhrsignalmonitor.cpp hdhrchannel.cpp 457 SOURCES += hdhrrecorder.cpp 457 SOURCES += hdhrrecorder.cpp hdhrstreamhandler.cpp 458 458 459 459 DEFINES += USING_HDHOMERUN 460 460 -
mythtv/libs/libmythtv/scanwizardscanner.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/scanwizardscanner.cpp release.20085.0302a/mythtv/libs/libmythtv/scanwizardscanner.cpp
518 518 #ifdef USING_HDHOMERUN 519 519 if ("HDHOMERUN" == card_type) 520 520 { 521 uint tuner = CardUtil::GetHDHRTuner(cardid); 522 channel = new HDHRChannel(NULL, device, tuner); 521 channel = new HDHRChannel(NULL, device); 523 522 } 524 523 #endif // USING_HDHOMERUN 525 524 -
mythtv/libs/libmythtv/tv_rec.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/tv_rec.cpp release.20085.0302a/mythtv/libs/libmythtv/tv_rec.cpp
174 174 else if (genOpt.cardtype == "HDHOMERUN") 175 175 { 176 176 #ifdef USING_HDHOMERUN 177 channel = new HDHRChannel(this, genOpt.videodev , dboxOpt.port);177 channel = new HDHRChannel(this, genOpt.videodev); 178 178 if (!channel->Open()) 179 179 return false; 180 180 InitChannel(genOpt.defaultinput, startchannel); … … 3433 3433 return; 3434 3434 3435 3435 ClearFlags(kFlagWaitingForRecPause); 3436 #ifdef USING_HDHOMERUN3437 if (GetHDHRRecorder())3438 {3439 // We currently need to close the file descriptor for3440 // HDHomeRun signal monitoring to work.3441 GetHDHRRecorder()->Close();3442 GetHDHRRecorder()->SetRingBuffer(NULL);3443 }3444 #endif // USING_HDHOMERUN3445 3436 VERBOSE(VB_RECORD, LOC + "Recorder paused, calling TuningFrequency"); 3446 3437 TuningFrequency(lastTuningRequest); 3447 3438 } … … 4080 4071 } 4081 4072 recorder->Reset(); 4082 4073 4083 #ifdef USING_HDHOMERUN4084 if (GetHDHRRecorder())4085 {4086 pauseNotify = false;4087 GetHDHRRecorder()->Close();4088 pauseNotify = true;4089 GetHDHRRecorder()->Open();4090 GetHDHRRecorder()->StartData();4091 }4092 #endif // USING_HDHOMERUN4093 4094 4074 // Set file descriptor of channel from recorder for V4L 4095 4075 channel->SetFd(recorder->GetVideoFd()); 4096 4076 -
mythtv/libs/libmythtv/videosource.cpp
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/videosource.cpp release.20085.0302a/mythtv/libs/libmythtv/videosource.cpp
47 47 #include "videodev_myth.h" 48 48 #endif 49 49 50 #include "hdhomerun_includes.h" 51 50 52 VideoSourceSelector::VideoSourceSelector(uint _initial_sourceid, 51 53 const QString &_card_types, 52 54 bool _must_have_mplexid) : … … 131 133 class RecorderOptions : public ConfigurationWizard 132 134 { 133 135 public: 134 RecorderOptions(CaptureCard& parent );136 RecorderOptions(CaptureCard& parent, QString type); 135 137 uint GetInstanceCount(void) const { return (uint) count->intValue(); } 136 138 137 139 private: … … 1283 1285 CaptureCard &parent; 1284 1286 }; 1285 1287 1286 class HDHomeRunDeviceID : public LineEditSetting, public CaptureCardDBStorage 1288 class HDHomeRunIP : public TransLabelSetting 1289 { 1290 public: 1291 HDHomeRunIP() 1292 { 1293 setLabel(QObject::tr("IP Address")); 1294 }; 1295 }; 1296 1297 class HDHomeRunTuner : public TransLabelSetting 1298 { 1299 public: 1300 HDHomeRunTuner() 1301 { 1302 setLabel(QObject::tr("Tuner")); 1303 }; 1304 }; 1305 1306 class HDHomeRunDeviceID : public ComboBoxSetting, public CaptureCardDBStorage 1287 1307 { 1288 1308 public: 1289 1309 HDHomeRunDeviceID(const CaptureCard &parent) : 1290 LineEditSetting(this),1310 ComboBoxSetting(this), 1291 1311 CaptureCardDBStorage(this, parent, "videodevice") 1292 1312 { 1293 setValue("FFFFFFFF");1294 1313 setLabel(QObject::tr("Device ID")); 1295 setHelpText(QObject::tr("IP address or Device ID from the bottom of " 1296 "the HDHomeRun. You may use " 1297 "'FFFFFFFF' if there is only one unit " 1298 "on your your network.")); 1314 setHelpText( 1315 QObject::tr("DevicedID and Tuner Number of available HDHomeRun " 1316 "devices. ")); 1317 fillSelections(""); 1318 }; 1319 1320 /// \brief Adds all available device-tuner combinations to list 1321 /// If current is >= 0 it will be considered available even 1322 /// if no device exists for it on the network 1323 void fillSelections(QString current) 1324 { 1325 clearSelections(); 1326 1327 // Get devices from filesystem 1328 vector<QString> devs = CardUtil::ProbeVideoDevices("HDHOMERUN"); 1329 1330 // Add current if needed 1331 if ((current != "") && 1332 (find(devs.begin(), devs.end(), current) == devs.end())) 1333 { 1334 devs.push_back(current); 1335 stable_sort(devs.begin(), devs.end()); 1336 } 1337 1338 vector<QString> db = CardUtil::GetVideoDevices("HDHOMERUN"); 1339 1340 QMap<QString, bool> in_use; 1341 QString sel = current; 1342 for (uint i = 0; i < devs.size(); i++) 1343 { 1344 const QString dev = devs[i]; 1345 in_use[devs[i]] = find(db.begin(), db.end(), dev) != db.end(); 1346 if (sel == "" && !in_use[devs[i]]) 1347 sel = dev; 1348 } 1349 1350 if (sel == "" && devs.size()) 1351 sel = devs[0]; 1352 1353 QString usestr = QString(" -- "); 1354 usestr += QObject::tr("Warning: already in use"); 1355 1356 for (uint i = 0; i < devs.size(); i++) 1357 { 1358 const QString dev = devs[i]; 1359 QString desc = dev + (in_use[devs[i]] ? usestr : ""); 1360 desc = (current == devs[i]) ? dev : desc; 1361 addSelection(desc, dev, dev == sel); 1362 } 1363 } 1364 1365 virtual void load(void) 1366 { 1367 clearSelections(); 1368 addSelection(""); 1369 1370 CaptureCardDBStorage::load(); 1371 1372 fillSelections(getValue()); 1299 1373 } 1300 1374 }; 1301 1375 … … 1329 1403 CaptureCard &parent; 1330 1404 }; 1331 1405 1332 class HDHomeRunTunerIndex : public ComboBoxSetting, public CaptureCardDBStorage 1406 HDHomeRunConfigurationGroup::HDHomeRunConfigurationGroup(CaptureCard& a_parent) : 1407 VerticalConfigurationGroup(false, true, false, false), 1408 parent(a_parent) 1333 1409 { 1334 public: 1335 HDHomeRunTunerIndex(const CaptureCard &parent) : 1336 ComboBoxSetting(this), 1337 CaptureCardDBStorage(this, parent, "dbox2_port") 1338 { 1339 setLabel(QObject::tr("Tuner")); 1340 addSelection("0"); 1341 addSelection("1"); 1342 } 1410 setUseLabel(false); 1411 deviceid = new HDHomeRunDeviceID(parent); 1412 addChild(deviceid); 1413 cardip = new HDHomeRunIP(); 1414 cardtuner = new HDHomeRunTuner(); 1415 1416 addChild(cardip); 1417 addChild(cardtuner); 1418 1419 addChild(new SignalTimeout(parent, 1000, 250)); 1420 addChild(new ChannelTimeout(parent, 3000, 1750)); 1421 addChild(new SingleCardInput(parent)); 1422 1423 TransButtonSetting *buttonRecOpt = new TransButtonSetting(); 1424 buttonRecOpt->setLabel(tr("Recording Options")); 1425 addChild(buttonRecOpt); 1426 1427 connect(buttonRecOpt, SIGNAL(pressed()), 1428 &parent, SLOT( recorderOptionsPanelHDHomerun())); 1429 connect(deviceid, SIGNAL(valueChanged(const QString&)), 1430 this, SLOT( probeCard (const QString&))); 1431 1432 1343 1433 }; 1344 1434 1345 class HDHomeRunConfigurationGroup : public VerticalConfigurationGroup 1435 void HDHomeRunConfigurationGroup::probeCard(const QString& deviceid) 1346 1436 { 1347 public: 1348 HDHomeRunConfigurationGroup(CaptureCard& a_parent) : 1349 VerticalConfigurationGroup(false, true, false, false), 1350 parent(a_parent) 1437 hdhomerun_device_t* thisdevice = hdhomerun_device_create_from_str(deviceid); 1438 1439 if (thisdevice) 1351 1440 { 1352 setUseLabel(false); 1353 addChild(new HDHomeRunDeviceID(parent)); 1354 addChild(new HDHomeRunTunerIndex(parent)); 1355 addChild(new SignalTimeout(parent, 1000, 250)); 1356 addChild(new ChannelTimeout(parent, 3000, 1750)); 1357 addChild(new SingleCardInput(parent)); 1358 }; 1441 uint device_ip = hdhomerun_device_get_device_ip(thisdevice); 1442 uint tuner = hdhomerun_device_get_tuner(thisdevice); 1443 hdhomerun_device_destroy(thisdevice); 1359 1444 1360 private: 1361 CaptureCard &parent; 1362 }; 1445 QString ip = QString("%1.%2.%3.%4") 1446 .arg((device_ip>>24) & 0xFF).arg((device_ip>>16) & 0xFF) 1447 .arg((device_ip>> 8) & 0xFF).arg((device_ip>> 0) & 0xFF); 1448 1449 cardip->setValue(ip); 1450 cardtuner->setValue(QString("%1").arg(tuner)); 1451 } 1452 else 1453 { 1454 cardip->setValue("Unknown"); 1455 cardtuner->setValue("Unknown"); 1456 } 1457 } 1363 1458 1364 1459 V4LConfigurationGroup::V4LConfigurationGroup(CaptureCard& a_parent) : 1365 1460 VerticalConfigurationGroup(false, true, false, false), … … 1528 1623 if ((cardtype.lower() == "dvb") && (1 != ++device_refs[videodevice])) 1529 1624 continue; 1530 1625 1626 if ((cardtype.lower() == "hdhomerun") && (1 != ++device_refs[videodevice])) 1627 continue; 1628 1531 1629 QString label = CardUtil::GetDeviceLabel( 1532 1630 cardid, cardtype, videodevice); 1533 1631 … … 2667 2765 if ((cardtype.lower() == "dvb") && (1 != ++device_refs[videodevice])) 2668 2766 continue; 2669 2767 2768 if ((cardtype.lower() == "hdhomerun") && (1 != ++device_refs[videodevice])) 2769 continue; 2770 2670 2771 QStringList inputLabels; 2671 2772 vector<CardInput*> cardInputs; 2672 2773 … … 2908 3009 connect(buttonDiSEqC, SIGNAL(pressed()), 2909 3010 this, SLOT( DiSEqCPanel())); 2910 3011 connect(buttonRecOpt, SIGNAL(pressed()), 2911 &parent, SLOT( recorderOptionsPanel ()));3012 &parent, SLOT( recorderOptionsPanelDVB())); 2912 3013 } 2913 3014 2914 3015 DVBConfigurationGroup::~DVBConfigurationGroup() … … 2953 3054 } 2954 3055 } 2955 3056 2956 void CaptureCard::recorderOptionsPanel() 3057 void CaptureCard::recorderOptionsPanelHDHomerun() 3058 { 3059 reload(); 3060 3061 RecorderOptions acw(*this, "HDHOMERUN"); 3062 acw.exec(); 3063 instance_count = acw.GetInstanceCount(); 3064 } 3065 3066 void CaptureCard::recorderOptionsPanelDVB() 2957 3067 { 2958 3068 reload(); 2959 3069 2960 RecorderOptions acw(*this );3070 RecorderOptions acw(*this, "DVB"); 2961 3071 acw.exec(); 2962 3072 instance_count = acw.GetInstanceCount(); 2963 3073 } 2964 3074 2965 RecorderOptions::RecorderOptions(CaptureCard &parent )3075 RecorderOptions::RecorderOptions(CaptureCard &parent, QString type) 2966 3076 : count(new InstanceCount(parent)) 2967 3077 { 2968 3078 VerticalConfigurationGroup* rec = new VerticalConfigurationGroup(false); … … 2970 3080 rec->setUseLabel(false); 2971 3081 2972 3082 rec->addChild(count); 2973 rec->addChild(new DVBNoSeqStart(parent)); 2974 rec->addChild(new DVBOnDemand(parent)); 2975 rec->addChild(new DVBEITScan(parent)); 2976 rec->addChild(new DVBTuningDelay(parent)); 3083 if (type == "DVB") 3084 { 3085 rec->addChild(new DVBNoSeqStart(parent)); 3086 rec->addChild(new DVBOnDemand(parent)); 3087 rec->addChild(new DVBEITScan(parent)); 3088 rec->addChild(new DVBTuningDelay(parent)); 3089 } 2977 3090 2978 3091 addChild(rec); 2979 3092 } 3093 -
mythtv/libs/libmythtv/videosource.h
diff -r -u -N -X diff.exclude -x release.20098.0303a -x release.20085.0302a release.20098.0303a/mythtv/libs/libmythtv/videosource.h release.20085.0302a/mythtv/libs/libmythtv/videosource.h
418 418 DiSEqCDevTree *diseqc_tree; 419 419 }; 420 420 421 class HDHomeRunDeviceID; 422 class HDHomeRunIP; 423 class HDHomeRunTuner; 424 class HDHomeRunConfigurationGroup : public VerticalConfigurationGroup 425 { 426 Q_OBJECT 427 public: 428 HDHomeRunConfigurationGroup(CaptureCard& a_parent); 429 430 public slots: 431 void probeCard(const QString& deviceid); 432 433 private: 434 HDHomeRunDeviceID *deviceid; 435 HDHomeRunIP *cardip; 436 HDHomeRunTuner *cardtuner; 437 438 CaptureCard &parent; 439 }; 440 441 421 442 class FirewireGUID; 422 443 class FirewireModel : public ComboBoxSetting, public CaptureCardDBStorage 423 444 { … … 477 498 uint GetInstanceCount(void) const { return instance_count; } 478 499 479 500 public slots: 480 void recorderOptionsPanel(); 501 void recorderOptionsPanelDVB(); 502 void recorderOptionsPanelHDHomerun(); 481 503 482 504 private: 483 505