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 // libmythtv
19 #include "previewgenerator.h"
20 
21 #define LOC QString("PreviewQueue: ")
22 
24 
41  uint maxAttempts, std::chrono::seconds minBlockSeconds)
42 {
43  s_pgq = new PreviewGeneratorQueue(mode, maxAttempts, minBlockSeconds);
44 }
45 
53 {
54  s_pgq->exit(0);
55  s_pgq->wait();
56  delete s_pgq;
57  s_pgq = nullptr;
58 }
59 
60 /*
61  * Create the queue object for holding preview generators.
62  *
63  * Create the singleton queue of preview generators. This should be
64  * called once at program start-up. All generation requests on this
65  * queue will will be created with the maxAttempts and minBlockSeconds
66  * parameters supplied here.
67  *
68  * \param[in] mode Local or Remote (or both)
69  * \param[in] maxAttempts How many times total will the code attempt
70  * to generate a preview for a specific file, before giving
71  * up and ignoring all future requests.
72  * \param[in] minBlockSeconds How long after a failed preview
73  * generation attempt will the code ignore subsequent
74  * requests.
75  *
76  * \note Never call this routine directly. Call the
77  * CreatePreviewGeneratorQueue function instead.
78  */
81  uint maxAttempts, std::chrono::seconds minBlockSeconds) :
82  MThread("PreviewGeneratorQueue"),
83  m_mode(mode),
84  m_maxAttempts(maxAttempts), m_minBlockSeconds(minBlockSeconds)
85 {
86  if (PreviewGenerator::kLocal & mode)
87  {
88  int idealThreads = QThread::idealThreadCount();
89  m_maxThreads = (idealThreads >= 1) ? idealThreads * 2 : 2;
90  }
91 
92  moveToThread(qthread());
93  start();
94 }
95 
105 {
106  // disconnect preview generators
107  QMutexLocker locker(&m_lock);
108  // NOLINTNEXTLINE(modernize-loop-convert)
109  for (auto it = m_previewMap.begin(); it != m_previewMap.end(); ++it)
110  {
111  if ((*it).m_gen)
112  (*it).m_gen->deleteLater();
113  (*it).m_gen = nullptr;
114  }
115  locker.unlock();
116  wait();
117 }
118 
141  const ProgramInfo &pginfo,
142  const QSize outputsize,
143  const QString &outputfile,
144  std::chrono::seconds time, long long frame,
145  const QString& token)
146 {
147  if (!s_pgq)
148  return;
149 
150  if (pginfo.GetPathname().isEmpty() ||
151  pginfo.GetBasename() == pginfo.GetPathname())
152  {
153  return;
154  }
155 
156  if (gCoreContext->GetNumSetting("JobAllowPreview", 1) == 0)
157  return;
158 
159  QStringList extra;
160  pginfo.ToStringList(extra);
161  extra += token;
162  extra += QString::number(outputsize.width());
163  extra += QString::number(outputsize.height());
164  extra += outputfile;
165  if (time >= 0s)
166  {
167  extra += QString::number(time.count());
168  extra += "1";
169  }
170  else
171  {
172  extra += QString::number(frame);
173  extra += "0";
174  }
175  auto *e = new MythEvent("GET_PREVIEW", extra);
176  QCoreApplication::postEvent(s_pgq, e);
177 }
178 
186 void PreviewGeneratorQueue::AddListener(QObject *listener)
187 {
188  if (!s_pgq)
189  return;
190 
191  QMutexLocker locker(&s_pgq->m_lock);
192  s_pgq->m_listeners.insert(listener);
193 }
194 
203 {
204  if (!s_pgq)
205  return;
206 
207  QMutexLocker locker(&s_pgq->m_lock);
208  s_pgq->m_listeners.remove(listener);
209 }
210 
228 {
229  if (e->type() != MythEvent::kMythEventMessage)
230  return QObject::event(e);
231 
232  auto *me = dynamic_cast<MythEvent*>(e);
233  if (me == nullptr)
234  return QObject::event(e);
235  if (me->Message() == "GET_PREVIEW")
236  {
237  const QStringList &list = me->ExtraDataList();
238  QStringList::const_iterator it = list.begin();
239  ProgramInfo evinfo(it, list.end());
240  QString token;
241  QSize outputsize;
242  QString outputfile;
243  long long time_or_frame = -1LL;
244  if (it != list.end())
245  token = (*it++);
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())
255  {
256  bool time_fmt_sec = (*it++).toInt() != 0;
257  if (time_fmt_sec)
258  {
259  GeneratePreviewImage(evinfo, outputsize, outputfile,
260  std::chrono::seconds(time_or_frame), -1, token);
261  }
262  else
263  {
264  GeneratePreviewImage(evinfo, outputsize, outputfile,
265  -1s, time_or_frame, token);
266  }
267  }
268  return true;
269  }
270  if (me->Message() == "PREVIEW_SUCCESS" ||
271  me->Message() == "PREVIEW_FAILED")
272  {
273  uint recordedingID = me->ExtraData(0).toUInt(); // pginfo->GetRecordingID()
274  const QString& filename = me->ExtraData(1); // outFileName
275  const QString& msg = me->ExtraData(2);
276  const QString& datetime = me->ExtraData(3);
277  const QString& token = me->ExtraData(4);
278 
279  {
280  QMutexLocker locker(&m_lock);
281  QMap<QString,QString>::iterator kit = m_tokenToKeyMap.find(token);
282  if (kit == m_tokenToKeyMap.end())
283  {
284  LOG(VB_GENERAL, LOG_ERR, LOC +
285  QString("Failed to find token %1 in map.").arg(token));
286  return true;
287  }
288  PreviewMap::iterator it = m_previewMap.find(*kit);
289  if (it == m_previewMap.end())
290  {
291  LOG(VB_GENERAL, LOG_ERR, LOC +
292  QString("Failed to find key %1 in map.").arg(*kit));
293  return true;
294  }
295 
296  if ((*it).m_gen)
297  (*it).m_gen->deleteLater();
298  (*it).m_gen = nullptr;
299  (*it).m_genStarted = false;
300  if (me->Message() == "PREVIEW_SUCCESS")
301  {
302  (*it).m_attempts = 0;
303  (*it).m_lastBlockTime = 0s;
304  (*it).m_blockRetryUntil = QDateTime();
305  }
306  else
307  {
308  (*it).m_lastBlockTime =
309  std::max(m_minBlockSeconds, (*it).m_lastBlockTime * 2);
310  (*it).m_blockRetryUntil =
311  MythDate::current().addSecs((*it).m_lastBlockTime.count());
312  }
313 
314  QStringList list;
315  list.push_back(QString::number(recordedingID));
316  list.push_back(filename);
317  list.push_back(msg);
318  list.push_back(datetime);
319  for (const auto & tok : std::as_const((*it).m_tokens))
320  {
321  kit = m_tokenToKeyMap.find(tok);
322  if (kit != m_tokenToKeyMap.end())
323  m_tokenToKeyMap.erase(kit);
324  list.push_back(tok);
325  }
326 
327  if (list.size() > 4)
328  {
329  for (auto *listener : std::as_const(m_listeners))
330  {
331  auto *le = new MythEvent(me->Message(), list);
332  QCoreApplication::postEvent(listener, le);
333  }
334  (*it).m_tokens.clear();
335  }
336 
337  m_running = (m_running > 0) ? m_running - 1 : 0;
338  }
339 
341 
342  return true;
343  }
344  return QObject::event(e);
345 }
346 
369  const ProgramInfo &pginfo,
370  const QString &eventname,
371  const QString &filename, const QString &token, const QString &msg,
372  const QDateTime &dt)
373 {
374  QStringList list;
375  list.push_back(QString::number(pginfo.GetRecordingID()));
376  list.push_back(filename);
377  list.push_back(msg);
378  list.push_back(dt.toUTC().toString(Qt::ISODate));
379  list.push_back(token);
380 
381  QMutexLocker locker(&m_lock);
382  for (auto *listener : std::as_const(m_listeners))
383  {
384  auto *e = new MythEvent(eventname, list);
385  QCoreApplication::postEvent(listener, e);
386  }
387 }
388 
425  ProgramInfo &pginfo,
426  const QSize size,
427  const QString &outputfile,
428  std::chrono::seconds time, long long frame,
429  const QString& token)
430 {
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())
436  .arg(pos_text);
437 
438  if (pginfo.GetAvailableStatus() == asPendingDelete)
439  {
440  SendEvent(pginfo, "PREVIEW_FAILED", key, token,
441  "Pending Delete", QDateTime());
442  return {};
443  }
444 
445  // keep in sync with default filename in PreviewGenerator::RunReal
446  QString filename = (outputfile.isEmpty()) ?
447  pginfo.GetPathname() + ".png" : outputfile;
448  QString ret_file = filename;
449  QString ret;
450 
451  bool is_special = !outputfile.isEmpty() || time >= 0s ||
452  (size.width() != 0) || (size.height() != 0);
453 
454  bool needs_gen = true;
455  if (!is_special)
456  {
457  QDateTime previewLastModified;
458  bool streaming = !filename.startsWith("/");
459  bool locally_accessible = false;
460  bool bookmark_updated = false;
461 
462  QDateTime bookmark_ts = pginfo.GetBookmarkUpdate();
463  QDateTime cmp_ts;
464  if (bookmark_ts.isValid())
465  cmp_ts = bookmark_ts;
466  else if (MythDate::current() >= pginfo.GetRecordingEndTime())
467  cmp_ts = pginfo.GetLastModifiedTime();
468  else
469  cmp_ts = pginfo.GetRecordingStartTime();
470 
471  if (streaming)
472  {
473  ret_file = QString("%1/%2")
474  .arg(GetRemoteCacheDir(), filename.section('/', -1));
475 
476  QFileInfo finfo(ret_file);
477  if (finfo.isReadable() && finfo.lastModified() >= cmp_ts)
478  {
479  // This is just an optimization to avoid
480  // hitting the backend if our cached copy
481  // is newer than the bookmark, or if we have
482  // a preview and do not update it when the
483  // bookmark changes.
484  previewLastModified = finfo.lastModified();
485  }
486  else if (!IsGeneratingPreview(key))
487  {
488  previewLastModified =
489  RemoteGetPreviewIfModified(pginfo, ret_file);
490  }
491  }
492  else
493  {
494  QFileInfo fi(filename);
495  locally_accessible = fi.isReadable();
496  if (locally_accessible)
497  previewLastModified = fi.lastModified();
498  }
499 
500  bookmark_updated =
501  (!previewLastModified.isValid() || (previewLastModified <= cmp_ts));
502 
503  if (bookmark_updated && bookmark_ts.isValid() &&
504  previewLastModified.isValid())
505  {
507  }
508 
509  bool preview_exists = previewLastModified.isValid();
510 
511 #if 0
512  QString alttext = (bookmark_ts.isValid()) ? QString() :
513  QString("\n\t\t\tcmp_ts: %1")
514  .arg(cmp_ts.toString(Qt::ISODate));
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")
519  .arg(previewLastModified.toString(Qt::ISODate))
520  .arg(bookmark_ts.toString(Qt::ISODate))
521  .arg(alttext)
522  .arg(pginfo.GetLastModifiedTime(MythDate::ISODate)) +
523  QString("Title: %1\n\t\t\t")
524  .arg(pginfo.toString(ProgramInfo::kTitleSubtitle)) +
525  QString("File '%1' \n\t\t\tCache '%2'")
526  .arg(filename).arg(ret_file) +
527  QString("\n\t\t\tPreview Exists: %1, Bookmark Updated: %2, "
528  "Need Preview: %3")
529  .arg(preview_exists).arg(bookmark_updated)
530  .arg((bookmark_updated || !preview_exists)));
531 #endif
532 
533  needs_gen = bookmark_updated || !preview_exists;
534 
535  if (!needs_gen)
536  {
537  if (locally_accessible)
538  ret = filename;
539  else if (preview_exists && QFileInfo(ret_file).isReadable())
540  ret = ret_file;
541  }
542  }
543 
544  if (needs_gen && !IsGeneratingPreview(key))
545  {
546  uint attempts = IncPreviewGeneratorAttempts(key);
547  if (attempts < m_maxAttempts)
548  {
549  LOG(VB_PLAYBACK, LOG_INFO, LOC +
550  QString("Requesting preview for '%1'") .arg(key));
551  auto *pg = new PreviewGenerator(&pginfo, token, m_mode);
552  if (!outputfile.isEmpty() || time >= 0s ||
553  size.width() || size.height())
554  {
555  pg->SetPreviewTime(time, frame);
556  pg->SetOutputFilename(outputfile);
557  pg->SetOutputSize(size);
558  }
559 
560  SetPreviewGenerator(key, pg);
561 
562  LOG(VB_PLAYBACK, LOG_INFO, LOC +
563  QString("Requested preview for '%1'").arg(key));
564  }
565  else
566  {
567  LOG(VB_GENERAL, LOG_ERR, LOC +
568  QString("Attempted to generate preview for '%1' "
569  "%2 times; >= max(%3)")
570  .arg(key).arg(attempts).arg(m_maxAttempts));
571  }
572  }
573  else if (needs_gen)
574  {
575  LOG(VB_PLAYBACK, LOG_INFO, LOC +
576  QString("Not requesting preview for %1,"
577  "as it is already being generated")
578  .arg(pginfo.toString(ProgramInfo::kTitleSubtitle)));
579  IncPreviewGeneratorPriority(key, token);
580  }
581 
583 
584  if (!ret.isEmpty())
585  {
586  QString msg = "On Disk";
587  QDateTime dt = QFileInfo(ret).lastModified();
588  SendEvent(pginfo, "PREVIEW_SUCCESS", ret, token, msg, dt);
589  }
590  else
591  {
592  uint queue_depth = 0;
593  uint token_cnt = 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());
598  }
599 
600  return ret;
601 }
602 
616  const QString &key, uint &queue_depth, uint &token_cnt)
617 {
618  QMutexLocker locker(&m_lock);
619  queue_depth = m_queue.size();
620  PreviewMap::iterator pit = m_previewMap.find(key);
621  token_cnt = (pit == m_previewMap.end()) ? 0 : (*pit).m_tokens.size();
622 }
623 
632  const QString &key, const QString& token)
633 {
634  QMutexLocker locker(&m_lock);
635  m_queue.removeAll(key);
636 
637  PreviewMap::iterator pit = m_previewMap.find(key);
638  if (pit == m_previewMap.end())
639  return;
640 
641  if ((*pit).m_gen && !(*pit).m_genStarted)
642  m_queue.push_back(key);
643 
644  if (!token.isEmpty())
645  {
646  m_tokenToKeyMap[token] = key;
647  (*pit).m_tokens.insert(token);
648  }
649 }
650 
656 {
657  QMutexLocker locker(&m_lock);
658  QStringList &q = m_queue;
659  if (!q.empty() && (m_running < m_maxThreads))
660  {
661  QString fn = q.back();
662  q.pop_back();
663  PreviewMap::iterator it = m_previewMap.find(fn);
664  if (it != m_previewMap.end() && (*it).m_gen && !(*it).m_genStarted)
665  {
666  m_running++;
667  (*it).m_gen->start();
668  (*it).m_genStarted = true;
669  }
670  }
671 }
672 
682  const QString &key, PreviewGenerator *g)
683 {
684  if (!g)
685  return;
686 
687  {
688  QMutexLocker locker(&m_lock);
689  m_tokenToKeyMap[g->GetToken()] = key;
690  PreviewGenState &state = m_previewMap[key];
691  if (state.m_gen)
692  {
693  if (state.m_gen != g)
694  {
695  if (!g->GetToken().isEmpty())
696  state.m_tokens.insert(g->GetToken());
697  g->deleteLater();
698  g = nullptr;
699  }
700  }
701  else
702  {
703  g->AttachSignals(this);
704  state.m_gen = g;
705  state.m_genStarted = false;
706  if (!g->GetToken().isEmpty())
707  state.m_tokens.insert(g->GetToken());
708  }
709  }
710 
712 }
713 
728 bool PreviewGeneratorQueue::IsGeneratingPreview(const QString &key) const
729 {
730  QMutexLocker locker(&m_lock);
731 
732  PreviewMap::const_iterator it = m_previewMap.find(key);
733  if (it == m_previewMap.end())
734  return false;
735 
736  if ((*it).m_blockRetryUntil.isValid())
737  return MythDate::current() < (*it).m_blockRetryUntil;
738 
739  return (*it).m_gen;
740 }
741 
751 {
752  QMutexLocker locker(&m_lock);
753  return m_previewMap[key].m_attempts++;
754 }
755 
766 {
767  QMutexLocker locker(&m_lock);
768  m_previewMap[key].m_attempts = 0;
769  m_previewMap[key].m_lastBlockTime = 0s;
770  m_previewMap[key].m_blockRetryUntil =
771  MythDate::current().addSecs(-60);
772 }
773 
774 
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:116
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:750
ProgramInfo::GetRecordingID
uint GetRecordingID(void) const
Definition: programinfo.h:450
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
PreviewGeneratorQueue::RemoveListener
static void RemoveListener(QObject *listener)
Stop receiving notifications when a preview event is generated.
Definition: previewgeneratorqueue.cpp:202
PreviewGeneratorQueue::CreatePreviewGeneratorQueue
static void CreatePreviewGeneratorQueue(PreviewGenerator::Mode mode, uint maxAttempts, std::chrono::seconds minBlockSeconds)
Create the singleton queue of preview generators.
Definition: previewgeneratorqueue.cpp:39
LOC
#define LOC
Definition: previewgeneratorqueue.cpp:21
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:368
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:413
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:424
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
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:405
ProgramInfo::GetPathname
QString GetPathname(void) const
Definition: programinfo.h:344
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
PreviewGenerator::kLocal
@ kLocal
Definition: previewgenerator.h:43
PreviewGeneratorQueue::ClearPreviewGeneratorAttempts
void ClearPreviewGeneratorAttempts(const QString &key)
Clears the number of times we have started a PreviewGenerator to create this file.
Definition: previewgeneratorqueue.cpp:765
PreviewGenState::m_tokens
QSet< QString > m_tokens
The full set of tokens for all callers that have requested this preview.
Definition: previewgeneratorqueue.h:48
mythlogging.h
PreviewGeneratorQueue::m_lock
QMutex m_lock
The thread interlock for this data structure.
Definition: previewgeneratorqueue.h:135
asPendingDelete
@ asPendingDelete
Definition: programtypes.h:178
PreviewGeneratorQueue::event
bool event(QEvent *e) override
The event handler running on the preview generation thread.
Definition: previewgeneratorqueue.cpp:227
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:631
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:1955
PreviewGeneratorQueue::AddListener
static void AddListener(QObject *listener)
Request notifications when a preview event is generated.
Definition: previewgeneratorqueue.cpp:186
PreviewGenState::m_gen
PreviewGenerator * m_gen
A pointer to the generator that this state object describes.
Definition: previewgeneratorqueue.h:29
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:918
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:280
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
PreviewGenerator::Mode
Mode
Definition: previewgenerator.h:40
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:52
ProgramInfo::kTitleSubtitle
@ kTitleSubtitle
Definition: programinfo.h:514
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
ProgramInfo::GetLastModifiedTime
QDateTime GetLastModifiedTime(void) const
Definition: programinfo.h:433
ProgramInfo::ToStringList
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
Definition: programinfo.cpp:1276
mythcorecontext.h
PreviewGeneratorQueue::GetInfo
void GetInfo(const QString &key, uint &queue_depth, uint &token_cnt)
Definition: previewgeneratorqueue.cpp:615
PreviewGeneratorQueue::IsGeneratingPreview
bool IsGeneratingPreview(const QString &key) const
Is a preview currently being generated for this key.
Definition: previewgeneratorqueue.cpp:728
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
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:79
PreviewGenerator::deleteLater
void deleteLater()
Definition: previewgenerator.cpp:110
PreviewGeneratorQueue::SetPreviewGenerator
void SetPreviewGenerator(const QString &key, PreviewGenerator *g)
Sets the PreviewGenerator for a specific file.
Definition: previewgeneratorqueue.cpp:681
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:345
build_compdb.filename
filename
Definition: build_compdb.py:21
ProgramInfo::GetAvailableStatus
AvailableStatusType GetAvailableStatus(void) const
Definition: programinfo.h:847
PreviewGeneratorQueue::~PreviewGeneratorQueue
~PreviewGeneratorQueue() override
Destroy the preview generation queue.
Definition: previewgeneratorqueue.cpp:104
uint
unsigned int uint
Definition: freesurround.h:24
ProgramInfo::GetBookmarkUpdate
QDateTime GetBookmarkUpdate(void) const
Definition: programinfo.h:478
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:655
PreviewGeneratorQueue::m_tokenToKeyMap
QMap< QString, QString > m_tokenToKeyMap
A mapping from requestor tokens to internal keys.
Definition: previewgeneratorqueue.h:142