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