8 #include <QCoreApplication>
24 #define LOC QString("PreviewQueue: ")
44 uint maxAttempts, std::chrono::seconds minBlockSeconds)
84 uint maxAttempts, std::chrono::seconds minBlockSeconds) :
85 MThread(
"PreviewGeneratorQueue"),
87 m_maxAttempts(maxAttempts), m_minBlockSeconds(minBlockSeconds)
91 int idealThreads = QThread::idealThreadCount();
92 m_maxThreads = (idealThreads >= 1) ? idealThreads * 2 : 2;
110 QMutexLocker locker(&
m_lock);
115 (*it).m_gen->deleteLater();
116 (*it).m_gen =
nullptr;
145 const QSize outputsize,
146 const QString &outputfile,
147 std::chrono::seconds time,
long long frame,
148 const QString& token)
165 extra += QString::number(outputsize.width());
166 extra += QString::number(outputsize.height());
170 extra += QString::number(time.count());
175 extra += QString::number(frame);
178 auto *e =
new MythEvent(
"GET_PREVIEW", extra);
179 QCoreApplication::postEvent(
s_pgq, e);
233 return QObject::event(e);
237 return QObject::event(e);
238 if (me->Message() ==
"GET_PREVIEW")
240 const QStringList &list = me->ExtraDataList();
241 QStringList::const_iterator it = list.begin();
246 long long time_or_frame = -1LL;
247 if (it != list.end())
249 if (it != list.end())
250 outputsize.setWidth((*it++).toInt());
251 if (it != list.end())
252 outputsize.setHeight((*it++).toInt());
253 if (it != list.end())
254 outputfile = (*it++);
255 if (it != list.end())
256 time_or_frame = (*it++).toLongLong();
257 if (it != list.end())
259 bool time_fmt_sec = (*it++).toInt() != 0;
263 std::chrono::seconds(time_or_frame), -1, token);
268 -1s, time_or_frame, token);
273 if (me->Message() ==
"PREVIEW_SUCCESS" ||
274 me->Message() ==
"PREVIEW_FAILED")
276 uint recordedingID = me->ExtraData(0).toUInt();
277 const QString&
filename = me->ExtraData(1);
278 const QString& msg = me->ExtraData(2);
279 const QString& datetime = me->ExtraData(3);
280 const QString& token = me->ExtraData(4);
283 QMutexLocker locker(&
m_lock);
287 LOG(VB_GENERAL, LOG_ERR,
LOC +
288 QString(
"Failed to find token %1 in map.").arg(token));
294 LOG(VB_GENERAL, LOG_ERR,
LOC +
295 QString(
"Failed to find key %1 in map.").arg(*kit));
300 (*it).m_gen->deleteLater();
301 (*it).m_gen =
nullptr;
302 (*it).m_genStarted =
false;
303 if (me->Message() ==
"PREVIEW_SUCCESS")
305 (*it).m_attempts = 0;
306 (*it).m_lastBlockTime = 0s;
307 (*it).m_blockRetryUntil = QDateTime();
311 (*it).m_lastBlockTime =
313 (*it).m_blockRetryUntil =
318 list.push_back(QString::number(recordedingID));
321 list.push_back(datetime);
322 for (
const auto & tok : qAsConst((*it).m_tokens))
334 auto *le =
new MythEvent(me->Message(), list);
335 QCoreApplication::postEvent(listener, le);
337 (*it).m_tokens.clear();
347 return QObject::event(e);
373 const QString &eventname,
374 const QString &
filename,
const QString &token,
const QString &msg,
382 list.push_back(token);
384 QMutexLocker locker(&
m_lock);
387 auto *e =
new MythEvent(eventname, list);
388 QCoreApplication::postEvent(listener, e);
430 const QString &outputfile,
431 std::chrono::seconds time,
long long frame,
432 const QString& token)
434 auto pos_text = (time >= 0s)
435 ? QString::number(time.count()) +
"s"
436 : QString::number(frame)+
"f";
437 QString key = QString(
"%1_%2x%3_%4")
438 .arg(pginfo.
GetBasename()).arg(size.width()).arg(size.height())
443 SendEvent(pginfo,
"PREVIEW_FAILED", key, token,
444 "Pending Delete", QDateTime());
449 QString
filename = (outputfile.isEmpty()) ?
454 bool is_special = !outputfile.isEmpty() || time >= 0s ||
455 (size.width() != 0) || (size.height() != 0);
457 bool needs_gen =
true;
460 QDateTime previewLastModified;
461 bool streaming = !
filename.startsWith(
"/");
462 bool locally_accessible =
false;
463 bool bookmark_updated =
false;
467 if (bookmark_ts.isValid())
468 cmp_ts = bookmark_ts;
476 ret_file = QString(
"%1/%2")
479 QFileInfo finfo(ret_file);
480 if (finfo.isReadable() && finfo.lastModified() >= cmp_ts)
487 previewLastModified = finfo.lastModified();
491 previewLastModified =
498 if ((locally_accessible = fi.isReadable()))
499 previewLastModified = fi.lastModified();
503 (!previewLastModified.isValid() || (previewLastModified <= cmp_ts));
505 if (bookmark_updated && bookmark_ts.isValid() &&
506 previewLastModified.isValid())
511 bool preview_exists = previewLastModified.isValid();
514 QString alttext = (bookmark_ts.isValid()) ? QString() :
515 QString(
"\n\t\t\tcmp_ts: %1")
517 LOG(VB_GENERAL, LOG_INFO,
518 QString(
"previewLastModified: %1\n\t\t\t"
519 "bookmark_ts: %2%3\n\t\t\t"
520 "pginfo.lastmodified: %4")
525 QString(
"Title: %1\n\t\t\t")
527 QString(
"File '%1' \n\t\t\tCache '%2'")
529 QString(
"\n\t\t\tPreview Exists: %1, Bookmark Updated: %2, "
531 .arg(preview_exists).arg(bookmark_updated)
532 .arg((bookmark_updated || !preview_exists)));
535 needs_gen = bookmark_updated || !preview_exists;
539 if (locally_accessible)
541 else if (preview_exists && QFileInfo(ret_file).isReadable())
551 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
552 QString(
"Requesting preview for '%1'") .arg(key));
554 if (!outputfile.isEmpty() || time >= 0s ||
555 size.width() || size.height())
557 pg->SetPreviewTime(time, frame);
558 pg->SetOutputFilename(outputfile);
559 pg->SetOutputSize(size);
564 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
565 QString(
"Requested preview for '%1'").arg(key));
569 LOG(VB_GENERAL, LOG_ERR,
LOC +
570 QString(
"Attempted to generate preview for '%1' "
571 "%2 times; >= max(%3)")
577 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
578 QString(
"Not requesting preview for %1,"
579 "as it is already being generated")
588 QString msg =
"On Disk";
589 QDateTime dt = QFileInfo(ret).lastModified();
590 SendEvent(pginfo,
"PREVIEW_SUCCESS", ret, token, msg, dt);
594 uint queue_depth = 0;
596 GetInfo(key, queue_depth, token_cnt);
597 QString msg = QString(
"Queue depth %1, our tokens %2")
598 .arg(queue_depth).arg(token_cnt);
599 SendEvent(pginfo,
"PREVIEW_QUEUED", ret, token, msg, QDateTime());
618 const QString &key,
uint &queue_depth,
uint &token_cnt)
620 QMutexLocker locker(&
m_lock);
623 token_cnt = (pit ==
m_previewMap.end()) ? 0 : (*pit).m_tokens.size();
634 const QString &key,
const QString& token)
636 QMutexLocker locker(&
m_lock);
643 if ((*pit).m_gen && !(*pit).m_genStarted)
646 if (!token.isEmpty())
649 (*pit).m_tokens.insert(token);
659 QMutexLocker locker(&
m_lock);
663 QString fn = q.back();
666 if (it !=
m_previewMap.end() && (*it).m_gen && !(*it).m_genStarted)
669 (*it).m_gen->start();
670 (*it).m_genStarted =
true;
690 QMutexLocker locker(&
m_lock);
695 if (state.
m_gen != g)
732 PreviewMap::const_iterator it;
733 QMutexLocker locker(&
m_lock);
738 if ((*it).m_blockRetryUntil.isValid())
754 QMutexLocker locker(&
m_lock);
769 QMutexLocker locker(&
m_lock);