Audacity  3.0.3
Public Types | Public Member Functions | Static Public Member Functions | Private Attributes | Friends | List of all members
Tags Class Referencefinal

ID3 Tags (for MP3) More...

#include <Tags.h>

Inheritance diagram for Tags:
[legend]
Collaboration diagram for Tags:
[legend]

Public Types

using Iterators = IteratorRange< TagMap::const_iterator >
 

Public Member Functions

 Tags ()
 
 Tags (const Tags &)=default
 
virtual ~Tags ()
 
std::shared_ptr< TagsDuplicate () const
 
void Merge (const Tags &other)
 
Tagsoperator= (const Tags &src)
 
bool ShowEditDialog (wxWindow *parent, const TranslatableString &title, bool force=false)
 
bool HandleXMLTag (const wxChar *tag, const wxChar **attrs) override
 
XMLTagHandlerHandleXMLChild (const wxChar *tag) override
 
void WriteXML (XMLWriter &xmlFile) const
 
void AllowEditTitle (bool editTitle)
 
void AllowEditTrackNumber (bool editTrackNumber)
 
void LoadDefaultGenres ()
 
void LoadGenres ()
 
void LoadDefaults ()
 
int GetNumUserGenres ()
 
wxString GetUserGenre (int value)
 
wxString GetGenre (int value)
 
int GetGenre (const wxString &name)
 
bool HasTag (const wxString &name) const
 
wxString GetTag (const wxString &name) const
 
Iterators GetRange () const
 
void SetTag (const wxString &name, const wxString &value, const bool bSpecialTag=false)
 
void SetTag (const wxString &name, const int &value)
 
bool IsEmpty ()
 
void Clear ()
 
- Public Member Functions inherited from XMLTagHandler
 XMLTagHandler ()
 
virtual ~XMLTagHandler ()
 
virtual void HandleXMLEndTag (const wxChar *WXUNUSED(tag))
 
virtual void HandleXMLContent (const wxString &WXUNUSED(content))
 
bool ReadXMLTag (const char *tag, const char **attrs)
 
void ReadXMLEndTag (const char *tag)
 
void ReadXMLContent (const char *s, int len)
 
XMLTagHandlerReadXMLChild (const char *tag)
 
- Public Member Functions inherited from ClientData::Base
virtual ~Base ()
 

Static Public Member Functions

static TagsGet (AudacityProject &project)
 
static const TagsGet (const AudacityProject &project)
 
static TagsSet (AudacityProject &project, const std::shared_ptr< Tags > &tags)
 

Private Attributes

TagMap mXref
 
TagMap mMap
 
wxArrayString mGenres
 
bool mEditTitle
 
bool mEditTrackNumber
 

Friends

bool operator== (const Tags &lhs, const Tags &rhs)
 

Detailed Description

ID3 Tags (for MP3)

This class started as an ID3 tag

This class holds a few informational tags, such as Title, Author, etc. that can be associated with a project or other audio file. It is modeled after the ID3 format for MP3 files, and it can both import and export ID3 tags from/to MP2, MP3, and AIFF files.

It can present the user with a dialog for editing this information.

Use of this functionality requires that libid3tag be compiled in with Audacity.

Definition at line 70 of file Tags.h.

Member Typedef Documentation

◆ Iterators

using Tags::Iterators = IteratorRange<TagMap::const_iterator>

Definition at line 119 of file Tags.h.

Constructor & Destructor Documentation

◆ Tags() [1/2]

Tags::Tags ( )

Definition at line 253 of file Tags.cpp.

254 {
255  mEditTitle = true;
256  mEditTrackNumber = true;
257 
258  LoadDefaults();
259  LoadGenres();
260 }

References LoadDefaults(), LoadGenres(), mEditTitle, and mEditTrackNumber.

Here is the call graph for this function:

◆ Tags() [2/2]

Tags::Tags ( const Tags )
default

◆ ~Tags()

Tags::~Tags ( )
virtual

