MythTV  0.26-pre
netgrabbermanager.cpp
Go to the documentation of this file.
00001 // qt
00002 #include <QString>
00003 #include <QCoreApplication>
00004 #include <QFile>
00005 #include <QDir>
00006 
00007 #include "mythdirs.h"
00008 #include "mythcontext.h"
00009 #include "mythsystem.h"
00010 #include "exitcodes.h"
00011 #include "mythmiscutil.h"
00012 #include "mythlogging.h"
00013 
00014 #include "netgrabbermanager.h"
00015 #include "netutils.h"
00016 
00017 #define LOC      QString("NetContent: ")
00018 
00019 using namespace std;
00020 
00021 // ---------------------------------------------------
00022 
00023 GrabberScript::GrabberScript(const QString& title, const QString& image,
00024               const ArticleType &type, const QString& author,
00025               const bool& search, const bool& tree,
00026               const QString& description, const QString& commandline,
00027               const double& version) :
00028     MThread("GrabberScript"), m_lock(QMutex::Recursive)
00029 {
00030     m_title = title;
00031     m_image = image;
00032     m_type = type;
00033     m_author = author;
00034     m_search = search;
00035     m_tree = tree;
00036     m_description = description;
00037     m_commandline = commandline;
00038     m_version = version;
00039 }
00040 
00041 GrabberScript::~GrabberScript()
00042 {
00043     wait();
00044 }
00045 
00046 void GrabberScript::run()
00047 {
00048     RunProlog();
00049     QMutexLocker locker(&m_lock);
00050 
00051     QString commandline = m_commandline;
00052     MythSystem getTree(commandline, QStringList("-T"),
00053                        kMSRunShell | kMSStdOut | kMSBuffered);
00054     getTree.Run(900);
00055     uint status = getTree.Wait();
00056 
00057     if( status == GENERIC_EXIT_CMD_NOT_FOUND )
00058         LOG(VB_GENERAL, LOG_ERR, LOC +
00059             QString("Internet Content Source %1 cannot run, file missing.")
00060                 .arg(m_title));
00061     else if( status == GENERIC_EXIT_OK )
00062     {
00063         LOG(VB_GENERAL, LOG_INFO, LOC +
00064             QString("Internet Content Source %1 completed download, "
00065                     "beginning processing...").arg(m_title));
00066 
00067         QByteArray result = getTree.ReadAll();
00068 
00069         QDomDocument domDoc;
00070         domDoc.setContent(result, true);
00071         QDomElement root = domDoc.documentElement();
00072         QDomElement channel = root.firstChildElement("channel");
00073 
00074         clearTreeItems(m_title);
00075 
00076         while (!channel.isNull())
00077         {
00078             parseDBTree(m_title, QString(), QString(), channel, GetType());
00079             channel = channel.nextSiblingElement("channel");
00080         }
00081         markTreeUpdated(this, QDateTime::currentDateTime());
00082         LOG(VB_GENERAL, LOG_INFO, LOC +
00083             QString("Internet Content Source %1 completed processing, "
00084                     "marking as updated.").arg(m_title));
00085     }
00086     else
00087         LOG(VB_GENERAL, LOG_ERR, LOC +
00088             QString("Internet Content Source %1 crashed while grabbing tree.")
00089                 .arg(m_title));
00090 
00091     emit finished();
00092     RunEpilog();
00093 }
00094 
00095 void GrabberScript::parseDBTree(const QString &feedtitle, const QString &path,
00096                                 const QString &pathThumb, QDomElement& domElem,
00097                                 const ArticleType &type)
00098 {
00099     QMutexLocker locker(&m_lock);
00100 
00101     Parse parse;
00102     ResultItem::resultList articles;
00103 
00104     // File Handling
00105     QDomElement fileitem = domElem.firstChildElement("item");
00106     while (!fileitem.isNull())
00107     {   // Fill the article list...
00108         articles.append(parse.ParseItem(fileitem));
00109         fileitem = fileitem.nextSiblingElement("item");
00110     }
00111 
00112     while (!articles.isEmpty())
00113     {   // Insert the articles in the DB...
00114         insertTreeArticleInDB(feedtitle, path,
00115                        pathThumb, articles.takeFirst(), type);
00116     }
00117 
00118     // Directory Handling
00119     QDomElement diritem = domElem.firstChildElement("directory");
00120     while (!diritem.isNull())
00121     {
00122         QDomElement subfolder = diritem;
00123         QString dirname = diritem.attribute("name");
00124         QString dirthumb = diritem.attribute("thumbnail");
00125         dirname.replace("/", "|");
00126         QString pathToUse;
00127 
00128         if (path.isEmpty())
00129             pathToUse = dirname;
00130         else
00131             pathToUse = QString("%1/%2").arg(path).arg(dirname);
00132 
00133         parseDBTree(feedtitle,
00134                     pathToUse,
00135                     dirthumb,
00136                     subfolder,
00137                     type);
00138         diritem = diritem.nextSiblingElement("directory");
00139     }
00140 }
00141 
00142 GrabberManager::GrabberManager() :     m_lock(QMutex::Recursive)
00143 {
00144     m_updateFreq = (gCoreContext->GetNumSetting(
00145                        "netsite.updateFreq", 24) * 3600 * 1000);
00146     m_timer = new QTimer();
00147     m_runningCount = 0;
00148     m_refreshAll = false;
00149     connect( m_timer, SIGNAL(timeout()),
00150                       this, SLOT(timeout()));
00151 }
00152 
00153 GrabberManager::~GrabberManager()
00154 {
00155     delete m_timer;
00156 }
00157 
00158 void GrabberManager::startTimer()
00159 {
00160     m_timer->start(m_updateFreq);
00161 }
00162 
00163 void GrabberManager::stopTimer()
00164 {
00165     m_timer->stop();
00166 }
00167 
00168 void GrabberManager::doUpdate()
00169 {
00170     GrabberDownloadThread *gdt = new GrabberDownloadThread(this);
00171     if (m_refreshAll)
00172        gdt->refreshAll();
00173     gdt->start(QThread::LowPriority);
00174 
00175     m_timer->start(m_updateFreq);
00176 }
00177 
00178 void GrabberManager::timeout()
00179 {
00180     QMutexLocker locker(&m_lock);
00181     doUpdate();
00182 }
00183 
00184 void GrabberManager::refreshAll()
00185 {
00186     m_refreshAll = true;
00187 }
00188 
00189 GrabberDownloadThread::GrabberDownloadThread(QObject *parent) :
00190     MThread("GrabberDownload")
00191 {
00192     m_parent = parent;
00193     m_refreshAll = false;
00194 }
00195 
00196 GrabberDownloadThread::~GrabberDownloadThread()
00197 {
00198     cancel();
00199     wait();
00200 }
00201 
00202 void GrabberDownloadThread::cancel()
00203 {
00204     m_mutex.lock();
00205     qDeleteAll(m_scripts);
00206     m_scripts.clear();
00207     m_mutex.unlock();
00208 }
00209 
00210 void GrabberDownloadThread::refreshAll()
00211 {
00212     m_mutex.lock();
00213     m_refreshAll = true;
00214     if (!isRunning())
00215         start();
00216     m_mutex.unlock();
00217 }
00218 
00219 void GrabberDownloadThread::run()
00220 {
00221     RunProlog();
00222 
00223     m_scripts = findAllDBTreeGrabbers();
00224     uint updateFreq = gCoreContext->GetNumSetting(
00225                "netsite.updateFreq", 24);
00226 
00227     while (m_scripts.count())
00228     {
00229         GrabberScript *script = m_scripts.takeFirst();
00230         if (script && (needsUpdate(script, updateFreq) || m_refreshAll))
00231         {
00232             LOG(VB_GENERAL, LOG_INFO, LOC +
00233                 QString("Internet Content Source %1 Updating...")
00234                     .arg(script->GetTitle()));
00235             script->run();
00236         }
00237         delete script;
00238     }
00239     emit finished();
00240     if (m_parent)
00241         QCoreApplication::postEvent(m_parent, new GrabberUpdateEvent());
00242 
00243     RunEpilog();
00244 }
00245 
00246 Search::Search()
00247     : m_searchProcess(NULL)
00248 {
00249     m_videoList.clear();
00250 }
00251 
00252 Search::~Search()
00253 {
00254     resetSearch();
00255 
00256     delete m_searchProcess;
00257     m_searchProcess = NULL;
00258 }
00259 
00260 
00261 void Search::executeSearch(const QString &script, const QString &query, uint pagenum)
00262 {
00263     resetSearch();
00264 
00265     LOG(VB_GENERAL, LOG_DEBUG, "Search::executeSearch");
00266     m_searchProcess = new MythSystem();
00267 
00268     connect(m_searchProcess, SIGNAL(finished()),
00269             this, SLOT(slotProcessSearchExit()));
00270     connect(m_searchProcess, SIGNAL(error(uint)),
00271             this, SLOT(slotProcessSearchExit(uint)));
00272 
00273     QString cmd = script;
00274 
00275     QStringList args;
00276 
00277     if (pagenum > 1)
00278     {
00279         args.append(QString("-p"));
00280         args.append(QString::number(pagenum));
00281     }
00282 
00283     args.append("-S");
00284     QString term = query;
00285     args.append(ShellEscape(term));
00286 
00287     LOG(VB_GENERAL, LOG_DEBUG, LOC +
00288         QString("Internet Search Query: %1 %2") .arg(cmd).arg(args.join(" ")));
00289 
00290     uint flags = kMSRunShell | kMSStdOut | kMSBuffered | kMSRunBackground;
00291     m_searchProcess->SetCommand(cmd, args, flags);
00292     m_searchProcess->Run(40);
00293 }
00294 
00295 void Search::resetSearch()
00296 {
00297     qDeleteAll(m_videoList);
00298     m_videoList.clear();
00299 }
00300 
00301 void Search::process()
00302 {
00303     Parse parse;
00304     m_videoList = parse.parseRSS(m_document);
00305 
00306     QDomNodeList entries = m_document.elementsByTagName("channel");
00307 
00308     if (entries.count() == 0)
00309     {
00310         m_numResults = 0;
00311         m_numReturned = 0;
00312         m_numIndex = 0;
00313         return;
00314     }
00315 
00316     QDomNode itemNode = entries.item(0);
00317 
00318     QDomNode Node = itemNode.namedItem(QString("numresults"));
00319     if (!Node.isNull())
00320     {
00321         m_numResults = Node.toElement().text().toUInt();
00322     }
00323     else
00324     {
00325         QDomNodeList count = m_document.elementsByTagName("item");
00326 
00327         if (count.count() == 0)
00328             m_numResults = 0;
00329         else
00330             m_numResults = count.count();
00331     }
00332 
00333     Node = itemNode.namedItem(QString("returned"));
00334     if (!Node.isNull())
00335     {
00336         m_numReturned = Node.toElement().text().toUInt();
00337     }
00338     else
00339     {
00340         QDomNodeList entries = m_document.elementsByTagName("item");
00341 
00342         if (entries.count() == 0)
00343             m_numReturned = 0;
00344         else
00345             m_numReturned = entries.count();
00346     }
00347 
00348     Node = itemNode.namedItem(QString("startindex"));
00349     if (!Node.isNull())
00350     {
00351         m_numIndex = Node.toElement().text().toUInt();
00352     }
00353     else
00354         m_numIndex = 0;
00355 
00356 }
00357 
00358 void Search::slotProcessSearchExit(uint exitcode)
00359 {
00360     if (exitcode == GENERIC_EXIT_TIMEOUT)
00361     {
00362         LOG(VB_GENERAL, LOG_WARNING, LOC + "Internet Search Timeout");
00363 
00364         if (m_searchProcess)
00365         {
00366             m_searchProcess->Term(true);
00367             m_searchProcess->deleteLater();
00368             m_searchProcess = NULL;
00369         }
00370         emit searchTimedOut(this);
00371         return;
00372     }
00373 
00374     if (exitcode != GENERIC_EXIT_OK)
00375     {
00376         m_document.setContent(QString());
00377     }
00378     else
00379     {
00380         LOG(VB_GENERAL, LOG_INFO, LOC +
00381             "Internet Search Successfully Completed");
00382 
00383         m_data = m_searchProcess->ReadAll();
00384         m_document.setContent(m_data, true);
00385     }
00386 
00387     m_searchProcess->deleteLater();
00388     m_searchProcess = NULL;
00389     emit finishedSearch(this);
00390 }
00391 
00392 void Search::SetData(QByteArray data)
00393 {
00394     m_data = data;
00395     m_document.setContent(m_data, true);
00396 
00397 }
00398 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends