8 #include <QCoreApplication>
21 #define LOC QString("PreviewQueue: ")
41 uint maxAttempts, std::chrono::seconds minBlockSeconds)
81 uint maxAttempts, std::chrono::seconds minBlockSeconds) :
82 MThread(
"PreviewGeneratorQueue"),
84 m_maxAttempts(maxAttempts), m_minBlockSeconds(minBlockSeconds)
88 int idealThreads = QThread::idealThreadCount();
89 m_maxThreads = (idealThreads >= 1) ? idealThreads * 2 : 2;
107 QMutexLocker locker(&
m_lock);
112 (*it).m_gen->deleteLater();
113 (*it).m_gen =
nullptr;
142 const QSize outputsize,
143 const QString &outputfile,
144 std::chrono::seconds time,
long long frame,
145 const QString& token)
162 extra += QString::number(outputsize.width());
163 extra += QString::number(outputsize.height());
167 extra += QString::number(time.count());
172 extra += QString::number(frame);
175 auto *e =
new MythEvent(
"GET_PREVIEW", extra);
176 QCoreApplication::postEvent(
s_pgq, e);
230 return QObject::event(e);
234 return QObject::event(e);
235 if (me->Message() ==
"GET_PREVIEW")
237 const QStringList &list = me->ExtraDataList();
238 QStringList::const_iterator it = list.begin();
243 long long time_or_frame = -1LL;
244 if (it != list.end())
246 if (it != list.end())
247 outputsize.setWidth((*it++).toInt());
248 if (it != list.end())
249 outputsize.setHeight((*it++).toInt());
250 if (it != list.end())
251 outputfile = (*it++);
252 if (it != list.end())
253 time_or_frame = (*it++).toLongLong();
254 if (it != list.end())
256 bool time_fmt_sec = (*it++).toInt() != 0;
260 std::chrono::seconds(time_or_frame), -1, token);
265 -1s, time_or_frame, token);
270 if (me->Message() ==
"PREVIEW_SUCCESS" ||
271 me->Message() ==
"PREVIEW_FAILED")
273 uint recordedingID = me->ExtraData(0).toUInt();
274 const QString&
filename = me->ExtraData(1);
275 const QString& msg = me->ExtraData(2);
276 const QString& datetime = me->ExtraData(3);
277 const QString& token = me->ExtraData(4);
280 QMutexLocker locker(&
m_lock);
284 LOG(VB_GENERAL, LOG_ERR,
LOC +
285 QString(
"Failed to find token %1 in map.").arg(token));
291 LOG(VB_GENERAL, LOG_ERR,
LOC +
292 QString(
"Failed to find key %1 in map.").arg(*kit));
297 (*it).m_gen->deleteLater();
298 (*it).m_gen =
nullptr;
299 (*it).m_genStarted =
false;
300 if (me->Message() ==
"PREVIEW_SUCCESS")
302 (*it).m_attempts = 0;
303 (*it).m_lastBlockTime = 0s;
304 (*it).m_blockRetryUntil = QDateTime();
308 (*it).m_lastBlockTime =
310 (*it).m_blockRetryUntil =
315 list.push_back(QString::number(recordedingID));
318 list.push_back(datetime);
319 for (
const auto & tok : std::as_const((*it).m_tokens))
331 auto *le =
new MythEvent(me->Message(), list);
332 QCoreApplication::postEvent(listener, le);
334 (*it).m_tokens.clear();
344 return QObject::event(e);
370 const QString &eventname,
371 const QString &
filename,
const QString &token,
const QString &msg,
379 list.push_back(token);
381 QMutexLocker locker(&
m_lock);
384 auto *e =
new MythEvent(eventname, list);
385 QCoreApplication::postEvent(listener, e);
427 const QString &outputfile,
428 std::chrono::seconds time,
long long frame,
429 const QString& token)
431 auto pos_text = (time >= 0s)
432 ? QString::number(time.count()) +
"s"
433 : QString::number(frame)+
"f";
434 QString key = QString(
"%1_%2x%3_%4")
435 .arg(pginfo.
GetBasename()).arg(size.width()).arg(size.height())
440 SendEvent(pginfo,
"PREVIEW_FAILED", key, token,
441 "Pending Delete", QDateTime());
446 QString
filename = (outputfile.isEmpty()) ?
451 bool is_special = !outputfile.isEmpty() || time >= 0s ||
452 (size.width() != 0) || (size.height() != 0);
454 bool needs_gen =
true;
457 QDateTime previewLastModified;
458 bool streaming = !
filename.startsWith(
"/");
459 bool locally_accessible =
false;
460 bool bookmark_updated =
false;
464 if (bookmark_ts.isValid())
465 cmp_ts = bookmark_ts;
473 ret_file = QString(
"%1/%2")
476 QFileInfo finfo(ret_file);
477 if (finfo.isReadable() && finfo.lastModified() >= cmp_ts)
484 previewLastModified = finfo.lastModified();
488 previewLastModified =
495 locally_accessible = fi.isReadable();
496 if (locally_accessible)
497 previewLastModified = fi.lastModified();
501 (!previewLastModified.isValid() || (previewLastModified <= cmp_ts));
503 if (bookmark_updated && bookmark_ts.isValid() &&
504 previewLastModified.isValid())
509 bool preview_exists = previewLastModified.isValid();
512 QString alttext = (bookmark_ts.isValid()) ? QString() :
513 QString(
"\n\t\t\tcmp_ts: %1")
515 LOG(VB_GENERAL, LOG_INFO,
516 QString(
"previewLastModified: %1\n\t\t\t"
517 "bookmark_ts: %2%3\n\t\t\t"
518 "pginfo.lastmodified: %4")
523 QString(
"Title: %1\n\t\t\t")
525 QString(
"File '%1' \n\t\t\tCache '%2'")
527 QString(
"\n\t\t\tPreview Exists: %1, Bookmark Updated: %2, "
529 .arg(preview_exists).arg(bookmark_updated)
530 .arg((bookmark_updated || !preview_exists)));
533 needs_gen = bookmark_updated || !preview_exists;
537 if (locally_accessible)
539 else if (preview_exists && QFileInfo(ret_file).isReadable())
549 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
550 QString(
"Requesting preview for '%1'") .arg(key));
552 if (!outputfile.isEmpty() || time >= 0s ||
553 size.width() || size.height())
555 pg->SetPreviewTime(time, frame);
556 pg->SetOutputFilename(outputfile);
557 pg->SetOutputSize(size);
562 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
563 QString(
"Requested preview for '%1'").arg(key));
567 LOG(VB_GENERAL, LOG_ERR,
LOC +
568 QString(
"Attempted to generate preview for '%1' "
569 "%2 times; >= max(%3)")
575 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
576 QString(
"Not requesting preview for %1,"
577 "as it is already being generated")
586 QString msg =
"On Disk";
587 QDateTime dt = QFileInfo(ret).lastModified();
588 SendEvent(pginfo,
"PREVIEW_SUCCESS", ret, token, msg, dt);
592 uint queue_depth = 0;
594 GetInfo(key, queue_depth, token_cnt);
595 QString msg = QString(
"Queue depth %1, our tokens %2")
596 .arg(queue_depth).arg(token_cnt);
597 SendEvent(pginfo,
"PREVIEW_QUEUED", ret, token, msg, QDateTime());
616 const QString &key,
uint &queue_depth,
uint &token_cnt)
618 QMutexLocker locker(&
m_lock);
621 token_cnt = (pit ==
m_previewMap.end()) ? 0 : (*pit).m_tokens.size();
632 const QString &key,
const QString& token)
634 QMutexLocker locker(&
m_lock);
641 if ((*pit).m_gen && !(*pit).m_genStarted)
644 if (!token.isEmpty())
647 (*pit).m_tokens.insert(token);
657 QMutexLocker locker(&
m_lock);
661 QString fn = q.back();
664 if (it !=
m_previewMap.end() && (*it).m_gen && !(*it).m_genStarted)
667 (*it).m_gen->start();
668 (*it).m_genStarted =
true;
688 QMutexLocker locker(&
m_lock);
693 if (state.
m_gen != g)
730 QMutexLocker locker(&
m_lock);
736 if ((*it).m_blockRetryUntil.isValid())
752 QMutexLocker locker(&
m_lock);
767 QMutexLocker locker(&
m_lock);