Definition at line 262 of file Tags.cpp.

263 {
264 }

Member Function Documentation

◆ AllowEditTitle()

void Tags::AllowEditTitle ( bool  editTitle)

Definition at line 377 of file Tags.cpp.

378 {
379  mEditTitle = editTitle;
380 }

References mEditTitle.

◆ AllowEditTrackNumber()

void Tags::AllowEditTrackNumber ( bool  editTrackNumber)

Definition at line 382 of file Tags.cpp.

383 {
384  mEditTrackNumber = editTrackNumber;
385 }

References mEditTrackNumber.

◆ Clear()

void Tags::Clear ( )

Definition at line 336 of file Tags.cpp.

337 {
338  mXref.clear();
339  mMap.clear();
340 }

References mMap, and mXref.

Referenced by FLACImportFileHandle::Import(), OggImportFileHandle::Import(), MP3ImportFileHandle::LoadID3(), TagsEditorDialog::OnClear(), and TagsEditorDialog::TransferDataFromWindow().

Here is the caller graph for this function:

◆ Duplicate()

std::shared_ptr< Tags > Tags::Duplicate ( ) const

Definition at line 266 of file Tags.cpp.

267 {
268  return std::make_shared<Tags>(*this);
269 }

◆ Get() [1/2]

Tags & Tags::Get ( AudacityProject project)
static

◆ Get() [2/2]

const Tags & Tags::Get ( const AudacityProject project)
static

Definition at line 241 of file Tags.cpp.

242 {
243  return Get( const_cast< AudacityProject & >( project ) );
244 }

References Get().

Here is the call graph for this function:

◆ GetGenre() [1/2]

int Tags::GetGenre ( const wxString &  name)

Definition at line 438 of file Tags.cpp.

439 {
440  int cnt = WXSIZEOF(DefaultGenres);
441 
442  for (int i = 0; i < cnt; i++) {
443  if (name.CmpNoCase(DefaultGenres[i])) {
444  return i;
445  }
446  }
447 
448  return 255;
449 }

References DefaultGenres, and name.

◆ GetGenre() [2/2]

wxString Tags::GetGenre ( int  value)

Definition at line 427 of file Tags.cpp.

428 {
429  int cnt = WXSIZEOF(DefaultGenres);
430 
431  if (i >= 0 && i < cnt) {
432  return DefaultGenres[i];
433  }
434 
435  return wxT("");
436 }

References DefaultGenres.

Referenced by PCMImportFileHandle::Import(), and MP3ImportFileHandle::LoadID3().

Here is the caller graph for this function:

◆ GetNumUserGenres()

int Tags::GetNumUserGenres ( )

Definition at line 387 of file Tags.cpp.

388 {
389  return mGenres.size();
390 }

References mGenres.

Referenced by GetUserGenre(), TagsEditorDialog::OnEdit(), TagsEditorDialog::OnReset(), and TagsEditorDialog::PopulateGenres().

Here is the caller graph for this function:

◆ GetRange()

Tags::Iterators Tags::GetRange ( ) const

Definition at line 480 of file Tags.cpp.

481 {
482  return { mMap.begin(), mMap.end() };
483 }

References mMap.

Referenced by ExportPCM::AddID3Chunk(), ExportMP3::AddTags(), ExportOGG::FillComment(), ExportCL::GetMetaChunk(), ExportFLAC::GetMetadata(), TagsEditorDialog::OnSaveDefaults(), and TagsEditorDialog::TransferDataToWindow().

Here is the caller graph for this function:

◆ GetTag()

wxString Tags::GetTag ( const wxString &  name) const

Definition at line 460 of file Tags.cpp.

461 {
462  wxString key = name;
463  key.UpperCase();
464 
465  auto iter = mXref.find(key);
466 
467  if (iter == mXref.end()) {
468  return wxEmptyString;
469  }
470 
471  auto iter2 = mMap.find(iter->second);
472  if (iter2 == mMap.end()) {
473  wxASSERT(false);
474  return wxEmptyString;
475  }
476  else
477  return iter2->second;
478 }

