Ticket #6159: MV-fanartdownloader.2.diff

File MV-fanartdownloader.2.diff, 13.1 KB (added by robert.mcnamara@…, 15 years ago)

Fix to keep Fanart from Overwriting Coverfile, supercedes previous.

  • 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{
     
    134138    //       OnPosterCopyFinished()
    135139    // OnVideoPosterSetDone() stop wait background
    136140    void StartVideoPosterSet(Metadata *metadata);
     141    void StartVideoFanartSet(Metadata *metadata);
    137142
    138143    // StartVideoSearchByUID() start wait background
    139144    //   OnVideoSearchByUIDDone() stop wait background
     
    150155    void OnPosterURL(QString uri, Metadata *metadata);
    151156    void OnPosterCopyFinished(CoverDownloadErrorState error, QString errorMsg,
    152157                              Metadata *metadata);
     158    void OnFanartURL(QString uri, Metadata *metadata);
     159    void OnFanartCopyFinished(FanartDownloadErrorState error, QString errorMsg,
     160                              Metadata *metadata);
    153161
    154162    // called during StartVideoSearchByTitle
    155163    void OnVideoSearchByTitleDone(bool normal_exit,
     
    160168
    161169    // StartVideoPosterSet end
    162170    void OnVideoPosterSetDone(Metadata *metadata);
     171    void OnVideoFanartSetDone(Metadata *metadata);
    163172
    164173    // StartVideoSearchByUID end
    165174    void OnVideoSearchByUIDDone(bool normal_exit,
  • 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");
     
    708776    vman->setLabel(QObject::tr("Video Manager"));
    709777    vman->addChild(SearchListingsCommand());
    710778    vman->addChild(GetPostersCommand());
     779    vman->addChild(GetFanartCommand());
    711780    vman->addChild(GetDataCommand());
    712781
    713782    VConfigPage page4(pages, false);
  • mythvideo/mythvideo/videodlg.cpp

     
    180180        CoverDownloadErrorState m_error_state;
    181181    };
    182182
     183    class FanartDownloadProxy : public QObject
     184    {
     185        Q_OBJECT
     186
     187      signals:
     188        void SigFinished(FanartDownloadErrorState reason, QString errorMsg,
     189                         Metadata *item);
     190      public:
     191        static FanartDownloadProxy *Create(const QUrl &url, const QString &dest,
     192                                          Metadata *item)
     193        {
     194            return new FanartDownloadProxy(url, dest, item);
     195        }
     196
     197      public:
     198        void StartCopy()
     199        {
     200            m_id = m_http.get(m_url.toString(), &m_data_buffer);
     201
     202            m_timer.start(gContext->GetNumSetting("FanartDownloadTimeout", 30)
     203                          * 1000);
     204        }
     205
     206        void Stop()
     207        {
     208            if (m_timer.isActive())
     209                m_timer.stop();
     210
     211            VERBOSE(VB_GENERAL, tr("Fanart download stopped."));
     212            m_http.abort();
     213        }
     214
     215      private:
     216        FanartDownloadProxy(const QUrl &url, const QString &dest,
     217                           Metadata *item) : m_item(item), m_dest_file(dest),
     218            m_id(0), m_url(url), m_error_state(fesOK)
     219        {
     220            connect(&m_http, SIGNAL(requestFinished(int, bool)),
     221                    SLOT(OnFinished(int, bool)));
     222
     223            connect(&m_timer, SIGNAL(timeout()), SLOT(OnDownloadTimeout()));
     224            m_timer.setSingleShot(true);
     225            m_http.setHost(m_url.host());
     226        }
     227
     228        ~FanartDownloadProxy() {}
     229
     230      private slots:
     231        void OnDownloadTimeout()
     232        {
     233            VERBOSE(VB_IMPORTANT, QString("Copying of '%1' timed out")
     234                    .arg(m_url.toString()));
     235            m_error_state = fesTimeout;
     236            Stop();
     237        }
     238
     239        void OnFinished(int id, bool error)
     240        {
     241            QString errorMsg;
     242            if (error)
     243                errorMsg = m_http.errorString();
     244
     245            if (id == m_id)
     246            {
     247                if (m_timer.isActive())
     248                    m_timer.stop();
     249
     250                if (!error)
     251                {
     252                    QFile dest_file(m_dest_file);
     253                    if (dest_file.exists())
     254                        dest_file.remove();
     255
     256                    if (dest_file.open(QIODevice::WriteOnly))
     257                    {
     258                        const QByteArray &data = m_data_buffer.data();
     259                        qint64 size = dest_file.write(data);
     260                        if (size != data.size())
     261                        {
     262                            errorMsg = tr("Error writing data to file %1.")
     263                                    .arg(m_dest_file);
     264                            m_error_state = fesError;
     265                        }
     266                    }
     267                    else
     268                    {
     269                        errorMsg = tr("Error: file error '%1' for file %2").
     270                                arg(dest_file.errorString()).arg(m_dest_file);
     271                        m_error_state = fesError;
     272                    }
     273                }
     274
     275                emit SigFinished(m_error_state, errorMsg, m_item);
     276            }
     277        }
     278
     279      private:
     280        Metadata *m_item;
     281        QHttp m_http;
     282        QBuffer m_data_buffer;
     283        QString m_dest_file;
     284        int m_id;
     285        QTimer m_timer;
     286        QUrl m_url;
     287        FanartDownloadErrorState m_error_state;
     288    };
     289
    183290    /** \class ExecuteExternalCommand
    184291     *
    185292     * \brief Base class for executing an external script or other process, must
     
    500607        Metadata *m_item;
    501608    };
    502609
     610    /** \class VideoFanartSearch
     611     *
     612     * \brief Execute external video fanart command.
     613     *
     614     */
     615    class VideoFanartSearch : public ExecuteExternalCommand
     616    {
     617        Q_OBJECT
     618
     619      signals:
     620        void SigFanartURL(QString url, Metadata *item);
     621
     622      public:
     623        VideoFanartSearch(QObject *oparent) :
     624            ExecuteExternalCommand(oparent), m_item(0) {}
     625
     626        void Run(QString video_uid, Metadata *item)
     627        {
     628            m_item = item;
     629
     630            const QString default_cmd =
     631                    QDir::cleanPath(QString("%1/%2")
     632                                        .arg(GetShareDir())
     633                                        .arg("mythvideo/scripts/tmdb.pl -B"));
     634            const QString cmd = gContext->GetSetting("MovieFanartCommandLine",
     635                                                        default_cmd);
     636            StartRun(cmd, QStringList(video_uid), "Fanart Query");
     637        }
     638
     639      private:
     640        ~VideoFanartSearch() {}
     641
     642        void OnExecDone(bool normal_exit, QStringList out, QStringList err)
     643        {
     644            (void) err;
     645            QString url;
     646            if (normal_exit && out.size())
     647            {
     648                for (QStringList::const_iterator p = out.begin();
     649                        p != out.end(); ++p)
     650                {
     651                    if ((*p).length())
     652                    {
     653                        url = *p;
     654                        break;
     655                    }
     656                }
     657            }
     658
     659            emit SigFanartURL(url, m_item);
     660            deleteLater();
     661        }
     662
     663      private:
     664        Metadata *m_item;
     665    };
     666
     667
    503668    class ParentalLevelNotifyContainer : public QObject
    504669    {
    505670        Q_OBJECT
     
    10201209        m_isFileBrowser = gContext->GetNumSetting("VideoDialogNoDB", 0);
    10211210
    10221211        m_artDir = gContext->GetSetting("VideoArtworkDir");
     1212        m_fanDir = gContext->GetSetting("VideoFanartDir");
    10231213    }
    10241214
    10251215    ~VideoDialogPrivate()
     
    10721262        }
    10731263    }
    10741264
     1265    void AddFanartDownload(FanartDownloadProxy *download)
     1266    {
     1267        m_running_fdownloads.insert(download);
     1268    }
     1269
     1270    void RemoveFanartDownload(FanartDownloadProxy *download)
     1271    {
     1272        if (download)
     1273        {
     1274            fanart_download_list::iterator p =
     1275                    m_running_fdownloads.find(download);
     1276            if (p != m_running_fdownloads.end())
     1277                m_running_fdownloads.erase(p);
     1278        }
     1279    }
     1280
    10751281    void StopAllRunningCoverDownloads()
    10761282    {
    10771283        cover_download_list tmp(m_running_downloads);
     
    10791285            (*p)->Stop();
    10801286    }
    10811287
     1288    void StopAllRunningFanartDownloads()
     1289    {
     1290        fanart_download_list tmp(m_running_fdownloads);
     1291        for (fanart_download_list::iterator p = tmp.begin(); p != tmp.end(); ++p)
     1292            (*p)->Stop();
     1293    }
     1294
     1295
    10821296  public:
    10831297    typedef std::set<CoverDownloadProxy *> cover_download_list;
    10841298    cover_download_list m_running_downloads;
     1299    typedef std::set<FanartDownloadProxy *> fanart_download_list;
     1300    fanart_download_list m_running_fdownloads;
    10851301    ParentalLevelNotifyContainer m_parentalLevel;
    10861302    bool m_switchingLayout;
    10871303
     
    11031319    VideoDialog::DialogType m_type;
    11041320
    11051321    QString m_artDir;
     1322    QString m_fanDir;
    11061323    VideoScanner *m_scanner;
    11071324
    11081325    QString m_lastTreeNodePath;
     
    22882580    connect(vps, SIGNAL(SigPosterURL(QString, Metadata *)),
    22892581            SLOT(OnPosterURL(QString, Metadata *)));
    22902582    vps->Run(metadata->InetRef(), metadata);
     2583
     2584    // Obtain video fanart
     2585    VideoFanartSearch *vfs = new VideoFanartSearch(this);
     2586    connect(vfs, SIGNAL(SigFanartURL(QString, Metadata *)),
     2587            SLOT(OnFanartURL(QString, Metadata *)));
     2588    vfs->Run(metadata->InetRef(), metadata);
     2589
    22912590}
    22922591
    22932592void VideoDialog::OnPosterURL(QString uri, Metadata *metadata)
     
    23842683    UpdateItem(GetItemCurrent());
    23852684}
    23862685
     2686void VideoDialog::OnFanartURL(QString uri, Metadata *metadata)
     2687{
     2688    if (metadata)
     2689    {
     2690        if (uri.length())
     2691        {
     2692            QString fileprefix = m_d->m_fanDir;
     2693
     2694            QDir dir;
     2695
     2696            // If the fanart setting hasn't been set default to
     2697            // using ~/.mythtv/MythVideo/Fanart
     2698            if (fileprefix.length() == 0)
     2699            {
     2700                fileprefix = GetConfDir();
     2701
     2702                dir.setPath(fileprefix);
     2703                if (!dir.exists())
     2704                    dir.mkdir(fileprefix);
     2705
     2706                fileprefix += "/MythVideo/Fanart";
     2707            }
     2708
     2709            dir.setPath(fileprefix);
     2710            if (!dir.exists())
     2711                dir.mkdir(fileprefix);
     2712
     2713            QUrl url(uri);
     2714
     2715            QString ext = QFileInfo(url.path()).suffix();
     2716            QString dest_file = QString("%1/%2.%3").arg(fileprefix)
     2717                    .arg(metadata->InetRef()).arg(ext);
     2718            VERBOSE(VB_IMPORTANT, QString("Copying '%1' -> '%2'...")
     2719                    .arg(url.toString()).arg(dest_file));
     2720
     2721            FanartDownloadProxy *d =
     2722                    FanartDownloadProxy::Create(url, dest_file, metadata);
     2723            metadata->setFanart(dest_file);
     2724
     2725            connect(d, SIGNAL(SigFinished(FanartDownloadErrorState,
     2726                                          QString, Metadata *)),
     2727                    SLOT(OnFanartCopyFinished(FanartDownloadErrorState,
     2728                                              QString, Metadata *)));
     2729
     2730            d->StartCopy();
     2731            m_d->AddFanartDownload(d);
     2732        }
     2733        else
     2734        {
     2735            metadata->setFanart("");
     2736            OnVideoFanartSetDone(metadata);
     2737        }
     2738    }
     2739    else
     2740        OnVideoFanartSetDone(metadata);
     2741}
     2742
     2743void VideoDialog::OnFanartCopyFinished(FanartDownloadErrorState error,
     2744                                       QString errorMsg, Metadata *item)
     2745{
     2746    QObject *src = sender();
     2747    if (src)
     2748        m_d->RemoveFanartDownload(dynamic_cast<FanartDownloadProxy *>
     2749                                       (src));
     2750
     2751    if (error != fesOK && item)
     2752        item->setFanart("");
     2753
     2754    VERBOSE(VB_IMPORTANT, tr("Fanart download finished: %1 %2")
     2755            .arg(errorMsg).arg(error));
     2756
     2757    if (error == fesTimeout)
     2758    {
     2759        createOkDialog(tr("Fanart exists for this item but could not be "
     2760                            "retrieved within the timeout period.\n"));
     2761    }
     2762
     2763    OnVideoFanartSetDone(item);
     2764}
     2765
     2766// This is the final call as part of a StartVideoFanartSet
     2767void VideoDialog::OnVideoFanartSetDone(Metadata *metadata)
     2768{
     2769    // The metadata has some fanart set
     2770    if (m_busyPopup)
     2771    {
     2772        m_busyPopup->Close();
     2773        m_busyPopup = NULL;
     2774    }
     2775
     2776    metadata->updateDatabase();
     2777    UpdateItem(GetItemCurrent());
     2778}
     2779
    23872780void VideoDialog::StartVideoSearchByUID(QString video_uid, Metadata *metadata)
    23882781{
    23892782    // Starting the busy dialog here triggers a bizarre segfault