| 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 | |
| 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 | |
| 2686 | void 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 | |
| 2743 | void 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 |
| 2767 | void 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 | |