References key, mMap, mXref, and name.

Referenced by ExportPCM::AddStrings(), PCMImportFileHandle::Import(), MP3ImportFileHandle::LoadID3(), TagsEditorDialog::OnLoad(), TagsEditorDialog::OnSave(), TagsEditorDialog::OnSaveDefaults(), ExportFFmpeg::SetMetadata(), and TagsEditorDialog::TransferDataToWindow().

Here is the caller graph for this function:

◆ GetUserGenre()

wxString Tags::GetUserGenre ( int  value)

Definition at line 418 of file Tags.cpp.

419 {
420  if (i >= 0 && i < GetNumUserGenres()) {
421  return mGenres[i];
422  }
423 
424  return wxT("");
425 }

References GetNumUserGenres(), and mGenres.

Referenced by TagsEditorDialog::OnEdit(), TagsEditorDialog::OnReset(), and TagsEditorDialog::PopulateGenres().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HandleXMLChild()

XMLTagHandler * Tags::HandleXMLChild ( const wxChar *  tag)
overridevirtual

Implements XMLTagHandler.

Definition at line 586 of file Tags.cpp.

587 {
588  if (wxStrcmp(tag, wxT("tags")) == 0) {
589  return this;
590  }
591 
592  if (wxStrcmp(tag, wxT("tag")) == 0) {
593  return this;
594  }
595 
596  return NULL;
597 }

◆ HandleXMLTag()

bool Tags::HandleXMLTag ( const wxChar *  tag,
const wxChar **  attrs 
)
overridevirtual

Implements XMLTagHandler.

Definition at line 545 of file Tags.cpp.

546 {
547  if (wxStrcmp(tag, wxT("tags")) == 0) {
548  return true;
549  }
550 
551  if (wxStrcmp(tag, wxT("tag")) == 0) {
552  wxString n, v;
553 
554  while (*attrs) {
555  wxString attr = *attrs++;
556  if (attr.empty())
557  break;
558  wxString value = *attrs++;
559 
560  if (!XMLValueChecker::IsGoodString(attr) ||
562  break;
563  }
564 
565  if (attr == wxT("name")) {
566  n = value;
567  }
568  else if (attr == wxT("value")) {
569  v = value;
570  }
571  }
572 
573  if (n == wxT("id3v2")) {
574  // LLL: This is obsolete, but it must be handled and ignored.
575  }
576  else {
577  SetTag(n, v);
578  }
579 
580  return true;
581  }
582 
583  return false;
584 }

References XMLValueChecker::IsGoodLongString(), XMLValueChecker::IsGoodString(), and SetTag().

Here is the call graph for this function:

◆ HasTag()

bool Tags::HasTag ( const wxString &  name) const

Definition at line 451 of file Tags.cpp.

452 {
453  wxString key = name;
454  key.UpperCase();
455 
456  auto iter = mXref.find(key);
457  return (iter != mXref.end());
458 }

References key, mXref, and name.

Referenced by ExportPCM::AddStrings(), FLACImportFileHandle::Import(), OggImportFileHandle::Import(), PCMImportFileHandle::Import(), IsEmpty(), MP3ImportFileHandle::LoadID3(), and ExportFFmpeg::SetMetadata().

Here is the caller graph for this function:

◆ IsEmpty()

bool Tags::IsEmpty ( )

Definition at line 325 of file Tags.cpp.

326 {
327  // At least one of these should be filled in, otherwise
328  // it's assumed that the tags have not been set...
330  return false;
331  }
332 
333  return true;
334 }

References HasTag(), TAG_ALBUM, TAG_ARTIST, and TAG_TITLE.

Referenced by FFmpegImportFileHandle::WriteMetadata().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadDefaultGenres()

void Tags::LoadDefaultGenres ( )

Definition at line 392 of file Tags.cpp.

