MythTV  master
metaio.cpp
Go to the documentation of this file.
1 
2 // POSIX C headers
3 #include <utime.h>
4 
5 // Qt
6 #include <QFileInfo>
7 
8 // libmythmetadata
9 #include "metaio.h"
10 #include "musicmetadata.h"
11 #include "metaioid3.h"
12 #include "metaiooggvorbis.h"
13 #include "metaioflacvorbis.h"
14 #include "metaiomp4.h"
15 #include "metaiowavpack.h"
16 #include "metaioavfcomment.h"
17 
18 // Libmyth
19 #include "libmyth/mythcontext.h"
20 
21 const QString MetaIO::kValidFileExtensions(".mp3|.mp2|.ogg|.oga|.flac|.wma|.wav|.ac3|.oma|.omg|"
22  ".atp|.ra|.dts|.aac|.m4a|.aa3|.tta|.mka|.aiff|.swa|.wv");
23 
24 // static
26 {
27  QFileInfo fi(filename);
28  QString extension = fi.suffix().toLower();
29 
30  if (extension.isEmpty() || !MetaIO::kValidFileExtensions.contains(extension))
31  {
32  LOG(VB_FILE, LOG_WARNING, QString("MetaIO: unknown extension: '%1'").arg(extension));
33  return nullptr;
34  }
35 
36  if (extension == "mp3" || extension == "mp2")
37  return new MetaIOID3;
38  if (extension == "ogg" || extension == "oga")
39  return new MetaIOOggVorbis;
40  if (extension == "flac")
41  {
42  auto *tagger = new MetaIOFLACVorbis;
43  if (tagger->TagExists(filename))
44  return tagger;
45  delete tagger;
46  return new MetaIOID3;
47  }
48  if (extension == "m4a")
49  return new MetaIOMP4;
50  if (extension == "wv")
51  return new MetaIOWavPack;
52  return new MetaIOAVFComment;
53 }
54 
55 // static
57 {
58  MusicMetadata *mdata = nullptr;
60  bool ignoreID3 = (gCoreContext->GetNumSetting("Ignore_ID3", 0) == 1);
61 
62  if (tagger)
63  {
64  if (!ignoreID3)
65  mdata = tagger->read(filename);
66 
67  if (ignoreID3 || !mdata)
68  mdata = tagger->readFromFilename(filename);
69 
70  delete tagger;
71  }
72 
73  if (!mdata)
74  {
75  LOG(VB_GENERAL, LOG_ERR,
76  QString("MetaIO::readMetadata(): Could not read '%1'")
77  .arg(filename));
78  }
79 
80  return mdata;
81 }
82 
83 // static
85 {
86  //FIXME: we need a relative path for createFromFilename()
87  // but readMetadata() needs an absolute path
89  if (mdata)
90  return mdata;
91 
92  return readMetadata(filename);
93 }
94 
95 void MetaIO::readFromFilename(const QString &filename,
96  QString &artist, QString &album, QString &title,
97  QString &genre, int &tracknum)
98 {
99  QString lfilename = filename;
100  // Clear
101  artist.clear();
102  album.clear();
103  title.clear();
104  genre.clear();
105  tracknum = 0;
106 
107  int part_num = 0;
108  // Replace
109  lfilename.replace('_', ' ');
110  lfilename = lfilename.section('.', 0, -2);
111  QStringList fmt_list = m_filenameFormat.split("/");
112  QStringList::iterator fmt_it = fmt_list.begin();
113 
114  // go through loop once to get minimum part number
115  for (; fmt_it != fmt_list.end(); ++fmt_it, --part_num) {}
116 
117  // reset to go through loop for real
118  fmt_it = fmt_list.begin();
119  for(; fmt_it != fmt_list.end(); ++fmt_it, ++part_num)
120  {
121  QString part_str = lfilename.section( "/", part_num, part_num);
122 
123  if ( *fmt_it == "GENRE" )
124  genre = part_str;
125  else if ( *fmt_it == "ARTIST" )
126  artist = part_str;
127  else if ( *fmt_it == "ALBUM" )
128  album = part_str;
129  else if ( *fmt_it == "TITLE" )
130  title = part_str;
131  else if ( *fmt_it == "TRACK_TITLE" )
132  {
133  QStringList tracktitle_list = part_str.split("-");
134  if (tracktitle_list.size() > 1)
135  {
136  tracknum = tracktitle_list[0].toInt();
137  title = tracktitle_list[1].simplified();
138  }
139  else
140  title = part_str;
141  }
142  else if ( *fmt_it == "ARTIST_TITLE" )
143  {
144  QStringList artisttitle_list = part_str.split("-");
145  if (artisttitle_list.size() > 1)
146  {
147  artist = artisttitle_list[0].simplified();
148  title = artisttitle_list[1].simplified();
149  }
150  else
151  {
152  if (title.isEmpty())
153  title = part_str;
154  if (artist.isEmpty())
155  artist = part_str;
156  }
157  }
158  }
159 }
160 
161 MusicMetadata* MetaIO::readFromFilename(const QString &filename, bool blnLength)
162 {
163  QString artist;
164  QString album;
165  QString title;
166  QString genre;
167  int tracknum = 0;
168 
169  readFromFilename(filename, artist, album, title, genre, tracknum);
170 
171  std::chrono::milliseconds length = (blnLength) ? getTrackLength(filename) : 0ms;
172 
173  auto *retdata = new MusicMetadata(filename, artist, "", album, title, genre,
174  0, tracknum, length);
175 
176  return retdata;
177 }
178 
185 {
186  QString artist;
187  QString album;
188  QString title;
189  QString genre;
190  int tracknum = 0;
191 
192  const QString filename = metadata->Filename(false);
193 
194  if (filename.isEmpty())
195  return;
196 
197  readFromFilename(filename, artist, album, title, genre, tracknum);
198 
199  if (metadata->Artist().isEmpty())
200  metadata->setArtist(artist);
201 
202  if (metadata->Album().isEmpty())
203  metadata->setAlbum(album);
204 
205  if (metadata->Title().isEmpty())
206  metadata->setTitle(title);
207 
208  if (metadata->Genre().isEmpty())
209  metadata->setGenre(genre);
210 
211  if (metadata->Track() <= 0)
212  metadata->setTrack(tracknum);
213 }
214 
216 {
217  if (stat(m_filename.toLocal8Bit().constData(), &m_fileinfo) == -1)
218  {
219  LOG(VB_GENERAL, LOG_ERR,
220  QString("MetaIO::saveTimeStamps: failed to stat file: %1").arg(m_filename) + ENO);
221  }
222 }
223 
225 {
226  struct utimbuf new_times {m_fileinfo.st_atime, m_fileinfo.st_mtime};
227 
228  if (utime(m_filename.toLocal8Bit().constData(), &new_times) < 0)
229  {
230  LOG(VB_GENERAL, LOG_ERR,
231  QString("MetaIO::restoreTimeStamps: failed to utime file: %1").arg(m_filename) + ENO);
232  }
233 }
MusicMetadata::Title
QString Title() const
Definition: musicmetadata.h:162
MusicMetadata::Filename
QString Filename(bool find=true)
Definition: musicmetadata.cpp:962
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
MusicMetadata::Genre
QString Genre() const
Definition: musicmetadata.h:175
MetaIO::createTagger
static MetaIO * createTagger(const QString &filename)
Finds an appropriate tagger for the given file.
Definition: metaio.cpp:25
MusicMetadata::setTrack
void setTrack(int ltrack)
Definition: musicmetadata.h:200
MetaIO
Definition: metaio.h:17
MusicMetadata::setAlbum
void setAlbum(const QString &lalbum, const QString &lalbum_sort=nullptr)
Definition: musicmetadata.h:152
MusicMetadata::Track
int Track() const
Definition: musicmetadata.h:199
MetaIO::m_filename
QString m_filename
Definition: metaio.h:169
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MusicMetadata
Definition: musicmetadata.h:80
metaioflacvorbis.h
MusicMetadata::Artist
QString Artist() const
Definition: musicmetadata.h:126
MetaIOAVFComment
Attempt to read metadata in files without a specific metadata reading implementation.
Definition: metaioavfcomment.h:19
MetaIO::readFromFilename
void readFromFilename(const QString &filename, QString &artist, QString &album, QString &title, QString &genre, int &tracknum)
Reads MusicMetadata based on the folder/filename.
Definition: metaio.cpp:95
MetaIO::restoreTimeStamps
void restoreTimeStamps(void)
Definition: metaio.cpp:224
MetaIO::m_fileinfo
Definition: metaio.h:172
MusicMetadata::setGenre
void setGenre(const QString &lgenre)
Definition: musicmetadata.h:176
MusicMetadata::setTitle
void setTitle(const QString &ltitle, const QString &ltitle_sort=nullptr)
Definition: musicmetadata.h:164
MetaIOOggVorbis
Read and write Vorbis (Xiph) tags in an Ogg container.
Definition: metaiooggvorbis.h:21
metaioavfcomment.h
metaiowavpack.h
MetaIO::getTrackLength
virtual std::chrono::milliseconds getTrackLength(const QString &filename)=0
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:912
MusicMetadata::Album
QString Album() const
Definition: musicmetadata.h:150
MusicMetadata::setArtist
void setArtist(const QString &lartist, const QString &lartist_sort=nullptr)
Definition: musicmetadata.h:128
metaio.h
MetaIOFLACVorbis
Read and write Vorbis (Xiph) tags in a FLAC file.
Definition: metaioflacvorbis.h:21
mythcontext.h
MetaIOMP4
Read and write metadata in MP4 container tags.
Definition: metaiomp4.h:16
metaioid3.h
metaiomp4.h
MetaIO::read
virtual MusicMetadata * read(const QString &filename)=0
Reads MusicMetadata from a file.
MetaIO::getMetadata
static MusicMetadata * getMetadata(const QString &filename)
Get the metadata for filename.
Definition: metaio.cpp:84
MusicMetadata::createFromFilename
static MusicMetadata * createFromFilename(const QString &filename)
Definition: musicmetadata.cpp:219
build_compdb.filename
filename
Definition: build_compdb.py:21
MetaIOID3
Read and write metadata in MPEG (mp3) ID3V2 tags.
Definition: metaioid3.h:38
MetaIO::kValidFileExtensions
static const QString kValidFileExtensions
Definition: metaio.h:161
MetaIO::readMetadata
static MusicMetadata * readMetadata(const QString &filename)
Read the metadata from filename directly.
Definition: metaio.cpp:56
MetaIO::m_filenameFormat
QString m_filenameFormat
Definition: metaio.h:170
musicmetadata.h
metaiooggvorbis.h
MetaIO::saveTimeStamps
void saveTimeStamps(void)
Definition: metaio.cpp:215
MetaIOWavPack
Read and write metadata in Wavpack APE tags.
Definition: metaiowavpack.h:23