Ticket #13339: hdhr-locking-pooling-4.patch

File hdhr-locking-pooling-4.patch, 34.5 KB (added by gigem, 3 years ago)
  • mythtv/libs/libmythtv/cardutil.cpp

    diff --git a/mythtv/libs/libmythtv/cardutil.cpp b/mythtv/libs/libmythtv/cardutil.cpp
    index bf797e6a57..58bf4735bb 100644
    a b QStringList CardUtil::ProbeVideoDevices(const QString &rawtype) 
    540540                                 .arg((result_list[i].ip_addr>> 8) & 0xFF)
    541541                                 .arg((result_list[i].ip_addr>> 0) & 0xFF);
    542542
    543             for (int tuner = 0; tuner < result_list[i].tuner_count; tuner++)
     543            QString hwmodel = "";
     544            hdhomerun_device_t *device = hdhomerun_device_create(
     545                result_list[i].device_id, 0, 0, nullptr);
     546            if (device)
    544547            {
    545                 QString hdhrdev = id.toUpper() + " " + ip + " " +
    546                                   QString("%1").arg(tuner);
    547                 devs.push_back(hdhrdev);
     548                hwmodel = hdhomerun_device_get_hw_model_str(device);
     549                hdhomerun_device_destroy(device);
    548550            }
     551
     552            QString hdhrdev = id.toUpper() + " " + ip + " " + hwmodel;
     553            devs.push_back(hdhrdev);
    549554        }
    550555    }
    551556#endif // USING_HDHOMERUN
    uint CardUtil::CreateDeviceInputGroup(uint inputid, 
    13961401{
    13971402    QString name = host + '|' + device;
    13981403    if (type == "FREEBOX" || type == "IMPORT" ||
    1399         type == "DEMO"    || type == "EXTERNAL")
     1404        type == "DEMO"    || type == "EXTERNAL" ||
     1405        type == "HDHOMERUN")
    14001406        name += QString("|%1").arg(inputid);
    14011407    return CreateInputGroup(name);
    14021408}
  • mythtv/libs/libmythtv/recorders/channelbase.cpp

    diff --git a/mythtv/libs/libmythtv/recorders/channelbase.cpp b/mythtv/libs/libmythtv/recorders/channelbase.cpp
    index 04d46da5e7..281583fb44 100644
    a b ChannelBase *ChannelBase::CreateChannel( 
    805805    {
    806806        if (channel &&
    807807            ((genOpt.inputtype == "DVB" && dvbOpt.dvb_on_demand) ||
     808             genOpt.inputtype == "HDHOMERUN" ||
    808809             CardUtil::IsV4L(genOpt.inputtype)))
    809810        {
    810811            channel->Close();
    bool ChannelBase::IsExternalChannelChangeInUse(void) 
    835836
    836837    return !m_externalChanger.isEmpty();
    837838}
     839
     840int ChannelBase::GetMajorID(void)
     841{
     842    return m_pParent ? m_pParent->GetMajorId() : m_inputid;
     843}
  • mythtv/libs/libmythtv/recorders/channelbase.h

    diff --git a/mythtv/libs/libmythtv/recorders/channelbase.h b/mythtv/libs/libmythtv/recorders/channelbase.h
    index 7711e10650..a326faffc6 100644
    a b class ChannelBase 
    100100    // \brief Set inputid for scanning
    101101    void SetInputID(uint _inputid) { m_inputid = _inputid; }
    102102
     103    // \brief Get major input ID
     104    int GetMajorID(void);
     105
    103106    static ChannelBase *CreateChannel(
    104107        TVRec                    *tv_rec,
    105108        const GeneralDBOptions   &genOpt,
  • mythtv/libs/libmythtv/recorders/hdhrchannel.cpp

    diff --git a/mythtv/libs/libmythtv/recorders/hdhrchannel.cpp b/mythtv/libs/libmythtv/recorders/hdhrchannel.cpp
    index 448a75635e..133fe827e1 100644
    a b bool HDHRChannel::Open(void) 
    5959    if (IsOpen())
    6060        return true;
    6161
    62     _stream_handler = HDHRStreamHandler::Get(_device_id, GetInputID());
     62    _stream_handler = HDHRStreamHandler::Get(GetDevice(), GetInputID(),
     63                                             GetMajorID());
    6364
    6465    _tuner_types = _stream_handler->GetTunerTypes();
    6566    tunerType = (_tuner_types.empty()) ?
    void HDHRChannel::Close(void) 
    8687
    8788bool HDHRChannel::EnterPowerSavingMode(void)
    8889{
    89     if (IsOpen())
    90         return _stream_handler->EnterPowerSavingMode();
    91     else
    92         return true;
     90    Close();
     91    return true;
    9392}
    9493
    9594bool HDHRChannel::IsOpen(void) const
  • mythtv/libs/libmythtv/recorders/hdhrrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/recorders/hdhrrecorder.cpp b/mythtv/libs/libmythtv/recorders/hdhrrecorder.cpp
    index 1138c8d046..f85c0015b5 100644
    a b bool HDHRRecorder::Open(void) 
    3636    ResetForNewFile();
    3737
    3838    _stream_handler = HDHRStreamHandler::Get(_channel->GetDevice(),
    39                                      (tvrec ? tvrec->GetInputId() : -1));
     39                                             _channel->GetInputID(),
     40                                             _channel->GetMajorID());
    4041
    4142    LOG(VB_RECORD, LOG_INFO, LOC + "HDHR opened successfully");
    4243
  • mythtv/libs/libmythtv/recorders/hdhrsignalmonitor.cpp

    diff --git a/mythtv/libs/libmythtv/recorders/hdhrsignalmonitor.cpp b/mythtv/libs/libmythtv/recorders/hdhrsignalmonitor.cpp
    index 71c0438a13..45c4857d98 100644
    a b HDHRSignalMonitor::HDHRSignalMonitor(int db_cardnum, 
    5151
    5252    AddFlags(kSigMon_WaitForSig);
    5353
    54     streamHandler = HDHRStreamHandler::Get(channel->GetDevice(), inputid);
     54    streamHandler = HDHRStreamHandler::Get(channel->GetDevice(),
     55                                           channel->GetInputID(),
     56                                           channel->GetMajorID());
    5557}
    5658
    5759/** \fn HDHRSignalMonitor::~HDHRSignalMonitor()
  • mythtv/libs/libmythtv/recorders/hdhrstreamhandler.cpp

    diff --git a/mythtv/libs/libmythtv/recorders/hdhrstreamhandler.cpp b/mythtv/libs/libmythtv/recorders/hdhrstreamhandler.cpp
    index 4254732c82..644e7dfd8b 100644
    a b  
    2121
    2222#define LOC      QString("HDHRSH[%1](%2): ").arg(_inputid).arg(_device)
    2323
    24 QMap<QString,HDHRStreamHandler*> HDHRStreamHandler::_handlers;
    25 QMap<QString,uint>               HDHRStreamHandler::_handlers_refcnt;
     24QMap<int,HDHRStreamHandler*>    HDHRStreamHandler::_handlers;
     25QMap<int,uint>                   HDHRStreamHandler::_handlers_refcnt;
    2626QMutex                           HDHRStreamHandler::_handlers_lock;
    2727
    2828HDHRStreamHandler *HDHRStreamHandler::Get(const QString &devname,
    29                                           int inputid)
     29                                          int inputid, int majorid)
    3030{
    3131    QMutexLocker locker(&_handlers_lock);
    3232
    33     QString devkey = devname.toUpper();
    34 
    35     QMap<QString,HDHRStreamHandler*>::iterator it = _handlers.find(devkey);
     33    QMap<int,HDHRStreamHandler*>::iterator it = _handlers.find(majorid);
    3634
    3735    if (it == _handlers.end())
    3836    {
    39         HDHRStreamHandler *newhandler = new HDHRStreamHandler(devkey, inputid);
     37        HDHRStreamHandler *newhandler = new HDHRStreamHandler(devname, inputid,
     38                                                              majorid);
    4039        newhandler->Open();
    41         _handlers[devkey] = newhandler;
    42         _handlers_refcnt[devkey] = 1;
     40        _handlers[majorid] = newhandler;
     41        _handlers_refcnt[majorid] = 1;
    4342
    4443        LOG(VB_RECORD, LOG_INFO,
    4544            QString("HDHRSH[%1]: Creating new stream handler %2 for %3")
    46             .arg(inputid).arg(devkey).arg(devname));
     45            .arg(inputid).arg(majorid).arg(devname));
    4746    }
    4847    else
    4948    {
    50         _handlers_refcnt[devkey]++;
    51         uint rcount = _handlers_refcnt[devkey];
     49        _handlers_refcnt[majorid]++;
     50        uint rcount = _handlers_refcnt[majorid];
    5251        LOG(VB_RECORD, LOG_INFO,
    5352            QString("HDHRSH[%1]: Using existing stream handler %2 for %3")
    54             .arg(inputid).arg(devkey)
     53            .arg(inputid).arg(majorid)
    5554            .arg(devname) + QString(" (%1 in use)").arg(rcount));
    5655    }
    5756
    58     return _handlers[devkey];
     57    return _handlers[majorid];
    5958}
    6059
    6160void HDHRStreamHandler::Return(HDHRStreamHandler * & ref, int inputid)
    6261{
    6362    QMutexLocker locker(&_handlers_lock);
    6463
    65     QString devname = ref->_device;
     64    int majorid = ref->_majorid;
    6665
    67     QMap<QString,uint>::iterator rit = _handlers_refcnt.find(devname);
     66    QMap<int,uint>::iterator rit = _handlers_refcnt.find(majorid);
    6867    if (rit == _handlers_refcnt.end())
    6968        return;
    7069
    71     QMap<QString,HDHRStreamHandler*>::iterator it = _handlers.find(devname);
     70    QMap<int,HDHRStreamHandler*>::iterator it = _handlers.find(majorid);
    7271    if (*rit > 1)
    7372    {
    7473        ref = nullptr;
    void HDHRStreamHandler::Return(HDHRStreamHandler * & ref, int inputid) 
    7978    if ((it != _handlers.end()) && (*it == ref))
    8079    {
    8180        LOG(VB_RECORD, LOG_INFO, QString("HDHRSH[%1]: Closing handler for %2")
    82             .arg(inputid).arg(devname));
     81            .arg(inputid).arg(majorid));
    8382        ref->Close();
    8483        delete *it;
    8584        _handlers.erase(it);
    void HDHRStreamHandler::Return(HDHRStreamHandler * & ref, int inputid) 
    8887    {
    8988        LOG(VB_GENERAL, LOG_ERR,
    9089            QString("HDHRSH[%1] Error: Couldn't find handler for %2")
    91             .arg(inputid).arg(devname));
     90            .arg(inputid).arg(majorid));
    9291    }
    9392
    9493    _handlers_refcnt.erase(rit);
    9594    ref = nullptr;
    9695}
    9796
    98 HDHRStreamHandler::HDHRStreamHandler(const QString &device, int inputid)
     97HDHRStreamHandler::HDHRStreamHandler(const QString &device, int inputid,
     98                                     int majorid)
    9999    : StreamHandler(device, inputid)
    100100    , _hdhomerun_device(nullptr)
    101101    , _tuner(-1)
    102102    , _tune_mode(hdhrTuneModeNone)
     103    , _majorid(majorid)
    103104    , _hdhr_lock(QMutex::Recursive)
    104105{
    105106    setObjectName("HDHRStreamHandler");
    HDHRStreamHandler::HDHRStreamHandler(const QString &device, int inputid) 
    110111 */
    111112void HDHRStreamHandler::run(void)
    112113{
    113     int tunerLock = 0;
    114     char *error = nullptr;
    115 
    116114    RunProlog();
    117     /* Get a tuner lock */
    118     tunerLock = hdhomerun_device_tuner_lockkey_request(_hdhomerun_device, &error);
    119     if(tunerLock < 1)
    120     {
    121         LOG(VB_GENERAL, LOG_ERR, LOC +
    122             QString("Get tuner lock failed. Aborting. Error: %1").arg(error));
    123         _error = true;
    124         RunEpilog();
    125         return;
    126     }
     115
    127116    /* Create TS socket. */
    128117    if (!hdhomerun_device_stream_start(_hdhomerun_device))
    129118    {
    void HDHRStreamHandler::run(void) 
    221210
    222211    LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "end");
    223212
    224     if(tunerLock == 1)
    225     {
    226         LOG(VB_RECORD, LOG_INFO, LOC + "Release tuner lock.");
    227         hdhomerun_device_tuner_lockkey_release(_hdhomerun_device);
    228     }
    229 
    230213    SetRunning(false, false, false);
     214
    231215    RunEpilog();
    232216}
    233217
    void HDHRStreamHandler::Close(void) 
    361345    if (_hdhomerun_device)
    362346    {
    363347        TuneChannel("none");
    364         hdhomerun_device_destroy(_hdhomerun_device);
     348        hdhomerun_device_tuner_lockkey_release(_hdhomerun_device);
    365349        _hdhomerun_device = nullptr;
    366350    }
     351    if (_device_selector)
     352    {
     353        hdhomerun_device_selector_destroy(_device_selector, true);
     354        _device_selector = nullptr;
     355    }
    367356}
    368357
    369358bool HDHRStreamHandler::Connect(void)
    370359{
    371     _hdhomerun_device = hdhomerun_device_create_from_str(
    372         _device.toLocal8Bit().constData(), nullptr);
    373 
    374     if (!_hdhomerun_device)
     360    _device_selector = hdhomerun_device_selector_create(nullptr);
     361    if (!_device_selector)
    375362    {
    376         LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create hdhomerun object");
     363        LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to create device selector");
    377364        return false;
    378365    }
    379366
    380     _tuner = hdhomerun_device_get_tuner(_hdhomerun_device);
     367    QStringList devices = _device.split(",");
     368    for (int i = 0; i < devices.size(); ++i)
     369    {
     370        QByteArray ba = devices[i].toUtf8();
     371        int n = hdhomerun_device_selector_load_from_str(
     372            _device_selector, ba.data());
     373        LOG(VB_GENERAL, LOG_INFO, LOC + QString("Added %1 devices from %3")
     374            .arg(n).arg(devices[i]));
     375    }
    381376
    382     if (hdhomerun_device_get_local_machine_addr(_hdhomerun_device) == 0)
     377    _hdhomerun_device = hdhomerun_device_selector_choose_and_lock(
     378        _device_selector, nullptr);
     379    if (!_hdhomerun_device)
    383380    {
    384         LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to connect to device");
     381        LOG(VB_GENERAL, LOG_ERR, LOC +
     382            QString("Unable to find a free device"));
     383        hdhomerun_device_selector_destroy(_device_selector, true);
     384        _device_selector = nullptr;
    385385        return false;
    386386    }
    387387
    388     LOG(VB_RECORD, LOG_INFO, LOC + "Successfully connected to device");
    389     return true;
    390 }
     388    _tuner = hdhomerun_device_get_tuner(_hdhomerun_device);
    391389
    392 bool HDHRStreamHandler::EnterPowerSavingMode(void)
    393 {
    394     QMutexLocker locker(&_listener_lock);
     390    LOG(VB_GENERAL, LOG_INFO, LOC +
     391        QString("Connected to device(%1)")
     392        .arg(hdhomerun_device_get_name(_hdhomerun_device)));
    395393
    396     if (!_stream_data_list.empty())
    397     {
    398         LOG(VB_RECORD, LOG_INFO, LOC +
    399             "Ignoring request - video streaming active");
    400         return false;
    401     }
    402     else
    403     {
    404         locker.unlock(); // _listener_lock
    405         return TuneChannel("none");
    406     }
     394    return true;
    407395}
    408396
    409397QString HDHRStreamHandler::TunerGet(
  • mythtv/libs/libmythtv/recorders/hdhrstreamhandler.h

    diff --git a/mythtv/libs/libmythtv/recorders/hdhrstreamhandler.h b/mythtv/libs/libmythtv/recorders/hdhrstreamhandler.h
    index 70f8ae1853..02cb7f27b3 100644
    a b class DeviceReadBuffer; 
    3030#endif
    3131#else
    3232struct hdhomerun_device_t { int dummy; };
     33struct hdhomerun_device_selector_t { int dummy; };
    3334#endif
    3435
    3536enum HDHRTuneMode {
    enum HDHRTuneMode { 
    4950class HDHRStreamHandler : public StreamHandler
    5051{
    5152  public:
    52     static HDHRStreamHandler *Get(const QString &devicename, int inputid);
     53    static HDHRStreamHandler *Get(const QString &devicename, int inputid,
     54                                  int majorid);
    5355    static void Return(HDHRStreamHandler * & ref, int inputid);
    5456
    5557    void AddListener(MPEGStreamData *data,
    class HDHRStreamHandler : public StreamHandler 
    6870    bool TuneChannel(const QString &chanid);
    6971    bool TuneProgram(uint mpeg_prog_num);
    7072    bool TuneVChannel(const QString &vchn);
    71     bool EnterPowerSavingMode(void);
    7273
    7374  private:
    74     explicit HDHRStreamHandler(const QString &, int inputid);
     75    explicit HDHRStreamHandler(const QString &, int inputid, int majorid);
    7576
    7677    bool Connect(void);
    7778
    class HDHRStreamHandler : public StreamHandler 
    9192
    9293  private:
    9394    hdhomerun_device_t     *_hdhomerun_device;
     95    hdhomerun_device_selector_t *_device_selector;
    9496    int                     _tuner;
    9597    vector<DTVTunerType>    _tuner_types;
    9698    HDHRTuneMode            _tune_mode; // debug self check
     99    int                     _majorid;
    97100
    98101    mutable QMutex          _hdhr_lock;
    99102
    100103    // for implementing Get & Return
    101104    static QMutex                            _handlers_lock;
    102     static QMap<QString, HDHRStreamHandler*> _handlers;
    103     static QMap<QString, uint>               _handlers_refcnt;
     105    static QMap<int, HDHRStreamHandler*>    _handlers;
     106    static QMap<int, uint>                   _handlers_refcnt;
    104107};
    105108
    106109#endif // _HDHRSTREAMHANDLER_H_
  • mythtv/libs/libmythtv/tv_rec.h

    diff --git a/mythtv/libs/libmythtv/tv_rec.h b/mythtv/libs/libmythtv/tv_rec.h
    index a493582d47..3d8321a339 100644
    a b class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable 
    240240    /// \brief Returns the inputid
    241241    uint GetInputId(void) { return inputid; }
    242242    uint GetParentId(void) { return parentid; }
     243    uint GetMajorId(void) { return parentid ? parentid : inputid; }
    243244    /// \brief Returns true is "errored" is true, false otherwise.
    244245    bool IsErrored(void)  const { return HasFlags(kFlagErrored); }
    245246
  • mythtv/libs/libmythtv/videosource.cpp

    diff --git a/mythtv/libs/libmythtv/videosource.cpp b/mythtv/libs/libmythtv/videosource.cpp
    index 13d008bec5..06bffe4b38 100644
    a b static void FirewireConfigurationGroup(CaptureCard& parent, CardType& cardtype) 
    13831383// HDHomeRun Configuration
    13841384// -----------------------
    13851385
    1386 HDHomeRunIP::HDHomeRunIP()
     1386HDHomeRunDeviceID::HDHomeRunDeviceID(const CaptureCard &parent,
     1387                                     HDHomeRunConfigurationGroup &_group) :
     1388    MythUITextEditSetting(
     1389        new CaptureCardDBStorage(this, parent, "videodevice")),
     1390    group(_group)
    13871391{
    1388     setLabel(QObject::tr("IP Address"));
    1389     setEnabled(false);
    1390     connect(this, SIGNAL(valueChanged( const QString&)),
    1391             this, SLOT(  UpdateDevices(const QString&)));
    1392     _oldValue="";
    1393 };
    1394 
    1395 void HDHomeRunIP::setEnabled(bool e)
    1396 {
    1397     MythUITextEditSetting::setEnabled(e);
    1398     if (e)
    1399     {
    1400         if (!_oldValue.isEmpty())
    1401             setValue(_oldValue);
    1402         emit NewIP(getValue());
    1403     }
    1404     else
    1405     {
    1406         _oldValue = getValue();
    1407         _oldValue.detach();
    1408     }
    1409 }
    1410 
    1411 void HDHomeRunIP::UpdateDevices(const QString &v)
    1412 {
    1413    if (isEnabled())
    1414    {
    1415 #if 0
    1416        LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewIP(%1)").arg(v));
    1417 #endif
    1418        emit NewIP(v);
    1419    }
    1420 }
    1421 
    1422 HDHomeRunTunerIndex::HDHomeRunTunerIndex()
    1423 {
    1424     setLabel(QObject::tr("Tuner"));
    1425     setEnabled(false);
    1426     connect(this, SIGNAL(valueChanged( const QString&)),
    1427             this, SLOT(  UpdateDevices(const QString&)));
    1428     _oldValue = "";
     1392    setVisible(false);
    14291393};
    14301394
    1431 void HDHomeRunTunerIndex::setEnabled(bool e)
    1432 {
    1433     MythUITextEditSetting::setEnabled(e);
    1434     if (e) {
    1435         if (!_oldValue.isEmpty())
    1436             setValue(_oldValue);
    1437         emit NewTuner(getValue());
    1438     }
    1439     else
    1440     {
    1441         _oldValue = getValue();
    1442     }
    1443 }
    1444 
    1445 void HDHomeRunTunerIndex::UpdateDevices(const QString &v)
    1446 {
    1447    if (isEnabled())
    1448    {
    1449 #if 0
    1450        LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewTuner(%1)").arg(v));
    1451 #endif
    1452        emit NewTuner(v);
    1453    }
    1454 }
    1455 
    1456 HDHomeRunDeviceID::HDHomeRunDeviceID(const CaptureCard &parent) :
    1457     MythUITextEditSetting(new CaptureCardDBStorage(this, parent, "videodevice"))
    1458 {
    1459     setLabel(tr("Device ID"));
    1460     setHelpText(tr("Device ID of HDHomeRun device"));
    1461     setEnabled(false);
    1462 }
    1463 
    1464 void HDHomeRunDeviceID::SetIP(const QString &ip)
    1465 {
    1466 #if 0
    1467     LOG(VB_GENERAL, LOG_DEBUG, QString("Setting IP to %1").arg(ip));
    1468 #endif
    1469     _ip = ip;
    1470     setValue(QString("%1-%2").arg(_ip).arg(_tuner));
    1471 #if 0
    1472     LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting IP to %1").arg(ip));
    1473 #endif
    1474 }
    1475 
    1476 void HDHomeRunDeviceID::SetTuner(const QString &tuner)
    1477 {
    1478 #if 0
    1479     LOG(VB_GENERAL, LOG_DEBUG, QString("Setting Tuner to %1").arg(tuner));
    1480 #endif
    1481     _tuner = tuner;
    1482     setValue(QString("%1-%2").arg(_ip).arg(_tuner));
    1483 #if 0
    1484     LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting Tuner to %1").arg(tuner));
    1485 #endif
    1486 }
    1487 
    1488 void HDHomeRunDeviceID::SetOverrideDeviceID(const QString &deviceid)
    1489 {
    1490     _overridedeviceid = deviceid;
    1491     setValue(deviceid);
    1492 }
    1493 
    14941395void HDHomeRunDeviceID::Load(void)
    14951396{
    1496     GetStorage()->Load();
    1497     if (!_overridedeviceid.isEmpty())
    1498     {
    1499         setValue(_overridedeviceid);
    1500         _overridedeviceid.clear();
    1501     }
    1502 }
    1503 
    1504 HDHomeRunDeviceIDList::HDHomeRunDeviceIDList(
    1505     HDHomeRunDeviceID   *deviceid,
    1506     StandardSetting     *desc,
    1507     HDHomeRunIP         *cardip,
    1508     HDHomeRunTunerIndex *cardtuner,
    1509     HDHomeRunDeviceList *devicelist,
    1510     const CaptureCard &parent) :
    1511     _deviceid(deviceid),
    1512     _desc(desc),
    1513     _cardip(cardip),
    1514     _cardtuner(cardtuner),
    1515     _devicelist(devicelist),
    1516     m_parent(parent)
    1517 {
    1518     setLabel(QObject::tr("Available devices"));
    1519     setHelpText(
    1520         QObject::tr(
    1521             "Device ID and Tuner Number of available HDHomeRun devices."));
    1522 
    1523     connect(this, SIGNAL(valueChanged( const QString&)),
    1524             this, SLOT(  UpdateDevices(const QString&)));
    1525 
    1526     _oldValue = "";
    1527 };
    1528 
    1529 /// \brief Adds all available device-tuner combinations to list
    1530 /// If current is >= 0 it will be considered available even
    1531 /// if no device exists for it on the network
    1532 void HDHomeRunDeviceIDList::fillSelections(const QString &cur)
    1533 {
    1534     clearSelections();
    1535 
    1536     vector<QString> devs;
    1537     QMap<QString, bool> in_use;
    1538 
    1539     QString current = cur;
    1540 
    1541 #if 0
    1542     LOG(VB_GENERAL, LOG_DEBUG, QString("Filling List, current = '%1'")
    1543             .arg(current));
    1544 #endif
    1545 
    1546     HDHomeRunDeviceList::iterator it = _devicelist->begin();
    1547     for (; it != _devicelist->end(); ++it)
    1548     {
    1549         if ((*it).discovered)
    1550         {
    1551             devs.push_back(it.key());
    1552             in_use[it.key()] = (*it).inuse;
    1553         }
    1554     }
    1555 
    1556     QString man_addr = HDHomeRunDeviceIDList::tr("Manually Enter IP Address");
    1557     QString sel = man_addr;
    1558     devs.push_back(sel);
    1559 
    1560     if (3 == devs.size() && current.startsWith("FFFFFFFF", Qt::CaseInsensitive))
    1561     {
    1562         current = sel = (current.endsWith("0")) ?
    1563             *(devs.begin()) : *(++devs.begin());
    1564     }
    1565     else
    1566     {
    1567         vector<QString>::const_iterator it = devs.begin();
    1568         for (; it != devs.end(); ++it)
    1569             sel = (current == *it) ? *it : sel;
    1570     }
    1571 
    1572     QString usestr = QString(" -- ");
    1573     usestr += QObject::tr("Warning: already in use");
    1574 
    1575     for (uint i = 0; i < devs.size(); i++)
    1576     {
    1577         const QString dev = devs[i];
    1578         QString desc = dev + (in_use[devs[i]] ? usestr : "");
    1579         desc = (current == devs[i]) ? dev : desc;
    1580         addSelection(desc, dev, dev == sel);
    1581     }
    1582 
    1583     if (current != cur)
    1584     {
    1585         _deviceid->SetOverrideDeviceID(current);
    1586     }
    1587     else if (sel == man_addr && !current.isEmpty())
    1588     {
    1589         // Populate the proper values for IP address and tuner
    1590         QStringList selection = current.split("-");
    1591 
    1592         _cardip->SetOldValue(selection.first());
    1593         _cardtuner->SetOldValue(selection.last());
    1594 
    1595         _cardip->setValue(selection.first());
    1596         _cardtuner->setValue(selection.last());
    1597     }
     1397    MythUITextEditSetting::Load();
     1398    group.SetDeviceCheckBoxes(getValue());
    15981399}
    15991400
    1600 void HDHomeRunDeviceIDList::Load(void)
     1401void HDHomeRunDeviceID::Save(void)
    16011402{
    1602     clearSelections();
    1603 
    1604     int cardid = m_parent.getCardID();
    1605     QString device = CardUtil::GetVideoDevice(cardid);
    1606     fillSelections(device);
     1403    setValue(group.GetDeviceCheckBoxes());
     1404    MythUITextEditSetting::Save();
    16071405}
    16081406
    1609 void HDHomeRunDeviceIDList::UpdateDevices(const QString &v)
    1610 {
    1611 #if 0
    1612     LOG(VB_GENERAL, LOG_DEBUG, QString("Got signal with %1").arg(v));
    1613 #endif
    1614     if (v == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
    1615     {
    1616         _cardip->setEnabled(true);
    1617         _cardtuner->setEnabled(true);
    1618 #if 0
    1619         LOG(VB_GENERAL, LOG_DEBUG, "Done");
    1620 #endif
    1621     }
    1622     else if (!v.isEmpty())
    1623     {
    1624         if (_oldValue == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
    1625         {
    1626             _cardip->setEnabled(false);
    1627             _cardtuner->setEnabled(false);
    1628         }
    1629         _deviceid->setValue(v);
    1630 
    1631         // Update _cardip and cardtuner
    1632         _cardip->setValue((*_devicelist)[v].cardip);
    1633         _cardtuner->setValue(QString("%1").arg((*_devicelist)[v].cardtuner));
    1634         _desc->setValue((*_devicelist)[v].desc);
    1635     }
    1636     _oldValue = v;
    1637 };
    1638 
    16391407// -----------------------
    16401408// VBOX Configuration
    16411409// -----------------------
    class HDHomeRunEITScan : public MythUICheckBoxSetting 
    20781846};
    20791847
    20801848
     1849class UseHDHomeRunDevice : public TransMythUICheckBoxSetting
     1850{
     1851  public:
     1852    explicit UseHDHomeRunDevice(QString &deviceid, QString &hwmodel,
     1853                                QString &ipaddr) :
     1854        TransMythUICheckBoxSetting()
     1855    {
     1856        setLabel(QObject::tr("Use HDHomeRun %1 (%2 %3)")
     1857                 .arg(deviceid).arg(hwmodel).arg(ipaddr));
     1858        setValue(false);
     1859        setHelpText(
     1860            QObject::tr("If enabled, use tuners from this HDHomeRun "
     1861                        "device."));
     1862    };
     1863};
     1864
    20811865HDHomeRunConfigurationGroup::HDHomeRunConfigurationGroup
    20821866        (CaptureCard& a_parent, CardType &a_cardtype) :
    20831867    parent(a_parent)
    HDHomeRunConfigurationGroup::HDHomeRunConfigurationGroup 
    20871871    // Fill Device list
    20881872    FillDeviceList();
    20891873
    2090     deviceid     = new HDHomeRunDeviceID(parent);
    2091     desc         = new GroupSetting();
    2092     desc->setLabel(tr("Description"));
    2093     cardip       = new HDHomeRunIP();
    2094     cardtuner    = new HDHomeRunTunerIndex();
    2095     deviceidlist = new HDHomeRunDeviceIDList(
    2096         deviceid, desc, cardip, cardtuner, &devicelist, parent);
     1874    deviceid     = new HDHomeRunDeviceID(parent, *this);
    20971875
    2098     a_cardtype.addTargetedChild("HDHOMERUN", deviceidlist);
     1876    QMap<QString, HDHomeRunDevice>::iterator dit;
     1877    for (dit = devicelist.begin(); dit != devicelist.end(); ++dit)
     1878    {
     1879        HDHomeRunDevice &dev = *dit;
     1880        dev.checkbox = new UseHDHomeRunDevice(
     1881            dev.deviceid, dev.hwmodel, dev.cardip);
     1882        a_cardtype.addTargetedChild("HDHOMERUN", dev.checkbox);
     1883    }
    20991884    a_cardtype.addTargetedChild("HDHOMERUN", new EmptyAudioDevice(parent));
    21001885    a_cardtype.addTargetedChild("HDHOMERUN", new EmptyVBIDevice(parent));
    21011886    a_cardtype.addTargetedChild("HDHOMERUN", deviceid);
    2102     a_cardtype.addTargetedChild("HDHOMERUN", desc);
    2103     a_cardtype.addTargetedChild("HDHOMERUN", cardip);
    2104     a_cardtype.addTargetedChild("HDHOMERUN", cardtuner);
    21051887
    21061888    GroupSetting *buttonRecOpt = new GroupSetting();
    21071889    buttonRecOpt->setLabel(tr("Recording Options"));
    HDHomeRunConfigurationGroup::HDHomeRunConfigurationGroup 
    21091891    buttonRecOpt->addChild(new ChannelTimeout(parent, 3000, 1750));
    21101892    buttonRecOpt->addChild(new HDHomeRunEITScan(parent));
    21111893    a_cardtype.addTargetedChild("HDHOMERUN", buttonRecOpt);
    2112 
    2113     connect(cardip,    SIGNAL(NewIP(const QString&)),
    2114             deviceid,  SLOT(  SetIP(const QString&)));
    2115     connect(cardtuner, SIGNAL(NewTuner(const QString&)),
    2116             deviceid,  SLOT(  SetTuner(const QString&)));
    21171894};
    21181895
    21191896void HDHomeRunConfigurationGroup::FillDeviceList(void)
    void HDHomeRunConfigurationGroup::FillDeviceList(void) 
    21321909        QStringList devinfo = dev.split(" ");
    21331910        QString devid = devinfo.at(0);
    21341911        QString devip = devinfo.at(1);
    2135         QString devtuner = devinfo.at(2);
     1912        QString hwmodel = devinfo.at(2);
    21361913
    21371914        HDHomeRunDevice tmpdevice;
    2138         tmpdevice.deviceid   = devid;
    2139         tmpdevice.desc       = CardUtil::GetHDHRdesc(devid);
    2140         tmpdevice.cardip     = devip;
    2141         tmpdevice.inuse      = false;
    2142         tmpdevice.discovered = true;
    2143         tmpdevice.cardtuner = devtuner;
    2144         tmpdevice.mythdeviceid =
    2145             tmpdevice.deviceid + "-" + tmpdevice.cardtuner;
    2146         devicelist[tmpdevice.mythdeviceid] = tmpdevice;
    2147     }
    2148     uint found_device_count = devicelist.size();
    2149 
    2150     // Now find configured devices
    2151 
    2152     // returns "xxxxxxxx-n" or "ip.ip.ip.ip-n" values
    2153     QStringList db = CardUtil::GetVideoDevices("HDHOMERUN");
    2154 
    2155     for (it = db.begin(); it != db.end(); ++it)
    2156     {
    2157         QMap<QString, HDHomeRunDevice>::iterator dit;
    2158 
    2159         dit = devicelist.find(*it);
    2160 
    2161         if (dit == devicelist.end())
    2162         {
    2163             if ((*it).toUpper() == "FFFFFFFF-0" && 2 == found_device_count)
    2164                 dit = devicelist.begin();
    2165 
    2166             if ((*it).toUpper() == "FFFFFFFF-1" && 2 == found_device_count)
    2167             {
    2168                 dit = devicelist.begin();
    2169                 ++dit;
    2170             }
    2171         }
    2172 
    2173         if (dit != devicelist.end())
    2174         {
    2175             (*dit).inuse = true;
    2176             continue;
    2177         }
    2178 
    2179         HDHomeRunDevice tmpdevice;
    2180         tmpdevice.mythdeviceid = *it;
    2181         tmpdevice.inuse        = true;
    2182         tmpdevice.discovered   = false;
    2183 
    2184         if (ProbeCard(tmpdevice))
    2185             devicelist[tmpdevice.mythdeviceid] = tmpdevice;
     1915        tmpdevice.hwmodel  = hwmodel;
     1916        tmpdevice.cardip   = devip;
     1917        tmpdevice.deviceid = devid;
     1918        devicelist[tmpdevice.deviceid] = tmpdevice;
    21861919    }
    21871920
    21881921#if 0
    void HDHomeRunConfigurationGroup::FillDeviceList(void) 
    21901923    QMap<QString, HDHomeRunDevice>::iterator debugit;
    21911924    for (debugit = devicelist.begin(); debugit != devicelist.end(); ++debugit)
    21921925    {
    2193         LOG(VB_GENERAL, LOG_DEBUG, QString("%1: %2 %3 %4 %5 %6 %7")
    2194                 .arg(debugit.key())
    2195                 .arg((*debugit).mythdeviceid)
    2196                 .arg((*debugit).deviceid)
    2197                 .arg((*debugit).cardip)
    2198                 .arg((*debugit).cardtuner)
    2199                 .arg((*debugit).inuse)
    2200                 .arg((*debugit).discovered));
     1926        LOG(VB_GENERAL, LOG_DEBUG, QString("%1: %2 %3")
     1927            .arg(debugit.key()).arg((*debugit).hwmodel)
     1928            .arg((*debugit).cardip));
    22011929    }
    22021930#endif
    22031931}
    22041932
    2205 bool HDHomeRunConfigurationGroup::ProbeCard(HDHomeRunDevice &tmpdevice)
     1933void HDHomeRunConfigurationGroup::SetDeviceCheckBoxes(QString devices)
    22061934{
    2207 #ifdef USING_HDHOMERUN
    2208     hdhomerun_device_t *thisdevice =
    2209         hdhomerun_device_create_from_str(
    2210             tmpdevice.mythdeviceid.toLocal8Bit().constData(), nullptr);
    2211 
    2212     if (thisdevice)
     1935    QStringList devstrs = devices.split(",");
     1936    for (int i = 0; i < devstrs.size(); ++i)
    22131937    {
    2214         uint device_id = hdhomerun_device_get_device_id(thisdevice);
    2215         uint device_ip = hdhomerun_device_get_device_ip(thisdevice);
    2216         uint tuner     = hdhomerun_device_get_tuner(thisdevice);
    2217         hdhomerun_device_destroy(thisdevice);
    2218 
    2219         if (device_id == 0)
    2220             tmpdevice.deviceid = "NOTFOUND";
    2221         else
    2222         {
    2223             tmpdevice.deviceid = QString("%1").arg(device_id, 8, 16);
    2224             tmpdevice.desc     = CardUtil::GetHDHRdesc(tmpdevice.deviceid);
    2225         }
    2226 
    2227         tmpdevice.deviceid = tmpdevice.deviceid.toUpper();
     1938        // Get the HDHomeRun device ID using libhdhomerun.  We need to
     1939        // do it this way because legacy configurations could use an
     1940        // IP address and a tuner nubmer.
     1941        QByteArray ba = devstrs[i].toUtf8();
     1942        hdhomerun_device_t *device = hdhomerun_device_create_from_str(
     1943            ba.data(), nullptr);
     1944        if (!device)
     1945            continue;
     1946        QString devid = QString("%1").arg(
     1947            hdhomerun_device_get_device_id(device), 8, 16).toUpper();
     1948        hdhomerun_device_destroy(device);
    22281949
    2229         tmpdevice.cardip = QString("%1.%2.%3.%4")
    2230             .arg((device_ip>>24) & 0xFF).arg((device_ip>>16) & 0xFF)
    2231             .arg((device_ip>> 8) & 0xFF).arg((device_ip>> 0) & 0xFF);
     1950        // If we know about this device, set its checkbox to on.
     1951        QMap<QString, HDHomeRunDevice>::iterator dit;
     1952        dit = devicelist.find(devid);
     1953        if (dit != devicelist.end())
     1954            (*dit).checkbox->setValue(true);
     1955    }
     1956}
    22321957
    2233         tmpdevice.cardtuner = QString("%1").arg(tuner);
    2234         return true;
     1958QString HDHomeRunConfigurationGroup::GetDeviceCheckBoxes(void)
     1959{
     1960    // Return a string listing each HDHomeRun device with its checbox
     1961    // turned on.
     1962    QStringList devstrs;   
     1963    QMap<QString, HDHomeRunDevice>::iterator dit;
     1964    for (dit = devicelist.begin(); dit != devicelist.end(); ++dit)
     1965    {
     1966        if ((*dit).checkbox->boolValue())
     1967            devstrs << (*dit).deviceid;
    22351968    }
    2236 #endif // USING_HDHOMERUN
    2237     Q_UNUSED(tmpdevice);
    2238     return false;
     1969    QString devices = devstrs.join(",");
     1970    return devices;
    22391971}
    22401972
    22411973// -----------------------
  • mythtv/libs/libmythtv/videosource.h

    diff --git a/mythtv/libs/libmythtv/videosource.h b/mythtv/libs/libmythtv/videosource.h
    index a18fde4ee7..00f443950b 100644
    a b public: 
    380380    static void fillSelections(MythUIComboBoxSetting* setting);
    381381};
    382382
     383class UseHDHomeRunDevice;
     384
    383385class HDHomeRunDevice
    384386{
    385387  public:
    386     QString mythdeviceid;
    387388    QString deviceid;
    388     QString desc;
     389    QString hwmodel;
    389390    QString cardip;
    390     QString cardtuner;
    391     bool    inuse;
    392     bool    discovered;
     391    UseHDHomeRunDevice *checkbox;
    393392};
    394393
    395394typedef QMap<QString, HDHomeRunDevice> HDHomeRunDeviceList;
    396395
    397 class HDHomeRunDeviceIDList;
    398396class HDHomeRunDeviceID;
    399 class HDHomeRunIP;
    400 class HDHomeRunTunerIndex;
    401397class HDHomeRunConfigurationGroup : public GroupSetting
    402398{
    403399    Q_OBJECT
    class HDHomeRunConfigurationGroup : public GroupSetting 
    406402
    407403  public:
    408404    HDHomeRunConfigurationGroup(CaptureCard &parent, CardType &cardtype);
     405    void SetDeviceCheckBoxes(QString devices);
     406    QString GetDeviceCheckBoxes(void);
    409407
    410408  private:
    411409    void FillDeviceList(void);
    412     bool ProbeCard(HDHomeRunDevice&);
    413410
    414411  private:
    415412    CaptureCard           &parent;
    416     StandardSetting       *desc;
    417     HDHomeRunDeviceIDList *deviceidlist;
    418413    HDHomeRunDeviceID     *deviceid;
    419     HDHomeRunIP           *cardip;
    420     HDHomeRunTunerIndex   *cardtuner;
    421414    HDHomeRunDeviceList    devicelist;
    422415};
    423416
    class CardInput : public GroupSetting 
    878871    MythUICheckBoxSetting *schedgroup;
    879872};
    880873
    881 class HDHomeRunDeviceID;
    882 class HDHomeRunTunerIndex;
    883 
    884 class HDHomeRunIP : public MythUITextEditSetting
    885 {
    886     Q_OBJECT
    887 
    888   public:
    889     HDHomeRunIP();
    890 
    891     void setEnabled(bool e) override; // StandardSetting
    892     void SetOldValue(const QString &s)
    893         { _oldValue = s; _oldValue.detach(); };
    894 
    895   signals:
    896     void NewIP(const QString&);
    897 
    898   public slots:
    899     void UpdateDevices(const QString&);
    900 
    901   private:
    902     QString _oldValue;
    903 };
    904 
    905 class HDHomeRunTunerIndex : public MythUITextEditSetting
    906 {
    907     Q_OBJECT
    908 
    909   public:
    910     HDHomeRunTunerIndex();
    911 
    912     void setEnabled(bool e) override; // StandardSetting
    913     void SetOldValue(const QString &s)
    914         { _oldValue = s; _oldValue.detach(); };
    915 
    916   signals:
    917     void NewTuner(const QString&);
    918 
    919   public slots:
    920     void UpdateDevices(const QString&);
    921 
    922   private:
    923     QString _oldValue;
    924 };
    925 
    926 
    927 class HDHomeRunDeviceIDList : public TransMythUIComboBoxSetting
    928 {
    929     Q_OBJECT
    930 
    931   public:
    932     HDHomeRunDeviceIDList(HDHomeRunDeviceID *deviceid,
    933                           StandardSetting *desc,
    934                           HDHomeRunIP       *cardip,
    935                           HDHomeRunTunerIndex *cardtuner,
    936                           HDHomeRunDeviceList *devicelist,
    937                           const CaptureCard &parent);
    938 
    939     void fillSelections(const QString &current);
    940 
    941     void Load(void) override; // StandardSetting
    942 
    943   public slots:
    944     void UpdateDevices(const QString&);
    945 
    946   private:
    947     HDHomeRunDeviceID   *_deviceid;
    948     StandardSetting     *_desc;
    949     HDHomeRunIP         *_cardip;
    950     HDHomeRunTunerIndex *_cardtuner;
    951     HDHomeRunDeviceList *_devicelist;
    952     const CaptureCard &m_parent;
    953 
    954     QString              _oldValue;
    955 };
    956 
    957874class HDHomeRunDeviceID : public MythUITextEditSetting
    958875{
    959876    Q_OBJECT
    960877
    961878  public:
    962     explicit HDHomeRunDeviceID(const CaptureCard &parent);
    963 
     879    HDHomeRunDeviceID(const CaptureCard &parent,
     880                      HDHomeRunConfigurationGroup &_group);
    964881    void Load(void) override; // StandardSetting
    965 
    966   public slots:
    967     void SetIP(const QString&);
    968     void SetTuner(const QString&);
    969     void SetOverrideDeviceID(const QString&);
     882    void Save(void) override; // StandardSetting
    970883
    971884  private:
    972     QString _ip;
    973     QString _tuner;
    974     QString _overridedeviceid;
     885    HDHomeRunConfigurationGroup &group;
    975886};
    976887
    977888///