1 /********************************************************************** 2 3 Audacity: A Digital Audio Editor 4 5 Tags.h 6 7 Dominic Mazzoni 8 9 This class holds a few informational tags, such as Title, Author, 10 etc. that can be associated with a project or other audio file. 11 It is modeled after the ID3 format for MP3 files, and it can 12 both import ID3 tags from MP3 files, and export them as well. 13 14 It can present the user with a dialog for editing this information. 15 16 It only keeps track of the fields that are standard in ID3v1 17 (title, author, artist, track num, year, genre, and comments), 18 but it can export both ID3v1 or the newer ID3v2 format. The primary 19 reason you would want to export ID3v2 tags instead of ID3v1, 20 since we're not supporting any v2 fields, is that ID3v2 tags are 21 inserted at the BEGINNING of an mp3 file, which is far more 22 useful for streaming. 23 24 Use of this functionality requires that libid3tag be compiled in 25 with Audacity. 26 27 **********************************************************************/ 28 29 #ifndef __AUDACITY_TAGS__ 30 #define __AUDACITY_TAGS__ 31 32 33 34 #include "XMLTagHandler.h" 35 36 #include "ClientData.h" 37 #include <utility> 38 39 #include "widgets/wxPanelWrapper.h" // to inherit 40 41 #include <memory> 42 #include <unordered_map> 43 #include "Identifier.h" 44 45 class wxArrayString; 46 class wxComboBox; 47 class wxGridCellChoiceEditor; 48 class wxGridCellStringRenderer; 49 class wxGridEvent; 50 class wxTextCtrl; 51 52 class AudacityProject; 53 class Grid; 54 class ShuttleGui; 55 class TagsEditorDialog; 56 class ComboEditor; 57 58 using TagMap = std::unordered_map< wxString, wxString >; 59 60 #define TAG_TITLE wxT("TITLE") 61 #define TAG_ARTIST wxT("ARTIST") 62 #define TAG_ALBUM wxT("ALBUM") 63 #define TAG_TRACK wxT("TRACKNUMBER") 64 #define TAG_YEAR wxT("YEAR") 65 #define TAG_GENRE wxT("GENRE") 66 #define TAG_COMMENTS wxT("COMMENTS") 67 #define TAG_SOFTWARE wxT("Software") 68 #define TAG_COPYRIGHT wxT("Copyright") 69 70 class AUDACITY_DLL_API Tags final 71 : public XMLTagHandler 72 , public std::enable_shared_from_this< Tags > 73 , public ClientData::Base 74 { 75 76 public: 77 78 static Tags &Get( AudacityProject &project ); 79 static const Tags &Get( const AudacityProject &project ); 80 // Returns reference to *tags 81 static Tags &Set( 82 AudacityProject &project, const std::shared_ptr<Tags> &tags ); 83 84 Tags(); // constructor 85 Tags( const Tags& ) = default; 86 //Tags( Tags && ) = default; 87 virtual ~Tags(); 88 89 std::shared_ptr<Tags> Duplicate() const; 90 91 void Merge( const Tags &other ); 92 93 Tags & operator= (const Tags & src ); 94 95 bool ShowEditDialog( 96 wxWindow *parent, const TranslatableString &title, bool force = false); 97 98 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override; 99 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override; 100 void WriteXML(XMLWriter &xmlFile) const /* not override */; 101 102 void AllowEditTitle(bool editTitle); 103 void AllowEditTrackNumber(bool editTrackNumber); 104 105 void LoadDefaultGenres(); 106 void LoadGenres(); 107 108 void LoadDefaults(); 109 110 int GetNumUserGenres(); 111 wxString GetUserGenre(int value); 112 113 wxString GetGenre(int value); 114 int GetGenre(const wxString & name); 115 116 bool HasTag(const wxString & name) const; 117 wxString GetTag(const wxString & name) const; 118 119 using Iterators = IteratorRange<TagMap::const_iterator>; 120 Iterators GetRange() const; 121 122 void SetTag(const wxString & name, const wxString & value, const bool bSpecialTag=false); 123 void SetTag(const wxString & name, const int & value); 124 125 bool IsEmpty(); 126 void Clear(); 127 128 friend bool operator == (const Tags &lhs, const Tags &rhs); 129 130 private: 131 TagMap mXref; 132 TagMap mMap; 133 134 wxArrayString mGenres; 135 136 bool mEditTitle; 137 bool mEditTrackNumber; 138 }; 139 140 inline bool operator != (const Tags &lhs, const Tags &rhs) 141 { return !(lhs == rhs); } 142 143 class TagsEditorDialog final : public wxDialogWrapper 144 { 145 public: 146 // constructors and destructors 147 TagsEditorDialog(wxWindow * parent, 148 const TranslatableString &title, 149 Tags * tags, 150 bool editTitle, 151 bool editTrack); 152 153 virtual ~TagsEditorDialog(); 154 155 #if !defined(__WXMSW__) IsEscapeKey(const wxKeyEvent &)156 bool IsEscapeKey(const wxKeyEvent& /*event*/) override { return false; } 157 #endif 158 159 void PopulateOrExchange(ShuttleGui & S); 160 161 void OnDontShow( wxCommandEvent & Evt); 162 void OnHelp(wxCommandEvent & Evt); 163 bool TransferDataToWindow() override; 164 bool TransferDataFromWindow() override; 165 166 private: 167 void PopulateGenres(); 168 void SetEditors(); 169 170 void OnChange(wxGridEvent & event); 171 172 void OnEdit(wxCommandEvent & event); 173 void OnReset(wxCommandEvent & event); 174 175 void OnClear(wxCommandEvent & event); 176 177 void OnLoad(wxCommandEvent & event); 178 void OnSave(wxCommandEvent & event); 179 void OnSaveDefaults(wxCommandEvent & event); 180 181 void OnAdd(wxCommandEvent & event); 182 void OnRemove(wxCommandEvent & event); 183 184 void OnOk(wxCommandEvent & event); 185 void DoCancel(bool escKey); 186 void OnCancel(wxCommandEvent & event); 187 188 void OnKeyDown(wxKeyEvent &event); 189 190 bool IsWindowRectValid(const wxRect *windowRect) const; 191 192 private: 193 Tags *mTags; 194 bool mEditTitle; 195 bool mEditTrack; 196 197 Tags mLocal; 198 199 Grid *mGrid; 200 ComboEditor *mComboEditor; 201 wxGridCellStringRenderer *mStringRenderer; 202 203 DECLARE_EVENT_TABLE() 204 }; 205 206 #endif 207