MythTV  master
musicmetautils.cpp
Go to the documentation of this file.
1 // qt
2 #include <QDir>
3 #include <QProcess>
4 #include <QDomDocument>
5 
6 // libmyth* headers
7 #include "mythconfig.h"
8 #include "exitcodes.h"
9 #include "mythlogging.h"
10 #include "storagegroup.h"
11 #include "musicmetadata.h"
12 #include "metaio.h"
13 #include "mythcontext.h"
14 #include "musicfilescanner.h"
15 #include "musicutils.h"
16 #include "mythdirs.h"
17 
18 extern "C" {
19 #include <libavformat/avformat.h>
20 #include <libavcodec/avcodec.h>
21 }
22 
23 // mythutils headers
24 #include "commandlineparser.h"
25 #include "musicmetautils.h"
26 
28 {
29  bool ok = true;
30  int result = GENERIC_EXIT_OK;
31 
32  if (cmdline.toString("songid").isEmpty())
33  {
34  LOG(VB_GENERAL, LOG_ERR, "Missing --songid option");
36  }
37  int songID = cmdline.toInt("songid");
38 
40  if (!mdata)
41  {
42  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find metadata for trackid: %1").arg(songID));
43  return GENERIC_EXIT_NOT_OK;
44  }
45 
46  if (!cmdline.toString("title").isEmpty())
47  mdata->setTitle(cmdline.toString("title"));
48 
49  if (!cmdline.toString("artist").isEmpty())
50  mdata->setArtist(cmdline.toString("artist"));
51 
52  if (!cmdline.toString("album").isEmpty())
53  mdata->setAlbum(cmdline.toString("album"));
54 
55  if (!cmdline.toString("genre").isEmpty())
56  mdata->setGenre(cmdline.toString("genre"));
57 
58  if (!cmdline.toString("trackno").isEmpty())
59  mdata->setTrack(cmdline.toInt("trackno"));
60 
61  if (!cmdline.toString("year").isEmpty())
62  mdata->setYear(cmdline.toInt("year"));
63 
64  if (!cmdline.toString("rating").isEmpty())
65  mdata->setRating(cmdline.toInt("rating"));
66 
67  if (!cmdline.toString("playcount").isEmpty())
68  mdata->setPlaycount(cmdline.toInt("playcount"));
69 
70  if (!cmdline.toString("lastplayed").isEmpty())
71  mdata->setLastPlay(cmdline.toDateTime("lastplayed"));
72 
73  mdata->dumpToDatabase();
74 
75  MetaIO *tagger = mdata->getTagger();
76  if (tagger)
77  {
78  ok = tagger->write(mdata->getLocalFilename(), mdata);
79 
80  if (!ok)
81  LOG(VB_GENERAL, LOG_ERR, QString("Failed to write to tag for trackid: %1").arg(songID));
82  }
83 
84  // tell any clients that the metadata for this track has changed
85  gCoreContext->SendMessage(QString("MUSIC_METADATA_CHANGED %1").arg(songID));
86 
87  if (!ok)
88  result = GENERIC_EXIT_NOT_OK;
89 
90  return result;
91 }
92 
94 {
95  if (cmdline.toString("songid").isEmpty())
96  {
97  LOG(VB_GENERAL, LOG_ERR, "Missing --songid option");
99  }
100 
101  if (cmdline.toString("imagetype").isEmpty())
102  {
103  LOG(VB_GENERAL, LOG_ERR, "Missing --imagetype option");
105  }
106 
107  int songID = cmdline.toInt("songid");
108  ImageType type = (ImageType)cmdline.toInt("imagetype");
109 
111  if (!mdata)
112  {
113  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find metadata for trackid: %1").arg(songID));
114  return GENERIC_EXIT_NOT_OK;
115  }
116 
117  AlbumArtImage *image = mdata->getAlbumArtImages()->getImage(type);
118  if (!image)
119  {
120  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find image of type: %1").arg(type));
121  return GENERIC_EXIT_NOT_OK;
122  }
123 
124  MetaIO *tagger = mdata->getTagger();
125  if (!tagger)
126  {
127  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find a tagger for this file: %1").arg(mdata->Filename(false)));
128  return GENERIC_EXIT_NOT_OK;
129  }
130 
131 
132  if (!image->m_embedded || !tagger->supportsEmbeddedImages())
133  {
134  LOG(VB_GENERAL, LOG_ERR, QString("Either the image isn't embedded or the tagger doesn't support embedded images"));
135  return GENERIC_EXIT_NOT_OK;
136  }
137 
138  // find the tracks actual filename
139  StorageGroup musicGroup("Music", gCoreContext->GetHostName(), false);
140  QString trackFilename = musicGroup.FindFile(mdata->Filename(false));
141 
142  // where are we going to save the image
143  QString path;
144  StorageGroup artGroup("MusicArt", gCoreContext->GetHostName(), false);
145  QStringList dirList = artGroup.GetDirList();
146  if (!dirList.empty())
147  path = artGroup.FindNextDirMostFree();
148 
149  if (!QDir(path).exists())
150  {
151  LOG(VB_GENERAL, LOG_ERR, "Cannot find a directory in the 'MusicArt' storage group to save to");
152  return GENERIC_EXIT_NOT_OK;
153  }
154 
155  path += "/AlbumArt/";
156  QDir dir(path);
157 
158  QString filename = QString("%1-%2.jpg").arg(mdata->ID()).arg(AlbumArtImages::getTypeFilename(image->m_imageType));
159 
160  if (QFile::exists(path + filename))
161  QFile::remove(path + filename);
162 
163  if (!dir.exists())
164  dir.mkpath(path);
165 
166  QImage *saveImage = tagger->getAlbumArt(trackFilename, image->m_imageType);
167  if (saveImage)
168  {
169  saveImage->save(path + filename, "JPEG");
170  delete saveImage;
171  }
172 
173  delete tagger;
174 
175  // tell any clients that the albumart for this track has changed
176  gCoreContext->SendMessage(QString("MUSIC_ALBUMART_CHANGED %1 %2").arg(songID).arg(type));
177 
178  return GENERIC_EXIT_OK;
179 }
180 
182 {
183  auto *fscan = new MusicFileScanner(cmdline.toBool("musicforce"));
184  QStringList dirList;
185 
187  {
188  LOG(VB_GENERAL, LOG_ERR, "Failed to find any directories in the 'Music' storage group");
189  delete fscan;
190  return GENERIC_EXIT_NOT_OK;
191  }
192 
193  fscan->SearchDirs(dirList);
194  delete fscan;
195 
196  return GENERIC_EXIT_OK;
197 }
198 
199 static int UpdateRadioStreams(const MythUtilCommandLineParser &/*cmdline*/)
200 {
201  // check we have the correct Music Schema Version (maybe the FE hasn't been run yet)
202  if (gCoreContext->GetNumSetting("MusicDBSchemaVer", 0) < 1024)
203  {
204  LOG(VB_GENERAL, LOG_ERR, "Can't update the radio streams the DB schema hasn't been updated yet! Aborting");
205  return GENERIC_EXIT_NOT_OK;
206  }
207 
209  return GENERIC_EXIT_NOT_OK;
210 
211  return GENERIC_EXIT_OK;
212 }
213 
215 {
216  if (cmdline.toString("songid").isEmpty())
217  {
218  LOG(VB_GENERAL, LOG_ERR, "Missing --songid option");
220  }
221 
222  int songID = cmdline.toInt("songid");
223 
225  if (!mdata)
226  {
227  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find metadata for trackid: %1").arg(songID));
228  return GENERIC_EXIT_NOT_OK;
229  }
230 
231  QString musicFile = mdata->getLocalFilename();
232 
233  if (musicFile.isEmpty() || !QFile::exists(musicFile))
234  {
235  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find file for trackid: %1").arg(songID));
236  return GENERIC_EXIT_NOT_OK;
237  }
238 
239  AVFormatContext *inputFC = nullptr;
240  AVInputFormat *fmt = nullptr;
241 
242  // Open track
243  LOG(VB_GENERAL, LOG_DEBUG, QString("CalcTrackLength: Opening '%1'")
244  .arg(musicFile));
245 
246  QByteArray inFileBA = musicFile.toLocal8Bit();
247 
248  int ret = avformat_open_input(&inputFC, inFileBA.constData(), fmt, nullptr);
249 
250  if (ret)
251  {
252  LOG(VB_GENERAL, LOG_ERR, "CalcTrackLength: Couldn't open input file" +
253  ENO);
254  return GENERIC_EXIT_NOT_OK;
255  }
256 
257  // Getting stream information
258  ret = avformat_find_stream_info(inputFC, nullptr);
259 
260  if (ret < 0)
261  {
262  LOG(VB_GENERAL, LOG_ERR,
263  QString("CalcTrackLength: Couldn't get stream info, error #%1").arg(ret));
264  avformat_close_input(&inputFC);
265  inputFC = nullptr;
266  return GENERIC_EXIT_NOT_OK;;
267  }
268 
269  int duration = 0;
270  long long time = 0;
271 
272  for (uint i = 0; i < inputFC->nb_streams; i++)
273  {
274  AVStream *st = inputFC->streams[i];
275  char buf[256];
276 
277  const AVCodec *pCodec = avcodec_find_decoder(st->codecpar->codec_id);
278  if (!pCodec)
279  {
280  LOG(VB_GENERAL, LOG_WARNING,
281  QString("avcodec_find_decoder fail for %1").arg(st->codecpar->codec_id));
282  continue;
283  }
284  AVCodecContext *avctx = avcodec_alloc_context3(pCodec);
285  avcodec_parameters_to_context(avctx, st->codecpar);
286  avctx->pkt_timebase = st->time_base;
287 
288  avcodec_string(buf, sizeof(buf), avctx, static_cast<int>(false));
289 
290  switch (inputFC->streams[i]->codecpar->codec_type)
291  {
292  case AVMEDIA_TYPE_AUDIO:
293  {
294  AVPacket pkt;
295  av_init_packet(&pkt);
296 
297  while (av_read_frame(inputFC, &pkt) >= 0)
298  {
299  if (pkt.stream_index == (int)i)
300  time = time + pkt.duration;
301 
302  av_packet_unref(&pkt);
303  }
304 
305  duration = time * av_q2d(inputFC->streams[i]->time_base);
306  break;
307  }
308 
309  default:
310  LOG(VB_GENERAL, LOG_ERR,
311  QString("Skipping unsupported codec %1 on stream %2")
312  .arg(inputFC->streams[i]->codecpar->codec_type).arg(i));
313  break;
314  }
315  avcodec_free_context(&avctx);
316  }
317 
318  // Close input file
319  avformat_close_input(&inputFC);
320  inputFC = nullptr;
321 
322  if (mdata->Length() / 1000 != duration)
323  {
324  LOG(VB_GENERAL, LOG_INFO, QString("The length of this track in the database was %1s "
325  "it is now %2s").arg(mdata->Length() / 1000).arg(duration));
326 
327  // update the track length in the database
328  mdata->setLength(duration * 1000);
329  mdata->dumpToDatabase();
330 
331  // tell any clients that the metadata for this track has changed
332  gCoreContext->SendMessage(QString("MUSIC_METADATA_CHANGED %1").arg(songID));
333  }
334  else
335  {
336  LOG(VB_GENERAL, LOG_INFO, QString("The length of this track is unchanged %1s")
337  .arg(mdata->Length() / 1000));
338  }
339 
340  return GENERIC_EXIT_OK;
341 }
342 
344 {
345 public:
346  QString m_name;
347  QString m_filename;
348  int m_priority {99};
349 };
350 
352 {
353  // make sure our lyrics cache directory exists
354  QString lyricsDir = GetConfDir() + "/MythMusic/Lyrics/";
355  QDir dir(lyricsDir);
356  if (!dir.exists())
357  dir.mkpath(lyricsDir);
358 
359  if (cmdline.toString("songid").isEmpty())
360  {
361  LOG(VB_GENERAL, LOG_ERR, "Missing --songid option");
363  }
364 
365  int songID = cmdline.toInt("songid");
366  QString grabberName = "ALL";
367  QString lyricsFile;
368  QString artist;
369  QString album;
370  QString title;
371  QString filename;
372 
373  if (!cmdline.toString("grabber").isEmpty())
374  grabberName = cmdline.toString("grabber");
375 
376  if (ID_TO_REPO(songID) == RT_Database)
377  {
379  if (!mdata)
380  {
381  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find metadata for trackid: %1").arg(songID));
382  return GENERIC_EXIT_NOT_OK;
383  }
384 
385  QString musicFile = mdata->getLocalFilename();
386 
387  if (musicFile.isEmpty() || !QFile::exists(musicFile))
388  {
389  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find file for trackid: %1").arg(songID));
390  //return GENERIC_EXIT_NOT_OK;
391  }
392 
393  // first check if we have already saved a lyrics file for this track
394  lyricsFile = GetConfDir() + QString("/MythMusic/Lyrics/%1.txt").arg(songID);
395  if (QFile::exists(lyricsFile))
396  {
397  // if the user specified a specific grabber assume they want to
398  // re-search for the lyrics using the given grabber
399  if (grabberName != "ALL")
400  QFile::remove(lyricsFile);
401  else
402  {
403  // load these lyrics to speed up future lookups
404  QFile file(QLatin1String(qPrintable(lyricsFile)));
405  QString lyrics;
406 
407  if (file.open(QIODevice::ReadOnly))
408  {
409  QTextStream stream(&file);
410 
411  while (!stream.atEnd())
412  {
413  lyrics.append(stream.readLine());
414  }
415 
416  file.close();
417  }
418 
419  // tell any clients that a lyrics file is available for this track
420  gCoreContext->SendMessage(QString("MUSIC_LYRICS_FOUND %1 %2").arg(songID).arg(lyrics));
421 
422  return GENERIC_EXIT_OK;
423  }
424  }
425 
426  artist = mdata->Artist();
427  album = mdata->Album();
428  title = mdata->Title();
429  filename = mdata->getLocalFilename();
430  }
431  else
432  {
433  // must be a CD or Radio Track
434  if (cmdline.toString("artist").isEmpty())
435  {
436  LOG(VB_GENERAL, LOG_ERR, "Missing --artist option");
438  }
439  artist = cmdline.toString("artist");
440 
441  if (cmdline.toString("album").isEmpty())
442  {
443  LOG(VB_GENERAL, LOG_ERR, "Missing --album option");
445  }
446  album = cmdline.toString("album");
447 
448  if (cmdline.toString("title").isEmpty())
449  {
450  LOG(VB_GENERAL, LOG_ERR, "Missing --title option");
452  }
453  title = cmdline.toString("title");
454  }
455 
456  // not found so try the grabbers
457  // first get a list of available grabbers
458  QString scriptDir = GetShareDir() + "metadata/Music/lyrics";
459  QDir d(scriptDir);
460 
461  if (!d.exists())
462  {
463  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find lyric scripts directory: %1").arg(scriptDir));
464  gCoreContext->SendMessage(QString("MUSIC_LYRICS_ERROR NO_SCRIPTS_DIR"));
465  return GENERIC_EXIT_NOT_OK;
466  }
467 
468  d.setFilter(QDir::Files | QDir::NoDotAndDotDot);
469  d.setNameFilters(QStringList("*.py"));
470  QFileInfoList list = d.entryInfoList();
471  if (list.isEmpty())
472  {
473  LOG(VB_GENERAL, LOG_ERR, QString("Cannot find any lyric scripts in: %1").arg(scriptDir));
474  gCoreContext->SendMessage(QString("MUSIC_LYRICS_ERROR NO_SCRIPTS_FOUND"));
475  return GENERIC_EXIT_NOT_OK;
476  }
477 
478  QStringList scripts;
479  QFileInfoList::const_iterator it = list.begin();
480 
481  while (it != list.end())
482  {
483  const QFileInfo *fi = &(*it);
484  ++it;
485  LOG(VB_GENERAL, LOG_NOTICE, QString("Found lyric script at: %1").arg(fi->filePath()));
486  scripts.append(fi->filePath());
487  }
488 
489  QMap<int, LyricsGrabber> grabberMap;
490 
491  // query the grabbers to get their priority
492  for (int x = 0; x < scripts.count(); x++)
493  {
494  QStringList args { scripts.at(x), "-v" };
495  QProcess p;
496  p.start(PYTHON_EXE, args);
497  p.waitForFinished(-1);
498  QString result = p.readAllStandardOutput();
499 
500  QDomDocument domDoc;
501  QString errorMsg;
502  int errorLine = 0;
503  int errorColumn = 0;
504 
505  if (!domDoc.setContent(result, false, &errorMsg, &errorLine, &errorColumn))
506  {
507  LOG(VB_GENERAL, LOG_ERR,
508  QString("FindLyrics: Could not parse version from %1").arg(scripts.at(x)) +
509  QString("\n\t\t\tError at line: %1 column: %2 msg: %3").arg(errorLine).arg(errorColumn).arg(errorMsg));
510  continue;
511  }
512 
513  QDomNodeList itemList = domDoc.elementsByTagName("grabber");
514  QDomNode itemNode = itemList.item(0);
515 
516  LyricsGrabber grabber;
517  grabber.m_name = itemNode.namedItem(QString("name")).toElement().text();
518  grabber.m_priority = itemNode.namedItem(QString("priority")).toElement().text().toInt();
519  grabber.m_filename = scripts.at(x);
520 
521  grabberMap.insert(grabber.m_priority, grabber);
522  }
523 
524  // try each grabber in turn until we find a match
525  QMap<int, LyricsGrabber>::const_iterator i = grabberMap.constBegin();
526  while (i != grabberMap.constEnd())
527  {
528  LyricsGrabber grabber = i.value();
529 
530  ++i;
531 
532  if (grabberName != "ALL" && grabberName != grabber.m_name)
533  continue;
534 
535  LOG(VB_GENERAL, LOG_NOTICE, QString("Trying grabber: %1, Priority: %2").arg(grabber.m_name).arg(grabber.m_priority));
536  QString statusMessage = QObject::tr("Searching '%1' for lyrics...").arg(grabber.m_name);
537  gCoreContext->SendMessage(QString("MUSIC_LYRICS_STATUS %1 %2").arg(songID).arg(statusMessage));
538 
539  QProcess p;
540  QStringList args { grabber.m_filename,
541  QString(R"(--artist="%1")").arg(artist),
542  QString(R"(--album="%1")").arg(album),
543  QString(R"(--title="%1")").arg(title),
544  QString(R"(--filename="%1")").arg(filename) };
545  p.start(PYTHON_EXE, args);
546  p.waitForFinished(-1);
547  QString result = p.readAllStandardOutput();
548 
549  LOG(VB_GENERAL, LOG_DEBUG, QString("Grabber: %1, Exited with code: %2").arg(grabber.m_name).arg(p.exitCode()));
550 
551  if (p.exitCode() == 0)
552  {
553  LOG(VB_GENERAL, LOG_NOTICE, QString("Lyrics Found using: %1").arg(grabber.m_name));
554 
555  // save these lyrics to speed up future lookups if it is a DB track
556  if (ID_TO_REPO(songID) == RT_Database)
557  {
558  QFile file(QLatin1String(qPrintable(lyricsFile)));
559 
560  if (file.open(QIODevice::WriteOnly))
561  {
562  QTextStream stream(&file);
563  stream << result;
564  file.close();
565  }
566  }
567 
568  gCoreContext->SendMessage(QString("MUSIC_LYRICS_FOUND %1 %2").arg(songID).arg(result));
569  return GENERIC_EXIT_OK;
570  }
571  }
572 
573  // if we got here we didn't find any lyrics
574  gCoreContext->SendMessage(QString("MUSIC_LYRICS_NOTFOUND %1").arg(songID));
575 
576  return GENERIC_EXIT_OK;
577 }
578 
580 {
581  utilMap["updatemeta"] = &UpdateMeta;
582  utilMap["extractimage"] = &ExtractImage;
583  utilMap["scanmusic"] = &ScanMusic;
584  utilMap["updateradiostreams"] = &UpdateRadioStreams;
585  utilMap["calctracklen"] = &CalcTrackLength;
586  utilMap["findlyrics"] = &FindLyrics;
587 }
UpdateRadioStreams
static int UpdateRadioStreams(const MythUtilCommandLineParser &)
Definition: musicmetautils.cpp:199
commandlineparser.h
build_compdb.args
args
Definition: build_compdb.py:11
MusicMetadata::Title
QString Title() const
Definition: musicmetadata.h:162
UpdateMeta
static int UpdateMeta(const MythUtilCommandLineParser &cmdline)
Definition: musicmetautils.cpp:27
MythCoreContext::SendMessage
void SendMessage(const QString &message)
Definition: mythcorecontext.cpp:1526
MusicMetadata::Filename
QString Filename(bool find=true)
Definition: musicmetadata.cpp:973
AlbumArtImage::m_imageType
ImageType m_imageType
Definition: musicmetadata.h:51
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:72
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
MetaIO::getAlbumArt
virtual QImage * getAlbumArt(const QString &filename, ImageType type)
Definition: metaio.h:103
MusicMetadata::setLength
void setLength(int llength)
Definition: musicmetadata.h:206
MusicMetadata::getAlbumArtImages
AlbumArtImages * getAlbumArtImages(void)
Definition: musicmetadata.cpp:1372
MusicMetadata::createFromID
static MusicMetadata * createFromID(int trackid)
Definition: musicmetadata.cpp:264
MetaIO::write
virtual bool write(const QString &filename, MusicMetadata *mdata)=0
Writes all metadata back to a file.
title
QString title
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:633
StorageGroup::FindFile
QString FindFile(const QString &filename)
Definition: storagegroup.cpp:602
musicmetautils.h
d
static const uint16_t * d
Definition: iso6937tables.cpp:1025
MusicMetadata::setTrack
void setTrack(int ltrack)
Definition: musicmetadata.h:200
arg
arg(title).arg(filename).arg(doDelete))
MetaIO
Definition: metaio.h:18
MusicMetadata::ID
IdType ID() const
Definition: musicmetadata.h:217
MusicMetadata::setAlbum
void setAlbum(const QString &lalbum, const QString &lalbum_sort=nullptr)
Definition: musicmetadata.h:152
MusicMetadata::setRating
void setRating(int lrating)
Definition: musicmetadata.h:241
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MusicMetadata
Definition: musicmetadata.h:81
build_compdb.file
file
Definition: build_compdb.py:55
mythdirs.h
GENERIC_EXIT_INVALID_CMDLINE
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
MusicMetadata::getLocalFilename
QString getLocalFilename(void)
try to find the track on the local file system
Definition: musicmetadata.cpp:1034
MythUtilCommandLineParser
Definition: mythutil/commandlineparser.h:9
MusicMetadata::Artist
QString Artist() const
Definition: musicmetadata.h:126
RT_Database
@ RT_Database
Definition: musicmetadata.h:60
ScanMusic
static int ScanMusic(const MythUtilCommandLineParser &cmdline)
Definition: musicmetautils.cpp:181
musicutils.h
AlbumArtImages::getImage
AlbumArtImage * getImage(ImageType type)
Definition: musicmetadata.cpp:2120
musicfilescanner.h
MetaIO::supportsEmbeddedImages
virtual bool supportsEmbeddedImages(void)
Does the tag support embedded cover art.
Definition: metaio.h:60
mythlogging.h
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:224
StorageGroup::FindDirs
static bool FindDirs(const QString &group="Default", const QString &hostname="", QStringList *dirlist=nullptr)
Finds and and optionally initialize a directory list associated with a Storage Group.
Definition: storagegroup.cpp:537
hardwareprofile.config.p
p
Definition: config.py:33
MusicMetadata::setGenre
void setGenre(const QString &lgenre)
Definition: musicmetadata.h:176
GetShareDir
QString GetShareDir(void)
Definition: mythdirs.cpp:222
LyricsGrabber::m_priority
int m_priority
Definition: musicmetautils.cpp:348
MusicMetadata::setTitle
void setTitle(const QString &ltitle, const QString &ltitle_sort=nullptr)
Definition: musicmetadata.h:164
MusicMetadata::updateStreamList
static bool updateStreamList(void)
Definition: musicmetadata.cpp:325
ExtractImage
static int ExtractImage(const MythUtilCommandLineParser &cmdline)
Definition: musicmetautils.cpp:93
AlbumArtImages::getTypeFilename
static QString getTypeFilename(ImageType type)
Definition: musicmetadata.cpp:2178
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:634
storagegroup.h
StorageGroup::GetDirList
QStringList GetDirList(void) const
Definition: storagegroup.h:23
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MusicFileScanner
Definition: musicfilescanner.h:13
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:930
MusicMetadata::Album
QString Album() const
Definition: musicmetadata.h:150
LyricsGrabber::m_name
QString m_name
Definition: musicmetautils.cpp:346
cmdline
MythCommFlagCommandLineParser cmdline
Definition: mythtv/programs/mythcommflag/main.cpp:77
MusicMetadata::dumpToDatabase
void dumpToDatabase(void)
Definition: musicmetadata.cpp:678
FindLyrics
static int FindLyrics(const MythUtilCommandLineParser &cmdline)
Definition: musicmetautils.cpp:351
MusicMetadata::setArtist
void setArtist(const QString &lartist, const QString &lartist_sort=nullptr)
Definition: musicmetadata.h:128
UtilMap
QMap< QString, UtilFunc > UtilMap
Definition: mythutil.h:15
MythCommandLineParser::toString
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2100
GENERIC_EXIT_NOT_OK
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:1955
StorageGroup::FindNextDirMostFree
QString FindNextDirMostFree(void)
Definition: storagegroup.cpp:671
dir
QDir dir
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1171
metaio.h
AlbumArtImage
Definition: musicmetadata.h:40
mythcontext.h
dirList
QStringList dirList
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1169
StorageGroup
Definition: storagegroup.h:12
MusicMetadata::setPlaycount
void setPlaycount(int lplaycount)
Definition: musicmetadata.h:215
MusicMetadata::setLastPlay
void setLastPlay()
Definition: musicmetadata.cpp:1199
MusicMetadata::setYear
void setYear(int lyear)
Definition: musicmetadata.h:197
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:856
registerMusicUtils
void registerMusicUtils(UtilMap &utilMap)
Definition: musicmetautils.cpp:579
exitcodes.h
MythCommandLineParser::toInt
int toInt(const QString &key) const
Returns stored QVariant as an integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:1975
ID_TO_REPO
#define ID_TO_REPO(x)
Definition: musicmetadata.h:71
MusicMetadata::getTagger
MetaIO * getTagger(void)
Definition: musicmetadata.cpp:1396
MusicMetadata::Length
int Length() const
Definition: musicmetadata.h:205
MythCommandLineParser::toDateTime
QDateTime toDateTime(const QString &key) const
Returns stored QVariant as a QDateTime, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2192
ImageType
ImageType
Definition: musicmetadata.h:29
CalcTrackLength
static int CalcTrackLength(const MythUtilCommandLineParser &cmdline)
Definition: musicmetautils.cpp:214
musicmetadata.h
LyricsGrabber
Definition: musicmetautils.cpp:344
LyricsGrabber::m_filename
QString m_filename
Definition: musicmetautils.cpp:347
AlbumArtImage::m_embedded
bool m_embedded
Definition: musicmetadata.h:53