393 {
394  mGenres.clear();
395  for (size_t i = 0; i < WXSIZEOF(DefaultGenres); i++) {
396  mGenres.push_back(DefaultGenres[i]);
397  }
398 }

References DefaultGenres, and mGenres.

Referenced by LoadGenres(), and TagsEditorDialog::OnReset().

Here is the caller graph for this function:

◆ LoadDefaults()

void Tags::LoadDefaults ( )

Definition at line 294 of file Tags.cpp.

295 {
296  wxString path;
297  wxString name;
298  wxString value;
299  long ndx;
300  bool cont;
301 
302  // Set the parent group
303  path = gPrefs->GetPath();
304  gPrefs->SetPath(wxT("/Tags"));
305 
306  // Process all entries in the group
307  cont = gPrefs->GetFirstEntry(name, ndx);
308  while (cont) {
309  gPrefs->Read(name, &value, wxT(""));
310 
311  if (name == wxT("ID3V2")) {
312  // LLL: This is obsolute, but it must be handled and ignored.
313  }
314  else {
315  SetTag(name, value);
316  }
317 
318  cont = gPrefs->GetNextEntry(name, ndx);
319  }
320 
321  // Restore original group
322  gPrefs->SetPath(path);
323 }

References FileConfig::GetFirstEntry(), FileConfig::GetNextEntry(), FileConfig::GetPath(), gPrefs, name, FileConfig::SetPath(), and SetTag().

Referenced by Tags().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadGenres()

void Tags::LoadGenres ( )

Definition at line 400 of file Tags.cpp.

401 {
402  wxFileName fn(FileNames::DataDir(), wxT("genres.txt"));
403  wxTextFile tf(fn.GetFullPath());
404 
405  if (!tf.Exists() || !tf.Open()) {
407  return;
408  }
409 
410  mGenres.clear();
411 
412  int cnt = tf.GetLineCount();
413  for (int i = 0; i < cnt; i++) {
414  mGenres.push_back(tf.GetLine(i));
415  }
416 }

References FileNames::DataDir(), fn, LoadDefaultGenres(), and mGenres.

Referenced by TagsEditorDialog::OnEdit(), TagsEditorDialog::OnReset(), and Tags().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Merge()

void Tags::Merge ( const Tags other)

Definition at line 271 of file Tags.cpp.

272 {
273  for ( auto &pair : other.mMap ) {
274  SetTag( pair.first, pair.second );
275  }
276 }

References mMap, and SetTag().

Referenced by anonymous_namespace{ProjectFileManager.cpp}::ImportProject().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

Tags & Tags::operator= ( const Tags src)

Definition at line 278 of file Tags.cpp.

279 {
280  mEditTitle = src.mEditTitle;
282 
283  mXref.clear();
284  mXref = src.mXref;
285  mMap.clear();
286  mMap = src.mMap;
287 
288  mGenres.clear();
289  mGenres = src.mGenres;
290 
291  return *this;
292 }

References mEditTitle, mEditTrackNumber, mGenres, mMap, and mXref.

◆ Set()

Tags & Tags::Set ( AudacityProject project,
const std::shared_ptr< Tags > &  tags 
)
static

Definition at line 246 of file Tags.cpp.

247 {
248  auto &result = *tags;
249  project.AttachedObjects::Assign( key, tags );
250  return result;
251 }

References key.

Referenced by Exporter::DoEditMetadata(), ProjectFileManager::Import(), and ProjectHistory::PopState().

Here is the caller graph for this function:

◆ SetTag() [1/2]

void Tags::SetTag ( const wxString &  name,
const int &  value 
)

Definition at line 540 of file Tags.cpp.

541 {
542  SetTag(name, wxString::Format(wxT("%d"), value));
543 }

References name, and SetTag().

Here is the call graph for this function:

◆ SetTag() [2/2]

void Tags::SetTag ( const wxString &  name,
const wxString &  value,
const bool  bSpecialTag = false 
)

