| 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 | |
| 2589 | void VideoDialog::OnFanartURL(QString uri, Metadata *metadata) |
| 2590 | { |
| 2591 | if (metadata) |
| 2592 | { |
| 2593 | if (uri.length()) |
| 2594 | { |
| 2595 | QString fileprefix = m_d->m_fanDir; |
| 2596 | |
| 2597 | QDir dir; |
| 2598 | |
| 2599 | // If the fanart setting hasn't been set default to |
| 2600 | // using ~/.mythtv/MythVideo/Fanart |
| 2601 | if (fileprefix.length() == 0) |
| 2602 | { |
| 2603 | fileprefix = GetConfDir(); |
| 2604 | |
| 2605 | dir.setPath(fileprefix); |
| 2606 | if (!dir.exists()) |
| 2607 | dir.mkdir(fileprefix); |
| 2608 | |
| 2609 | fileprefix += "/MythVideo/Fanart"; |
| 2610 | } |
| 2611 | |
| 2612 | dir.setPath(fileprefix); |
| 2613 | if (!dir.exists()) |
| 2614 | dir.mkdir(fileprefix); |
| 2615 | |
| 2616 | QUrl url(uri); |
| 2617 | |
| 2618 | QString ext = QFileInfo(url.path()).suffix(); |
| 2619 | QString dest_file = QString("%1/%2.%3").arg(fileprefix) |
| 2620 | .arg(metadata->InetRef()).arg(ext); |
| 2621 | VERBOSE(VB_IMPORTANT, QString("Copying '%1' -> '%2'...") |
| 2622 | .arg(url.toString()).arg(dest_file)); |
| 2623 | |
| 2624 | FanartDownloadProxy *d = |
| 2625 | FanartDownloadProxy::Create(url, dest_file, metadata); |
| 2626 | metadata->setFanart(dest_file); |
| 2627 | |
| 2628 | connect(d, SIGNAL(SigFinished(FanartDownloadErrorState, |
| 2629 | QString, Metadata *)), |
| 2630 | SLOT(OnFanartCopyFinished(FanartDownloadErrorState, |
| 2631 | QString, Metadata *))); |
| 2632 | |
| 2633 | d->StartCopy(); |
| 2634 | m_d->AddFanartDownload(d); |
| 2635 | } |
| 2636 | else |
| 2637 | { |
| 2638 | metadata->setFanart(""); |
| 2639 | OnVideoFanartSetDone(metadata); |
| 2640 | } |
| 2641 | } |
| 2642 | else |
| 2643 | OnVideoFanartSetDone(metadata); |
| 2644 | } |
| 2645 | |
| 2646 | void VideoDialog::OnFanartCopyFinished(FanartDownloadErrorState error, |
| 2647 | QString errorMsg, Metadata *item) |
| 2648 | { |
| 2649 | QObject *src = sender(); |
| 2650 | if (src) |
| 2651 | m_d->RemoveFanartDownload(dynamic_cast<FanartDownloadProxy *> |
| 2652 | (src)); |
| 2653 | |
| 2654 | if (error != fesOK && item) |
| 2655 | item->setFanart(""); |
| 2656 | |
| 2657 | VERBOSE(VB_IMPORTANT, tr("Fanart download finished: %1 %2") |
| 2658 | .arg(errorMsg).arg(error)); |
| 2659 | |
| 2660 | if (error == fesTimeout) |
| 2661 | { |
| 2662 | createOkDialog(tr("Fanart exists for this item but could not be " |
| 2663 | "retrieved within the timeout period.\n")); |
| 2664 | } |
| 2665 | |
| 2666 | OnVideoFanartSetDone(item); |
| 2667 | } |
| 2668 | |
| 2669 | // This is the final call as part of a StartVideoFanartSet |
| 2670 | void VideoDialog::OnVideoFanartSetDone(Metadata *metadata) |
| 2671 | { |
| 2672 | // The metadata has some fanart set |
| 2673 | if (m_busyPopup) |
| 2674 | { |
| 2675 | m_busyPopup->Close(); |
| 2676 | m_busyPopup = NULL; |
| 2677 | } |
| 2678 | |
| 2679 | metadata->updateDatabase(); |
| 2680 | UpdateItem(GetItemCurrent()); |
| 2681 | } |
| 2682 | |