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 : std::as_const((*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 locally_accessible = fi.isReadable();
499 if (locally_accessible)
500 previewLastModified = fi.lastModified();
504 (!previewLastModified.isValid() || (previewLastModified <= cmp_ts));
506 if (bookmark_updated && bookmark_ts.isValid() &&
507 previewLastModified.isValid())
512 bool preview_exists = previewLastModified.isValid();
515 QString alttext = (bookmark_ts.isValid()) ? QString() :
516 QString(
"\n\t\t\tcmp_ts: %1")
518 LOG(VB_GENERAL, LOG_INFO,
519 QString(
"previewLastModified: %1\n\t\t\t"
520 "bookmark_ts: %2%3\n\t\t\t"
521 "pginfo.lastmodified: %4")
526 QString(
"Title: %1\n\t\t\t")
528 QString(
"File '%1' \n\t\t\tCache '%2'")
530 QString(
"\n\t\t\tPreview Exists: %1, Bookmark Updated: %2, "
532 .arg(preview_exists).arg(bookmark_updated)
533 .arg((bookmark_updated || !preview_exists)));
536 needs_gen = bookmark_updated || !preview_exists;
540 if (locally_accessible)
542 else if (preview_exists && QFileInfo(ret_file).isReadable())
552 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
553 QString(
"Requesting preview for '%1'") .arg(key));
555 if (!outputfile.isEmpty() || time >= 0s ||
556 size.width() || size.height())
558 pg->SetPreviewTime(time, frame);
559 pg->SetOutputFilename(outputfile);
560 pg->SetOutputSize(size);
565 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
566 QString(
"Requested preview for '%1'").arg(key));
570 LOG(VB_GENERAL, LOG_ERR,
LOC +
571 QString(
"Attempted to generate preview for '%1' "
572 "%2 times; >= max(%3)")
578 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
579 QString(
"Not requesting preview for %1,"
580 "as it is already being generated")
589 QString msg =
"On Disk";
590 QDateTime dt = QFileInfo(ret).lastModified();
591 SendEvent(pginfo,
"PREVIEW_SUCCESS", ret, token, msg, dt);
595 uint queue_depth = 0;
597 GetInfo(key, queue_depth, token_cnt);
598 QString msg = QString(
"Queue depth %1, our tokens %2")
599 .arg(queue_depth).arg(token_cnt);
600 SendEvent(pginfo,
"PREVIEW_QUEUED", ret, token, msg, QDateTime());
619 const QString &key,
uint &queue_depth,
uint &token_cnt)
621 QMutexLocker locker(&
m_lock);
624 token_cnt = (pit ==
m_previewMap.end()) ? 0 : (*pit).m_tokens.size();
635 const QString &key,
const QString& token)
637 QMutexLocker locker(&
m_lock);
644 if ((*pit).m_gen && !(*pit).m_genStarted)
647 if (!token.isEmpty())
650 (*pit).m_tokens.insert(token);
660 QMutexLocker locker(&
m_lock);
664 QString fn = q.back();
667 if (it !=
m_previewMap.end() && (*it).m_gen && !(*it).m_genStarted)
670 (*it).m_gen->start();
671 (*it).m_genStarted =
true;
691 QMutexLocker locker(&
m_lock);
696 if (state.
m_gen != g)
733 QMutexLocker locker(&
m_lock);
739 if ((*it).m_blockRetryUntil.isValid())
755 QMutexLocker locker(&
m_lock);
770 QMutexLocker locker(&
m_lock);