| 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 | |
| 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 | |
| 2896 | void 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 | |
| 2953 | void 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 |
| 2977 | void 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 | |