MythTV  master
previewgeneratorqueue.cpp
Go to the documentation of this file.
1 
3 
4 // C++
5 #include <algorithm>
6 
7 // QT
8 #include <QCoreApplication>
9 #include <QFileInfo>
10 
11 // libmythbase
12 #include "libmythbase/mthread.h"
14 #include "libmythbase/mythdirs.h"
16 #include "libmythbase/remoteutil.h"
17 
18 // libmyth
19 #include "libmyth/mythcontext.h"
20 
21 // libmythtv
22 #include "previewgenerator.h"
23 
24 #define LOC QString("PreviewQueue: ")
25 
27 
44  uint maxAttempts, std::chrono::seconds minBlockSeconds)
45 {
46  s_pgq = new PreviewGeneratorQueue(mode, maxAttempts, minBlockSeconds);
47 }
48 
56 {
57  s_pgq->exit(0);
58  s_pgq->wait();
59  delete s_pgq;
60  s_pgq = nullptr;
61 }
62 
63 /*
64  * Create the queue object for holding preview generators.
65  *
66  * Create the singleton queue of preview generators. This should be
67  * called once at program start-up. All generation requests on this
68  * queue will will be created with the maxAttempts and minBlockSeconds
69  * parameters supplied here.
70  *
71  * \param[in] mode Local or Remote (or both)
72  * \param[in] maxAttempts How many times total will the code attempt
73  * to generate a preview for a specific file, before giving
74  * up and ignoring all future requests.
75  * \param[in] minBlockSeconds How long after a failed preview
76  * generation attempt will the code ignore subsequent
77  * requests.
78  *
79  * \note Never call this routine directly. Call the
80  * CreatePreviewGeneratorQueue function instead.
81  */
84  uint maxAttempts, std::chrono::seconds minBlockSeconds) :
85  MThread("PreviewGeneratorQueue"),
86  m_mode(mode),
87  m_maxAttempts(maxAttempts), m_minBlockSeconds(minBlockSeconds)
88 {
89  if (PreviewGenerator::kLocal & mode)
90  {
91  int idealThreads = QThread::idealThreadCount();
92  m_maxThreads = (idealThreads >= 1) ? idealThreads * 2 : 2;
93  }
94 
95  moveToThread(qthread());
96  start();
97 }
98 
108 {
109  // disconnect preview generators
110  QMutexLocker locker(&m_lock);
111  // NOLINTNEXTLINE(modernize-loop-convert)
112  for (auto it = m_previewMap.begin(); it != m_previewMap.end(); ++it)
113  {
114  if ((*it).m_gen)
115  (*it).m_gen->deleteLater();
116  (*it).m_gen = nullptr;
117  }
118  locker.unlock();
119  wait();
120 }
121 
144  const ProgramInfo &pginfo,
145  const QSize outputsize,
146  const QString &outputfile,
147  std::chrono::seconds time, long long frame,
148  const QString& token)
149 {
150  if (!s_pgq)
151  return;
152 
153  if (pginfo.GetPathname().isEmpty() ||
154  pginfo.GetBasename() == pginfo.GetPathname())
155  {
156  return;
157  }
158 
159  if (gCoreContext->GetNumSetting("JobAllowPreview", 1) == 0)
160  return;
161 
162  QStringList extra;
163  pginfo.ToStringList(extra);
164  extra += token;
165  extra += QString::number(outputsize.width());
166  extra += QString::number(outputsize.height());
167  extra += outputfile;
168  if (time >= 0s)
169  {
170  extra += QString::number(time.count());
171  extra += "1";
172  }
173  else
174  {
175  extra += QString::number(frame);
176  extra += "0";
177  }
178  auto *e = new MythEvent("GET_PREVIEW", extra);
179  QCoreApplication::postEvent(s_pgq, e);
180 }
181 
189 void PreviewGeneratorQueue::AddListener(QObject *listener)
190 {
191  if (!s_pgq)
192  return;
193 
194  QMutexLocker locker(&s_pgq->m_lock);
195  s_pgq->m_listeners.insert(listener);
196 }
197 
206 {
207  if (!s_pgq)
208  return;
209 
210  QMutexLocker locker(&s_pgq->m_lock);
211  s_pgq->m_listeners.remove(listener);
212 }
213 
231 {
232  if (e->type() != MythEvent::kMythEventMessage)
233  return QObject::event(e);
234 
235  auto *me = dynamic_cast<MythEvent*>(e);
236  if (me == nullptr)
237  return QObject::event(e);
238  if (me->Message() == "GET_PREVIEW")
239  {
240  const QStringList &list = me->ExtraDataList();
241  QStringList::const_iterator it = list.begin();
242  ProgramInfo evinfo(it, list.end());
243  QString token;
244  QSize outputsize;
245  QString outputfile;
246  long long time_or_frame = -1LL;
247  if (it != list.end())
248  token = (*it++);
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())
258  {
259  bool time_fmt_sec = (*it++).toInt() != 0;
260  if (time_fmt_sec)
261  {
262  GeneratePreviewImage(evinfo, outputsize, outputfile,
263  std::chrono::seconds(time_or_frame), -1, token);
264  }
265  else
266  {
267  GeneratePreviewImage(evinfo, outputsize, outputfile,
268  -1s, time_or_frame, token);
269  }
270  }
271  return true;
272  }
273  if (me->Message() == "PREVIEW_SUCCESS" ||
274  me->Message() == "PREVIEW_FAILED")
275  {
276  uint recordedingID = me->ExtraData(0).toUInt(); // pginfo->GetRecordingID()
277  const QString& filename = me->ExtraData(1); // outFileName
278  const QString& msg = me->ExtraData(2);
279  const QString& datetime = me->ExtraData(3);
280  const QString& token = me->ExtraData(4);
281 
282  {
283  QMutexLocker locker(&m_lock);
284  QMap<QString,QString>::iterator kit = m_tokenToKeyMap.find(token);
285  if (kit == m_tokenToKeyMap.end())
286  {
287  LOG(VB_GENERAL, LOG_ERR, LOC +
288  QString("Failed to find token %1 in map.").arg(token));
289  return true;
290  }
291  PreviewMap::iterator it = m_previewMap.find(*kit);
292  if (it == m_previewMap.end())
293  {
294  LOG(VB_GENERAL, LOG_ERR, LOC +
295  QString("Failed to find key %1 in map.").arg(*kit));
296  return true;
297  }
298 
299  if ((*it).m_gen)
300  (*it).m_gen->deleteLater();
301  (*it).m_gen = nullptr;
302  (*it).m_genStarted = false;
303  if (me->Message() == "PREVIEW_SUCCESS")
304  {
305  (*it).m_attempts = 0;
306  (*it).m_lastBlockTime = 0s;
307  (*it).m_blockRetryUntil = QDateTime();
308  }
309  else
310  {
311  (*it).m_lastBlockTime =
312  std::max(m_minBlockSeconds, (*it).m_lastBlockTime * 2);
313  (*it).m_blockRetryUntil =
314  MythDate::current().addSecs((*it).m_lastBlockTime.count());
315  }
316 
317  QStringList list;
318  list.push_back(QString::number(recordedingID));
319  list.push_back(filename);
320  list.push_back(msg);
321  list.push_back(datetime);
322  for (const auto & tok : qAsConst((*it).m_tokens))
323  {
324  kit = m_tokenToKeyMap.find(tok);
325  if (kit != m_tokenToKeyMap.end())
326  m_tokenToKeyMap.erase(kit);
327  list.push_back(tok);
328  }
329 
330  if (list.size() > 4)
331  {
332  for (auto *listener : qAsConst(m_listeners))
333  {
334  auto *le = new MythEvent(me->Message(), list);
335  QCoreApplication::postEvent(listener, le);
336  }
337  (*it).m_tokens.clear();
338  }
339 
340  m_running = (m_running > 0) ? m_running - 1 : 0;
341  }
342 
344 
345  return true;
346  }
347  return QObject::event(e);
348 }
349 
372  const ProgramInfo &pginfo,
373  const QString &eventname,
374  const QString &filename, const QString &token, const QString &msg,
375  const QDateTime &dt)
376 {
377  QStringList list;
378  list.push_back(QString::number(pginfo.GetRecordingID()));
379  list.push_back(filename);
380  list.push_back(msg);
381  list.push_back(dt.toUTC().toString(Qt::ISODate));
382  list.push_back(token);
383 
384  QMutexLocker locker(&m_lock);
385  for (auto *listener : qAsConst(m_listeners))
386  {
387  auto *e = new MythEvent(eventname, list);
388  QCoreApplication::postEvent(listener, e);
389  }
390 }
391 
428  ProgramInfo &pginfo,
429  const QSize size,
430  const QString &outputfile,
431  std::chrono::seconds time, long long frame,
432  const QString& token)
433 {
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())
439  .arg(pos_text);
440 
441  if (pginfo.GetAvailableStatus() == asPendingDelete)
442  {
443  SendEvent(pginfo, "PREVIEW_FAILED", key, token,
444  "Pending Delete", QDateTime());
445  return {};
446  }
447 
448  // keep in sync with default filename in PreviewGenerator::RunReal
449  QString filename = (outputfile.isEmpty()) ?
450  pginfo.GetPathname() + ".png" : outputfile;
451  QString ret_file = filename;
452  QString ret;
453 
454  bool is_special = !outputfile.isEmpty() || time >= 0s ||
455  (size.width() != 0) || (size.height() != 0);
456 
457  bool needs_gen = true;
458  if (!is_special)
459  {
460  QDateTime previewLastModified;
461  bool streaming = !filename.startsWith("/");
462  bool locally_accessible = false;
463  bool bookmark_updated = false;
464 
465  QDateTime bookmark_ts = pginfo.GetBookmarkUpdate();
466  QDateTime cmp_ts;
467  if (bookmark_ts.isValid())
468  cmp_ts = bookmark_ts;
469  else if (MythDate::current() >= pginfo.GetRecordingEndTime())
470  cmp_ts = pginfo.GetLastModifiedTime();
471  else
472  cmp_ts = pginfo.GetRecordingStartTime();
473 
474  if (streaming)
475  {
476  ret_file = QString("%1/%2")
477  .arg(GetRemoteCacheDir(), filename.section('/', -1));
478 
479  QFileInfo finfo(ret_file);
480  if (finfo.isReadable() && finfo.lastModified() >= cmp_ts)
481  {
482  // This is just an optimization to avoid
483  // hitting the backend if our cached copy
484  // is newer than the bookmark, or if we have
485  // a preview and do not update it when the
486  // bookmark changes.
487  previewLastModified = finfo.lastModified();
488  }
489  else if (!IsGeneratingPreview(key))
490  {
491  previewLastModified =
492  RemoteGetPreviewIfModified(pginfo, ret_file);
493  }
494  }
495  else
496  {
497  QFileInfo fi(filename);
498  if ((locally_accessible = fi.isReadable()))
499  previewLastModified = fi.lastModified();
500  }
501 
502  bookmark_updated =
503  (!previewLastModified.isValid() || (previewLastModified <= cmp_ts));
504 
505  if (bookmark_updated && bookmark_ts.isValid() &&
506  previewLastModified.isValid())
507  {
509  }
510 
511  bool preview_exists = previewLastModified.isValid();
512 
513 #if 0
514  QString alttext = (bookmark_ts.isValid()) ? QString() :
515  QString("\n\t\t\tcmp_ts: %1")
516  .arg(cmp_ts.toString(Qt::ISODate));
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")
521  .arg(previewLastModified.toString(Qt::ISODate))
522  .arg(bookmark_ts.toString(Qt::ISODate))
523  .arg(alttext)
524  .arg(pginfo.GetLastModifiedTime(MythDate::ISODate)) +
525  QString("Title: %1\n\t\t\t")
526  .arg(pginfo.toString(ProgramInfo::kTitleSubtitle)) +
527  QString("File '%1' \n\t\t\tCache '%2'")
528  .arg(filename).arg(ret_file) +
529  QString("\n\t\t\tPreview Exists: %1, Bookmark Updated: %2, "
530  "Need Preview: %3")
531  .arg(preview_exists).arg(bookmark_updated)
532  .arg((bookmark_updated || !preview_exists)));
533 #endif
534 
535  needs_gen = bookmark_updated || !preview_exists;
536 
537  if (!needs_gen)
538  {
539  if (locally_accessible)
540  ret = filename;
541  else if (preview_exists && QFileInfo(ret_file).isReadable())
542  ret = ret_file;
543  }
544  }
545 
546  if (needs_gen && !IsGeneratingPreview(key))
547  {
548  uint attempts = IncPreviewGeneratorAttempts(key);
549  if (attempts < m_maxAttempts)
550  {
551  LOG(VB_PLAYBACK, LOG_INFO, LOC +
552  QString("Requesting preview for '%1'") .arg(key));
553  auto *pg = new PreviewGenerator(&pginfo, token, m_mode);
554  if (!outputfile.isEmpty() || time >= 0s ||
555  size.width() || size.height())
556  {
557  pg->SetPreviewTime(time, frame);
558  pg->SetOutputFilename(outputfile);
559  pg->SetOutputSize(size);
560  }
561 
562  SetPreviewGenerator(key, pg);
563 
564  LOG(VB_PLAYBACK, LOG_INFO, LOC +
565  QString("Requested preview for '%1'").arg(key));
566  }
567  else
568  {
569  LOG(VB_GENERAL, LOG_ERR, LOC +
570  QString("Attempted to generate preview for '%1' "
571  "%2 times; >= max(%3)")
572  .arg(key).arg(attempts).arg(m_maxAttempts));
573  }
574  }
575  else if (needs_gen)
576  {
577  LOG(VB_PLAYBACK, LOG_INFO, LOC +
578  QString("Not requesting preview for %1,"
579  "as it is already being generated")
580  .arg(pginfo.toString(ProgramInfo::kTitleSubtitle)));
581  IncPreviewGeneratorPriority(key, token);
582  }
583 
585 
586  if (!ret.isEmpty())
587  {
588  QString msg = "On Disk";
589  QDateTime dt = QFileInfo(ret).lastModified();
590  SendEvent(pginfo, "PREVIEW_SUCCESS", ret, token, msg, dt);
591  }
592  else
593  {
594  uint queue_depth = 0;
595  uint token_cnt = 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());
600  }
601 
602  return ret;
603 }
604 
618  const QString &key, uint &queue_depth, uint &token_cnt)
619 {
620  QMutexLocker locker(&m_lock);
621  queue_depth = m_queue.size();
622  PreviewMap::iterator pit = m_previewMap.find(key);
623  token_cnt = (pit == m_previewMap.end()) ? 0 : (*pit).m_tokens.size();
624 }
625 
634  const QString &key, const QString& token)
635 {
636  QMutexLocker locker(&m_lock);
637  m_queue.removeAll(key);
638 
639  PreviewMap::iterator pit = m_previewMap.find(key);
640  if (pit == m_previewMap.end())
641  return;
642 
643  if ((*pit).m_gen && !(*pit).m_genStarted)
644  m_queue.push_back(key);
645 
646  if (!token.isEmpty())
647  {
648  m_tokenToKeyMap[token] = key;
649  (*pit).m_tokens.insert(token);
650  }
651 }
652 
658 {
659  QMutexLocker locker(&m_lock);
660  QStringList &q = m_queue;
661  if (!q.empty() && (m_running < m_maxThreads))
662  {
663  QString fn = q.back();
664  q.pop_back();
665  PreviewMap::iterator it = m_previewMap.find(fn);
666  if (it != m_previewMap.end() && (*it).m_gen && !(*it).m_genStarted)
667  {
668  m_running++;
669  (*it).m_gen->start();
670  (*it).m_genStarted = true;
671  }
672  }
673 }
674 
684  const QString &key, PreviewGenerator *g)
685 {
686  if (!g)
687  return;
688 
689  {
690  QMutexLocker locker(&m_lock);
691  m_tokenToKeyMap[g->GetToken()] = key;
692  PreviewGenState &state = m_previewMap[key];
693  if (state.m_gen)
694  {
695  if (state.m_gen != g)
696  {
697  if (!g->GetToken().isEmpty())
698  state.m_tokens.insert(g->GetToken());
699  g->deleteLater();
700  g = nullptr;
701  }
702  }
703  else
704  {
705  g->AttachSignals(this);
706  state.m_gen = g;
707  state.m_genStarted = false;
708  if (!g->GetToken().isEmpty())
709  state.m_tokens.insert(g->GetToken());
710  }
711  }
712 
714 }
715 
730 bool PreviewGeneratorQueue::IsGeneratingPreview(const QString &key) const
731 {
732  PreviewMap::const_iterator it;
733  QMutexLocker locker(&m_lock);
734 
735  if ((it = m_previewMap.find(key)) == m_previewMap.end())
736  return false;
737 
738  if ((*it).m_blockRetryUntil.isValid())
739  return MythDate::current() < (*it).m_blockRetryUntil;
740 
741  return (*it).m_gen;
742 }
743 
753 {
754  QMutexLocker locker(&m_lock);
755  return m_previewMap[key].m_attempts++;
756 }
757 
768 {
769  QMutexLocker locker(&m_lock);
770  m_previewMap[key].m_attempts = 0;
771  m_previewMap[key].m_lastBlockTime = 0s;
772  m_previewMap[key].m_blockRetryUntil =
773  MythDate::current().addSecs(-60);
774 }
775 
776 
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
MythEvent::kMythEventMessage
static const Type kMythEventMessage
Definition: mythevent.h:79
PreviewGenState
This class holds all the state information related to a specific preview generator.
Definition: previewgeneratorqueue.h:23
PreviewGenerator::AttachSignals
void AttachSignals(QObject *obj)
Definition: previewgenerator.cpp:115
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
PreviewGeneratorQueue::IncPreviewGeneratorAttempts
uint IncPreviewGeneratorAttempts(const QString &key)
Increments and returns number of times we have started a PreviewGenerator to create this file.
Definition: previewgeneratorqueue.cpp:752
ProgramInfo::GetRecordingID
uint GetRecordingID(void) const
Definition: programinfo.h:446
PreviewGenerator
This class creates a preview image of a recording.
Definition: previewgenerator.h:27
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
ProgramInfo::kTitleSubtitle
@ kTitleSubtitle
Definition: programinfo.h:509
PreviewGeneratorQueue::RemoveListener
static void RemoveListener(QObject *listener)
Stop receiving notifications when a preview event is generated.
Definition: previewgeneratorqueue.cpp:205
PreviewGeneratorQueue::CreatePreviewGeneratorQueue
static void CreatePreviewGeneratorQueue(PreviewGenerator::Mode mode, uint maxAttempts, std::chrono::seconds minBlockSeconds)
Create the singleton queue of preview generators.
Definition: previewgeneratorqueue.cpp:42
LOC
#define LOC
Definition: previewgeneratorqueue.cpp:24
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
PreviewGeneratorQueue::SendEvent
void SendEvent(const ProgramInfo &pginfo, const QString &eventname, const QString &filename, const QString &token, const QString &msg, const QDateTime &dt)
Send a message back to all objects that have requested creation of a specific preview.
Definition: previewgeneratorqueue.cpp:371
mythdirs.h
ProgramInfo::GetRecordingEndTime
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:412
remoteutil.h
PreviewGeneratorQueue::GeneratePreviewImage
QString GeneratePreviewImage(ProgramInfo &pginfo, QSize size, const QString &outputfile, std::chrono::seconds time, long long frame, const QString &token)
Generate a preview image for the specified program.
Definition: previewgeneratorqueue.cpp:427
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
PreviewGeneratorQueue::m_running
uint m_running
The number of threads currently generating previews.
Definition: previewgeneratorqueue.h:147
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:404
ProgramInfo::GetPathname
QString GetPathname(void) const
Definition: programinfo.h:343
PreviewGeneratorQueue::m_maxAttempts
uint m_maxAttempts
How many times total will the code attempt to generate a preview for a specific file,...
Definition: previewgeneratorqueue.h:154
PreviewGeneratorQueue::m_mode
PreviewGenerator::Mode m_mode
Definition: previewgeneratorqueue.h:137
PreviewGeneratorQueue::ClearPreviewGeneratorAttempts
void ClearPreviewGeneratorAttempts(const QString &key)
Clears the number of times we have started a PreviewGenerator to create this file.
Definition: previewgeneratorqueue.cpp:767
PreviewGenState::m_tokens
QSet< QString > m_tokens
The full set of tokens for all callers that have requested this preview.
Definition: previewgeneratorqueue.h:48
asPendingDelete
@ asPendingDelete
Definition: programtypes.h:179
mythlogging.h
PreviewGeneratorQueue::m_lock
QMutex m_lock
The thread interlock for this data structure.
Definition: previewgeneratorqueue.h:135
PreviewGeneratorQueue::event
bool event(QEvent *e) override
The event handler running on the preview generation thread.
Definition: previewgeneratorqueue.cpp:230
PreviewGeneratorQueue::m_minBlockSeconds
std::chrono::seconds m_minBlockSeconds
How long after a failed preview generation attempt will the code ignore subsequent requests.
Definition: previewgeneratorqueue.h:157
PreviewGeneratorQueue::IncPreviewGeneratorPriority
void IncPreviewGeneratorPriority(const QString &key, const QString &token)
Definition: previewgeneratorqueue.cpp:633
MThread::qthread
QThread * qthread(void)
Returns the thread, this will always return the same pointer no matter how often you restart the thre...
Definition: mthread.cpp:233
ProgramInfo::toString
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
Definition: programinfo.cpp:1934
PreviewGeneratorQueue::AddListener
static void AddListener(QObject *listener)
Request notifications when a preview event is generated.
Definition: previewgeneratorqueue.cpp:189
PreviewGenState::m_gen
PreviewGenerator * m_gen
A pointer to the generator that this state object describes.
Definition: previewgeneratorqueue.h:29
uint
unsigned int uint
Definition: compat.h:81
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:911
PreviewGeneratorQueue::m_maxThreads
uint m_maxThreads
The maximum number of threads that may concurrently generate previews.
Definition: previewgeneratorqueue.h:150
GetRemoteCacheDir
QString GetRemoteCacheDir(void)
Returns the directory for all files cached from the backend.
Definition: mythdirs.cpp:273
PreviewGeneratorQueue::m_previewMap
PreviewMap m_previewMap
A mapping from the generated preview name to the state information on the progress of generating the ...
Definition: previewgeneratorqueue.h:140
PreviewGeneratorQueue::m_listeners
QSet< QObject * > m_listeners
The set of all listeners that want messages when a preview request is queued or finishes.
Definition: previewgeneratorqueue.h:133
PreviewGeneratorQueue::TeardownPreviewGeneratorQueue
static void TeardownPreviewGeneratorQueue()
Destroy the singleton queue of preview generators.
Definition: previewgeneratorqueue.cpp:55
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
ProgramInfo::GetLastModifiedTime
QDateTime GetLastModifiedTime(void) const
Definition: programinfo.h:429
ProgramInfo::ToStringList
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
Definition: programinfo.cpp:1267
mythcorecontext.h
PreviewGeneratorQueue::GetInfo
void GetInfo(const QString &key, uint &queue_depth, uint &token_cnt)
Definition: previewgeneratorqueue.cpp:617
PreviewGeneratorQueue::IsGeneratingPreview
bool IsGeneratingPreview(const QString &key) const
Is a preview currently being generated for this key.
Definition: previewgeneratorqueue.cpp:730
PreviewGenerator::GetToken
QString GetToken(void) const
Definition: previewgenerator.h:64
PreviewGeneratorQueue::GetPreviewImage
static void GetPreviewImage(const ProgramInfo &pginfo, const QString &token)
Submit a request for the generation of a preview image.
Definition: previewgeneratorqueue.h:89
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
PreviewGenState::m_genStarted
bool m_genStarted
The preview generator for this file is currently running.
Definition: previewgeneratorqueue.h:32
mythcontext.h
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
PreviewGeneratorQueue::m_queue
QStringList m_queue
The queue of previews to be generated.
Definition: previewgeneratorqueue.h:145
mthread.h
MThread::exit
void exit(int retcode=0)
Use this to exit from the thread if you are using a Qt event loop.
Definition: mthread.cpp:278
previewgeneratorqueue.h
PreviewGeneratorQueue::PreviewGeneratorQueue
PreviewGeneratorQueue(PreviewGenerator::Mode mode, uint maxAttempts, std::chrono::seconds minBlockSeconds)
Definition: previewgeneratorqueue.cpp:82
PreviewGenerator::deleteLater
void deleteLater()
Definition: previewgenerator.cpp:109
PreviewGeneratorQueue::SetPreviewGenerator
void SetPreviewGenerator(const QString &key, PreviewGenerator *g)
Sets the PreviewGenerator for a specific file.
Definition: previewgeneratorqueue.cpp:683
PreviewGenerator::kLocal
@ kLocal
Definition: previewgenerator.h:43
previewgenerator.h
PreviewGeneratorQueue::s_pgq
static PreviewGeneratorQueue * s_pgq
The singleton queue.
Definition: previewgeneratorqueue.h:130
PreviewGeneratorQueue
This class implements a queue of preview generation requests.
Definition: previewgeneratorqueue.h:68
RemoteGetPreviewIfModified
QDateTime RemoteGetPreviewIfModified(const ProgramInfo &pginfo, const QString &cachefile)
Download preview & get timestamp if newer than cachefile's last modified time, otherwise just get the...
Definition: remoteutil.cpp:236
ProgramInfo::GetBasename
QString GetBasename(void) const
Definition: programinfo.h:344
build_compdb.filename
filename
Definition: build_compdb.py:21
ProgramInfo::GetAvailableStatus
AvailableStatusType GetAvailableStatus(void) const
Definition: programinfo.h:842
PreviewGenerator::Mode
Mode
Definition: previewgenerator.h:40
PreviewGeneratorQueue::~PreviewGeneratorQueue
~PreviewGeneratorQueue() override
Destroy the preview generation queue.
Definition: previewgeneratorqueue.cpp:107
ProgramInfo::GetBookmarkUpdate
QDateTime GetBookmarkUpdate(void) const
Definition: programinfo.h:474
PreviewGeneratorQueue::UpdatePreviewGeneratorThreads
void UpdatePreviewGeneratorThreads(void)
As long as there are items in the queue, make sure we're running the maximum allowed number of previe...
Definition: previewgeneratorqueue.cpp:657
PreviewGeneratorQueue::m_tokenToKeyMap
QMap< QString, QString > m_tokenToKeyMap
A mapping from requestor tokens to internal keys.
Definition: previewgeneratorqueue.h:142