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