Definition at line 485 of file Tags.cpp.

486 {
487  // We don't like empty names
488  if (name.empty()) {
489  return;
490  }
491 
492  // Tag name must be ascii
493  if (!name.IsAscii()) {
494  wxLogError("Tag rejected (Non-ascii character in name)");
495  return;
496  }
497 
498  // All keys are uppercase
499  wxString key = name;
500  key.UpperCase();
501 
502  // Look it up
503  TagMap::iterator iter = mXref.find(key);
504 
505  // The special tags, if empty, should not exist.
506  // However it is allowable for a custom tag to be empty.
507  // See Bug 440 and Bug 1382
508  if (value.empty() && bSpecialTag) {
509  // Erase the tag
510  if (iter == mXref.end())
511  // nothing to do
512  ;
513  else {
514  mMap.erase(iter->second);
515  mXref.erase(iter);
516  }
517  }
518  else
519  {
520  if (iter == mXref.end()) {
521  // Didn't find the tag
522 
523  // Add a NEW tag
524  mXref[key] = name;
525  mMap[name] = value;
526  }
527  else if (iter->second != name) {
528  // Watch out for case differences!
529  mMap[name] = value;
530  mMap.erase(iter->second);
531  iter->second = name;
532  }
533  else {
534  // Update the value
535  mMap[iter->second] = value;
536  }
537  }
538 }

References key, mMap, mXref, and name.

Referenced by FFmpegImportFileHandle::GetMetadata(), AUPImportFileHandle::HandleTag(), AUPImportFileHandle::HandleTags(), HandleXMLTag(), FLACImportFileHandle::Import(), OggImportFileHandle::Import(), PCMImportFileHandle::Import(), LoadDefaults(), MP3ImportFileHandle::LoadID3(), Merge(), TagsEditorDialog::OnLoad(), TagsEditorDialog::OnSave(), TagsEditorDialog::OnSaveDefaults(), GStreamerImportFileHandle::OnTag(), SetTag(), and TagsEditorDialog::TransferDataFromWindow().

Here is the caller graph for this function:

◆ ShowEditDialog()

bool Tags::ShowEditDialog ( wxWindow *  parent,
const TranslatableString title,
bool  force = false 
)

Definition at line 616 of file Tags.cpp.

617 {
618  if (force) {
619  TagsEditorDialog dlg(parent, title, this, mEditTitle, mEditTrackNumber);
620 
621  return dlg.ShowModal() == wxID_OK;
622  }
623 
624  return true;
625 }

References mEditTitle, and mEditTrackNumber.

◆ WriteXML()

void Tags::WriteXML ( XMLWriter xmlFile) const

Definition at line 599 of file Tags.cpp.

601 {
602  xmlFile.StartTag(wxT("tags"));
603 
604  for (const auto &pair : GetRange()) {
605  const auto &n = pair.first;
606  const auto &v = pair.second;
607  xmlFile.StartTag(wxT("tag"));
608  xmlFile.WriteAttr(wxT("name"), n);
609  xmlFile.WriteAttr(wxT("value"), v);
610  xmlFile.EndTag(wxT("tag"));
611  }
612 
613  xmlFile.EndTag(wxT("tags"));
614 }

Referenced by TagsEditorDialog::OnSave().

Here is the caller graph for this function:

Friends And Related Function Documentation

◆ operator==

bool operator== ( const Tags lhs,
const Tags rhs 
)
friend

Definition at line 360 of file Tags.cpp.

361 {
362  if (!EqualMaps(lhs.mXref, rhs.mXref))
363  return false;
364 
365  if (!EqualMaps(lhs.mMap, rhs.mMap))
366  return false;
367 
368  return
369  lhs.mGenres == rhs.mGenres
370  &&
371  lhs.mEditTitle == rhs.mEditTitle
372  &&
374  ;
375 }

Member Data Documentation

◆ mEditTitle

bool Tags::mEditTitle
private

