Ticket #9265: backendvideoscan.diff

File backendvideoscan.diff, 18.1 KB (added by robertm, 14 years ago)

Backend video scanner, version 1

  • libs/libmyth/mythcommandlineparser.cpp

     
    3434    setverbose(false),
    3535    resched(false),
    3636    nosched(false),
     37    scanvideos(false),
    3738    noupnp(false),
    3839    nojobqueue(false),
    3940    nohousekeeper(false),
     
    238239        nosched = true;
    239240        return true;
    240241    }
     242    else if ((parseTypes && kCLPReschedule) &&
     243             !strcmp(argv[argpos],"--scanvideos"))
     244    {
     245        scanvideos = true;
     246        return true;
     247    }
    241248    else if ((parseTypes && kCLPNoUPnP) &&
    242249             !strcmp(argv[argpos],"--noupnp"))
    243250    {
     
    836843            << "Do not perform any scheduling" << endl;
    837844    }
    838845
     846    if (parseTypes & kCLPScanVideos)
     847    {
     848        msg << "--scanvideos                   "
     849            << "Scan for new video content" << endl;
     850    }
     851
    839852    if (parseTypes & kCLPNoUPnP)
    840853    {
    841854        msg << "--noupnp                       "
  • libs/libmyth/mythcommandlineparser.h

     
    4444    kCLPStartTime            = 0x0080000000ULL,
    4545    kCLPPrintExpire          = 0x0100000000ULL,
    4646    kCLPGeneratePreview      = 0x0200000000ULL,
     47    kCLPScanVideos           = 0x0400000000ULL,
    4748} ParseType;
    4849
    4950class MPUBLIC MythCommandLineParser
     
    8788
    8889    bool SetVerbose(void)           const { return setverbose;  }
    8990    bool Reschedule(void)           const { return resched;     }
     91    bool ScanVideos(void)           const { return scanvideos;  }
    9092    bool ClearSettingsCache(void)   const { return clearsettingscache; }
    9193    bool WantUPnPRebuild(void)      const { return wantupnprebuild; }
    9294
     
    101103            !eventString.isEmpty()    || wantupnprebuild       ||
    102104            setverbose                || clearsettingscache    ||
    103105            printsched                || testsched             ||
    104             resched                   || !printexpire.isEmpty();
     106            resched                   || scanvideos            ||
     107            !printexpire.isEmpty();
    105108    }
    106109
    107110    bool    WantsToExit(void) const { return wantsToExit; }
     
    137140    bool                  setverbose;
    138141    bool                  resched;
    139142    bool                  nosched;
     143    bool                  scanvideos;
    140144    bool                  noupnp;
    141145    bool                  nojobqueue;
    142146    bool                  nohousekeeper;
  • libs/libmythmetadata/videometadata.cpp

     
    77
    88#include "mythcontext.h"
    99#include "mythdb.h"
     10#include "storagegroup.h"
    1011#include "remotefile.h"
    1112#include "remoteutil.h"
    1213#include "util.h"
     
    942943QString VideoMetadata::VideoFileHash(const QString &file_name,
    943944                           const QString &host)
    944945{
    945     if (!host.isEmpty())
     946    if (!host.isEmpty() && !isHostMaster(host))
    946947    {
    947948        QString url = generate_file_url("Videos", host, file_name);
    948949        return RemoteFile::GetFileHash(url);
    949950    }
     951    else if (!host.isEmpty())
     952    {
     953        StorageGroup sgroup("Videos", host);
     954        QString fullname = sgroup.FindRecordingFile(file_name);
     955        return FileHash(fullname);
     956    }
    950957    else
    951958        return FileHash(file_name);
    952959}
  • libs/libmythmetadata/videoscan.cpp

     
    8181        VideoMetadataListManager::metadata_list ml;
    8282        VideoMetadataListManager::loadAllFromDatabase(ml);
    8383        m_dbmetadata->setList(ml);
    84 
     84        m_HasGUI = gCoreContext->HasGUI();
    8585        m_ListUnknown = gCoreContext->GetNumSetting("VideoListUnknownFiletypes", 0);
    8686    }
    8787
     
    100100            imageExtensions.push_back(QString(*p));
    101101        }
    102102
     103        VERBOSE(VB_GENERAL, QString("Beginning Video Scan."));
     104
    103105        uint counter = 0;
    104106        FileCheckList fs_files;
    105107        failedSGHosts.clear();
    106108
    107         SendProgressEvent(counter, (uint)m_directories.size(),
    108                           tr("Searching for video files"));
     109        if (m_HasGUI)
     110            SendProgressEvent(counter, (uint)m_directories.size(),
     111                              tr("Searching for video files"));
    109112        for (QStringList::const_iterator iter = m_directories.begin();
    110113             iter != m_directories.end(); ++iter)
    111114        {
     
    122125                    VERBOSE(VB_GENERAL, QString("Failed to scan :%1:").arg(*iter));
    123126                }
    124127            }
    125 
    126             SendProgressEvent(++counter);
     128            if (m_HasGUI)
     129                SendProgressEvent(++counter);
    127130        }
    128131
    129132        PurgeList db_remove;
     
    184187        int counter = 0;
    185188        FileCheckList::iterator iter;
    186189
    187         SendProgressEvent(counter, (uint)m_dbmetadata->getList().size(),
    188                           tr("Verifying video files"));
     190        if (m_HasGUI)
     191            SendProgressEvent(counter, (uint)m_dbmetadata->getList().size(),
     192                              tr("Verifying video files"));
    189193
    190194        // For every file we know about, check to see if it still exists.
    191195        for (VideoMetadataListManager::metadata_list::const_iterator p =
     
    223227                    }
    224228                }
    225229            }
    226 
    227             SendProgressEvent(++counter);
     230            if (m_HasGUI)
     231                SendProgressEvent(++counter);
    228232        }
    229233    }
    230234
     
    234238        int ret = 0;
    235239        uint counter = 0;
    236240        QList<int> preservelist;
    237         SendProgressEvent(counter, (uint)(add.size() + remove.size()),
    238                           tr("Updating video database"));
     241        if (m_HasGUI)
     242            SendProgressEvent(counter, (uint)(add.size() + remove.size()),
     243                              tr("Updating video database"));
    239244
    240245        for (FileCheckList::const_iterator p = add.begin(); p != add.end(); ++p)
    241246        {
     
    289294                }
    290295                ret += 1;
    291296            }
    292             SendProgressEvent(++counter);
     297            if (m_HasGUI)
     298                SendProgressEvent(++counter);
    293299        }
    294300
    295301        // When prompting is restored, account for the answer here.
     
    299305        {
    300306            if (!preservelist.contains(p->first))
    301307                removeOrphans(p->first, p->second);
    302             SendProgressEvent(++counter);
     308            if (m_HasGUI)
     309                SendProgressEvent(++counter);
    303310        }
    304311
    305312        return ret;
     
    332339    bool m_ListUnknown;
    333340    bool m_RemoveAll;
    334341    bool m_KeepAll;
     342    bool m_HasGUI;
    335343    QStringList m_directories;
    336344    QStringList failedSGHosts;
    337345
     
    357365    if (m_scanThread->isRunning())
    358366        return;
    359367
    360     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
     368    if (gCoreContext->HasGUI())
     369    {
     370        MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
    361371
    362     MythUIProgressDialog *progressDlg = new MythUIProgressDialog("",
    363             popupStack, "videoscanprogressdialog");
     372        MythUIProgressDialog *progressDlg = new MythUIProgressDialog("",
     373                popupStack, "videoscanprogressdialog");
    364374
    365     if (progressDlg->Create())
    366     {
    367         popupStack->AddScreen(progressDlg, false);
    368         connect(m_scanThread, SIGNAL(finished()),
    369                 progressDlg, SLOT(Close()));
    370         connect(m_scanThread, SIGNAL(finished()),
    371                 SLOT(finishedScan()));
     375        if (progressDlg->Create())
     376        {
     377            popupStack->AddScreen(progressDlg, false);
     378            connect(m_scanThread, SIGNAL(finished()),
     379                    progressDlg, SLOT(Close()));
     380            connect(m_scanThread, SIGNAL(finished()),
     381                    SLOT(finishedScan()));
     382        }
     383        else
     384        {
     385            delete progressDlg;
     386            progressDlg = NULL;
     387        }
     388        m_scanThread->SetProgressDialog(progressDlg);
    372389    }
    373     else
    374     {
    375         delete progressDlg;
    376         progressDlg = NULL;
    377     }
    378390
    379391    m_scanThread->SetDirs(dirs);
    380     m_scanThread->SetProgressDialog(progressDlg);
    381392    m_scanThread->start();
    382393}
    383394
  • libs/libmythmetadata/videoscan.h

     
    2626
    2727  private:
    2828    class VideoScannerThread *m_scanThread;
    29     bool                m_cancel;
     29    bool                      m_cancel;
    3030};
    3131
    3232#endif
  • libs/libmythmetadata/dirscan.cpp

     
    99#include "mythcontext.h"
    1010#include "mythverbose.h"
    1111#include "videoutils.h"
     12#include "storagegroup.h"
    1213
    1314DirectoryHandler::~DirectoryHandler()
    1415{
     
    111112
    112113    bool scan_sg_dir(const QString &start_path, const QString &host,
    113114                     const QString &base_path, DirectoryHandler *handler,
    114                              const ext_lookup &ext_settings)
     115                     const ext_lookup &ext_settings, bool isMaster = false)
    115116    {
    116117        QString path = start_path;
    117118
     
    125126            path = "";
    126127
    127128        QStringList list;
    128         bool ok = RemoteGetFileList(host, start_path, &list, "Videos");
     129        bool ok = false;
    129130
    130         if (!ok || list.at(0).startsWith("SLAVE UNREACHABLE"))
     131        if (isMaster)
    131132        {
     133            StorageGroup sg("Videos", host);
     134            list = sg.GetFileInfoList(start_path);
     135            ok = true;
     136        }
     137        else
     138            ok = RemoteGetFileList(host, start_path, &list, "Videos");
     139
     140        if (!ok || (!list.isEmpty() && list.at(0).startsWith("SLAVE UNREACHABLE")))
     141        {
    132142            VERBOSE(VB_GENERAL, QString("Backend : %1 : Is currently Unreachable. Skipping this one.")
    133143                                .arg(host));
    134144            return false;
    135145        }
    136146
    137         if ((!list.size()) || (list.at(0) == "EMPTY LIST")) 
     147        if ((!list.size()) || (list.at(0) == "EMPTY LIST"))
    138148            return true;
    139149
    140150        for (QStringList::iterator p = list.begin(); p != list.end(); ++p)
     
    164174                // so ignore the results and continue. As long as we reached it once
    165175                // to make it this far than we know he SG/Path exists
    166176                (void) scan_sg_dir(start_path + "/" + fileName, host, base_path,
    167                              dh, ext_settings);
     177                             dh, ext_settings, isMaster);
    168178            }
    169179            else
    170180            {
     
    231241        QString host = sgurl.host();
    232242        QString path = sgurl.path();
    233243
    234         if (!scan_sg_dir(path, host, path, handler, extlookup))
     244        if (!scan_sg_dir(path, host, path, handler, extlookup, isHostMaster(host)))
    235245        {
    236246            VERBOSE(VB_GENERAL, QString("MythVideo::ScanVideoDirectory failed to scan %1 ").arg(host));
    237247            pathScanned = false;
  • libs/libmythmetadata/videoutils.cpp

     
    241241        ret = "no";
    242242    return ret;
    243243}
     244
     245bool isHostMaster(const QString &host)
     246{
     247    bool isMaster = false;
     248    QString masterIP = gCoreContext->GetSetting("MasterServerIP");
     249    QString hostIP;
     250
     251    MSqlQuery query(MSqlQuery::InitCon());
     252    query.prepare("SELECT data FROM settings WHERE "
     253                  "value = 'BackendServerIP' AND "
     254                  "hostname = :HOSTNAME;");
     255    query.bindValue(":HOSTNAME", host);
     256
     257    if (query.exec() && query.next())
     258    {
     259        hostIP = query.value(0).toString();
     260        if (hostIP == masterIP)
     261            isMaster = true;
     262    }
     263
     264    return isMaster;
     265}
  • libs/libmythmetadata/videoutils.h

     
    5151MPUBLIC QString ParentalLevelToState(const ParentalLevel &level);
    5252MPUBLIC QString WatchedToState(bool watched);
    5353
     54MPUBLIC bool isHostMaster(const QString &host);
     55
    5456// this needs to be an inline and pull in the storage group and context
    5557// headers since it this used in dbcheck.cpp.
    5658#include <storagegroup.h>
  • programs/programs-libs.pro

     
    11INCLUDEPATH += ../.. ../../libs/ ../../libs/libmyth ../../libs/libmythtv
    22INCLUDEPATH += ../../external/FFmpeg
    3 INCLUDEPATH += ../../libs/libmythupnp ../../libs/libmythui
     3INCLUDEPATH += ../../libs/libmythupnp ../../libs/libmythui ../../libs/libmythmetadata
    44INCLUDEPATH += ../../libs/libmythlivemedia ../../libs/libmythdb ../../libmythhdhomerun
    55INCLUDEPATH += ../../libs/libmythdvdnav ../../libs/libmythbluray ../../libs/libmythsamplerate
    66
     
    1313LIBS += -L../../libs/libmythdb
    1414LIBS += -L../../libs/libmythui
    1515LIBS += -L../../libs/libmythupnp
     16LIBS += -L../../libs/libmythmetdata
    1617
    1718LIBS += -lmythtv-$$LIBVERSION
    1819LIBS += -lmythswscale
     
    2425LIBS += -lmythdb-$$LIBVERSION
    2526LIBS += -lmythui-$$LIBVERSION
    2627LIBS += -lmyth-$$LIBVERSION
     28LIBS += -lmythmetadata-$$LIBVERSION
    2729
    2830using_live:LIBS += -L../../libs/libmythlivemedia -lmythlivemedia-$$LIBVERSION
    2931using_mheg:LIBS += -L../../libs/libmythfreemheg -lmythfreemheg-$$LIBVERSION
  • programs/mythbackend/mainserver.h

     
    2828class ProcessRequestThread;
    2929class QUrl;
    3030class MythServer;
     31class VideoScanner;
    3132class QTimer;
    3233
    3334class MainServer : public QObject, public MythSocketCBs
     
    6667    void reconnectTimeout(void);
    6768    void deferredDeleteSlot(void);
    6869    void autoexpireUpdate(void);
     70    void finishVideoScan(bool changed);
    6971
    7072  private slots:
    7173    void newConnection(MythSocket *);
     
    158160    void HandleSetBookmark(QStringList &tokens, PlaybackSock *pbs);
    159161    void HandleSettingQuery(QStringList &tokens, PlaybackSock *pbs);
    160162    void HandleSetSetting(QStringList &tokens, PlaybackSock *pbs);
     163    void HandleScanVideos(PlaybackSock *pbs);
    161164    void HandleVersion(MythSocket *socket, const QStringList &slist);
    162165    void HandleBackendRefresh(MythSocket *socket);
    163166    void HandleQueryLoad(PlaybackSock *pbs);
     
    209212    QMap<int, EncoderLink *> *encoderList;
    210213
    211214    MythServer *mythserver;
     215    VideoScanner *videoscanner;
    212216
    213217    QReadWriteLock sockListLock;
    214218    vector<PlaybackSock *> playbackList;
  • programs/mythbackend/main.cpp

     
    8181        kCLPTestSchedule         |
    8282        kCLPReschedule           |
    8383        kCLPNoSchedule           |
     84        kCLPScanVideos           |
    8485        kCLPNoUPnP               |
    8586        kCLPUPnPRebuild          |
    8687        kCLPNoJobqueue           |
  • programs/mythbackend/main_helpers.cpp

     
    511511        return (ok) ? BACKEND_EXIT_OK : BACKEND_EXIT_NO_CONNECT;
    512512    }
    513513
     514    if (cmdline.ScanVideos())
     515    {
     516        bool ok = false;
     517        if (gCoreContext->ConnectToMasterServer())
     518        {
     519            RemoteSendMessage("SCAN_VIDEOS");
     520            VERBOSE(VB_IMPORTANT, "Requested video scan");
     521            ok = true;
     522        }
     523        else
     524            VERBOSE(VB_IMPORTANT, "Cannot connect to master for video scan");
     525
     526        return (ok) ? BACKEND_EXIT_OK : BACKEND_EXIT_NO_CONNECT;
     527    }
     528
    514529    if (!cmdline.GetPrintExpire().isEmpty())
    515530    {
    516531        expirer = new AutoExpire();
  • programs/mythbackend/mainserver.cpp

     
    6464#include "mythcoreutil.h"
    6565#include "mythdirs.h"
    6666#include "mythdownloadmanager.h"
     67#include "videoscan.h"
     68#include "videoutils.h"
    6769
    68 
    6970/** Milliseconds to wait for an existing thread from
    7071 *  process request thread pool.
    7172 */
     
    645646        else
    646647            HandleSetSetting(tokens, pbs);
    647648    }
     649    else if (command == "SCAN_VIDEOS")
     650    {
     651        HandleScanVideos(pbs);
     652    }
    648653    else if (command == "ALLOW_SHUTDOWN")
    649654    {
    650655        if (tokens.size() != 1)
     
    21822187    return ok;
    21832188}
    21842189
     2190void MainServer::finishVideoScan(bool changed)
     2191{
     2192    if (changed)
     2193        VERBOSE(VB_FILE, QString("Video scan completed, new entries added"));
     2194    delete videoscanner;
     2195    videoscanner = NULL;
     2196
     2197}
     2198
    21852199void MainServer::HandleCheckRecordingActive(QStringList &slist,
    21862200                                            PlaybackSock *pbs)
    21872201{
     
    47984812    return;
    47994813}
    48004814
     4815void MainServer::HandleScanVideos(PlaybackSock *pbs)
     4816{
     4817    MythSocket *pbssock = pbs->getSocket();
     4818
     4819    QStringList retlist;
     4820
     4821    videoscanner = new VideoScanner();
     4822
     4823    if (videoscanner)
     4824    {
     4825        connect(videoscanner, SIGNAL(finished(bool)),
     4826            SLOT(finishVideoScan(bool)));
     4827        videoscanner->doScan(GetVideoDirs());
     4828        retlist << "OK";
     4829    }
     4830    else
     4831        retlist << "ERROR";
     4832
     4833    if (pbssock)
     4834        SendResponse(pbssock, retlist);
     4835}
     4836
    48014837void MainServer::HandleFileTransferQuery(QStringList &slist,
    48024838                                         QStringList &commands,
    48034839                                         PlaybackSock *pbs)