void PreviewGeneratorQueue::GetPreviewImage( const ProgramInfo &pginfo, const QSize &outputsize, const QString &outputfile, long long time, bool in_seconds, QString token) { if (!s_pgq) return; if (pginfo.GetPathname().isEmpty() || pginfo.GetBasename() == pginfo.GetPathname()) { return; } QStringList extra; pginfo.ToStringList(extra); extra += token; extra += QString::number(outputsize.width()); extra += QString::number(outputsize.height()); extra += outputfile; extra += QString::number(time); extra += (in_seconds ? "1" : "0"); MythEvent *e = new MythEvent("GET_PREVIEW", extra); QCoreApplication::postEvent(s_pgq, e); }
void RecordingSelector::titleChanged(MythUIButtonListItem *item) { ProgramInfo *p; p = qVariantValue<ProgramInfo *>(item->GetData()); if (!p) return; if (m_titleText) m_titleText->SetText(p->GetTitle()); if (m_datetimeText) m_datetimeText->SetText(p->GetScheduledStartTime() .toString("dd MMM yy (hh:mm)")); if (m_descriptionText) { m_descriptionText->SetText( ((!p->GetSubtitle().isEmpty()) ? p->GetSubtitle() + "\n" : "") + p->GetDescription()); } if (m_filesizeText) { m_filesizeText->SetText(formatSize(p->GetFilesize() / 1024)); } if (m_cutlistImage) { if (p->HasCutlist()) m_cutlistImage->Show(); else m_cutlistImage->Hide(); } if (m_previewImage) { // try to locate a preview image if (QFile::exists(p->GetPathname() + ".png")) { m_previewImage->SetFilename(p->GetPathname() + ".png"); m_previewImage->Load(); } else { m_previewImage->SetFilename("blank.png"); m_previewImage->Load(); } } }
QString PreviewGeneratorQueue::GeneratePreviewImage( ProgramInfo &pginfo, const QSize &size, const QString &outputfile, long long time, bool in_seconds, QString token) { QString key = QString("%1_%2x%3_%4%5") .arg(pginfo.GetBasename()).arg(size.width()).arg(size.height()) .arg(time).arg(in_seconds?"s":"f"); if (pginfo.GetAvailableStatus() == asPendingDelete) { SendEvent(pginfo, "PREVIEW_FAILED", key, token, "Pending Delete", QDateTime()); return QString(); } QString filename = (outputfile.isEmpty()) ? pginfo.GetPathname() + ".png" : outputfile; QString ret_file = filename; QString ret; bool is_special = !outputfile.isEmpty() || time >= 0 || size.width() || size.height(); bool needs_gen = true; if (!is_special) { QDateTime previewLastModified; bool streaming = filename.left(1) != "/"; bool locally_accessible = false; bool bookmark_updated = false; QDateTime bookmark_ts = pginfo.QueryBookmarkTimeStamp(); QDateTime cmp_ts; if (bookmark_ts.isValid()) cmp_ts = bookmark_ts; else if (MythDate::current() >= pginfo.GetRecordingEndTime()) cmp_ts = pginfo.GetLastModifiedTime(); else cmp_ts = pginfo.GetRecordingStartTime(); if (streaming) { ret_file = QString("%1/remotecache/%2") .arg(GetConfDir()).arg(filename.section('/', -1)); QFileInfo finfo(ret_file); if (finfo.isReadable() && finfo.lastModified() >= cmp_ts) { // This is just an optimization to avoid // hitting the backend if our cached copy // is newer than the bookmark, or if we have // a preview and do not update it when the // bookmark changes. previewLastModified = finfo.lastModified(); } else if (!IsGeneratingPreview(key)) { previewLastModified = RemoteGetPreviewIfModified(pginfo, ret_file); } } else { QFileInfo fi(filename); if ((locally_accessible = fi.isReadable())) previewLastModified = fi.lastModified(); } bookmark_updated = (!previewLastModified.isValid() || (previewLastModified <= cmp_ts)); if (bookmark_updated && bookmark_ts.isValid() && previewLastModified.isValid()) { ClearPreviewGeneratorAttempts(key); } bool preview_exists = previewLastModified.isValid(); if (0) { QString alttext = (bookmark_ts.isValid()) ? QString() : QString("\n\t\t\tcmp_ts: %1") .arg(cmp_ts.toString(Qt::ISODate)); LOG(VB_GENERAL, LOG_INFO, QString("previewLastModified: %1\n\t\t\t" "bookmark_ts: %2%3\n\t\t\t" "pginfo.lastmodified: %4") .arg(previewLastModified.toString(Qt::ISODate)) .arg(bookmark_ts.toString(Qt::ISODate)) .arg(alttext) .arg(pginfo.GetLastModifiedTime(MythDate::ISODate)) + QString("Title: %1\n\t\t\t") .arg(pginfo.toString(ProgramInfo::kTitleSubtitle)) + QString("File '%1' \n\t\t\tCache '%2'") .arg(filename).arg(ret_file) + QString("\n\t\t\tPreview Exists: %1, Bookmark Updated: %2, " "Need Preview: %3") .arg(preview_exists).arg(bookmark_updated) .arg((bookmark_updated || !preview_exists))); } needs_gen = bookmark_updated || !preview_exists; if (!needs_gen) { if (locally_accessible) ret = filename; else if (preview_exists && QFileInfo(ret_file).isReadable()) ret = ret_file; } } if (needs_gen && !IsGeneratingPreview(key)) { uint attempts = IncPreviewGeneratorAttempts(key); if (attempts < m_maxAttempts) { LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Requesting preview for '%1'") .arg(key)); PreviewGenerator *pg = new PreviewGenerator(&pginfo, token, m_mode); if (!outputfile.isEmpty() || time >= 0 || size.width() || size.height()) { pg->SetPreviewTime(time, in_seconds); pg->SetOutputFilename(outputfile); pg->SetOutputSize(size); } SetPreviewGenerator(key, pg); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Requested preview for '%1'").arg(key)); } else if (attempts >= m_maxAttempts) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Attempted to generate preview for '%1' " "%2 times; >= max(%3)") .arg(key).arg(attempts).arg(m_maxAttempts)); } } else if (needs_gen) { LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Not requesting preview for %1," "as it is already being generated") .arg(pginfo.toString(ProgramInfo::kTitleSubtitle))); IncPreviewGeneratorPriority(key, token); } UpdatePreviewGeneratorThreads(); if (!ret.isEmpty()) { QString msg = "On Disk"; QDateTime dt = QFileInfo(ret).lastModified(); SendEvent(pginfo, "PREVIEW_SUCCESS", ret, token, msg, dt); } else { uint queue_depth, token_cnt; GetInfo(key, queue_depth, token_cnt); QString msg = QString("Queue depth %1, our tokens %2") .arg(queue_depth).arg(token_cnt); SendEvent(pginfo, "PREVIEW_QUEUED", ret, token, msg, QDateTime()); } return ret; }
static int internal_play_media(const QString &mrl, const QString &plot, const QString &title, const QString &subtitle, const QString &director, int season, int episode, int lenMins, const QString &year) { int res = -1; QFile checkFile(mrl); if ((!checkFile.exists() && !mrl.startsWith("dvd:") && !mrl.startsWith("bd:") && !mrl.startsWith("myth:"))) { QString errorText = QObject::tr("Failed to open \n '%1' in %2 \n" "Check if the video exists") .arg(mrl.section('/', -1)) .arg(mrl.section('/', 0, -2)); ShowOkPopup(errorText); return res; } ProgramInfo *pginfo = new ProgramInfo( mrl, plot, title, subtitle, director, season, episode, lenMins, (year.toUInt()) ? year.toUInt() : 1900); int64_t pos = 0; if (pginfo->IsVideoDVD()) { RingBuffer *tmprbuf = RingBuffer::Create(pginfo->GetPathname(), false); if (!tmprbuf) { delete pginfo; return res; } QString name; QString serialid; if (tmprbuf->IsDVD() && tmprbuf->DVD()->GetNameAndSerialNum(name, serialid)) { QStringList fields = pginfo->QueryDVDBookmark(serialid); if (!fields.empty()) { QStringList::Iterator it = fields.begin(); pos = (int64_t)((*++it).toLongLong() & 0xffffffffLL); } } delete tmprbuf; } else if (pginfo->IsVideo()) pos = pginfo->QueryBookmark(); if (pos > 0) { MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); BookmarkDialog *bookmarkdialog = new BookmarkDialog(pginfo, mainStack); if (!bookmarkdialog->Create()) { delete bookmarkdialog; delete pginfo; return res; } } else { TV::StartTV(pginfo, kStartTVNoFlags); res = 0; delete pginfo; } return res; }
static int RunCCExtract(const ProgramInfo &program_info) { QString filename = program_info.GetPlaybackURL(); if (filename.startsWith("myth://")) { QString msg = QString("Only locally accessible files are supported (%1).") .arg(program_info.GetPathname()); cerr << qPrintable(msg) << endl; return GENERIC_EXIT_INVALID_CMDLINE; } if (!QFile::exists(filename)) { cerr << qPrintable( QString("Could not open input file (%1).").arg(filename)) << endl; return GENERIC_EXIT_INVALID_CMDLINE; } RingBuffer *tmprbuf = RingBuffer::Create(filename, false); if (!tmprbuf) { cerr << qPrintable(QString("Unable to create RingBuffer for %1") .arg(filename)) << endl; return GENERIC_EXIT_PERMISSIONS_ERROR; } if (program_info.GetRecordingEndTime() > MythDate::current()) { cout << "Program will end @ " << qPrintable(program_info.GetRecordingEndTime(MythDate::ISODate)) << endl; tmprbuf->SetWaitForWrite(); } PlayerFlags flags = (PlayerFlags)(kVideoIsNull | kAudioMuted | kDecodeNoLoopFilter | kDecodeFewBlocks | kDecodeLowRes | kDecodeSingleThreaded | kDecodeNoDecode); MythCCExtractorPlayer *ccp = new MythCCExtractorPlayer(flags, true, filename); PlayerContext *ctx = new PlayerContext(kCCExtractorInUseID); ctx->SetPlayingInfo(&program_info); ctx->SetRingBuffer(tmprbuf); ctx->SetPlayer(ccp); ccp->SetPlayerInfo(NULL, NULL, ctx); if (ccp->OpenFile() < 0) { cerr << "Failed to open " << qPrintable(filename) << endl; return GENERIC_EXIT_NOT_OK; } if (!ccp->run()) { cerr << "Failed to decode " << qPrintable(filename) << endl; return GENERIC_EXIT_NOT_OK; } delete ctx; return GENERIC_EXIT_OK; }