File indexing completed on 2024-05-26 04:57:59
0001 /** 0002 * \file frame.h 0003 * Generalized frame. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 25 Aug 2007 0008 * 0009 * Copyright (C) 2007-2024 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #pragma once 0028 0029 #include <QString> 0030 #include <QVariant> 0031 #include <QList> 0032 #include <QSet> 0033 #include <QHash> 0034 #include <set> 0035 #include "formatreplacer.h" 0036 #include "framenotice.h" 0037 #include "kid3api.h" 0038 0039 /** Generalized frame. */ 0040 class KID3_CORE_EXPORT Frame { 0041 Q_GADGET 0042 Q_ENUMS(Type) 0043 Q_ENUMS(FieldId) 0044 Q_ENUMS(TextEncoding) 0045 Q_ENUMS(PictureType) 0046 Q_ENUMS(TagVersion) 0047 Q_ENUMS(TagNumber) 0048 public: 0049 /** Generalized frame types. */ 0050 enum Type { 0051 FT_Title, 0052 FT_FirstFrame = FT_Title, 0053 FT_Artist, 0054 FT_Album, 0055 FT_Comment, 0056 FT_Date, 0057 FT_Track, 0058 FT_Genre, 0059 FT_LastV1Frame = FT_Genre, 0060 FT_AlbumArtist, 0061 FT_Arranger, 0062 FT_Author, 0063 FT_Bpm, 0064 FT_CatalogNumber, 0065 FT_Compilation, 0066 FT_Composer, 0067 FT_Conductor, 0068 FT_Copyright, 0069 FT_Disc, 0070 FT_EncodedBy, 0071 FT_EncoderSettings, 0072 FT_EncodingTime, 0073 FT_Grouping, 0074 FT_InitialKey, 0075 FT_Isrc, 0076 FT_Language, 0077 FT_Lyricist, 0078 FT_Lyrics, 0079 FT_Media, 0080 FT_Mood, 0081 FT_OriginalAlbum, 0082 FT_OriginalArtist, 0083 FT_OriginalDate, 0084 FT_Description, 0085 FT_Performer, 0086 FT_Picture, 0087 FT_Publisher, 0088 FT_ReleaseCountry, 0089 FT_Remixer, 0090 FT_SortAlbum, 0091 FT_SortAlbumArtist, 0092 FT_SortArtist, 0093 FT_SortComposer, 0094 FT_SortName, 0095 FT_Subtitle, 0096 FT_Website, 0097 FT_WWWAudioFile, 0098 FT_WWWAudioSource, 0099 FT_ReleaseDate, 0100 FT_Rating, 0101 FT_Work, 0102 FT_Custom1, 0103 FT_Custom2, 0104 FT_Custom3, 0105 FT_Custom4, 0106 FT_Custom5, 0107 FT_Custom6, 0108 FT_Custom7, 0109 FT_Custom8, 0110 FT_LastFrame = FT_Custom8, 0111 FT_Other, 0112 FT_UnknownFrame 0113 }; 0114 0115 /** Maximum number of custom frame names. */ 0116 static const int NUM_CUSTOM_FRAME_NAMES = FT_LastFrame - FT_Custom1 + 1; 0117 0118 /** 0119 * Check if a frame type is a custom frame. 0120 * @param type frame type 0121 * @return true if @a type is a custom frame type. 0122 */ 0123 static constexpr bool isCustomFrameType(Type type) { 0124 return type >= FT_Custom1 && type <= FT_LastFrame; 0125 } 0126 0127 /** 0128 * Check if a frame type is a custom frame or FT_Other 0129 * @param type frame type 0130 * @return true if @a type is a custom frame type or FT_Other. 0131 */ 0132 static constexpr bool isCustomFrameTypeOrOther(Type type) { 0133 return type >= FT_Custom1 && type <= FT_Other; 0134 } 0135 0136 /** 0137 * Types of fields in a frame, must be the same as id3lib's ID3_FieldID. 0138 **/ 0139 enum FieldId { 0140 ID_NoField, 0141 ID_TextEnc, 0142 ID_Text, 0143 ID_Url, 0144 ID_Data, 0145 ID_Description, 0146 ID_Owner, 0147 ID_Email, 0148 ID_Rating, 0149 ID_Filename, 0150 ID_Language, 0151 ID_PictureType, 0152 ID_ImageFormat, 0153 ID_MimeType, 0154 ID_Counter, 0155 ID_Id, 0156 ID_VolumeAdj, 0157 ID_NumBits, 0158 ID_VolChgRight, 0159 ID_VolChgLeft, 0160 ID_PeakVolRight, 0161 ID_PeakVolLeft, 0162 ID_TimestampFormat, 0163 ID_ContentType, 0164 0165 // These are additional fields used by TagLib 0166 ID_Price, 0167 ID_Date, 0168 ID_Seller, 0169 0170 // Additional field for METADATA_BLOCK_PICTURE 0171 ID_ImageProperties, 0172 0173 // Type of subframe in CTOC and CHAP frames 0174 ID_Subframe 0175 }; 0176 0177 /** Text encoding for fields of type ID_TextEnc. */ 0178 enum TextEncoding { 0179 TE_ISO8859_1 = 0, 0180 TE_UTF16 = 1, 0181 TE_UTF16BE = 2, 0182 TE_UTF8 = 3 0183 }; 0184 0185 /** Picture type, compatible with ID3v2 and FLAC. */ 0186 enum PictureType { 0187 PT_Other = 0, 0188 PT_Png32Icon = 1, 0189 PT_OtherIcon = 2, 0190 PT_CoverFront = 3, 0191 PT_CoverBack = 4, 0192 PT_LeafletPage = 5, 0193 PT_Media = 6, 0194 PT_LeadArtist = 7, 0195 PT_Artist = 8, 0196 PT_Conductor = 9, 0197 PT_Band = 10, 0198 PT_Composer = 11, 0199 PT_Lyricist = 12, 0200 PT_RecordingLocation = 13, 0201 PT_DuringRecording = 14, 0202 PT_DuringPerformance = 15, 0203 PT_Video = 16, 0204 PT_Fish = 17, 0205 PT_Illustration = 18, 0206 PT_ArtistLogo = 19, 0207 PT_PublisherLogo = 20 0208 }; 0209 0210 /** Supported tags. */ 0211 enum TagNumber { 0212 Tag_1, /**< First tag */ 0213 Tag_2, /**< Second tag */ 0214 Tag_3, /**< Third tag */ 0215 Tag_NumValues, /**< Total number of tags */ 0216 0217 // Special uses of tags 0218 Tag_Id3v1 = Tag_1, /**< Tag which can be ID3v1 tag */ 0219 Tag_Id3v2 = Tag_2, /**< Tag which can be ID3v2 tag */ 0220 Tag_Picture = Tag_2 /**< Tag used for pictures */ 0221 }; 0222 0223 /** Tag version contained in track data. */ 0224 enum TagVersion { 0225 TagNone = 0, /**< Empty or imported and not from a tag */ 0226 TagV1 = 1 << Tag_1, /**< Tag 1 */ 0227 TagV2 = 1 << Tag_2, /**< Tag 2 */ 0228 TagV3 = 1 << Tag_3, /**< Tag 3 */ 0229 /** Tag 1 and 2 or merged from tag 2 and tag 1 (where tag 2 is not set) */ 0230 TagV2V1 = TagV1 | TagV2, 0231 TagVAll = TagV1 | TagV2 | TagV3 /**< All tags */ 0232 }; 0233 0234 /** 0235 * Cast a mask of tag version bits to a TagVersion enum. 0236 * @param tagMask tag mask (bit 0 for tag 1, bit 1 for tag 2) 0237 * @return tag version mask. 0238 */ 0239 static TagVersion tagVersionCast(int tagMask) { 0240 return static_cast<TagVersion>(tagMask & TagVAll); 0241 } 0242 0243 /** 0244 * @brief Cast an integer to a tag number. 0245 * @param nr number 0246 * @return tag number, Tag_NumValues if invalid. 0247 */ 0248 static TagNumber tagNumberCast(int nr) { 0249 return nr >= Tag_1 && nr < Tag_NumValues 0250 ? static_cast<TagNumber>(nr) : Tag_NumValues; 0251 } 0252 0253 /** 0254 * Get a tag mask from a tag number. 0255 * @param tagNr tag number 0256 * @return tag version mask. 0257 */ 0258 static TagVersion tagVersionFromNumber(TagNumber tagNr) { 0259 return tagNr < Tag_NumValues 0260 ? static_cast<TagVersion>(1 << tagNr) : TagNone; 0261 } 0262 0263 /** 0264 * Get list of available tag versions with translated description. 0265 * @return tag version/description pairs. 0266 */ 0267 static const QList<QPair<TagVersion, QString> > availableTagVersions(); 0268 0269 /** 0270 * Get highest priority tag number which is set in a tag mask. 0271 * @param tagMask tag mask with bits set for tags 0272 * @return tag number, Tag_NumValues if no tag is set. 0273 */ 0274 static TagNumber tagNumberFromMask(TagVersion tagMask) { 0275 return (tagMask & TagV2) 0276 ? Tag_2 : (tagMask & TagV1) 0277 ? Tag_1 : (tagMask & TagV3) 0278 ? Tag_3 : Tag_NumValues; 0279 } 0280 0281 /** 0282 * Get tag numbers which are set in a tag mask, ordered from highest 0283 * to lowest priority. 0284 * @param tagMask tag mask with bits set for tags 0285 * @return list of tag numbers. 0286 */ 0287 static const QList<TagNumber> tagNumbersFromMask(TagVersion tagMask) { 0288 QList<TagNumber> result; 0289 if (tagMask & TagV2) result << Tag_2; 0290 if (tagMask & TagV1) result << Tag_1; 0291 if (tagMask & TagV3) result << Tag_3; 0292 return result; 0293 } 0294 0295 /** 0296 * Get all tag numbers, ordered from highest to lowest priority. 0297 * @return list of tag numbers. 0298 */ 0299 static const QList<TagNumber> allTagNumbers() { 0300 return tagNumbersFromMask(TagVAll); 0301 } 0302 0303 /** 0304 * Get string representation for tag number. 0305 * @param tagNr tag number 0306 * @return "1" for Tag_1, "2" for Tag_2, ..., null if invalid. 0307 */ 0308 static QString tagNumberToString(TagNumber tagNr); 0309 0310 /** 0311 * Get tag number from string representation. 0312 * @param str string representation 0313 * @return Tag_1 for "1", Tag_2 for "2", ..., Tag_NumValues if invalid. 0314 */ 0315 static TagNumber tagNumberFromString(const QString& str); 0316 0317 /** for loop through all TagNumber values. */ 0318 #define FOR_ALL_TAGS(variable) \ 0319 for (Frame::TagNumber variable = Frame::Tag_1; \ 0320 variable < Frame::Tag_NumValues; \ 0321 variable = static_cast<Frame::TagNumber>(variable + 1)) 0322 0323 /** for loop through TagNumber values set in mask. */ 0324 #define FOR_TAGS_IN_MASK(variable, mask) \ 0325 FOR_ALL_TAGS(variable) \ 0326 if ((mask) & (1 << variable)) 0327 0328 /** Field in frame. */ 0329 struct KID3_CORE_EXPORT Field { 0330 /** 0331 * Equality operator. 0332 * @param rhs right hand side to compare 0333 * @return true if this == rhs. 0334 */ 0335 bool operator==(const Field& rhs) const { 0336 return m_id == rhs.m_id && m_value == rhs.m_value; 0337 } 0338 0339 int m_id; /**< type of field. */ 0340 QVariant m_value; /**< value of field. */ 0341 0342 /** 0343 * Get a translated string for a field ID. 0344 * 0345 * @param type field ID type 0346 * 0347 * @return field ID type, null string if unknown. 0348 */ 0349 static QString getFieldIdName(FieldId type); 0350 0351 /** 0352 * List of field ID strings, NULL terminated. 0353 */ 0354 static const char* const* getFieldIdNames(); 0355 0356 /** 0357 * Get field ID from field name. 0358 * @param fieldName name of field, can be English or translated 0359 * @return field ID, ID_NoField if not found. 0360 */ 0361 static FieldId getFieldId(const QString& fieldName); 0362 0363 /** 0364 * Get a translated string for a text encoding. 0365 * 0366 * @param type text encoding type 0367 * 0368 * @return text encoding type, null string if unknown. 0369 */ 0370 static QString getTextEncodingName(TextEncoding type); 0371 0372 /** 0373 * List of text encoding strings, NULL terminated. 0374 */ 0375 static const char* const* getTextEncodingNames(); 0376 0377 /** 0378 * Get a translated string for a timestamp format. 0379 * 0380 * @param type timestamp format type 0381 * 0382 * @return timestamp format type, null string if unknown. 0383 */ 0384 static QString getTimestampFormatName(int type); 0385 0386 /** 0387 * List of timestamp format strings, NULL terminated. 0388 */ 0389 static const char* const* getTimestampFormatNames(); 0390 0391 /** 0392 * Get a translated string for a content type. 0393 * 0394 * @param type content type 0395 * 0396 * @return content type, null string if unknown. 0397 */ 0398 static QString getContentTypeName(int type); 0399 0400 /** 0401 * List of content type strings, NULL terminated. 0402 */ 0403 static const char* const* getContentTypeNames(); 0404 0405 /** 0406 * Compare two field lists in a tolerant way. 0407 * This function can be used instead of the standard QList equality 0408 * operator if the field lists can be from different tag formats, which 0409 * may not all support the same field types. 0410 * @param fl1 first field list 0411 * @param fl2 second field list 0412 * @return true if they are similar enough. 0413 */ 0414 static bool fuzzyCompareFieldLists(const QList<Field>& fl1, 0415 const QList<Field>& fl2); 0416 0417 }; 0418 0419 /** list of fields. */ 0420 typedef QList<Field> FieldList; 0421 0422 /** 0423 * Type and name of frame. 0424 */ 0425 class KID3_CORE_EXPORT ExtendedType { 0426 public: 0427 /** 0428 * Constructor. 0429 */ 0430 ExtendedType() : m_type(FT_UnknownFrame) {} 0431 0432 /** 0433 * Constructor. 0434 * @param type type 0435 * @param name internal name 0436 */ 0437 ExtendedType(Type type, const QString& name) : m_type(type), m_name(name) {} 0438 0439 /** 0440 * Constructor. 0441 * @param name internal name 0442 */ 0443 explicit ExtendedType(const QString& name); 0444 0445 /** 0446 * Constructor. 0447 * @param type type 0448 */ 0449 explicit ExtendedType(Type type); 0450 0451 /** 0452 * Get name of type. 0453 * @return name. 0454 */ 0455 QString getName() const; 0456 0457 /** 0458 * Get translated name of type. 0459 * @return name. 0460 */ 0461 QString getTranslatedName() const; 0462 0463 /** 0464 * Get internal name of type. 0465 * @return name. 0466 */ 0467 QString getInternalName() const { return m_name; } 0468 0469 /** 0470 * Less than operator. 0471 * @param rhs right hand side to compare 0472 * @return true if this < rhs. 0473 */ 0474 bool operator<(const ExtendedType& rhs) const { 0475 return m_type < rhs.m_type || 0476 (m_type == FT_Other && m_type == rhs.m_type && m_name < rhs.m_name); 0477 } 0478 0479 /** 0480 * Equality operator. 0481 * @param rhs right hand side to compare 0482 * @return true if this == rhs. 0483 */ 0484 bool operator==(const ExtendedType& rhs) const { 0485 return m_type == rhs.m_type && 0486 (m_type != FT_Other || m_name == rhs.m_name); 0487 } 0488 0489 /** 0490 * Get type 0491 * @return type. 0492 */ 0493 Type getType() const { return m_type; } 0494 0495 private: 0496 friend class Frame; 0497 Type m_type; 0498 QString m_name; 0499 }; 0500 0501 0502 /** 0503 * Constructor. 0504 */ 0505 Frame(); 0506 0507 /** 0508 * Constructor. 0509 * @param type type 0510 * @param value value 0511 * @param name internal name 0512 * @param index index inside tag, -1 if unknown 0513 */ 0514 Frame(Type type, const QString& value, const QString& name, int index); 0515 0516 /** 0517 * Constructor. 0518 * @param type type and internal name 0519 * @param value value 0520 * @param index index inside tag, -1 if unknown 0521 */ 0522 Frame(const ExtendedType& type, const QString& value, int index); 0523 0524 /** 0525 * Less than operator. 0526 * Needed for sorting in multiset. 0527 * @param rhs right hand side to compare 0528 * @return true if this < rhs. 0529 */ 0530 bool operator<(const Frame& rhs) const { 0531 return m_extendedType < rhs.m_extendedType; 0532 } 0533 0534 #ifdef Q_CC_MSVC 0535 /** 0536 * Equality operator. 0537 * Needed when building with MSVC and BUILD_SHARED_LIBS. 0538 * @param rhs right hand side to compare 0539 * @return true if this == rhs. 0540 */ 0541 bool operator==(const Frame& rhs) const { 0542 return m_extendedType == rhs.m_extendedType && m_value == rhs.m_value && 0543 m_fieldList == rhs.m_fieldList; 0544 } 0545 #endif 0546 0547 /** 0548 * Get type of frame. 0549 * @return type. 0550 */ 0551 Type getType() const { return m_extendedType.m_type; } 0552 0553 /** 0554 * Set type of frame. 0555 * @param type type of frame 0556 */ 0557 void setType(Type type) { m_extendedType.m_type = type; } 0558 0559 /** 0560 * Get type and name of frame. 0561 * @return extended type. 0562 */ 0563 ExtendedType getExtendedType() const { return m_extendedType; } 0564 0565 /** 0566 * Set type and name of frame. 0567 * @param type extended type of frame 0568 */ 0569 void setExtendedType(const ExtendedType& type) { m_extendedType = type; } 0570 0571 /** 0572 * Get index of frame. 0573 * @return index. 0574 */ 0575 int getIndex() const { return m_index; } 0576 0577 /** 0578 * Set index of frame. 0579 * @param index index of frame 0580 */ 0581 void setIndex(int index) { m_index = index; } 0582 0583 /** 0584 * Get name of frame. 0585 * @return name. 0586 */ 0587 QString getName() const { return m_extendedType.getName(); } 0588 0589 /** 0590 * Get internal name of frame. 0591 * @return name. 0592 */ 0593 QString getInternalName() const { return m_extendedType.getInternalName(); } 0594 0595 /** 0596 * Get value as string. 0597 * @return value. 0598 */ 0599 QString getValue() const { return m_value; } 0600 0601 /** 0602 * Set value as string. 0603 * @param value value as string 0604 */ 0605 void setValue(const QString& value) { m_value = value; } 0606 0607 /** 0608 * Get value as integer. 0609 * @return value. 0610 */ 0611 int getValueAsNumber() const; 0612 0613 /** 0614 * Set value as integer. 0615 * @param n value as number 0616 */ 0617 void setValueAsNumber(int n); 0618 0619 /** 0620 * Check if value is empty. 0621 * @return true if empty. 0622 */ 0623 bool isEmpty() const { return m_value.isEmpty(); } 0624 0625 /** 0626 * Check if the value of this frame is fuzzy equal to another frame. 0627 * Other than with strict equality, total values and some fields which are 0628 * not supported in all tag formats are ignored. 0629 * @param other frame to compare 0630 * @return true if more or less equal. 0631 */ 0632 bool isFuzzyEqual(const Frame& other) const; 0633 0634 /** 0635 * Check if frame is inactive. 0636 * @return true if inactive. 0637 */ 0638 bool isInactive() const { return m_value.isNull(); } 0639 0640 /** 0641 * Set frame inactive. 0642 */ 0643 void setInactive() { m_value = QString(); } 0644 0645 /** 0646 * Check if frame represents different frames in multiple files. 0647 * @return true if different. 0648 */ 0649 bool isDifferent() const { return m_value == differentRepresentation(); } 0650 0651 /** 0652 * Represents different frames in multiple files. 0653 */ 0654 void setDifferent() { m_value = differentRepresentation(); } 0655 0656 /** 0657 * Get warning notice if frame is marked. 0658 * @return notice. 0659 */ 0660 FrameNotice getNotice() const { return m_marked; } 0661 0662 /** 0663 * Check if frame is marked. 0664 * @return true if marked. 0665 */ 0666 bool isMarked() const { return m_marked; } 0667 0668 /** 0669 * Mark frame. 0670 * @param notice warning notice 0671 */ 0672 void setMarked(FrameNotice notice) { m_marked = notice; } 0673 0674 /** 0675 * Check if value is changed. 0676 * @return true if changed. 0677 */ 0678 bool isValueChanged() const { return m_valueChanged; } 0679 0680 /** 0681 * Mark the value as changed. 0682 * @param changed true to mark as changed 0683 */ 0684 void setValueChanged(bool changed = true) { m_valueChanged = changed; } 0685 0686 /** 0687 * Set value as string and mark it as changed if it is changed. 0688 * This method will avoid setting "different" representations. 0689 * @param value value as string 0690 */ 0691 void setValueIfChanged(const QString& value); 0692 0693 /** 0694 * Set the value from a field in the field list. 0695 */ 0696 void setValueFromFieldList(); 0697 0698 /** 0699 * Read value text from file. 0700 * @param fileName name of data file 0701 * @return true if file read and value set. 0702 */ 0703 bool setValueFromFile(const QString& fileName); 0704 0705 /** 0706 * Save value text to a file. 0707 * @param fileName name of data file to save 0708 * @return true if saved. 0709 */ 0710 bool writeValueToFile(const QString& fileName) const; 0711 0712 /** 0713 * Set a field in the field list from the value. 0714 */ 0715 void setFieldListFromValue(); 0716 0717 /** 0718 * Get fields in the frame. 0719 * @return field list. 0720 */ 0721 const FieldList& getFieldList() const { return m_fieldList; } 0722 0723 /** 0724 * Set fields in the frame. 0725 * @param fields field list 0726 */ 0727 void setFieldList(const FieldList& fields) { m_fieldList = fields; } 0728 0729 /** 0730 * Get fields in the frame. 0731 * @return reference to field list. 0732 */ 0733 FieldList& fieldList() { return m_fieldList; } 0734 0735 /** 0736 * Get the value of a field. 0737 * 0738 * @param id field ID 0739 * 0740 * @return field value, invalid if field not found. 0741 */ 0742 QVariant getFieldValue(FieldId id) const; 0743 0744 /** 0745 * Check if the fields in another frame are equal. 0746 * 0747 * @param other other frame 0748 * 0749 * @return true if equal. 0750 */ 0751 bool isEqual(const Frame& other) const; 0752 0753 #ifndef QT_NO_DEBUG 0754 /** 0755 * Dump contents of frame to debug console. 0756 */ 0757 void dump() const; 0758 #endif 0759 0760 /** 0761 * If a frame contains a string list as a value, it is stored in a single 0762 * string, separated by this special separator character. 0763 * 0764 * @return separator character. 0765 */ 0766 static QLatin1Char stringListSeparator() { return QLatin1Char('|'); } 0767 0768 /** 0769 * Split a string into a string list using stringListSeparator(). 0770 * @param str string to split at stringListSeparator(), with support of 0771 * '\' as an escape character. 0772 * @return list of strings split at separator character not prefixed with 0773 * escape character. 0774 */ 0775 static QStringList splitStringList(const QString& str); 0776 0777 /** 0778 * Join a string list using stringListSeparator(). 0779 * @param strs strings to join, if they contain the separator character, 0780 * it will be escaped with '\'. 0781 * @return escaped strings joined by separator characters. 0782 */ 0783 static QString joinStringList(const QStringList& strs); 0784 0785 /** 0786 * Convert string (e.g. "track/total number of tracks") to number. 0787 * 0788 * @param str string to convert 0789 * @param ok if not 0, true is returned here if conversion is ok 0790 * 0791 * @return number in string ignoring total after slash. 0792 */ 0793 static int numberWithoutTotal(const QString& str, bool* ok = nullptr); 0794 0795 /** 0796 * Get representation of different frames in multiple files. 0797 * @return "different" representation. 0798 */ 0799 static QChar differentRepresentation() { return QChar(0x2260); } 0800 0801 /** 0802 * Set value of a field. 0803 * 0804 * @param frame frame to set 0805 * @param id field ID 0806 * @param value field value 0807 * 0808 * @return true if field found and set. 0809 */ 0810 static bool setField(Frame& frame, FieldId id, const QVariant& value); 0811 0812 /** 0813 * Set value of a field. 0814 * 0815 * @param frame frame to set 0816 * @param fieldName name of field, can be English or translated 0817 * @param value field value 0818 * 0819 * @return true if field found and set. 0820 */ 0821 static bool setField(Frame& frame, const QString& fieldName, 0822 const QVariant& value); 0823 0824 /** 0825 * Get value of a field. 0826 * 0827 * @param frame frame to get 0828 * @param id field ID 0829 * 0830 * @return field value, invalid if not found. 0831 */ 0832 static QVariant getField(const Frame& frame, FieldId id); 0833 0834 /** 0835 * Get value of a field. 0836 * 0837 * @param frame frame to get 0838 * @param fieldName name of field, can be English or translated 0839 * 0840 * @return field value, invalid if not found. 0841 */ 0842 static QVariant getField(const Frame& frame, const QString& fieldName); 0843 0844 /** 0845 * Get type of frame from English name. 0846 * 0847 * @param name name, spaces and case are ignored 0848 * 0849 * @return type. 0850 */ 0851 static Type getTypeFromName(const QString& name); 0852 0853 /** 0854 * Get a translated string for a frame type. 0855 * 0856 * @param type frame type 0857 * 0858 * @return frame type, null string if unknown. 0859 */ 0860 static QString getFrameTypeName(Type type); 0861 0862 /** 0863 * Get a display name for a frame name. 0864 * @param name frame name as returned by getName() 0865 * @return display name, transformed if necessary and translated. 0866 */ 0867 static QString getDisplayName(const QString& name); 0868 0869 /** 0870 * Get a map with display names as keys and frame names as values. 0871 * @param names frame names as returned by getName() 0872 * @return mapping of display names to frame names. 0873 */ 0874 static QMap<QString, QString> getDisplayNameMap(const QStringList& names); 0875 0876 /** 0877 * Get the frame name for a translated display name. 0878 * @param name translated display name 0879 * @return English frame name for @a name if found, else @a name. 0880 */ 0881 static QString getNameForTranslatedFrameName(const QString& name); 0882 0883 /** 0884 * Get internal frame ID of non unified frame for a translated display name. 0885 * @param name translated display name 0886 * @return internal frame ID, e.g. "SYLT", "keyw" of non unified frame, 0887 * null if @a name is not the name of a supported non unified frame. 0888 */ 0889 static QByteArray getFrameIdForTranslatedFrameName(const QString& name); 0890 0891 /** 0892 * Get the internal name for a custom frame. 0893 * @param type custom frame type (FT_Custom1..FT_LastFrame) 0894 * @return custom frame name, empty if not used. 0895 */ 0896 static QByteArray getNameForCustomFrame(Frame::Type type); 0897 0898 /** 0899 * Get type of frame from custom frame name. 0900 * @param name custom frame name 0901 * @return type, FT_Other if no custom frame with @a name exists. 0902 */ 0903 static Frame::Type getTypeFromCustomFrameName(const QByteArray& name); 0904 0905 /** 0906 * Set the internal names for all custom frames. 0907 * The number of custom frames is limited. The internal vector will be resized 0908 * to fit the fixed number of custom frames. 0909 * 0910 * @param customNames names for the custom frame types (FT_Custom1...), 0911 * leading '!' will be removed from the names 0912 * @return true if custom frame names were changed. 0913 */ 0914 static bool setNamesForCustomFrames(const QStringList& customNames); 0915 0916 /** 0917 * Get the names for all custom frames. 0918 * The returned list does not contain empty names. 0919 * 0920 * @return names for the custom frame types (FT_Custom1, ...). 0921 */ 0922 static QStringList getNamesForCustomFrames(); 0923 0924 /** 0925 * Convert frame index to a negative index used for a second collection. 0926 * This can be a collection containing picture frames, the mapping is 0927 * -1 -> -1, 0 -> -2, 1 -> -3, 2 -> -4, ... 0928 * @param index positive index, -1 is the unknown index 0929 * @return negative index <= -1. 0930 */ 0931 static int toNegativeIndex(int index) { return -2 - index; } 0932 0933 /** 0934 * Convert negative index used for a second collection to a frame index. 0935 * This can be used to get the index of a collection containing picture 0936 * frames, the mapping is 0937 * -1 -> -1, -2 -> 0, -3 -> 1, -4 -> 2, ... 0938 * @param negativeIndex negative index, -1 is the unknown index 0939 * @return frame negative >= -1. 0940 */ 0941 static int fromNegativeIndex(int negativeIndex) { return -2 - negativeIndex; } 0942 0943 private: 0944 friend class TaggedFile; 0945 0946 ExtendedType m_extendedType; 0947 int m_index; 0948 QString m_value; 0949 FieldList m_fieldList; 0950 FrameNotice m_marked; 0951 bool m_valueChanged; 0952 }; 0953 0954 /** Filter to enable a subset of frame types. */ 0955 class KID3_CORE_EXPORT FrameFilter { 0956 public: 0957 /** 0958 * Constructor. 0959 * All frames are disabled 0960 */ 0961 FrameFilter(); 0962 0963 /** 0964 * Enable all frames. 0965 */ 0966 void enableAll(); 0967 0968 /** 0969 * Check if all fields are true. 0970 * 0971 * @return true if all fields are true. 0972 */ 0973 bool areAllEnabled() const; 0974 0975 /** 0976 * Check if frame is enabled. 0977 * 0978 * @param type frame type 0979 * @param name frame name 0980 * 0981 * @return true if frame is enabled. 0982 */ 0983 bool isEnabled(Frame::Type type, const QString& name = QString()) const; 0984 0985 /** 0986 * Enable or disable frame. 0987 * 0988 * @param type frame type 0989 * @param name frame name 0990 * @param en true to enable 0991 */ 0992 void enable(Frame::Type type, const QString& name = QString(), bool en = true); 0993 0994 private: 0995 static const quint64 FTM_AllFrames = (1ULL << (Frame::FT_LastFrame + 1)) - 1; 0996 quint64 m_enabledFrames; 0997 std::set<QString> m_disabledOtherFrames; 0998 }; 0999 1000 /** Collection of frames. */ 1001 class KID3_CORE_EXPORT FrameCollection : public std::multiset<Frame> { 1002 public: 1003 /** 1004 * Default value for quick access frames. 1005 */ 1006 static constexpr quint64 DEFAULT_QUICK_ACCESS_FRAMES = 1007 (1ULL << Frame::FT_Title) | 1008 (1ULL << Frame::FT_Artist) | 1009 (1ULL << Frame::FT_Album) | 1010 (1ULL << Frame::FT_Comment) | 1011 (1ULL << Frame::FT_Date) | 1012 (1ULL << Frame::FT_Track) | 1013 (1ULL << Frame::FT_Genre); 1014 1015 /** 1016 * Set values which are different inactive. 1017 * 1018 * @param others frames to compare, will be modified! 1019 * @param differentValues optional storage for the different values 1020 */ 1021 void filterDifferent(FrameCollection& others, 1022 QHash<Frame::ExtendedType, QSet<QString>>* differentValues = nullptr); 1023 1024 /** 1025 * Add standard frames which are missing. 1026 */ 1027 void addMissingStandardFrames(); 1028 1029 /** 1030 * Copy enabled frames. 1031 * 1032 * @param flt filter with enabled frames 1033 * 1034 * @return copy with enabled frames. 1035 */ 1036 FrameCollection copyEnabledFrames(const FrameFilter& flt) const; 1037 1038 /** 1039 * Remove all frames which are not enabled from the collection. 1040 * 1041 * @param flt filter with enabled frames 1042 */ 1043 void removeDisabledFrames(const FrameFilter& flt); 1044 1045 /** 1046 * Set the index of all frames to -1. 1047 */ 1048 void setIndexesInvalid(); 1049 1050 /** 1051 * Copy frames which are empty or inactive from other frames. 1052 * This can be used to merge two frame collections. 1053 * 1054 * @param frames other frames 1055 */ 1056 void merge(const FrameCollection& frames); 1057 1058 /** 1059 * Check if the standard tags are empty or inactive. 1060 * 1061 * @return true if empty or inactive. 1062 */ 1063 bool isEmptyOrInactive() const; 1064 1065 /** 1066 * Find a frame by name. 1067 * 1068 * @param name the name of the frame to find, if the exact name is not 1069 * found, a case-insensitive search for the first name 1070 * starting with this string is performed 1071 * @param index 0 for first frame with @a name, 1 for second, etc. 1072 * 1073 * @return iterator or end() if not found. 1074 */ 1075 const_iterator findByName(const QString& name, int index = 0) const; 1076 1077 /** 1078 * Find a frame by type or name. 1079 * 1080 * @param type type and name of the frame to find, if the exact name is not 1081 * found, a case-insensitive search for the first name 1082 * starting with this string is performed 1083 * @param index 0 for first frame with @a type, 1 for second, etc. 1084 * 1085 * @return iterator or end() if not found. 1086 */ 1087 const_iterator findByExtendedType(const Frame::ExtendedType& type, 1088 int index = 0) const; 1089 1090 /** 1091 * Find a frame by index. 1092 * 1093 * @param index the index in the frame, see \ref Frame::getIndex() 1094 * 1095 * @return iterator or end() if not found. 1096 */ 1097 const_iterator findByIndex(int index) const; 1098 1099 /** 1100 * Get value by type. 1101 * 1102 * @param type type 1103 * 1104 * @return value, QString::null if not found. 1105 */ 1106 QString getValue(Frame::Type type) const; 1107 1108 /** 1109 * Get value by type and name. 1110 * 1111 * @param type type and name of the frame to find, if the exact name is not 1112 * found, a case-insensitive search for the first name 1113 * starting with this string is performed 1114 * 1115 * @return value, QString::null if not found. 1116 */ 1117 QString getValue(const Frame::ExtendedType& type) const; 1118 1119 /** 1120 * Set value by type. 1121 * 1122 * @param type type 1123 * @param value value, nothing is done if QString::null 1124 */ 1125 void setValue(Frame::Type type, const QString& value); 1126 1127 /** 1128 * Set value by type and name. 1129 * 1130 * @param type type and name of the frame to find, if the exact name is not 1131 * found, a case-insensitive search for the first name 1132 * starting with this string is performed 1133 * @param value value, nothing is done if QString::null 1134 */ 1135 void setValue(const Frame::ExtendedType& type, const QString& value); 1136 1137 /** 1138 * Get integer value by type. 1139 * 1140 * @param type type 1141 * 1142 * @return value, 0 if empty, -1 if not found. 1143 */ 1144 int getIntValue(Frame::Type type) const; 1145 1146 /** 1147 * Set integer value by type. 1148 * 1149 * @param type type 1150 * @param value value, 0 to set empty, nothing is done if -1 1151 */ 1152 void setIntValue(Frame::Type type, int value); 1153 1154 /** 1155 * Get artist. 1156 * 1157 * @return artist, QString::null if not found. 1158 */ 1159 QString getArtist() const { return getValue(Frame::FT_Artist); } 1160 1161 /** 1162 * Set artist. 1163 * 1164 * @param artist artist, nothing is done if QString::null 1165 */ 1166 void setArtist(const QString& artist) { setValue(Frame::FT_Artist, artist); } 1167 1168 /** 1169 * Get album. 1170 * 1171 * @return album, QString::null if not found. 1172 */ 1173 QString getAlbum() const { return getValue(Frame::FT_Album); } 1174 1175 /** 1176 * Set album. 1177 * 1178 * @param album album, nothing is done if QString::null 1179 */ 1180 void setAlbum(const QString& album) { setValue(Frame::FT_Album, album); } 1181 1182 /** 1183 * Get title. 1184 * 1185 * @return title, QString::null if not found. 1186 */ 1187 QString getTitle() const { return getValue(Frame::FT_Title); } 1188 1189 /** 1190 * Set title. 1191 * 1192 * @param title title, nothing is done if QString::null 1193 */ 1194 void setTitle(const QString& title) { setValue(Frame::FT_Title, title); } 1195 1196 /** 1197 * Get comment. 1198 * 1199 * @return comment, QString::null if not found. 1200 */ 1201 QString getComment() const { return getValue(Frame::FT_Comment); } 1202 1203 /** 1204 * Set comment. 1205 * 1206 * @param comment comment, nothing is done if QString::null 1207 */ 1208 void setComment(const QString& comment) { setValue(Frame::FT_Comment, comment); } 1209 1210 /** 1211 * Get genre. 1212 * 1213 * @return genre, QString::null if not found. 1214 */ 1215 QString getGenre() const { return getValue(Frame::FT_Genre); } 1216 1217 /** 1218 * Set genre. 1219 * 1220 * @param genre genre, nothing is done if QString::null 1221 */ 1222 void setGenre(const QString& genre) { setValue(Frame::FT_Genre, genre); } 1223 1224 /** 1225 * Get track. 1226 * 1227 * @return track, -1 if not found. 1228 */ 1229 int getTrack() const { return getIntValue(Frame::FT_Track); } 1230 1231 /** 1232 * Set track. 1233 * 1234 * @param track track, nothing is done if -1 1235 */ 1236 void setTrack(int track) { setIntValue(Frame::FT_Track, track); } 1237 1238 /** 1239 * Get year. 1240 * 1241 * @return year, -1 if not found. 1242 */ 1243 int getYear() const { return getIntValue(Frame::FT_Date); } 1244 1245 /** 1246 * Set year. 1247 * 1248 * @param year year, nothing is done if -1 1249 */ 1250 void setYear(int year) { setIntValue(Frame::FT_Date, year); } 1251 1252 /** 1253 * Compare the frames with another frame collection and mark the value as 1254 * changed on frames which are different. 1255 * 1256 * @param other other frame collection 1257 */ 1258 void markChangedFrames(const FrameCollection& other); 1259 1260 #ifndef QT_NO_DEBUG 1261 /** 1262 * Dump contents of frame collection to debug console. 1263 */ 1264 void dump() const; 1265 #endif 1266 1267 /** 1268 * Set mask containing the bits of all frame types which shall be used as 1269 * quick access frames. 1270 * @param mask bit mask with bits for quick access frames set, default is 1271 * DEFAULT_QUICK_ACCESS_FRAMES. 1272 */ 1273 static void setQuickAccessFrames(quint64 mask) { 1274 s_quickAccessFrames = mask; 1275 } 1276 1277 /** 1278 * Get mask containing the bits of all frame types which shall be used as 1279 * quick access frames. 1280 * @return mask bit mask with bits for quick access frames set. 1281 */ 1282 static quint64 getQuickAccessFrames() { 1283 return s_quickAccessFrames; 1284 } 1285 1286 /** 1287 * Create a frame collection from a list of subframe fields. 1288 * 1289 * The given subframe fields must start with a Frame::ID_Subframe field with 1290 * the frame name as its value, followed by the fields of the frame. More 1291 * subframes may follow. 1292 * 1293 * @param begin iterator to begin of subframes 1294 * @param end iterator after end of subframes 1295 * 1296 * @return frames constructed from subframe fields. 1297 */ 1298 static FrameCollection fromSubframes(Frame::FieldList::const_iterator begin, 1299 Frame::FieldList::const_iterator end); 1300 1301 private: 1302 /** 1303 * Search for a frame only by name. 1304 * 1305 * @param name the name of the frame to find, a case-insensitive search for 1306 * the first name starting with this string is performed 1307 * 1308 * @return iterator or end() if not found. 1309 */ 1310 const_iterator searchByName(const QString& name) const; 1311 1312 /** 1313 * Bit mask containing the bits of all frame types which shall be used as 1314 * quick access frames. 1315 * This mask has to be handled like FrameFilter::m_enabledFrames. 1316 */ 1317 static quint64 s_quickAccessFrames; 1318 }; 1319 1320 1321 /** 1322 * Replaces frame format codes in a string. 1323 */ 1324 class KID3_CORE_EXPORT FrameFormatReplacer : public FormatReplacer { 1325 public: 1326 /** 1327 * Constructor. 1328 * 1329 * @param frames frame collection 1330 * @param str string with format codes 1331 */ 1332 explicit FrameFormatReplacer( 1333 const FrameCollection& frames, const QString& str = QString()); 1334 1335 /** 1336 * Destructor. 1337 */ 1338 ~FrameFormatReplacer() override = default; 1339 1340 FrameFormatReplacer(const FrameFormatReplacer& other) = delete; 1341 FrameFormatReplacer &operator=(const FrameFormatReplacer& other) = delete; 1342 1343 /** 1344 * Get help text for supported format codes. 1345 * 1346 * @param onlyRows if true only the tr elements are returned, 1347 * not the surrounding table 1348 * 1349 * @return help text. 1350 */ 1351 static QString getToolTip(bool onlyRows = false); 1352 1353 protected: 1354 /** 1355 * Replace a format code (one character %c or multiple characters %{chars}). 1356 * Supported format fields: 1357 * %s title (song) 1358 * %l album 1359 * %a artist 1360 * %c comment 1361 * %y year 1362 * %t track, two digits, i.e. leading zero if < 10 1363 * %T track, without leading zeroes 1364 * %g genre 1365 * 1366 * @param code format code 1367 * 1368 * @return replacement string, 1369 * QString::null if code not found. 1370 */ 1371 QString getReplacement(const QString& code) const override; 1372 1373 private: 1374 const FrameCollection& m_frames; 1375 }; 1376 1377 /** Hash function to use Frame::ExtendedType as a QHash key. */ 1378 inline uint qHash(const Frame::ExtendedType& key) { 1379 return qHash(key.getType()) ^ qHash(key.getInternalName()); 1380 }