Ticket #11870: mythtv_ChannelScanSM_simplify_locking_poc.patch

File mythtv_ChannelScanSM_simplify_locking_poc.patch, 24.4 KB (added by Rune Petersen <rune@…>, 11 years ago)
  • mythtv/libs/libmythtv/channelscan/channelscan_sm.cpp

    diff --git a/mythtv/libs/libmythtv/channelscan/channelscan_sm.cpp b/mythtv/libs/libmythtv/channelscan/channelscan_sm.cpp
    index 3f02209..cbb685c 100644
    a b void ChannelScanSM::SetAnalog(bool is_analog) 
    253253
    254254void ChannelScanSM::HandleAllGood(void)
    255255{
    256     QMutexLocker locker(&lock);
    257 
    258     QString cur_chan = (*current).FriendlyName;
    259     QStringList list = cur_chan.split(" ", QString::SkipEmptyParts);
    260     QString freqid = (list.size() >= 2) ? list[1] : cur_chan;
    261 
    262     bool ok = false;
    263 
    264     QString msg = QObject::tr("Updated Channel %1").arg(cur_chan);
    265 
    266     if (!ChannelUtil::FindChannel(sourceID, freqid))
    267     {
    268         int chanid = ChannelUtil::CreateChanID(sourceID, freqid);
    269 
    270         QString callsign = QString("%1-%2")
    271             .arg(ChannelUtil::GetUnknownCallsign()).arg(chanid);
    272 
    273         ok = ChannelUtil::CreateChannel(
    274             0      /* mplexid */,
    275             sourceID,
    276             chanid,
    277             callsign,
    278             ""     /* service name       */,
    279             freqid /* channum            */,
    280             0      /* service id         */,
    281             0      /* ATSC major channel */,
    282             0      /* ATSC minor channel */,
    283             false  /* use on air guide   */,
    284             false  /* hidden             */,
    285             false  /* hidden in guide    */,
    286             freqid);
    287 
    288         msg = (ok) ?
    289             QObject::tr("Added Channel %1").arg(cur_chan) :
    290             QObject::tr("Failed to add channel %1").arg(cur_chan);
    291     }
    292     else
    293     {
    294         // nothing to do here, XMLTV & DataDirect have better info
    295     }
    296 
    297     scan_monitor->ScanAppendTextToLog(msg);
    298 
    299     // tell UI we are done with these channels
    300     if (scanning)
    301     {
    302         UpdateScanPercentCompleted();
    303         waitingForTables = false;
    304         nextIt = current.nextTransport();
    305     }
     256    postEvent(Event(kEventReceivedAllGood));
    306257}
    307258
    308259/**
    bool ChannelScanSM::ScanExistingTransports(uint sourceid, bool follow_nit) 
    360311
    361312void ChannelScanSM::HandlePAT(const ProgramAssociationTable *pat)
    362313{
    363     QMutexLocker locker(&lock);
    364 
    365     LOG(VB_CHANSCAN, LOG_INFO, LOC +
    366         QString("Got a Program Association Table for %1")
    367             .arg((*current).FriendlyName) + "\n" + pat->toString());
    368 
    369     // Add pmts to list, so we can do MPEG scan properly.
    370     ScanStreamData *sd = GetDTVSignalMonitor()->GetScanStreamData();
    371     for (uint i = 0; i < pat->ProgramCount(); i++)
    372     {
    373         if (pat->ProgramPID(i)) // don't add NIT "program", MPEG/ATSC safe.
    374             sd->AddListeningPID(pat->ProgramPID(i));
    375     }
     314    Event event(kEventReceivedPAT);
     315    event.table = new ProgramAssociationTable(*pat);
     316    postEvent(event);
    376317}
    377318
    378319void ChannelScanSM::HandlePMT(uint, const ProgramMapTable *pmt)
    379320{
    380     QMutexLocker locker(&lock);
    381 
    382     LOG(VB_CHANSCAN, LOG_INFO, LOC + QString("Got a Program Map Table for %1")
    383             .arg((*current).FriendlyName) + "\n" + pmt->toString());
    384 
    385     if (!currentTestingDecryption && pmt->IsEncrypted(GetDTVChannel()->GetSIStandard()))
    386         currentEncryptionStatus[pmt->ProgramNumber()] = kEncUnknown;
     321    Event event(kEventReceivedPMT);
     322    event.table = new ProgramMapTable(*pmt);
     323    postEvent(event);
    387324}
    388325
    389326void ChannelScanSM::HandleVCT(uint, const VirtualChannelTable *vct)
    390327{
    391     QMutexLocker locker(&lock);
     328    Event event(kEventReceivedVCT);
     329    switch( vct->TableID() )
     330    {
     331    case TableID::TVCT:
     332        event.table = new TerrestrialVirtualChannelTable(*vct);
     333        break;
    392334
    393     LOG(VB_CHANSCAN, LOG_INFO, LOC +
    394         QString("Got a Virtual Channel Table for %1")
    395             .arg((*current).FriendlyName) + "\n" + vct->toString());
     335    case TableID::CVCT:
     336        event.table = new CableVirtualChannelTable(*vct);
     337        break;
    396338
    397     for (uint i = 0; !currentTestingDecryption && i < vct->ChannelCount(); i++)
    398     {
    399         if (vct->IsAccessControlled(i))
    400         {
    401             currentEncryptionStatus[vct->ProgramNumber(i)] = kEncUnknown;
    402         }
     339    default: assert(0);
    403340    }
    404 
    405     UpdateChannelInfo(true);
     341    postEvent(event);
    406342}
    407343
    408344void ChannelScanSM::HandleMGT(const MasterGuideTable *mgt)
    409345{
    410     QMutexLocker locker(&lock);
    411 
    412     LOG(VB_CHANSCAN, LOG_INFO, LOC + QString("Got the Master Guide for %1")
    413             .arg((*current).FriendlyName) + "\n" + mgt->toString());
    414 
    415     UpdateChannelInfo(true);
     346    Event event(kEventReceivedMGT);
     347    event.table = new MasterGuideTable(*mgt);
     348    postEvent(event);
    416349}
    417350
    418351void ChannelScanSM::HandleSDT(uint tsid, const ServiceDescriptionTable *sdt)
    419352{
    420     QMutexLocker locker(&lock);
    421 
    422     LOG(VB_CHANSCAN, LOG_INFO, LOC +
    423         QString("Got a Service Description Table for %1")
    424             .arg((*current).FriendlyName) + "\n" + sdt->toString());
    425 
    426     // If this is Astra 28.2 add start listening for Freesat BAT and SDTo
    427     if (!setOtherTables && (sdt->OriginalNetworkID() == 2 ||
    428         sdt->OriginalNetworkID() == 59))
    429     {
    430         GetDTVSignalMonitor()->GetScanStreamData()->
    431                                SetFreesatAdditionalSI(true);
    432         setOtherTables = true;
    433         // The whole BAT & SDTo group comes round in 10s
    434         otherTableTimeout = 10000;
    435         // Delay processing the SDT until we've seen BATs and SDTos
    436         otherTableTime = timer.elapsed() + otherTableTimeout;
    437 
    438         LOG(VB_CHANSCAN, LOG_INFO, LOC +
    439             QString("SDT has OriginalNetworkID %1, look for "
    440                     "additional Freesat SI").arg(sdt->OriginalNetworkID()));
    441     }
    442 
    443     if ((uint)timer.elapsed() < otherTableTime)
    444     {
    445         // Set the version for the SDT so we see it again.
    446         GetDTVSignalMonitor()->GetDVBStreamData()->SetVersionSDT(sdt->TSID(), -1, 0);
    447     }
    448 
    449     uint id = sdt->OriginalNetworkID() << 16 | sdt->TSID();
    450     ts_scanned.insert(id);
    451 
    452     for (uint i = 0; !currentTestingDecryption && i < sdt->ServiceCount(); i++)
    453     {
    454         if (sdt->IsEncrypted(i))
    455         {
    456             currentEncryptionStatus[sdt->ServiceID(i)] = kEncUnknown;
    457         }
    458     }
    459 
    460     UpdateChannelInfo(true);
     353    Event event(kEventReceivedSDT);
     354    event.tsid = tsid;
     355    event.table = new ServiceDescriptionTable(*sdt);
     356    postEvent(event);
    461357}
    462358
    463359void ChannelScanSM::HandleNIT(const NetworkInformationTable *nit)
    464360{
    465     QMutexLocker locker(&lock);
    466 
    467     LOG(VB_CHANSCAN, LOG_INFO, LOC +
    468         QString("Got a Network Information Table for %1")
    469             .arg((*current).FriendlyName) + "\n" + nit->toString());
    470 
    471     UpdateChannelInfo(true);
     361    Event event(kEventReceivedNIT);
     362    event.table = new NetworkInformationTable(*nit);
     363    postEvent(event);
    472364}
    473365
    474366void ChannelScanSM::HandleBAT(const BouquetAssociationTable *bat)
    475367{
    476     QMutexLocker locker(&lock);
    477 
    478     LOG(VB_CHANSCAN, LOG_INFO, LOC + "Got a Bouquet Association Table\n" +
    479         bat->toString());
    480 
    481     otherTableTime = timer.elapsed() + otherTableTimeout;
    482 
    483     for (uint i = 0; i < bat->TransportStreamCount(); i++)
    484     {
    485         uint tsid = bat->TSID(i);
    486         uint netid = bat->OriginalNetworkID(i);
    487         desc_list_t parsed =
    488             MPEGDescriptor::Parse(bat->TransportDescriptors(i),
    489                                   bat->TransportDescriptorsLength(i));
    490         // Look for default authority
    491         const unsigned char *def_auth =
    492             MPEGDescriptor::Find(parsed, DescriptorID::default_authority);
    493         const unsigned char *serv_list =
    494             MPEGDescriptor::Find(parsed, DescriptorID::service_list);
    495 
    496         if (def_auth && serv_list)
    497         {
    498             DefaultAuthorityDescriptor authority(def_auth);
    499             ServiceListDescriptor services(serv_list);
    500 
    501             for (uint j = 0; j < services.ServiceCount(); j++)
    502             {
    503                 // If the default authority is given in the SDT this
    504                 // overrides any definition in the BAT (or in the NIT)
    505                 LOG(VB_CHANSCAN, LOG_INFO, LOC +
    506                     QString("found default authority(BAT) for service %1 %2 %3")
    507                         .arg(netid).arg(tsid).arg(services.ServiceID(j)));
    508                uint64_t index = ((uint64_t)netid << 32) | (tsid << 16) |
    509                                  services.ServiceID(j);
    510                if (! defAuthorities.contains(index))
    511                    defAuthorities[index] = authority.DefaultAuthority();
    512             }
    513         }
    514     }
     368    Event event(kEventReceivedBAT);
     369    event.table = new BouquetAssociationTable(*bat);
     370    postEvent(event);
    515371}
    516372
    517373void ChannelScanSM::HandleSDTo(uint tsid, const ServiceDescriptionTable *sdt)
    518374{
    519     QMutexLocker locker(&lock);
    520 
    521     LOG(VB_CHANSCAN, LOG_INFO, LOC +
    522         "Got a Service Description Table (other)\n" + sdt->toString());
    523 
    524     otherTableTime = timer.elapsed() + otherTableTimeout;
    525 
    526     uint netid = sdt->OriginalNetworkID();
    527 
    528     for (uint i = 0; i < sdt->ServiceCount(); i++)
    529     {
    530         uint serviceId = sdt->ServiceID(i);
    531         desc_list_t parsed =
    532             MPEGDescriptor::Parse(sdt->ServiceDescriptors(i),
    533                                   sdt->ServiceDescriptorsLength(i));
    534         // Look for default authority
    535         const unsigned char *def_auth =
    536             MPEGDescriptor::Find(parsed, DescriptorID::default_authority);
    537         if (def_auth)
    538         {
    539             DefaultAuthorityDescriptor authority(def_auth);
    540             LOG(VB_CHANSCAN, LOG_INFO, LOC +
    541                 QString("found default authority(SDTo) for service %1 %2 %3")
    542                     .arg(netid).arg(tsid).arg(serviceId));
    543             defAuthorities[((uint64_t)netid << 32) | (tsid << 16) | serviceId] =
    544                 authority.DefaultAuthority();
    545         }
    546     }
     375    Event event(kEventReceivedSDTo);
     376    event.tsid = tsid;
     377    event.table = new ServiceDescriptionTable(*sdt);
     378    postEvent(event);
    547379}
    548380
    549381void ChannelScanSM::HandleEncryptionStatus(uint pnum, bool encrypted)
    550382{
    551     QMutexLocker locker(&lock);
    552 
    553     currentEncryptionStatus[pnum] = encrypted ? kEncEncrypted : kEncDecrypted;
    554 
    555     if (kEncDecrypted == currentEncryptionStatus[pnum])
    556         currentTestingDecryption = false;
    557 
    558     UpdateChannelInfo(true);
     383    Event event(kEventEncryptionStatus);
     384    event.pnum = pnum;
     385    event.encrypted = encrypted;
     386    postEvent(event);
    559387}
    560388
    561389bool ChannelScanSM::TestNextProgramEncryption(void)
    void ChannelScanSM::run(void) 
    14781306
    14791307    while (!threadExit)
    14801308    {
     1309        Event event;
     1310        if( waitEvent(event, 50) )
     1311        {
     1312            processEvent(event);
     1313        }
     1314       
    14811315        if (scanning)
    14821316            HandleActiveScan();
    1483 
    1484         usleep(10 * 1000);
    14851317    }
    14861318
    14871319    LOG(VB_CHANSCAN, LOG_INFO, LOC + "run -- end");
    bool ChannelScanSM::HasTimedOut(void) 
    15711403 */
    15721404void ChannelScanSM::HandleActiveScan(void)
    15731405{
    1574     QMutexLocker locker(&lock);
    1575 
    15761406    bool do_post_insertion = waitingForTables;
    15771407
    15781408    if (!HasTimedOut())
    void ChannelScanSM::HandleActiveScan(void) 
    15851415            return;
    15861416
    15871417        // Stop signal monitor for previous transport
    1588         locker.unlock();
    15891418        signalMonitor->Stop();
    1590         locker.relock();
    15911419    }
    15921420
    15931421    if (0 == nextIt.offset() && nextIt == scanTransports.begin())
    bool ChannelScanSM::CheckImportedList( 
    20771905
    20781906    return found;
    20791907}
     1908
     1909void ChannelScanSM::postEvent(const Event &event)
     1910{
     1911    {
     1912        QMutexLocker locker(&eventLock);
     1913        eventQueue.push_back(event);
     1914    }
     1915    eventSemaphore.release();
     1916}
     1917
     1918bool ChannelScanSM::waitEvent(Event &event, int32_t timeout)
     1919{
     1920    if( eventSemaphore.tryAcquire(1, timeout) )
     1921    {
     1922        QMutexLocker locker(&eventLock);
     1923        event = eventQueue.front();
     1924        eventQueue.pop_front();
     1925        return true;
     1926    }
     1927    return false;
     1928}
     1929void ChannelScanSM::processEvent(Event &event)
     1930{
     1931    if( !scanning )
     1932    {
     1933        delete event.table;
     1934        event.table = NULL;
     1935        return;
     1936    }
     1937
     1938    assert( event.type!=kEventInvalid );
     1939    switch( event.type )
     1940    {
     1941        case kEventInvalid:
     1942            //TODO:: print error or assert
     1943            break;
     1944        case kEventWakeup:
     1945            UpdateChannelInfo(true);
     1946            break;
     1947        case kEventReceivedPAT:
     1948            processPAT(static_cast<ProgramAssociationTable *>(event.table));
     1949            break;
     1950        case kEventReceivedPMT:
     1951            processPMT(static_cast<ProgramMapTable *>(event.table));
     1952            break;
     1953        case kEventEncryptionStatus:
     1954            processEncryptionStatus(event.pnum, event.encrypted);
     1955            break;
     1956        case kEventReceivedMGT:
     1957            processMGT(static_cast<MasterGuideTable *>(event.table));
     1958            break;
     1959        case kEventReceivedVCT:
     1960            processVCT(event.tsid, static_cast<VirtualChannelTable *>(event.table));
     1961            break;
     1962        case kEventReceivedNIT:
     1963            processNIT(static_cast<NetworkInformationTable *>(event.table));
     1964            break;
     1965        case kEventReceivedSDT:
     1966            processSDT(event.tsid, static_cast<ServiceDescriptionTable *>(event.table));
     1967            break;
     1968        case kEventReceivedSDTo:
     1969            processSDTo(event.tsid, static_cast<ServiceDescriptionTable *>(event.table));
     1970            break;
     1971        case kEventReceivedBAT:
     1972            processBAT(static_cast<BouquetAssociationTable *>(event.table));
     1973            break;
     1974        case kEventReceivedAllGood:
     1975            processAllGood();
     1976            break;
     1977     }
     1978
     1979    delete event.table;
     1980    event.table = NULL;
     1981}
     1982
     1983void ChannelScanSM::processPAT(const ProgramAssociationTable *pat)
     1984{
     1985    LOG(VB_CHANSCAN, LOG_INFO, LOC +
     1986        QString("Got a Program Association Table for %1")
     1987            .arg((*current).FriendlyName) + "\n" + pat->toString());
     1988
     1989    // Add pmts to list, so we can do MPEG scan properly.
     1990    ScanStreamData *sd = GetDTVSignalMonitor()->GetScanStreamData();
     1991    for (uint i = 0; i < pat->ProgramCount(); i++)
     1992    {
     1993        if (pat->ProgramPID(i)) // don't add NIT "program", MPEG/ATSC safe.
     1994            sd->AddListeningPID(pat->ProgramPID(i));
     1995    }
     1996}
     1997
     1998void ChannelScanSM::processPMT(const ProgramMapTable*pmt)
     1999{
     2000    LOG(VB_CHANSCAN, LOG_INFO, LOC + QString("Got a Program Map Table for %1")
     2001            .arg((*current).FriendlyName) + "\n" + pmt->toString());
     2002
     2003    if (!currentTestingDecryption && pmt->IsEncrypted(GetDTVChannel()->GetSIStandard()))
     2004        currentEncryptionStatus[pmt->ProgramNumber()] = kEncUnknown;
     2005}
     2006
     2007void ChannelScanSM::processEncryptionStatus(uint pnum, bool encrypted)
     2008{
     2009    currentEncryptionStatus[pnum] = encrypted ? kEncEncrypted : kEncDecrypted;
     2010
     2011    if (kEncDecrypted == currentEncryptionStatus[pnum])
     2012        currentTestingDecryption = false;
     2013
     2014    UpdateChannelInfo(true);
     2015}
     2016
     2017void ChannelScanSM::processMGT(const MasterGuideTable *mgt)
     2018{
     2019    LOG(VB_CHANSCAN, LOG_INFO, LOC + QString("Got the Master Guide for %1")
     2020            .arg((*current).FriendlyName) + "\n" + mgt->toString());
     2021
     2022    UpdateChannelInfo(true);
     2023}
     2024
     2025void ChannelScanSM::processVCT(uint tsid, const VirtualChannelTable *vct)
     2026{
     2027    LOG(VB_CHANSCAN, LOG_INFO, LOC +
     2028        QString("Got a Virtual Channel Table for %1")
     2029            .arg((*current).FriendlyName) + "\n" + vct->toString());
     2030
     2031    for (uint i = 0; !currentTestingDecryption && i < vct->ChannelCount(); i++)
     2032    {
     2033        if (vct->IsAccessControlled(i))
     2034        {
     2035            currentEncryptionStatus[vct->ProgramNumber(i)] = kEncUnknown;
     2036        }
     2037    }
     2038
     2039    UpdateChannelInfo(true);
     2040}
     2041
     2042void ChannelScanSM::processNIT(const NetworkInformationTable *nit)
     2043{
     2044    LOG(VB_CHANSCAN, LOG_INFO, LOC +
     2045        QString("Got a Network Information Table for %1")
     2046            .arg((*current).FriendlyName) + "\n" + nit->toString());
     2047
     2048    UpdateChannelInfo(true);
     2049}
     2050
     2051void ChannelScanSM::processSDT(uint tsid, const ServiceDescriptionTable *sdt)
     2052{
     2053    LOG(VB_CHANSCAN, LOG_INFO, LOC +
     2054        QString("Got a Service Description Table for %1")
     2055            .arg((*current).FriendlyName) + "\n" + sdt->toString());
     2056
     2057    // If this is Astra 28.2 add start listening for Freesat BAT and SDTo
     2058    if (!setOtherTables && (sdt->OriginalNetworkID() == 2 ||
     2059        sdt->OriginalNetworkID() == 59))
     2060    {
     2061        GetDTVSignalMonitor()->GetScanStreamData()->
     2062                               SetFreesatAdditionalSI(true);
     2063        setOtherTables = true;
     2064        // The whole BAT & SDTo group comes round in 10s
     2065        otherTableTimeout = 10000;
     2066        // Delay processing the SDT until we've seen BATs and SDTos
     2067        otherTableTime = timer.elapsed() + otherTableTimeout;
     2068
     2069        LOG(VB_CHANSCAN, LOG_INFO, LOC +
     2070            QString("SDT has OriginalNetworkID %1, look for "
     2071                    "additional Freesat SI").arg(sdt->OriginalNetworkID()));
     2072    }
     2073
     2074    if ((uint)timer.elapsed() < otherTableTime)
     2075    {
     2076        // Set the version for the SDT so we see it again.
     2077        GetDTVSignalMonitor()->GetDVBStreamData()->SetVersionSDT(sdt->TSID(), -1, 0);
     2078    }
     2079
     2080    uint id = sdt->OriginalNetworkID() << 16 | sdt->TSID();
     2081    ts_scanned.insert(id);
     2082
     2083    for (uint i = 0; !currentTestingDecryption && i < sdt->ServiceCount(); i++)
     2084    {
     2085        if (sdt->IsEncrypted(i))
     2086        {
     2087            currentEncryptionStatus[sdt->ServiceID(i)] = kEncUnknown;
     2088        }
     2089    }
     2090
     2091    UpdateChannelInfo(true);
     2092}
     2093
     2094void ChannelScanSM::processSDTo(uint tsid, const ServiceDescriptionTable *sdt)
     2095{
     2096    LOG(VB_CHANSCAN, LOG_INFO, LOC +
     2097        "Got a Service Description Table (other)\n" + sdt->toString());
     2098
     2099    otherTableTime = timer.elapsed() + otherTableTimeout;
     2100
     2101    uint netid = sdt->OriginalNetworkID();
     2102
     2103    for (uint i = 0; i < sdt->ServiceCount(); i++)
     2104    {
     2105        uint serviceId = sdt->ServiceID(i);
     2106        desc_list_t parsed =
     2107            MPEGDescriptor::Parse(sdt->ServiceDescriptors(i),
     2108                                  sdt->ServiceDescriptorsLength(i));
     2109        // Look for default authority
     2110        const unsigned char *def_auth =
     2111            MPEGDescriptor::Find(parsed, DescriptorID::default_authority);
     2112        if (def_auth)
     2113        {
     2114            DefaultAuthorityDescriptor authority(def_auth);
     2115            LOG(VB_CHANSCAN, LOG_INFO, LOC +
     2116                QString("found default authority(SDTo) for service %1 %2 %3")
     2117                    .arg(netid).arg(tsid).arg(serviceId));
     2118            defAuthorities[((uint64_t)netid << 32) | (tsid << 16) | serviceId] =
     2119                authority.DefaultAuthority();
     2120        }
     2121    }
     2122}
     2123
     2124void ChannelScanSM::processBAT(const BouquetAssociationTable *bat)
     2125{
     2126    LOG(VB_CHANSCAN, LOG_INFO, LOC + "Got a Bouquet Association Table\n" +
     2127        bat->toString());
     2128
     2129    otherTableTime = timer.elapsed() + otherTableTimeout;
     2130
     2131    for (uint i = 0; i < bat->TransportStreamCount(); i++)
     2132    {
     2133        uint tsid = bat->TSID(i);
     2134        uint netid = bat->OriginalNetworkID(i);
     2135        desc_list_t parsed =
     2136            MPEGDescriptor::Parse(bat->TransportDescriptors(i),
     2137                                  bat->TransportDescriptorsLength(i));
     2138        // Look for default authority
     2139        const unsigned char *def_auth =
     2140            MPEGDescriptor::Find(parsed, DescriptorID::default_authority);
     2141        const unsigned char *serv_list =
     2142            MPEGDescriptor::Find(parsed, DescriptorID::service_list);
     2143
     2144        if (def_auth && serv_list)
     2145        {
     2146            DefaultAuthorityDescriptor authority(def_auth);
     2147            ServiceListDescriptor services(serv_list);
     2148
     2149            for (uint j = 0; j < services.ServiceCount(); j++)
     2150            {
     2151                // If the default authority is given in the SDT this
     2152                // overrides any definition in the BAT (or in the NIT)
     2153                LOG(VB_CHANSCAN, LOG_INFO, LOC +
     2154                    QString("found default authority(BAT) for service %1 %2 %3")
     2155                        .arg(netid).arg(tsid).arg(services.ServiceID(j)));
     2156               uint64_t index = ((uint64_t)netid << 32) | (tsid << 16) |
     2157                                 services.ServiceID(j);
     2158               if (! defAuthorities.contains(index))
     2159                   defAuthorities[index] = authority.DefaultAuthority();
     2160            }
     2161        }
     2162    }
     2163}
     2164
     2165void ChannelScanSM::processAllGood()
     2166{
     2167    QString cur_chan = (*current).FriendlyName;
     2168    QStringList list = cur_chan.split(" ", QString::SkipEmptyParts);
     2169    QString freqid = (list.size() >= 2) ? list[1] : cur_chan;
     2170
     2171    bool ok = false;
     2172
     2173    QString msg = QObject::tr("Updated Channel %1").arg(cur_chan);
     2174
     2175    if (!ChannelUtil::FindChannel(sourceID, freqid))
     2176    {
     2177        int chanid = ChannelUtil::CreateChanID(sourceID, freqid);
     2178
     2179        QString callsign = QString("%1-%2")
     2180            .arg(ChannelUtil::GetUnknownCallsign()).arg(chanid);
     2181
     2182        ok = ChannelUtil::CreateChannel(
     2183            0      /* mplexid */,
     2184            sourceID,
     2185            chanid,
     2186            callsign,
     2187            ""     /* service name       */,
     2188            freqid /* channum            */,
     2189            0      /* service id         */,
     2190            0      /* ATSC major channel */,
     2191            0      /* ATSC minor channel */,
     2192            false  /* use on air guide   */,
     2193            false  /* hidden             */,
     2194            false  /* hidden in guide    */,
     2195            freqid);
     2196
     2197        msg = (ok) ?
     2198            QObject::tr("Added Channel %1").arg(cur_chan) :
     2199            QObject::tr("Failed to add channel %1").arg(cur_chan);
     2200    }
     2201    else
     2202    {
     2203        // nothing to do here, XMLTV & DataDirect have better info
     2204    }
     2205
     2206    scan_monitor->ScanAppendTextToLog(msg);
     2207
     2208    // tell UI we are done with these channels
     2209    if (scanning)
     2210    {
     2211        UpdateScanPercentCompleted();
     2212        waitingForTables = false;
     2213        nextIt = current.nextTransport();
     2214    }
     2215}
  • mythtv/libs/libmythtv/channelscan/channelscan_sm.h

    diff --git a/mythtv/libs/libmythtv/channelscan/channelscan_sm.h b/mythtv/libs/libmythtv/channelscan/channelscan_sm.h
    index 813113a..2c90a9b 100644
    a b  
    3737#include <QPair>
    3838#include <QMap>
    3939#include <QSet>
     40#include <QSemaphore>
    4041
    4142// MythTV includes
    4243#include "frequencytables.h"
    class ChannelScanSM : public MPEGStreamListener, 
    154155    void HandleBAT(const BouquetAssociationTable*);
    155156
    156157  private:
     158    enum EventType
     159    {
     160        kEventInvalid,
     161        kEventWakeup,
     162        kEventReceivedPAT,
     163        kEventReceivedPMT,
     164        kEventEncryptionStatus,
     165        kEventReceivedMGT,
     166        kEventReceivedVCT,
     167        kEventReceivedNIT,
     168        kEventReceivedSDT,
     169        kEventReceivedSDTo,
     170        kEventReceivedBAT,
     171        kEventReceivedAllGood,
     172    };
     173    struct Event
     174    {
     175        Event() : type(kEventInvalid), tsid(0), table(NULL), encrypted(false) {}
     176        Event(EventType type_) : type(type_), tsid(0), table(NULL), encrypted(false) {}
     177        EventType   type;
     178        union
     179        {
     180            uint    tsid;
     181            uint    pnum;
     182        };
     183        PSIPTable  *table;
     184        bool        encrypted;
     185    };
     186  private:
    157187    // some useful gets
    158188    DTVChannel       *GetDTVChannel(void);
    159189    const DTVChannel *GetDTVChannel(void) const;
    class ChannelScanSM : public MPEGStreamListener, 
    195225
    196226    static QString loc(const ChannelScanSM*);
    197227
     228    void postEvent(const Event &event);
     229    bool waitEvent(Event &event, int32_t timeout);
     230
     231    void processEvent(Event &event);
     232    void processPAT(const ProgramAssociationTable*);
     233    void processPMT(const ProgramMapTable*);
     234    void processEncryptionStatus(uint pnum, bool encrypted);
     235
     236    void processMGT(const MasterGuideTable*);
     237    void processVCT(uint tsid, const VirtualChannelTable*);
     238    void processNIT(const NetworkInformationTable*);
     239    void processSDT(uint tsid, const ServiceDescriptionTable*);
     240    void processSDTo(uint tsid, const ServiceDescriptionTable*);
     241    void processBAT(const BouquetAssociationTable*);
     242    void processAllGood();
     243
    198244    static const uint kDVBTableTimeout;
    199245    static const uint kATSCTableTimeout;
    200246    static const uint kMPEGTableTimeout;
    class ChannelScanSM : public MPEGStreamListener, 
    217263    // Optional info
    218264    DTVTunerType      scanDTVTunerType;
    219265
    220     /// The big lock
    221     mutable QMutex    lock;
    222 
    223266    // State
    224267    bool              scanning;
    225268    volatile bool     threadExit;
    class ChannelScanSM : public MPEGStreamListener, 
    248291
    249292    /// Scanner thread, runs ChannelScanSM::run()
    250293    MThread          *scannerThread;
     294
     295    QSemaphore       eventSemaphore;
     296    QMutex           eventLock;
     297    QVector<Event>   eventQueue;
     298   
    251299};
    252300
    253301inline void ChannelScanSM::UpdateScanPercentCompleted(void)