Ticket #6159: fanart-download.final.diff

File fanart-download.final.diff, 13.3 KB (added by robert.mcnamara@…, 15 years ago)

Fix for IsHostSet?() breakage, and updated fanart downloader

  • mythvideo/mythvideo/videodlg.h

     
    2727typedef QMap<QString, QString> SearchListResults;
    2828
    2929enum CoverDownloadErrorState { esOK, esError, esTimeout };
     30enum FanartDownloadErrorState { fesOK, fesError, fesTimeout };
    3031
    3132class VideoDialog : public MythScreenType
    3233{
     
    138139    //       OnPosterCopyFinished()
    139140    // OnVideoPosterSetDone() stop wait background
    140141    void StartVideoPosterSet(Metadata *metadata);
     142    void StartVideoFanartSet(Metadata *metadata);
    141143
    142144    // StartVideoSearchByUID() start wait background
    143145    //   OnVideoSearchByUIDDone() stop wait background
     
    154156    void OnPosterURL(QString uri, Metadata *metadata);
    155157    void OnPosterCopyFinished(CoverDownloadErrorState error, QString errorMsg,
    156158                              Metadata *metadata);
     159    void OnFanartURL(QString uri, Metadata *metadata);
     160    void OnFanartCopyFinished(FanartDownloadErrorState error, QString errorMsg,
     161                              Metadata *metadata);
    157162
    158163    // called during StartVideoSearchByTitle
    159164    void OnVideoSearchByTitleDone(bool normal_exit,
     
    164169
    165170    // StartVideoPosterSet end
    166171    void OnVideoPosterSetDone(Metadata *metadata);
     172    void OnVideoFanartSetDone(Metadata *metadata);
    167173
    168174    // StartVideoSearchByUID end
    169175    void OnVideoSearchByUIDDone(bool normal_exit,
  • mythvideo/mythvideo/metadata.cpp

     
    397397
    398398bool MetadataImp::IsHostSet() const
    399399{
    400     return m_host.isEmpty();
     400    return !m_host.isEmpty();
    401401}
    402402
    403403void MetadataImp::fillGenres()
  • mythvideo/mythvideo/globalsettings.cpp

     
    215215    return gc;
    216216}
    217217
     218HostLineEdit *GetFanartCommand()
     219{
     220    HostLineEdit *gc = new HostLineEdit("MovieFanartCommandLine");
     221    gc->setLabel(QObject::tr("Command to search for movie fanart"));
     222    gc->setValue(GetShareDir() + "mythvideo/scripts/tmdb.pl -B");
     223    gc->setHelpText(QObject::tr("This command must be "
     224                    "executable by the user running MythVideo."));
     225    return gc;
     226}
     227
    218228HostLineEdit *GetDataCommand()
    219229{
    220230    HostLineEdit *gc = new HostLineEdit("MovieDataCommandLine");
     
    744776    vman->setLabel(QObject::tr("Video Manager"));
    745777    vman->addChild(SearchListingsCommand());
    746778    vman->addChild(GetPostersCommand());
     779    vman->addChild(GetFanartCommand());
    747780    vman->addChild(GetDataCommand());
    748781
    749782    VConfigPage page4(pages, false);
  • mythvideo/mythvideo/videodlg.cpp

     
    181181        CoverDownloadErrorState m_error_state;
    182182    };
    183183
     184    class FanartDownloadProxy : public QObject
     185    {
     186        Q_OBJECT
     187
     188      signals:
     189        void SigFinished(FanartDownloadErrorState reason, QString errorMsg,
     190                         Metadata *item);
     191      public:
     192        static FanartDownloadProxy *Create(const QUrl &url, const QString &dest,
     193                                          Metadata *item)
     194        {
     195            return new FanartDownloadProxy(url, dest, item);
     196        }
     197
     198      public:
     199        void StartCopy()
     200        {
     201            m_id = m_http.get(m_url.toString(), &m_data_buffer);
     202
     203            m_timer.start(gContext->GetNumSetting("FanartDownloadTimeout", 30)
     204                          * 1000);
     205        }
     206
     207        void Stop()
     208        {
     209            if (m_timer.isActive())
     210                m_timer.stop();
     211
     212            VERBOSE(VB_GENERAL, tr("Fanart download stopped."));
     213            m_http.abort();
     214        }
     215
     216      private:
     217        FanartDownloadProxy(const QUrl &url, const QString &dest,
     218                           Metadata *item) : m_item(item), m_dest_file(dest),
     219            m_id(0), m_url(url), m_error_state(fesOK)
     220        {
     221            connect(&m_http, SIGNAL(requestFinished(int, bool)),
     222                    SLOT(OnFinished(int, bool)));
     223
     224            connect(&m_timer, SIGNAL(timeout()), SLOT(OnDownloadTimeout()));
     225            m_timer.setSingleShot(true);
     226            m_http.setHost(m_url.host());
     227        }
     228
     229        ~FanartDownloadProxy() {}
     230
     231      private slots:
     232        void OnDownloadTimeout()
     233        {
     234            VERBOSE(VB_IMPORTANT, QString("Copying of '%1' timed out")
     235                    .arg(m_url.toString()));
     236            m_error_state = fesTimeout;
     237            Stop();
     238        }
     239
     240        void OnFinished(int id, bool error)
     241        {
     242            QString errorMsg;
     243            if (error)
     244                errorMsg = m_http.errorString();
     245
     246            if (id == m_id)
     247            {
     248                if (m_timer.isActive())
     249                    m_timer.stop();
     250
     251                if (!error)
     252                {
     253                    QFile dest_file(m_dest_file);
     254                    if (dest_file.exists())
     255                        dest_file.remove();
     256
     257                    if (dest_file.open(QIODevice::WriteOnly))
     258                    {
     259                        const QByteArray &data = m_data_buffer.data();
     260                        qint64 size = dest_file.write(data);
     261                        if (size != data.size())
     262                        {
     263                            errorMsg = tr("Error writing data to file %1.")
     264                                    .arg(m_dest_file);
     265                            m_error_state = fesError;
     266                        }
     267                    }
     268                    else
     269                    {
     270                        errorMsg = tr("Error: file error '%1' for file %2").
     271                                arg(dest_file.errorString()).arg(m_dest_file);
     272                        m_error_state = fesError;
     273                    }
     274                }
     275
     276                emit SigFinished(m_error_state, errorMsg, m_item);
     277            }
     278        }
     279
     280      private:
     281        Metadata *m_item;
     282        QHttp m_http;
     283        QBuffer m_data_buffer;
     284        QString m_dest_file;
     285        int m_id;
     286        QTimer m_timer;
     287        QUrl m_url;
     288        FanartDownloadErrorState m_error_state;
     289    };
     290
    184291    /** \class ExecuteExternalCommand
    185292     *
    186293     * \brief Base class for executing an external script or other process, must
     
    501608        Metadata *m_item;
    502609    };
    503610
     611    /** \class VideoFanartSearch
     612     *
     613     * \brief Execute external video fanart command.
     614     *
     615     */
     616    class VideoFanartSearch : public ExecuteExternalCommand
     617    {
     618        Q_OBJECT
     619
     620      signals:
     621        void SigFanartURL(QString url, Metadata *item);
     622
     623      public:
     624        VideoFanartSearch(QObject *oparent) :
     625            ExecuteExternalCommand(oparent), m_item(0) {}
     626
     627        void Run(QString video_uid, Metadata *item)
     628        {
     629            m_item = item;
     630
     631            const QString default_cmd =
     632                    QDir::cleanPath(QString("%1/%2")
     633                                        .arg(GetShareDir())
     634                                        .arg("mythvideo/scripts/tmdb.pl -B"));
     635            const QString cmd = gContext->GetSetting("MovieFanartCommandLine",
     636                                                        default_cmd);
     637            StartRun(cmd, QStringList(video_uid), "Fanart Query");
     638        }
     639
     640      private:
     641        ~VideoFanartSearch() {}
     642
     643        void OnExecDone(bool normal_exit, QStringList out, QStringList err)
     644        {
     645            (void) err;
     646            QString url;
     647            if (normal_exit && out.size())
     648            {
     649                for (QStringList::const_iterator p = out.begin();
     650                        p != out.end(); ++p)
     651                {
     652                    if ((*p).length())
     653                    {
     654                        url = *p;
     655                        break;
     656                    }
     657                }
     658            }
     659
     660            emit SigFanartURL(url, m_item);
     661            deleteLater();
     662        }
     663
     664      private:
     665        Metadata *m_item;
     666    };
     667
     668
    504669    class ParentalLevelNotifyContainer : public QObject
    505670    {
    506671        Q_OBJECT
     
    10861250        m_isFileBrowser = gContext->GetNumSetting("VideoDialogNoDB", 0);
    10871251
    10881252        m_artDir = gContext->GetSetting("VideoArtworkDir");
     1253        m_fanDir = gContext->GetSetting("VideoFanartDir");
    10891254    }
    10901255
    10911256    ~VideoDialogPrivate()
     
    11381303        }
    11391304    }
    11401305
     1306    void AddFanartDownload(FanartDownloadProxy *download)
     1307    {
     1308        m_running_fdownloads.insert(download);
     1309    }
     1310
     1311    void RemoveFanartDownload(FanartDownloadProxy *download)
     1312    {
     1313        if (download)
     1314        {
     1315            fanart_download_list::iterator p =
     1316                    m_running_fdownloads.find(download);
     1317            if (p != m_running_fdownloads.end())
     1318                m_running_fdownloads.erase(p);
     1319        }
     1320    }
     1321
    11411322    void StopAllRunningCoverDownloads()
    11421323    {
    11431324        cover_download_list tmp(m_running_downloads);
     
    11451326            (*p)->Stop();
    11461327    }
    11471328
     1329    void StopAllRunningFanartDownloads()
     1330    {
     1331        fanart_download_list tmp(m_running_fdownloads);
     1332        for (fanart_download_list::iterator p = tmp.begin(); p != tmp.end(); ++p)
     1333            (*p)->Stop();
     1334    }
     1335
     1336
    11481337  public:
    11491338    typedef std::set<CoverDownloadProxy *> cover_download_list;
    11501339    cover_download_list m_running_downloads;
     1340    typedef std::set<FanartDownloadProxy *> fanart_download_list;
     1341    fanart_download_list m_running_fdownloads;
    11511342    ParentalLevelNotifyContainer m_parentalLevel;
    11521343    bool m_switchingLayout;
    11531344
     
    11691360    VideoDialog::DialogType m_type;
    11701361
    11711362    QString m_artDir;
     1363    QString m_fanDir;
    11721364    VideoScanner *m_scanner;
    11731365
    11741366    QString m_lastTreeNodePath;
     
    23552547    }
    23562548
    23572549    return metadata;
     2550
     2551    // Obtain video fanart
     2552    VideoFanartSearch *vfs = new VideoFanartSearch(this);
     2553    connect(vfs, SIGNAL(SigFanartURL(QString, Metadata *)),
     2554            SLOT(OnFanartURL(QString, Metadata *)));
     2555    vfs->Run(metadata->GetInetRef(), metadata);
     2556
    23582557}
    23592558
    23602559void VideoDialog::customEvent(QEvent *levent)
     
    26942893    UpdateItem(GetItemCurrent());
    26952894}
    26962895
     2896void VideoDialog::OnFanartURL(QString uri, Metadata *metadata)
     2897{
     2898    if (metadata)
     2899    {
     2900        if (uri.length())
     2901        {
     2902            QString fileprefix = m_d->m_fanDir;
     2903
     2904            QDir dir;
     2905
     2906            // If the fanart setting hasn't been set default to
     2907            // using ~/.mythtv/MythVideo/Fanart
     2908            if (fileprefix.length() == 0)
     2909            {
     2910                fileprefix = GetConfDir();
     2911
     2912                dir.setPath(fileprefix);
     2913                if (!dir.exists())
     2914                    dir.mkdir(fileprefix);
     2915
     2916                fileprefix += "/MythVideo/Fanart";
     2917            }
     2918
     2919            dir.setPath(fileprefix);
     2920            if (!dir.exists())
     2921                dir.mkdir(fileprefix);
     2922
     2923            QUrl url(uri);
     2924
     2925            QString ext = QFileInfo(url.path()).suffix();
     2926            QString dest_file = QString("%1/%2.%3").arg(fileprefix)
     2927                    .arg(metadata->GetInetRef()).arg(ext);
     2928            VERBOSE(VB_IMPORTANT, QString("Copying '%1' -> '%2'...")
     2929                    .arg(url.toString()).arg(dest_file));
     2930
     2931            FanartDownloadProxy *d =
     2932                    FanartDownloadProxy::Create(url, dest_file, metadata);
     2933            metadata->SetFanart(dest_file);
     2934
     2935            connect(d, SIGNAL(SigFinished(FanartDownloadErrorState,
     2936                                          QString, Metadata *)),
     2937                    SLOT(OnFanartCopyFinished(FanartDownloadErrorState,
     2938                                              QString, Metadata *)));
     2939
     2940            d->StartCopy();
     2941            m_d->AddFanartDownload(d);
     2942        }
     2943        else
     2944        {
     2945            metadata->SetFanart("");
     2946            OnVideoFanartSetDone(metadata);
     2947        }
     2948    }
     2949    else
     2950        OnVideoFanartSetDone(metadata);
     2951}
     2952
     2953void VideoDialog::OnFanartCopyFinished(FanartDownloadErrorState error,
     2954                                       QString errorMsg, Metadata *item)
     2955{
     2956    QObject *src = sender();
     2957    if (src)
     2958        m_d->RemoveFanartDownload(dynamic_cast<FanartDownloadProxy *>
     2959                                       (src));
     2960
     2961    if (error != fesOK && item)
     2962        item->SetFanart("");
     2963
     2964    VERBOSE(VB_IMPORTANT, tr("Fanart download finished: %1 %2")
     2965            .arg(errorMsg).arg(error));
     2966
     2967    if (error == fesTimeout)
     2968    {
     2969        createOkDialog(tr("Fanart exists for this item but could not be "
     2970                            "retrieved within the timeout period.\n"));
     2971    }
     2972
     2973    OnVideoFanartSetDone(item);
     2974}
     2975
     2976// This is the final call as part of a StartVideoFanartSet
     2977void VideoDialog::OnVideoFanartSetDone(Metadata *metadata)
     2978{
     2979    // The metadata has some fanart set
     2980    if (m_busyPopup)
     2981    {
     2982        m_busyPopup->Close();
     2983        m_busyPopup = NULL;
     2984    }
     2985
     2986    metadata->UpdateDatabase();
     2987    UpdateItem(GetItemCurrent());
     2988}
     2989
    26972990void VideoDialog::StartVideoSearchByUID(QString video_uid, Metadata *metadata)
    26982991{
    26992992    // Starting the busy dialog here triggers a bizarre segfault