Definition at line 136 of file Tags.h.

Referenced by AllowEditTitle(), operator=(), operator==(), ShowEditDialog(), and Tags().

◆ mEditTrackNumber

bool Tags::mEditTrackNumber
private

Definition at line 137 of file Tags.h.

Referenced by AllowEditTrackNumber(), operator=(), operator==(), ShowEditDialog(), and Tags().

◆ mGenres

wxArrayString Tags::mGenres
private

◆ mMap

TagMap Tags::mMap
private

Definition at line 132 of file Tags.h.

Referenced by Clear(), GetRange(), GetTag(), Merge(), operator=(), operator==(), and SetTag().

◆ mXref

TagMap Tags::mXref
private

Definition at line 131 of file Tags.h.

Referenced by Clear(), GetTag(), HasTag(), operator=(), operator==(), and SetTag().


The documentation for this class was generated from the following files:
XMLWriter::EndTag
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:100
FileConfig::SetPath
virtual void SetPath(const wxString &strPath) wxOVERRIDE
Definition: FileConfig.cpp:103
key
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: Tags.cpp:232
Tags::LoadDefaultGenres
void LoadDefaultGenres()
Definition: Tags.cpp:392
Tags::mEditTrackNumber
bool mEditTrackNumber
Definition: Tags.h:137
fn
static const auto fn
Definition: WaveformView.cpp:1102
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:68
Tags::HasTag
bool HasTag(const wxString &name) const
Definition: Tags.cpp:451
Tags
ID3 Tags (for MP3)
Definition: Tags.h:74
Tags::GetRange
Iterators GetRange() const
Definition: Tags.cpp:480
FileNames::DataDir
AUDACITY_DLL_API FilePath DataDir()
Audacity user data directory.
Tags::LoadGenres
void LoadGenres()
Definition: Tags.cpp:400
Tags::mXref
TagMap mXref
Definition: Tags.h:131
FileConfig::GetFirstEntry
virtual bool GetFirstEntry(wxString &str, long &lIndex) const wxOVERRIDE
Definition: FileConfig.cpp:123
XMLValueChecker::IsGoodString
static bool IsGoodString(const wxString &str)
Definition: XMLTagHandler.cpp:39
FileConfig::GetNextEntry
virtual bool GetNextEntry(wxString &str, long &lIndex) const wxOVERRIDE
Definition: FileConfig.cpp:128
Tags::Get
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:236
Tags::mEditTitle
bool mEditTitle
Definition: Tags.h:136
DefaultGenres
static const wxChar * DefaultGenres[]
Definition: Tags.cpp:72
Tags::SetTag
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:485
anonymous_namespace{Tags.cpp}::EqualMaps
bool EqualMaps(const TagMap &map1, const TagMap &map2)
Definition: Tags.cpp:343
Tags::mGenres
wxArrayString mGenres
Definition: Tags.h:134
Tags::mMap
TagMap mMap
Definition: Tags.h:132
TagsEditorDialog
Derived from ExpandingToolBar, this dialog allows editing of Tags.
Definition: Tags.h:144
Tags::GetNumUserGenres
int GetNumUserGenres()
Definition: Tags.cpp:387
XMLValueChecker::IsGoodLongString
static bool IsGoodLongString(const wxString &str)
Definition: XMLTagHandler.cpp:52
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:112
Tags::LoadDefaults
void LoadDefaults()
Definition: Tags.cpp:294
XMLWriter::WriteAttr
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:34
TAG_ARTIST
#define TAG_ARTIST
Definition: Tags.h:61
name
wxString name
Definition: Tags.cpp:756
XMLWriter::StartTag
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:77
TAG_TITLE
#define TAG_TITLE
Definition: Tags.h:60
FileConfig::GetPath
virtual const wxString & GetPath() const wxOVERRIDE
Definition: FileConfig.cpp:108
TAG_ALBUM
#define TAG_ALBUM
Definition: Tags.h:62