Ticket #49: analogscan.patch

File analogscan.patch, 14.5 KB (added by John Pullan <john.pullan@…>, 19 years ago)

makes analog scan use the channel class.

  • analogscan.h

     
    5858    /** @brief Stops the scanning thread running */
    5959    void stop();
    6060
    61     /** @brief Scans the given frequency list, implies start()
    62         @see start()
    63      */
    64     bool scan(unsigned nList);
    65     /** @brief Scans the given frequency table, implies start()
    66         @see start()
    67      */
    68     bool scan(const QString& table);
     61    /** @brief Scans the given frequency list, implies starting the thread() */
     62    bool scan();
    6963
    7064signals:
    7165    /** @brief Indicates how far through the scan we are as a percentage
     
    8680    unsigned sourceid;
    8781    unsigned cardid;
    8882    unsigned nTable;
    89     int fd;
    90     QString device;
    91     QString vbidevice;
    92     struct vbi *vbi;
    9383
    94     /** @brief Is the current channel tuned
    95         @returns true if tuned
    96       */
    97     bool isTuned();
    9884    /** @brief adds a found channel to the database
    9985        @param name name of the channel
    10086        @param frequency freqency/frequencyid of the channel
    10187      */
    102     void addChannel(const QString& name, int frequency);
    103     /** @brief find the next available channel id
    104         @param sourceID the source id of the video source to check
    105     */
    106     int generateNewChanID(int sourceID);
    107     /** @brief Starts the scanning thread running */
    108     bool start();
    109 
    110     /** @brief Controls access to the thread*/
    111     pthread_mutex_t lock;
     88    void addChannel(int number, const QString& channum,
     89                    const QString& name, int frequency);
    11290    /** @brief Scanning thread*/
    11391    pthread_t thread;
    114     /** @brief vbi thread*/
    115     pthread_t threadVBI;
    11692
    11793    /** @brief Actual scanning proc */
    11894    void doScan();
    11995    /** @brief Actual thread proc , calls doScan*/
    12096    static void *spawn(void *param);
    121     /** @brief Actual thread proc for vbi, calls doVBI*/
    122     static void *spawnVBI(void *param);
    123     /** @brief Actual vbi proc */
    124     void doVBI();
    125     /** @brief vbi callback proc */
    126     static void vbi_event(AnalogScan* data, struct vt_event *ev);
    12797};
    12898#endif //ANALOGSCAN_H
  • videosource.h

     
    6767    static DISEQC_TYPES GetDISEqCType(uint cardid);
    6868
    6969    static CARD_TYPES   GetDVBType(uint device, QString &name);
     70    static QString      GetDefaultInput(uint cardid);
    7071};
    7172
    7273class VideoSource;
  • videosource.cpp

     
    297297    return (DISEQC_TYPES)iRet;
    298298}
    299299
     300/** \fn CardUtil::GetDefaultInput(uint)
     301 *  \brief Returns the default input for the card
     302 *  \param [in]nCardID card id to check
     303 *  \return the default input
     304 */
     305QString CardUtil::GetDefaultInput(uint nCardID)
     306{
     307    QString str;
     308    MSqlQuery query(MSqlQuery::InitCon());
     309    query.prepare("SELECT defaultinput "
     310                  "FROM capturecard "
     311                  "WHERE capturecard.cardid = :CARDID");
     312    query.bindValue(":CARDID", nCardID);
     313
     314    if (query.exec() && query.isActive() && query.size() > 0)
     315    {
     316        query.next();
     317        str = query.value(0).toString();
     318    }
     319    return str;
     320}
     321
    300322QString VSSetting::whereClause(void)
    301323{
    302324    return QString("sourceid = %1").arg(parent.getSourceID());
  • scanwizard.cpp

     
    308308        //Create an analog scan object
    309309        analogScan = new AnalogScan(nVideoSource, parent->captureCard());
    310310
    311         MSqlQuery query(MSqlQuery::InitCon());
    312 
    313         QString thequery = QString("SELECT freqtable "
    314                                "FROM videosource WHERE "
    315                                "sourceid = \"%1\";")
    316                                .arg(nVideoSource);
    317         query.prepare(thequery);
    318 
    319         if (!query.exec() || !query.isActive())
    320             MythContext::DBError("fetchtuningparams", query);
    321         if (query.size() <= 0)
    322              return;
    323         query.next();
    324 
    325         QString freqtable = query.value(0).toString();
    326 //        cerr << "frequency table = " << freqtable.ascii() << endl;
    327 
    328311        popupProgress = new ScanProgressPopup(this,false);
    329312        connect(analogScan,SIGNAL(serviceScanComplete(void)),
    330313                this,SLOT(scanComplete(void)));
     
    335318        popupProgress->progress(0);
    336319        popupProgress->exec(this);
    337320
    338         if (!analogScan->scan(freqtable))
     321        if (!analogScan->scan())
    339322        {
    340323             MythPopupBox::showOkPopup(gContext->GetMainWindow(),
    341324                                      tr("ScanWizard"),
  • channel.h

     
    5353    bool TuneMultiplex(uint mplexid);
    5454    bool Tune(uint frequency, QString inputname="",
    5555              QString modulation="analog");
     56    // V4L scanning stuff
     57    bool IsTuned() const;
    5658  private:
    5759    // Helper Sets
    5860    void SetColourAttribute(int attrib, const char *name);
  • analogscan.cpp

     
    3838#include <unistd.h>
    3939#include <fcntl.h>
    4040
    41 #include <qmutex.h>
    4241#include "mythcontext.h"
    4342#include "videosource.h"
    4443#include "frequencies.h"
    45 #include "videodev_myth.h"
     44#include "channel.h"
     45#include "channelutil.h"
    4646
    47 extern "C" {
    48 #include "vbitext/vbi.h"
    49 };
    50 
    5147#include "analogscan.h"
    5248
    5349AnalogScan::AnalogScan(unsigned _sourceid,unsigned _cardid) :
     
    5652    sourceid(_sourceid),
    5753    cardid(_cardid)
    5854{
    59     pthread_mutex_init(&lock, NULL);
    60     vbi=NULL;
    6155}
    6256
    6357AnalogScan::~AnalogScan()
    6458{
    65     pthread_mutex_destroy(&lock);
    6659}
    6760
    68 bool AnalogScan::start()
    69 {
    70     if (!CardUtil::GetVideoDevice(cardid, device, vbidevice))
    71         return false;
    72 
    73     fd = ::open(device.ascii(),O_RDWR);
    74     if (fd < 0)
    75         return false;
    76 
    77     pthread_mutex_lock(&lock);
    78     fRunning = true;
    79     fStop = false;
    80     pthread_mutex_unlock(&lock);
    81 
    82     pthread_create(&thread, NULL, spawn, this);
    83 #ifdef DOVBI
    84     pthread_create(&threadVBI, NULL, spawnVBI, this);
    85 #endif
    86 
    87     return true;
    88 }
    89 
    9061void AnalogScan::stop()
    9162{
    92     bool _stop = false;
    93     pthread_mutex_lock(&lock);
    94     if (fRunning && !fStop)
    95         _stop = true;
    96     fStop = true;
    97     pthread_mutex_unlock(&lock);
    98 
    99     if (_stop)
     63    if (fRunning)
    10064    {
    101         pthread_join(thread,NULL);
    102 #ifdef DO_VBI
    103         pthread_join(threadVBI,NULL);
    104 #endif
    105         if (fd >=0)
    106            ::close(fd);
    107    }
    108 }
    109 
    110 void AnalogScan::vbi_event(AnalogScan* _this, struct vt_event *ev)
    111 {
    112     (void)_this;
    113     //cerr << "AnalogScan::vbi_event " << ev->type << "\n";
    114     switch (ev->type)
    115     {
    116     case EV_HEADER:
    117         break;
    118     case EV_XPACKET:
    119         break;
    120 //    default:
    121 //        cerr << "AnalogScan unkown " << ev->type << "\n";
     65        fStop = true;
     66        pthread_join(thread, NULL);
    12267    }
    12368}
    12469
     
    12974    return NULL;
    13075}
    13176
    132 void *AnalogScan::spawnVBI(void *param)
    133 {
    134     AnalogScan *_this = (AnalogScan*)param;
    135     _this->doVBI();
    136     return NULL;
    137 }
    138 
    139 void AnalogScan::doVBI()
    140 {
    141     vbi = ::vbi_open(vbidevice.ascii(), NULL, 99, -1);
    142     if (!vbi)
    143         return;
    144     VERBOSE(VB_IMPORTANT, QString("AnalogScan opened vbi device: %1").arg(vbidevice));
    145     vbi_add_handler(vbi, (void*)vbi_event,this);
    146 
    147     while(!fStop)
    148     {
    149         struct timeval tv;
    150         fd_set rdset;
    151 
    152         tv.tv_sec = 0;
    153         tv.tv_usec = 10000;
    154         FD_ZERO(&rdset);
    155         FD_SET(vbi->fd, &rdset);
    156 
    157         switch (::select(vbi->fd + 1, &rdset, 0, 0, &tv))
    158         {
    159             case -1:
    160                   perror("vbi select");
    161                   continue;
    162             case 0:
    163                   //printf("vbi select timeout\n");
    164                   continue;
    165         }
    166         vbi_handler(vbi, vbi->fd);
    167     }
    168     vbi_del_handler(vbi, (void*)vbi_event,this);
    169     ::vbi_close(vbi);
    170 }
    171 
    17277void AnalogScan::doScan()
    17378{
    174     struct CHANLIST *l = chanlists[nTable].list;
    175     int count = chanlists[nTable].count;
    176     for (int i = 0; i < count && !fStop; i++,l++)
     79    fRunning = true;
     80    QString device;
     81    if (CardUtil::GetVideoDevice(cardid, device))
    17782    {
    178         //cerr << i << " " << l->name << " " << l->freq << endl;
    179         struct v4l2_frequency vf;
    180         memset(&vf, 0, sizeof(vf));
    181         vf.frequency = l->freq * 16 / 1000;
    182         vf.type = V4L2_TUNER_ANALOG_TV;
    183 
    184         ::ioctl(fd, VIDIOC_S_FREQUENCY, &vf);
    185         usleep(200000); /* 0.2 sec */
    186         if (isTuned())
    187         {
    188 #ifdef DOVBI
    189              usleep(2000000); /* 0.2 sec */
    190 #endif
    191              addChannel(l->name,l->freq);
    192              emit serviceScanUpdateText(QObject::tr("Channel %1").arg(l->name));
     83         Channel channel(NULL,device);
     84         if (channel.Open())
     85         {
     86             QString input = CardUtil::GetDefaultInput(cardid);
     87             struct CHANLIST *l = chanlists[nTable].list;
     88             int count = chanlists[nTable].count;
     89             for (int i = 0; i < count && !fStop; i++,l++)
     90             {
     91                 unsigned frequency = l->freq*1000;
     92                 channel.Tune(frequency,input);
     93                 usleep(200000); /* 0.2 sec */
     94                 if (channel.IsTuned())
     95                 {
     96                      //cerr << i << " " << l->name << " " << frequency <<  " Tuned " << endl;
     97                      QString name = QObject::tr("Channel %1").arg(l->name);
     98                      addChannel(i,l->name,name,l->freq);
     99                      emit serviceScanUpdateText(name);
     100                 }
     101                 emit serviceScanPCTComplete((i*100)/count);
     102             }
     103             channel.Close();
    193104        }
    194         emit serviceScanPCTComplete((i*100)/count);
    195105    }
    196106    emit serviceScanComplete();
    197     pthread_mutex_lock(&lock);
    198     fRunning = false;
    199     pthread_mutex_unlock(&lock);
    200107}
    201108
    202 bool AnalogScan::scan(const QString& freqtable)
     109bool AnalogScan::scan()
    203110{
    204111    int i = 0;
    205112    char *listname = (char *)chanlists[i].name;
    206113    QString table;
    207114
     115    MSqlQuery query(MSqlQuery::InitCon());
     116
     117    QString thequery = QString("SELECT freqtable FROM videosource WHERE "
     118                               "sourceid = \"%1\";").arg(sourceid);
     119    query.prepare(thequery);
     120
     121    if (!query.exec() || !query.isActive())
     122        MythContext::DBError("analog scan freqtable", query);
     123    if (query.size() <= 0)
     124         return false;
     125    query.next();
     126
     127    QString freqtable = query.value(0).toString();
     128//        cerr << "frequency table = " << freqtable.ascii() << endl;
     129
    208130    if (freqtable == "default" || freqtable.isNull() || freqtable.isEmpty())
    209131        table = gContext->GetSetting("FreqTable");
    210132    else
    211133        table = freqtable;
    212134
     135    nTable = 0;
    213136    while (listname != NULL)
    214137    {
    215138        if (table == listname)
    216             return scan(i);
     139        {
     140           nTable = i;
     141           break;
     142        }
    217143        i++;
    218144        listname = (char *)chanlists[i].name;
    219145    }
    220146
    221     return scan(0);
     147    if (!fRunning)
     148        pthread_create(&thread, NULL, spawn, this);
     149    while (!fRunning)
     150        usleep(50);
     151    return true;
    222152}
    223153
    224 bool AnalogScan::isTuned()
     154void AnalogScan::addChannel(int number,const QString& channumber,
     155                            const QString& name, int frequency)
    225156{
    226     struct v4l2_tuner tuner;
    227 
    228     memset(&tuner,0,sizeof(tuner));
    229     if (-1 == ::ioctl(fd,VIDIOC_G_TUNER,&tuner,0))
    230         return 0;
    231     return tuner.signal ? true : false;
    232 }
    233 
    234 bool AnalogScan::scan(unsigned table)
    235 {
    236     nTable = table;
    237     return start();
    238 }
    239 
    240 int AnalogScan::generateNewChanID(int sourceID)
    241 {
    242157    MSqlQuery query(MSqlQuery::InitCon());
    243 
    244     QString theQuery =
    245         QString("SELECT max(chanid) as maxchan "
    246                 "FROM channel WHERE sourceid=%1").arg(sourceID);
    247     query.prepare(theQuery);
    248 
    249     if(!query.exec())
    250         MythContext::DBError("Calculating new ChanID", query);
    251 
    252     if (!query.isActive())
    253         MythContext::DBError("Calculating new ChanID for Analog Channel",query);
    254 
    255     query.next();
    256 
    257     // If transport not present add it, and move on to the next
    258     if (query.size() <= 0)
    259         return sourceID * 1000;
    260 
    261     int MaxChanID = query.value(0).toInt();
    262 
    263     if (MaxChanID == 0)
    264         return sourceID * 1000;
    265     else
    266         return MaxChanID + 1;
    267 }
    268 
    269 void AnalogScan::addChannel(const QString& name, int frequency)
    270 {
    271     MSqlQuery query(MSqlQuery::InitCon());
    272158    query.prepare("DELETE FROM channel WHERE channum=:CHANNUM AND "
    273159                  "sourceid=:SOURCEID");
    274     query.bindValue(":CHANNUM",name);
     160    query.bindValue(":CHANNUM",channumber);
    275161    query.bindValue(":SOURCEID",sourceid);
    276162    query.exec();
    277163
     
    280166                   "VALUES (:CHANID,:CHANNUM,:SOURCEID,:CALLSIGN,"
    281167                   ":NAME,:FREQID);");
    282168
    283     query.bindValue(":CHANID",generateNewChanID(sourceid));
    284     query.bindValue(":CHANNUM",name);
     169    int chanid = ChannelUtil::CreateChanID(sourceid,QString::number(number));
     170    query.bindValue(":CHANID",chanid);
     171    query.bindValue(":CHANNUM",channumber);
    285172    query.bindValue(":SOURCEID",sourceid);
    286173    query.bindValue(":CALLSIGN",name);
    287174    query.bindValue(":NAME",name);
    288175    query.bindValue(":FREQID",frequency);
    289176
    290177    if(!query.exec())
    291         MythContext::DBError("Adding new DVB Channel", query);
     178        MythContext::DBError("Adding new Channel", query);
    292179
    293180    if (!query.isActive())
    294         MythContext::DBError("Adding new DVB Channel", query);
     181        MythContext::DBError("Adding new Channel", query);
    295182}
  • channel.cpp

     
    636636    return true;
    637637}
    638638
     639bool Channel::IsTuned() const
     640{
     641    if (usingv4l2)
     642    {
     643        struct v4l2_tuner tuner;
     644
     645        memset(&tuner,0,sizeof(tuner));
     646        if (-1 == ::ioctl(videofd,VIDIOC_G_TUNER,&tuner,0))
     647            return false;
     648        return tuner.signal ? true : false;
     649    }
     650    else
     651    {
     652        struct video_tuner tuner;
     653        memset(&tuner,0,sizeof(tuner));
     654        if (-1 == ::ioctl(videofd,VIDIOCGTUNER,&tuner,0))
     655             return false;
     656        return tuner.signal ? true : false;
     657    }
     658}
     659
    639660int Channel::GetCardID() const
    640661{
    641662    if (pParent)