MythTV  master
playbackboxhelper.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 
3 #include <QCoreApplication>
4 #include <QStringList>
5 #include <QDateTime>
6 #include <QFileInfo>
7 #include <QDir>
8 #include <QMap>
9 #include <QHash>
10 
11 #include "previewgeneratorqueue.h"
12 #include "metadataimagehelper.h"
13 #include "playbackboxhelper.h"
14 #include "mythcorecontext.h"
15 #include "filesysteminfo.h"
16 #include "tvremoteutil.h"
17 #include "storagegroup.h"
18 #include "mythlogging.h"
19 #include "programinfo.h"
20 #include "remoteutil.h"
21 #include "mythevent.h"
22 #include "mythdirs.h"
23 #include "mythmiscutil.h"
24 
25 #define LOC QString("PlaybackBoxHelper: ")
26 #define LOC_WARN QString("PlaybackBoxHelper Warning: ")
27 #define LOC_ERR QString("PlaybackBoxHelper Error: ")
28 
29 class PBHEventHandler : public QObject
30 {
31  public:
34  {
36  }
37  ~PBHEventHandler() override
38  {
40  killTimer(m_freeSpaceTimerId);
42  killTimer(m_checkAvailabilityTimerId);
43  }
44 
45  bool event(QEvent* /*e*/) override; // QObject
46  void UpdateFreeSpaceEvent(void);
47  AvailableStatusType CheckAvailability(const QStringList &slist);
51  static constexpr std::chrono::milliseconds kUpdateFreeSpaceInterval { 15s };
52  QMap<QString, QStringList> m_fileListCache;
53  QHash<uint, QStringList> m_checkAvailability;
54 };
55 
57 {
58  QTime tm = QTime::currentTime();
59 
60  QStringList::const_iterator it2 = slist.begin();
61  ProgramInfo evinfo(it2, slist.end());
62  QSet<CheckAvailabilityType> cats;
63  for (; it2 != slist.end(); ++it2)
64  cats.insert((CheckAvailabilityType)(*it2).toUInt());
65 
66  {
67  QMutexLocker locker(&m_pbh.m_lock);
68  QHash<uint, QStringList>::iterator cit =
69  m_checkAvailability.find(evinfo.GetRecordingID());
70  if (cit != m_checkAvailability.end())
71  m_checkAvailability.erase(cit);
73  {
74  killTimer(m_checkAvailabilityTimerId);
76  }
77  }
78 
79  if (cats.empty())
80  return asFileNotFound;
81 
82  AvailableStatusType availableStatus = asAvailable;
83  if (!evinfo.HasPathname() && !evinfo.GetChanID())
84  availableStatus = asFileNotFound;
85  else
86  {
87  // Note IsFileReadable() implicitly calls GetPlaybackURL
88  // when necessary, we rely on this.
89  if (!evinfo.IsFileReadable())
90  {
91  LOG(VB_GENERAL, LOG_ERR, LOC +
92  QString("CHECK_AVAILABILITY '%1' file not found")
93  .arg(evinfo.GetPathname()));
94  availableStatus = asFileNotFound;
95  }
96  else if (!evinfo.GetFilesize())
97  {
98  // This query should be unnecessary if the ProgramInfo Updater is working
99 // evinfo.SetFilesize(evinfo.QueryFilesize());
100 // if (!evinfo.GetFilesize())
101 // {
102  availableStatus =
105 // }
106  }
107  }
108 
109  QStringList list;
110  list.push_back(QString::number(evinfo.GetRecordingID()));
111  list.push_back(evinfo.GetPathname());
112  auto *e0 = new MythEvent("SET_PLAYBACK_URL", list);
113  QCoreApplication::postEvent(m_pbh.m_listener, e0);
114 
115  list.clear();
116  list.push_back(QString::number(evinfo.GetRecordingID()));
117  list.push_back(QString::number((int)*cats.begin()));
118  list.push_back(QString::number((int)availableStatus));
119  list.push_back(QString::number(evinfo.GetFilesize()));
120  list.push_back(QString::number(tm.hour()));
121  list.push_back(QString::number(tm.minute()));
122  list.push_back(QString::number(tm.second()));
123  list.push_back(QString::number(tm.msec()));
124 
125  for (auto type : qAsConst(cats))
126  {
127  if (type == kCheckForCache && cats.size() > 1)
128  continue;
129  list[1] = QString::number((int)type);
130  auto *e = new MythEvent("AVAILABILITY", list);
131  QCoreApplication::postEvent(m_pbh.m_listener, e);
132  }
133 
134  return availableStatus;
135 }
136 
137 bool PBHEventHandler::event(QEvent *e)
138 {
139  if (e->type() == QEvent::Timer)
140  {
141  auto *te = (QTimerEvent*)e;
142  const int timer_id = te->timerId();
143  if (timer_id == m_freeSpaceTimerId)
145  if (timer_id == m_checkAvailabilityTimerId)
146  {
147  QStringList slist;
148  {
149  QMutexLocker locker(&m_pbh.m_lock);
150  QHash<uint, QStringList>::iterator it =
151  m_checkAvailability.begin();
152  if (it != m_checkAvailability.end())
153  slist = *it;
154  }
155 
156  if (slist.size() >= 1 + NUMPROGRAMLINES)
157  CheckAvailability(slist);
158  }
159  return true;
160  }
161  if (e->type() == MythEvent::MythEventMessage)
162  {
163  auto *me = dynamic_cast<MythEvent*>(e);
164  if (me == nullptr)
165  return QObject::event(e);
166 
167  if (me->Message() == "UPDATE_FREE_SPACE")
168  {
170  return true;
171  }
172  if (me->Message() == "STOP_RECORDING")
173  {
174  ProgramInfo pginfo(me->ExtraDataList());
175  if (pginfo.GetChanID())
176  RemoteStopRecording(&pginfo);
177  return true;
178  }
179  if (me->Message() == "DELETE_RECORDINGS")
180  {
181  QStringList successes;
182  QStringList failures;
183  QStringList list = me->ExtraDataList();
184  while (list.size() >= 3)
185  {
186  uint recordingID = list[0].toUInt();
187  bool forceDelete = list[1].toUInt() != 0U;
188  bool forgetHistory = list[2].toUInt() != 0U;
189 
190  bool ok = RemoteDeleteRecording( recordingID, forceDelete,
191  forgetHistory);
192 
193  QStringList &res = (ok) ? successes : failures;
194  for (uint i = 0; i < 3; i++)
195  {
196  res.push_back(list.front());
197  list.pop_front();
198  }
199  }
200  if (!successes.empty())
201  {
202  auto *oe = new MythEvent("DELETE_SUCCESSES", successes);
203  QCoreApplication::postEvent(m_pbh.m_listener, oe);
204  }
205  if (!failures.empty())
206  {
207  auto *oe = new MythEvent("DELETE_FAILURES", failures);
208  QCoreApplication::postEvent(m_pbh.m_listener, oe);
209  }
210 
211  return true;
212  }
213  if (me->Message() == "UNDELETE_RECORDINGS")
214  {
215  QStringList successes;
216  QStringList failures;
217  QStringList list = me->ExtraDataList();
218  while (!list.empty())
219  {
220  uint recordingID = list[0].toUInt();
221 
222  bool ok = RemoteUndeleteRecording(recordingID);
223 
224  QStringList &res = (ok) ? successes : failures;
225 
226  res.push_back(QString::number(recordingID));
227  list.pop_front();
228  }
229  if (!successes.empty())
230  {
231  auto *oe = new MythEvent("UNDELETE_SUCCESSES", successes);
232  QCoreApplication::postEvent(m_pbh.m_listener, oe);
233  }
234  if (!failures.empty())
235  {
236  auto *oe = new MythEvent("UNDELETE_FAILURES", failures);
237  QCoreApplication::postEvent(m_pbh.m_listener, oe);
238  }
239 
240  return true;
241  }
242  if (me->Message() == "GET_PREVIEW")
243  {
244  const QString& token = me->ExtraData(0);
245  bool check_avail = (bool) me->ExtraData(1).toInt();
246  QStringList list = me->ExtraDataList();
247  QStringList::const_iterator it = list.cbegin()+2;
248  ProgramInfo evinfo(it, list.cend());
249  if (!evinfo.HasPathname())
250  return true;
251 
252  list.clear();
253  evinfo.ToStringList(list);
254  list += QString::number(kCheckForCache);
255  if (check_avail && (asAvailable != CheckAvailability(list)))
256  return true;
257  if (asAvailable != evinfo.GetAvailableStatus())
258  return true;
259 
260  // Now we can actually request the preview...
262 
263  return true;
264  }
265  if (me->Message() == "CHECK_AVAILABILITY")
266  {
267  if (me->ExtraData(0) != QString::number(kCheckForCache))
268  {
270  killTimer(m_checkAvailabilityTimerId);
271  m_checkAvailabilityTimerId = startTimer(0ms);
272  }
273  else if (!m_checkAvailabilityTimerId)
274  m_checkAvailabilityTimerId = startTimer(50ms);
275  }
276  else if (me->Message() == "LOCATE_ARTWORK")
277  {
278  const QString& inetref = me->ExtraData(0);
279  uint season = me->ExtraData(1).toUInt();
280  const auto type = (VideoArtworkType)me->ExtraData(2).toInt();
281 #if 0 /* const ref for an unused variable doesn't make much sense either */
282  uint recordingID = me->ExtraData(3).toUInt();
283  const QString &group = me->ExtraData(4);
284 #endif
285  const QString cacheKey = QString("%1:%2:%3")
286  .arg((int)type).arg(inetref).arg(season);
287 
288  ArtworkMap map = GetArtwork(inetref, season);
289 
290  ArtworkInfo info = map.value(type);
291 
292  QString foundFile;
293 
294  if (!info.url.isEmpty())
295  {
296  foundFile = info.url;
297  QMutexLocker locker(&m_pbh.m_lock);
298  m_pbh.m_artworkCache[cacheKey] = foundFile;
299  }
300 
301  if (!foundFile.isEmpty())
302  {
303  QStringList list = me->ExtraDataList();
304  list.push_back(foundFile);
305  auto *oe = new MythEvent("FOUND_ARTWORK", list);
306  QCoreApplication::postEvent(m_pbh.m_listener, oe);
307  }
308 
309  return true;
310  }
311  }
312 
313  return QObject::event(e);
314 }
315 
317 {
318  if (m_freeSpaceTimerId)
319  killTimer(m_freeSpaceTimerId);
322 }
323 
325 
327  MThread("PlaybackBoxHelper"),
328  m_listener(listener), m_eventHandler(new PBHEventHandler(*this))
329 {
330  start();
331  m_eventHandler->moveToThread(qthread());
332  // Prime the pump so the disk free display starts updating
334 }
335 
337 {
338  // delete the event handler
339  m_eventHandler->deleteLater();
340  m_eventHandler = nullptr;
341 
342  MThread::exit();
343  wait();
344 }
345 
347 {
348  QCoreApplication::postEvent(
349  m_eventHandler, new MythEvent("UPDATE_FREE_SPACE"));
350 }
351 
353 {
354  QStringList list;
355  pginfo.ToStringList(list);
356  auto *e = new MythEvent("STOP_RECORDING", list);
357  QCoreApplication::postEvent(m_eventHandler, e);
358 }
359 
360 void PlaybackBoxHelper::DeleteRecording( uint recordingID, bool forceDelete,
361  bool forgetHistory)
362 {
363  QStringList list;
364  list.push_back(QString::number(recordingID));
365  list.push_back((forceDelete) ? "1" : "0");
366  list.push_back((forgetHistory) ? "1" : "0");
367  DeleteRecordings(list);
368 }
369 
370 void PlaybackBoxHelper::DeleteRecordings(const QStringList &list)
371 {
372  auto *e = new MythEvent("DELETE_RECORDINGS", list);
373  QCoreApplication::postEvent(m_eventHandler, e);
374 }
375 
377 {
378  QStringList list;
379  list.push_back(QString::number(recordingID));
380  auto *e = new MythEvent("UNDELETE_RECORDINGS", list);
381  QCoreApplication::postEvent(m_eventHandler, e);
382 }
383 
385 {
386  QList<FileSystemInfo> fsInfos = FileSystemInfo::RemoteGetInfo();
387 
388  QMutexLocker locker(&m_lock);
389  for (const auto& fsInfo : qAsConst(fsInfos))
390  {
391  if (fsInfo.getPath() == "TotalDiskSpace")
392  {
393  m_freeSpaceTotalMB = (uint64_t) (fsInfo.getTotalSpace() >> 10);
394  m_freeSpaceUsedMB = (uint64_t) (fsInfo.getUsedSpace() >> 10);
395  }
396  }
397  auto *e = new MythEvent("UPDATE_USAGE_UI");
398  QCoreApplication::postEvent(m_listener, e);
399 }
400 
402 {
403  QMutexLocker locker(&m_lock);
404  return m_freeSpaceTotalMB;
405 }
406 
408 {
409  QMutexLocker locker(&m_lock);
410  return m_freeSpaceUsedMB;
411 }
412 
414  const ProgramInfo &pginfo, CheckAvailabilityType cat)
415 {
416  QString catstr = QString::number((int)cat);
417  QMutexLocker locker(&m_lock);
418  QHash<uint, QStringList>::iterator it =
420  if (it == m_eventHandler->m_checkAvailability.end())
421  {
422  QStringList list;
423  pginfo.ToStringList(list);
424  list += catstr;
426  }
427  else
428  {
429  (*it).push_back(catstr);
430  }
431  auto *e = new MythEvent("CHECK_AVAILABILITY", QStringList(catstr));
432  QCoreApplication::postEvent(m_eventHandler, e);
433 }
434 
436  const QString &inetref, uint season,
437  const VideoArtworkType type,
438  const ProgramInfo *pginfo,
439  const QString &groupname)
440 {
441  QString cacheKey = QString("%1:%2:%3")
442  .arg((int)type).arg(inetref).arg(season);
443 
444  QMutexLocker locker(&m_lock);
445 
446  InfoMap::const_iterator it =
447  m_artworkCache.constFind(cacheKey);
448 
449  if (it != m_artworkCache.constEnd())
450  return *it;
451 
452  QStringList list(inetref);
453  list.push_back(QString::number(season));
454  list.push_back(QString::number(type));
455  list.push_back((pginfo)?QString::number(pginfo->GetRecordingID()):"");
456  list.push_back(groupname);
457  auto *e = new MythEvent("LOCATE_ARTWORK", list);
458  QCoreApplication::postEvent(m_eventHandler, e);
459 
460  return QString();
461 }
462 
464  const ProgramInfo &pginfo, bool check_availability)
465 {
466  if (!check_availability && pginfo.GetAvailableStatus() != asAvailable)
467  return QString();
468 
469  if (pginfo.GetAvailableStatus() == asPendingDelete)
470  return QString();
471 
472  QString token = QString("%1:%2")
473  .arg(pginfo.MakeUniqueKey()).arg(MythRandom());
474 
475  QStringList extra(token);
476  extra.push_back(check_availability?"1":"0");
477  pginfo.ToStringList(extra);
478  auto *e = new MythEvent("GET_PREVIEW", extra);
479  QCoreApplication::postEvent(m_eventHandler, e);
480 
481  return token;
482 }
PlaybackBoxHelper::DeleteRecording
void DeleteRecording(uint recordingID, bool forceDelete, bool forgetHistory)
Definition: playbackboxhelper.cpp:360
filesysteminfo.h
PlaybackBoxHelper::m_freeSpaceUsedMB
uint64_t m_freeSpaceUsedMB
Definition: playbackboxhelper.h:61
mythevent.h
bool
bool
Definition: pxsup2dast.c:30
PBHEventHandler::UpdateFreeSpaceEvent
void UpdateFreeSpaceEvent(void)
Definition: playbackboxhelper.cpp:316
VideoArtworkType
VideoArtworkType
Definition: metadataimagehelper.h:10
ProgramInfo::MakeUniqueKey
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
Definition: programinfo.h:338
kCheckForCache
@ kCheckForCache
Definition: playbackboxhelper.h:20
MythEvent::MythEventMessage
static Type MythEventMessage
Definition: mythevent.h:78
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:286
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6262
PBHEventHandler::~PBHEventHandler
~PBHEventHandler() override
Definition: playbackboxhelper.cpp:37
metadataimagehelper.h
asFileNotFound
@ asFileNotFound
Definition: programtypes.h:181
PlaybackBoxHelper::m_eventHandler
PBHEventHandler * m_eventHandler
Definition: playbackboxhelper.h:56
PlaybackBoxHelper::GetFreeSpaceTotalMB
uint64_t GetFreeSpaceTotalMB(void) const
Definition: playbackboxhelper.cpp:401
PBHEventHandler::kUpdateFreeSpaceInterval
static constexpr std::chrono::milliseconds kUpdateFreeSpaceInterval
Definition: playbackboxhelper.cpp:51
asAvailable
@ asAvailable
Definition: programtypes.h:178
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
ProgramInfo::GetRecordingID
uint GetRecordingID(void) const
Definition: programinfo.h:445
hardwareprofile.devicelist.cat
def cat(file_name)
Definition: devicelist.py:95
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
PlaybackBoxHelper
Definition: playbackboxhelper.h:26
CheckAvailabilityType
CheckAvailabilityType
Definition: playbackboxhelper.h:19
GetArtwork
ArtworkMap GetArtwork(const QString &inetref, uint season, bool strict)
Definition: metadataimagehelper.cpp:23
PlaybackBoxHelper::m_freeSpaceTotalMB
uint64_t m_freeSpaceTotalMB
Definition: playbackboxhelper.h:60
RemoteUndeleteRecording
bool RemoteUndeleteRecording(uint recordingID)
Definition: remoteutil.cpp:139
AvailableStatusType
AvailableStatusType
Definition: programtypes.h:177
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
mythdirs.h
playbackboxhelper.h
PBHEventHandler::m_fileListCache
QMap< QString, QStringList > m_fileListCache
Definition: playbackboxhelper.cpp:52
remoteutil.h
PlaybackBoxHelper::UndeleteRecording
void UndeleteRecording(uint recordingID)
Definition: playbackboxhelper.cpp:376
StorageGroup::ClearGroupToUseCache
static void ClearGroupToUseCache(void)
Definition: storagegroup.cpp:860
ProgramInfo::GetPathname
QString GetPathname(void) const
Definition: programinfo.h:342
programinfo.h
asPendingDelete
@ asPendingDelete
Definition: programtypes.h:180
mythlogging.h
ProgramInfo::GetRecordingStatus
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:446
FileSystemInfo::RemoteGetInfo
static QList< FileSystemInfo > RemoteGetInfo(MythSocket *sock=nullptr)
Definition: filesysteminfo.cpp:143
RemoteStopRecording
bool RemoteStopRecording(uint inputid)
Definition: tvremoteutil.cpp:97
ArtworkInfo
Definition: metadataimagehelper.h:21
PlaybackBoxHelper::GetPreviewImage
QString GetPreviewImage(const ProgramInfo &pginfo, bool check_availability=true)
Definition: playbackboxhelper.cpp:463
LOC
#define LOC
Definition: playbackboxhelper.cpp:25
PlaybackBoxHelper::m_lock
QMutex m_lock
Definition: playbackboxhelper.h:57
PlaybackBoxHelper::DeleteRecordings
void DeleteRecordings(const QStringList &list)
Definition: playbackboxhelper.cpp:370
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
asZeroByte
@ asZeroByte
Definition: programtypes.h:182
PBHEventHandler::m_checkAvailabilityTimerId
int m_checkAvailabilityTimerId
Definition: playbackboxhelper.cpp:50
storagegroup.h
uint
unsigned int uint
Definition: compat.h:140
PlaybackBoxHelper::PlaybackBoxHelper
PlaybackBoxHelper(QObject *listener)
Definition: playbackboxhelper.cpp:326
PlaybackBoxHelper::~PlaybackBoxHelper
~PlaybackBoxHelper(void) override
Definition: playbackboxhelper.cpp:336
tvremoteutil.h
PlaybackBoxHelper::m_artworkCache
InfoMap m_artworkCache
Definition: playbackboxhelper.h:64
PBHEventHandler::m_pbh
PlaybackBoxHelper & m_pbh
Definition: playbackboxhelper.cpp:48
MythRandom
MBASE_PUBLIC uint32_t MythRandom()
Definition: mythmiscutil.h:21
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:371
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
PBHEventHandler::PBHEventHandler
PBHEventHandler(PlaybackBoxHelper &pbh)
Definition: playbackboxhelper.cpp:32
mythmiscutil.h
RecStatus::Recording
@ Recording
Definition: recStatus.h:30
ProgramInfo::ToStringList
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
Definition: programinfo.cpp:1281
mythcorecontext.h
ProgramInfo::IsFileReadable
bool IsFileReadable(void)
Attempts to ascertain if the main file for this ProgramInfo is readable.
Definition: programinfo.cpp:4875
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
PBHEventHandler
Definition: playbackboxhelper.cpp:29
PBHEventHandler::event
bool event(QEvent *) override
Definition: playbackboxhelper.cpp:137
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
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
PlaybackBoxHelper::UpdateFreeSpace
void UpdateFreeSpace(void)
Definition: playbackboxhelper.cpp:384
ArtworkMap
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
Definition: metadataimagehelper.h:31
PlaybackBoxHelper::StopRecording
void StopRecording(const ProgramInfo &pginfo)
Definition: playbackboxhelper.cpp:352
NUMPROGRAMLINES
#define NUMPROGRAMLINES
Definition: programinfo.h:28
PlaybackBoxHelper::LocateArtwork
QString LocateArtwork(const QString &inetref, uint season, VideoArtworkType type, const ProgramInfo *pginfo, const QString &groupname=nullptr)
Definition: playbackboxhelper.cpp:435
PBHEventHandler::m_checkAvailability
QHash< uint, QStringList > m_checkAvailability
Definition: playbackboxhelper.cpp:53
PlaybackBoxHelper::GetFreeSpaceUsedMB
uint64_t GetFreeSpaceUsedMB(void) const
Definition: playbackboxhelper.cpp:407
PBHEventHandler::CheckAvailability
AvailableStatusType CheckAvailability(const QStringList &slist)
Definition: playbackboxhelper.cpp:56
ProgramInfo::GetAvailableStatus
AvailableStatusType GetAvailableStatus(void) const
Definition: programinfo.h:827
RemoteDeleteRecording
bool RemoteDeleteRecording(uint recordingID, bool forceMetadataDelete, bool forgetHistory)
Definition: remoteutil.cpp:110
PlaybackBoxHelper::m_listener
QObject * m_listener
Definition: playbackboxhelper.h:55
asNotYetAvailable
@ asNotYetAvailable
Definition: programtypes.h:179
PlaybackBoxHelper::CheckAvailability
void CheckAvailability(const ProgramInfo &pginfo, CheckAvailabilityType cat=kCheckForCache)
Definition: playbackboxhelper.cpp:413
PlaybackBoxHelper::ForceFreeSpaceUpdate
void ForceFreeSpaceUpdate(void)
Definition: playbackboxhelper.cpp:346
ProgramInfo::HasPathname
bool HasPathname(void) const
Definition: programinfo.h:357
ArtworkInfo::url
QString url
Definition: metadataimagehelper.h:25
PBHEventHandler::m_freeSpaceTimerId
int m_freeSpaceTimerId
Definition: playbackboxhelper.cpp:49