Ticket #1704: fb-scan-v1.patch
File fb-scan-v1.patch, 19.5 KB (added by , 18 years ago) |
---|
-
libs/libmythtv/cardutil.h
84 84 FIREWIRE, 85 85 HDHOMERUN, 86 86 CRC_IP, 87 FREEBOX, 87 88 }; 88 89 89 90 static enum CARD_TYPES toCardType(const QString &name) … … 114 115 return HDHOMERUN; 115 116 if ("CRC_IP" == name) 116 117 return CRC_IP; 118 if ("FREEBOX" == name) 119 return FREEBOX; 117 120 return ERROR_UNKNOWN; 118 121 } 119 122 … … 134 137 static bool IsCardTypePresent(const QString &strType); 135 138 136 139 static QString GetRawCardType(uint cardid, uint sourceid) 137 { return get_on_source("cardtype", cardid, sourceid) ; }140 { return get_on_source("cardtype", cardid, sourceid).upper(); } 138 141 static QString GetVideoDevice(uint cardid, uint sourceid) 139 142 { return get_on_source("videodevice", cardid, sourceid); } 140 143 static bool GetVBIDevice(uint cardid, uint sourceid) … … 145 148 { return get_on_source("dbox2_port", cardid, sourceid).toUInt(); } 146 149 147 150 static QString GetRawCardType(uint cardid, const QString &input) 148 { return get_on_input("cardtype", cardid, input) ; }151 { return get_on_input("cardtype", cardid, input).upper(); } 149 152 static QString GetVideoDevice(uint cardid, const QString &input) 150 153 { return get_on_input("videodevice", cardid, input); } 151 154 static QString GetVBIDevice(uint cardid, const QString &input) -
libs/libmythtv/freeboxchannelfetcher.h
1 1 #ifndef _FREEBOXCHANNELFETCHER_H_ 2 2 #define _FREEBOXCHANNELFETCHER_H_ 3 3 4 // POSIX headers 5 #include <pthread.h> 6 7 // Qt headers 8 #include <qobject.h> 9 #include <qmutex.h> 10 11 // MythTV headers 4 12 #include "freeboxchannelinfo.h" 5 13 6 class FreeboxChannelFetcher 14 class FreeboxChannelFetcher : public QObject 7 15 { 8 private: 9 FreeboxChannelFetcher(); 16 Q_OBJECT 17 18 friend void *run_scan_thunk(void *param); 19 20 public: 21 FreeboxChannelFetcher(unsigned _sourceid, unsigned _cardid); 10 22 ~FreeboxChannelFetcher(); 11 23 12 public: 13 static QString DownloadPlaylist(const QString& url); 14 static fbox_chan_map_t ParsePlaylist(const QString& rawdata); 24 /// Stops the scanning thread running 25 void Stop(void); 26 /// Scans the given frequency list, implies starting the thread() 27 bool Scan(void); 28 29 static QString DownloadPlaylist(const QString &url, bool inQtThread); 30 static fbox_chan_map_t ParsePlaylist( 31 const QString &rawdata, FreeboxChannelFetcher *fetcher = NULL); 32 33 signals: 34 /** \brief Tells listener how far along we are from 0..100% 35 * \param p percentage completion 36 */ 37 void ServiceScanPercentComplete(int p); 38 /** \brief Status message from the scanner 39 * \param status The latest status message 40 */ 41 void ServiceScanUpdateText(const QString &status); 42 /// Signals that the scan is complete 43 void ServiceScanComplete(void); 44 45 private: 46 void SetTotalNumChannels(uint val) { chan_cnt = (val) ? val : 1; } 47 void SetNumChannelsParsed(uint); 48 void SetNumChannelsInserted(uint); 49 void SetMessage(const QString &status); 50 void RunScan(void); 51 52 uint sourceid; 53 uint cardid; 54 uint chan_cnt; 55 bool thread_running; 56 bool stop_now; 57 pthread_t thread; 58 QMutex lock; 15 59 }; 16 60 17 #endif //_FREEBOXCHANNELFETCHER_H_61 #endif //_FREEBOXCHANNELFETCHER_H_ 18 62 19 63 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/freeboxchannel.cpp
34 34 35 35 if (m_freeboxchannels.empty()) 36 36 { 37 QString content = FreeboxChannelFetcher::DownloadPlaylist(m_videodev); 37 QString content = FreeboxChannelFetcher::DownloadPlaylist( 38 m_videodev, true); 38 39 m_freeboxchannels = FreeboxChannelFetcher::ParsePlaylist(content); 39 40 VERBOSE(VB_IMPORTANT, LOC + QString("Loaded %1 channels from %2") 40 41 .arg(m_freeboxchannels.size()) -
libs/libmythtv/scanwizardhelpers.h
219 219 FullTransportScan, 220 220 // Scan of one transport already in the database 221 221 TransportScan, 222 // Freebox import of channels from M3U URL 223 FreeBoxImport, 222 224 // Imports lists from dvb-utils scanners 223 225 Import 224 226 }; -
libs/libmythtv/scanwizardscanner.cpp
61 61 #include "hdhrsignalmonitor.h" 62 62 #endif 63 63 64 #include "freeboxchannelfetcher.h" 65 64 66 #define LOC QString("SWizScan: ") 65 67 #define LOC_ERR QString("SWizScan, Error: ") 66 68 … … 103 105 log(new LogList()), 104 106 channel(NULL), popupProgress(NULL), 105 107 scanner(NULL), analogScanner(NULL), 108 freeboxScanner(NULL), 106 109 nScanType(-1), 107 110 nMultiplexToTuneTo(0), nVideoSource(0), 108 111 frequency(0), modulation("8vsb") … … 134 137 analogScanner = NULL; 135 138 } 136 139 #endif 140 141 #ifdef USING_FREEBOX 142 if (freeboxScanner) 143 { 144 freeboxScanner->Stop(); 145 delete freeboxScanner; 146 freeboxScanner = NULL; 147 } 148 #endif 137 149 } 138 150 139 151 void ScanWizardScanner::customEvent(QCustomEvent *e) … … 410 422 startChan["modulation"]); 411 423 #endif // USING_DVB 412 424 } 425 else if (nScanType == ScanTypeSetting::FreeBoxImport) 426 { 427 do_scan = false; 428 ScanFreeBox(cardid, nVideoSource); 429 } 413 430 else 414 431 { 415 432 do_scan = false; … … 630 647 #endif 631 648 } 632 649 650 void ScanWizardScanner::ScanFreeBox(uint cardid, uint sourceid) 651 { 652 #ifdef USING_FREEBOX 653 //Create an analog scan object 654 freeboxScanner = new FreeboxChannelFetcher(sourceid, cardid); 655 popupProgress = new ScanProgressPopup(this, false); 656 657 connect(freeboxScanner, SIGNAL(ServiceScanComplete(void)), 658 this, SLOT( scanComplete(void))); 659 connect(freeboxScanner, SIGNAL(ServiceScanUpdateText(const QString&)), 660 this, SLOT( updateText(const QString&))); 661 connect(freeboxScanner, SIGNAL(ServiceScanPercentComplete(int)), 662 this, SLOT( serviceScanPctComplete(int))); 663 664 popupProgress->progress(0); 665 popupProgress->exec(this); 666 667 if (!freeboxScanner->Scan()) 668 { 669 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 670 tr("ScanWizard"), 671 tr("Error starting scan")); 672 cancelScan(); 673 } 674 #endif // USING_FREEBOX 675 } 676 633 677 void ScanWizardScanner::HandleTuneComplete(void) 634 678 { 635 679 VERBOSE(VB_SIPARSER, LOC + "HandleTuneComplete()"); -
libs/libmythtv/freeboxchannelfetcher.cpp
1 // -*- Mode: c++ -*- 2 3 // Std C headers 4 #include <cmath> 5 6 // MythTV headers 7 #include "mythcontext.h" 8 #include "httpcomms.h" 9 #include "cardutil.h" 10 #include "channelutil.h" 1 11 #include "freeboxchannelfetcher.h" 2 12 3 #include "libmyth/httpcomms.h"4 #include "libmyth/mythcontext.h"5 6 13 #define LOC QString("FBChanFetch: ") 7 14 #define LOC_ERR QString("FBChanFetch, Error: ") 8 15 9 QString FreeboxChannelFetcher::DownloadPlaylist(const QString& url) 16 static bool parse_chan_info( 17 const QString &line1, QString &channum, QString &name); 18 19 FreeboxChannelFetcher::FreeboxChannelFetcher(unsigned _sourceid, 20 unsigned _cardid) : 21 sourceid(_sourceid), cardid(_cardid), 22 chan_cnt(1), thread_running(false), 23 stop_now(false), lock(false) 10 24 { 11 QString rwUrl(url);12 return QString::fromUtf8(HttpComms::getHttp(rwUrl));13 25 } 14 26 27 FreeboxChannelFetcher::~FreeboxChannelFetcher() 28 { 29 do 30 { 31 Stop(); 32 usleep(5000); 33 } 34 while (thread_running); 35 } 36 37 void FreeboxChannelFetcher::Stop(void) 38 { 39 lock.lock(); 40 41 if (thread_running) 42 { 43 stop_now = true; 44 lock.unlock(); 45 46 pthread_join(thread, NULL); 47 return; 48 } 49 50 lock.unlock(); 51 } 52 53 bool FreeboxChannelFetcher::Scan(void) 54 { 55 lock.lock(); 56 do { lock.unlock(); Stop(); lock.lock(); } while (thread_running); 57 58 // Should now have lock and no thread should be running. 59 60 stop_now = false; 61 62 pthread_create(&thread, NULL, run_scan_thunk, this); 63 64 while (!thread_running && !stop_now) 65 usleep(5000); 66 67 lock.unlock(); 68 69 return thread_running; 70 } 71 72 void *run_scan_thunk(void *param) 73 { 74 FreeboxChannelFetcher *chanscan = (FreeboxChannelFetcher*) param; 75 chanscan->RunScan(); 76 77 return NULL; 78 } 79 80 void FreeboxChannelFetcher::RunScan(void) 81 { 82 thread_running = true; 83 84 // Step 1/4 : Get info from DB 85 QString url = CardUtil::GetVideoDevice(cardid, sourceid); 86 87 if (stop_now || url.isEmpty()) 88 { 89 thread_running = false; 90 return; 91 } 92 93 VERBOSE(VB_CHANNEL, QString("Playlist URL: %1").arg(url)); 94 95 // Step 2/4 : Download 96 emit ServiceScanPercentComplete(5); 97 emit ServiceScanUpdateText(tr("Downloading Playlist")); 98 99 QString playlist = DownloadPlaylist(url, false); 100 101 if (stop_now || playlist.isEmpty()) 102 { 103 thread_running = false; 104 return; 105 } 106 107 // Step 3/4 : Process 108 emit ServiceScanPercentComplete(35); 109 emit ServiceScanUpdateText(tr("Processing Playlist")); 110 111 const fbox_chan_map_t channels = ParsePlaylist(playlist, this); 112 113 // Step 4/4 : Finish up 114 emit ServiceScanUpdateText(tr("Adding Channels")); 115 SetTotalNumChannels(channels.size()); 116 fbox_chan_map_t::const_iterator it = channels.begin(); 117 for (uint i = 1; it != channels.end(); ++it, ++i) 118 { 119 QString channum = it.key(); 120 QString name = (*it).m_name; 121 QString msg = tr("Channel #%1 : %2").arg(channum).arg(name); 122 123 int chanid = ChannelUtil::GetChanID(sourceid, channum); 124 if (chanid <= 0) 125 { 126 emit ServiceScanUpdateText(tr("Adding %1").arg(msg)); 127 chanid = ChannelUtil::CreateChanID(sourceid, channum); 128 ChannelUtil::CreateChannel( 129 0, sourceid, chanid, name, name, channum, 130 0, 0, 0, false, false, false, 0); 131 } 132 else 133 { 134 emit ServiceScanUpdateText(tr("Updating %1").arg(msg)); 135 ChannelUtil::UpdateChannel( 136 0, sourceid, chanid, name, name, channum, 0, 0, 0, 0); 137 } 138 139 SetNumChannelsInserted(i); 140 } 141 142 emit ServiceScanUpdateText(tr("Done")); 143 emit ServiceScanUpdateText(""); 144 emit ServiceScanPercentComplete(100); 145 emit ServiceScanComplete(); 146 147 thread_running = false; 148 } 149 150 void FreeboxChannelFetcher::SetNumChannelsParsed(uint val) 151 { 152 uint minval = 35, range = 70 - minval; 153 uint pct = minval + (uint) truncf((((float)val) / chan_cnt) * range); 154 emit ServiceScanPercentComplete(pct); 155 } 156 157 void FreeboxChannelFetcher::SetNumChannelsInserted(uint val) 158 { 159 uint minval = 70, range = 100 - minval; 160 uint pct = minval + (uint) truncf((((float)val) / chan_cnt) * range); 161 emit ServiceScanPercentComplete(pct); 162 } 163 164 void FreeboxChannelFetcher::SetMessage(const QString &status) 165 { 166 emit ServiceScanUpdateText(status); 167 } 168 169 QString FreeboxChannelFetcher::DownloadPlaylist(const QString &url, 170 bool inQtThread) 171 { 172 QString redirected_url = url; 173 174 QString tmp = HttpComms::getHttp( 175 redirected_url, 176 10000 /* ms */, 3 /* retries */, 177 3 /* redirects */, true /* allow gzip */, 178 NULL /* login */, inQtThread); 179 180 if (redirected_url != url) 181 { 182 VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1") 183 .arg(redirected_url)); 184 } 185 186 return QString::fromUtf8(tmp); 187 } 188 189 fbox_chan_map_t FreeboxChannelFetcher::ParsePlaylist( 190 const QString &rawdata, FreeboxChannelFetcher *fetcher) 191 { 192 fbox_chan_map_t chanmap; 193 194 // Verify header is ok 195 QString header = rawdata.section("\n", 0, 0); 196 if (header != "#EXTM3U") 197 { 198 VERBOSE(VB_IMPORTANT, LOC_ERR + 199 QString("Invalid channel list header (%1)").arg(header)); 200 201 if (fetcher) 202 fetcher->SetMessage(tr("ERROR: M3U channel list is malformed")); 203 204 return chanmap; 205 } 206 207 // estimate number of channels 208 for (uint i = 1; fetcher; i += 2) 209 { 210 QString url = rawdata.section("\n", i+1, i+1); 211 if (url.isEmpty()) 212 { 213 fetcher->SetTotalNumChannels(i>>1); 214 215 VERBOSE(VB_CHANNEL, "Estimating there are "<<(i>>1) 216 <<" channels in playlist"); 217 218 break; 219 } 220 } 221 222 // Parse each channel 223 for (int i = 1; true; i += 2) 224 { 225 QString tmp = rawdata.section("\n", i+0, i+0); 226 QString url = rawdata.section("\n", i+1, i+1); 227 if (tmp.isEmpty() || url.isEmpty()) 228 break; 229 230 QString channum, name; 231 QString msg = tr("Encountered malformed channel"); 232 if (parse_chan_info(tmp, channum, name)) 233 { 234 chanmap[channum] = FreeboxChannelInfo(name, url); 235 236 msg = tr("Parsing Channel #%1 : %2 : %3") 237 .arg(channum).arg(name).arg(url); 238 239 VERBOSE(VB_CHANNEL, msg); 240 241 msg = QString::null; // don't tell fetcher 242 } 243 244 if (fetcher) 245 { 246 if (!msg.isEmpty()) 247 fetcher->SetMessage(msg); 248 fetcher->SetNumChannelsParsed(1+(i>>1)); 249 } 250 } 251 252 return chanmap; 253 } 254 15 255 static bool parse_chan_info(const QString &line1, 16 256 QString &channum, QString &name) 17 257 { … … 63 303 return true; 64 304 } 65 305 66 fbox_chan_map_t FreeboxChannelFetcher::ParsePlaylist(const QString& rawdata)67 {68 fbox_chan_map_t chanmap;69 70 // Verify header is ok71 QString header = rawdata.section("\n", 0, 0);72 if (header != "#EXTM3U")73 {74 VERBOSE(VB_IMPORTANT, LOC_ERR +75 QString("Invalid channel list header (%1)").arg(header));76 77 return chanmap;78 }79 80 // Parse each channel81 for (int i = 1; true; i += 2)82 {83 QString tmp = rawdata.section("\n", i+0, i+0);84 QString url = rawdata.section("\n", i+1, i+1);85 if (tmp.isEmpty() || url.isEmpty())86 break;87 88 QString channum, name;89 if (parse_chan_info(tmp, channum, name))90 {91 chanmap[channum] = FreeboxChannelInfo(name, url);92 }93 }94 95 return chanmap;96 }97 98 306 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/scanwizardscanner.h
43 43 44 44 class ScanWizard; 45 45 class AnalogScan; 46 class FreeboxChannelFetcher; 46 47 class LogList; 47 48 class SIScan; 48 49 class ScanProgressPopup; … … 82 83 void PreScanCommon(uint cardid, uint sourceid); 83 84 void TunedScanCommon(uint cardid, uint sourceid, bool ok); 84 85 void ScanAnalog(uint cardid, uint sourceid); 86 void ScanFreeBox(uint cardid, uint sourceid); 85 87 86 88 void dvbLock(int); 87 89 void dvbSNR(int); … … 101 103 102 104 SIScan *scanner; 103 105 AnalogScan *analogScanner; 106 FreeboxChannelFetcher *freeboxScanner; 104 107 105 108 int nScanType; 106 109 int nMultiplexToTuneTo; -
libs/libmythtv/scanwizardhelpers.cpp
58 58 # endif // USING_IVTV 59 59 #endif // USING_V4L 60 60 61 #ifdef USING_FREEBOX 62 if (!cardTypes.isEmpty()) 63 cardTypes += ","; 64 cardTypes += "'FREEBOX'"; 65 #endif // USING_FREEBOX 66 61 67 #ifdef USING_HDHOMERUN 62 68 if (!cardTypes.isEmpty()) 63 69 cardTypes += ","; … … 335 341 #endif 336 342 */ 337 343 break; 344 case CardUtil::FREEBOX: 345 addSelection(tr("M3U Import"), 346 QString::number(FreeBoxImport), true); 347 return; 338 348 case CardUtil::ERROR_PROBE: 339 349 addSelection(QObject::tr("Failed to probe the card"), 340 350 QString::number(Error_Probe), true); … … 422 432 wizard->paneSingle); 423 433 addTarget(QString::number(ScanTypeSetting::FullTransportScan), 424 434 scanAllTransports); 435 addTarget(QString::number(ScanTypeSetting::FreeBoxImport), 436 new BlankSetting()); 425 437 addTarget(QString::number(ScanTypeSetting::Import), 426 438 filename); 427 439 } -
libs/libmyth/httpcomms.cpp
141 141 142 142 VERBOSE(VB_NETWORK, QString("done: %1 bytes").arg(m_data.size())); 143 143 144 m_done = true;145 146 144 if (m_timer) 147 145 m_timer->stop(); 146 147 m_done = true; 148 148 } 149 149 150 150 void HttpComms::stateChanged(int state) … … 260 260 } 261 261 262 262 263 // getHttp - static function for grabbing http data for a url 264 // this is a synchronous function, it will block according to the vars 265 QString HttpComms::getHttp(QString& url, int timeoutMS, int maxRetries, 266 int maxRedirects, bool allowGzip, Credentials* webCred) 263 /** \fn HttpComms::getHttp(QString&,int,int,int,bool,Credentials*,bool) 264 * \brief Static function for grabbing http data for a url. 265 * 266 * This is a synchronous function, it will block according to the vars. 267 */ 268 QString HttpComms::getHttp(QString &url, 269 int timeoutMS, int maxRetries, 270 int maxRedirects, bool allowGzip, 271 Credentials *webCred, bool isInQtEventThread) 267 272 { 268 273 int redirectCount = 0; 269 274 int timeoutCount = 0; … … 294 299 295 300 while (!httpGrabber->isDone()) 296 301 { 297 qApp->processEvents(); 302 if (isInQtEventThread) 303 qApp->processEvents(); 298 304 usleep(10000); 299 305 } 300 306 -
libs/libmyth/httpcomms.h
52 52 static QString getHttp(QString& url, int timeoutMS = 10000, 53 53 int maxRetries = 3, int maxRedirects = 3, 54 54 bool allowGzip = false, 55 Credentials* webCred = NULL); 55 Credentials* webCred = NULL, 56 bool isInQtEventThread = true); 56 57 57 58 static bool getHttpFile(const QString& file, QString& url, int timeoutMS = 10000, 58 59 int maxRetries = 3, int maxRedirects = 3,