tagparser/mediafileinfo.h

368 lines
11 KiB
C
Raw Normal View History

2015-04-22 19:22:01 +02:00
#ifndef MEDIAINFO_H
#define MEDIAINFO_H
2015-09-06 19:57:33 +02:00
#include "./signature.h"
#include "./statusprovider.h"
#include "./basicfileinfo.h"
#include "./abstractcontainer.h"
2015-04-22 19:22:01 +02:00
#include <string>
#include <fstream>
#include <vector>
#include <memory>
2015-09-06 15:42:18 +02:00
namespace Media {
2015-04-22 19:22:01 +02:00
class Tag;
class Id3v1Tag;
class Id3v2Tag;
class Mp4Container;
class Mp4Atom;
class Mp4Tag;
class MatroskaContainer;
class OggContainer;
class EbmlElement;
class MatroskaTag;
class AbstractTrack;
class WaveAudioStream;
class MpegAudioFrameStream;
enum class MediaType;
enum class TagType : unsigned int;
/*!
2015-10-06 22:39:51 +02:00
* \brief The TagUsage enum specifies the usage of a certain tag type.
2015-04-22 19:22:01 +02:00
*/
enum class TagUsage
{
Always, /**< a tag of the type is always used; a new tag is created if none exists yet */
KeepExisting, /**< existing tags of the type are kept and updated but no new tag is created */
Never /**< tags of the type are never used; a possibly existing tag of the type is removed */
};
2015-10-06 22:39:51 +02:00
/*!
* \brief The ParsingStatus enum specifies whether a certain part of the file (tracks, tags, ...) has
* been parsed yet and if what the parsing result is.
*/
enum class ParsingStatus : byte
{
NotParsedYet, /**< the part has not been parsed yet */
Ok, /**< the part has been parsed and no critical errors occured */
NotSupported, /**< tried to parse the part, but the format is not supported */
CriticalFailure /**< tried to parse the part, but critical errors occured */
};
2015-04-22 19:22:01 +02:00
class LIB_EXPORT MediaFileInfo : public BasicFileInfo, public StatusProvider
{
public:
// constructor, destructor
MediaFileInfo();
MediaFileInfo(const std::string &path);
MediaFileInfo(const MediaFileInfo &) = delete;
MediaFileInfo &operator=(const MediaFileInfo &) = delete;
virtual ~MediaFileInfo();
// methods to parse file
void parseContainerFormat();
void parseTracks();
void parseTags();
void parseChapters();
void parseAttachments();
void parseEverything();
// methods to apply changes
void applyChanges();
// methods to get parsed information regarding ...
// ... the container
ContainerFormat containerFormat() const;
const char *containerFormatName() const;
const char *containerFormatAbbreviation() const;
const char *containerFormatSubversion() const;
const char *mimeType() const;
uint64 containerOffset() const;
uint64 paddingSize() const;
AbstractContainer *container() const;
2015-10-06 22:39:51 +02:00
ParsingStatus containerParsingStatus() const;
2015-04-22 19:22:01 +02:00
// ... the capters
2015-10-06 22:39:51 +02:00
ParsingStatus chaptersParsingStatus() const;
2015-04-22 19:22:01 +02:00
std::vector<AbstractChapter *> chapters() const;
bool areChaptersSupported() const;
// ... the attachments
2015-10-06 22:39:51 +02:00
ParsingStatus attachmentsParsingStatus() const;
2015-04-22 19:22:01 +02:00
std::vector<AbstractAttachment *> attachments() const;
bool areAttachmentsSupported() const;
// ... the tracks
2015-10-06 22:39:51 +02:00
ParsingStatus tracksParsingStatus() const;
2015-04-22 19:22:01 +02:00
std::size_t trackCount() const;
std::vector<AbstractTrack *> tracks() const;
bool hasTracksOfType(Media::MediaType type) const;
ChronoUtilities::TimeSpan duration() const;
bool areTracksSupported() const;
// ... the tags
2015-10-06 22:39:51 +02:00
ParsingStatus tagsParsingStatus() const;
2015-04-22 19:22:01 +02:00
bool hasId3v1Tag() const;
bool hasId3v2Tag() const;
bool hasAnyTag() const;
Id3v1Tag *id3v1Tag() const;
const std::vector<std::unique_ptr<Id3v2Tag> > &id3v2Tags() const;
void tags(std::vector<Tag *> &tags) const;
std::vector<Tag *> tags() const;
Mp4Tag *mp4Tag() const;
const std::vector<std::unique_ptr<MatroskaTag> > &matroskaTags() const;
bool areTagsSupported() const;
// methods to create/remove tags
bool createAppropriateTags(bool treatUnknownFilesAsMp3Files = false, TagUsage id3v1usage = TagUsage::KeepExisting,
2015-10-16 21:46:36 +02:00
TagUsage id3v2usage = TagUsage::Always, bool mergeMultipleSuccessiveId3v2Tags = true,
bool keepExistingId3v2version = true, uint32 id3v2version = 3, const std::vector<TagTarget> &requiredTargets = std::vector<TagTarget>());
2015-04-22 19:22:01 +02:00
bool removeId3v1Tag();
Id3v1Tag *createId3v1Tag();
bool removeId3v2Tag(Id3v2Tag *tag);
bool removeAllId3v2Tags();
Id3v2Tag *createId3v2Tag();
void removeTag(Tag *tag);
void removeAllTags();
void mergeId3v2Tags();
// methods to get/wipe notifications
bool haveRelatedObjectsNotifications() const;
NotificationType worstNotificationTypeIncludingRelatedObjects() const;
2015-10-06 22:39:51 +02:00
void gatherRelatedNotifications(NotificationList &notifications) const;
2015-04-22 19:22:01 +02:00
NotificationList gatherRelatedNotifications() const;
void clearParsingResults();
// methods to get, set object behaviour
bool isForcingFullParse() const;
void setForceFullParse(bool forceFullParse);
protected:
virtual void invalidated();
private:
// private methods internally used when rewriting the file to apply new tag information
// currently only the makeMp3File() methods is present; corresponding methods for
// other formats are outsourced to container classes
void makeMp3File();
// fields related to the container
2015-10-06 22:39:51 +02:00
ParsingStatus m_containerParsingStatus;
2015-04-22 19:22:01 +02:00
ContainerFormat m_containerFormat;
std::streamoff m_containerOffset;
uint64 m_paddingSize;
bool m_actualExistingId3v1Tag;
std::list<std::streamoff> m_actualId3v2TagOffsets;
std::unique_ptr<AbstractContainer> m_container;
// fields related to the tracks
2015-10-06 22:39:51 +02:00
ParsingStatus m_tracksParsingStatus;
2015-07-15 00:10:24 +02:00
std::unique_ptr<AbstractTrack> m_singleTrack;
2015-04-22 19:22:01 +02:00
// fields related to the tag
2015-10-06 22:39:51 +02:00
ParsingStatus m_tagsParsingStatus;
2015-04-22 19:22:01 +02:00
std::unique_ptr<Id3v1Tag> m_id3v1Tag;
std::vector<std::unique_ptr<Id3v2Tag> > m_id3v2Tags;
2015-10-06 22:39:51 +02:00
// fields related to the chapters and the attachments
ParsingStatus m_chaptersParsingStatus;
ParsingStatus m_attachmentsParsingStatus;
2015-04-22 19:22:01 +02:00
// fields specifying object behaviour
bool m_forceFullParse;
};
/*!
* \brief Returns an indication whether the container format has been parsed yet.
*/
2015-10-06 22:39:51 +02:00
inline ParsingStatus MediaFileInfo::containerParsingStatus() const
2015-04-22 19:22:01 +02:00
{
2015-10-06 22:39:51 +02:00
return m_containerParsingStatus;
2015-04-22 19:22:01 +02:00
}
/*!
* \brief Returns the container format of the current file.
*
* parseContainerFormat() needs to be called before. Otherwise
* always ContainerFormat::Unknown will be returned.
*/
inline ContainerFormat MediaFileInfo::containerFormat() const
{
return m_containerFormat;
}
2015-07-15 00:24:19 +02:00
/*!
* \brief Returns the name of the container format as C-style string.
*
* parseContainerFormat() needs to be called before. Otherwise
* always the name "Unknown" will be returned.
*
* \sa containerFormat()
* \sa containerFormatAbbreviation()
* \sa parseContainerFormat()
*/
inline const char *MediaFileInfo::containerFormatName() const
{
return Media::containerFormatName(m_containerFormat);
}
/*!
* \brief Returns the subversion of the container format as C-style string.
*
* parseContainerFormat() needs to be called before. Otherwise
* always an empty string will be returned.
*
* \sa containerFormat()
* \sa containerFormatName()
* \sa parseContainerFormat()
*/
inline const char *MediaFileInfo::containerFormatSubversion() const
{
return Media::containerFormatSubversion(m_containerFormat);
}
2015-04-22 19:22:01 +02:00
/*!
* \brief Returns the actual container start offset.
*/
inline uint64 MediaFileInfo::containerOffset() const
{
return m_containerOffset;
}
/*!
* \brief Returns the padding size. Container format and tags should have been parsed yet.
*/
inline uint64 MediaFileInfo::paddingSize() const
{
return m_paddingSize;
}
/*!
* \brief Returns an indication whether tag information has been parsed yet.
*/
2015-10-06 22:39:51 +02:00
inline ParsingStatus MediaFileInfo::tagsParsingStatus() const
2015-04-22 19:22:01 +02:00
{
2015-10-06 22:39:51 +02:00
return m_tagsParsingStatus;
2015-04-22 19:22:01 +02:00
}
/*!
* \brief Returns an indication whether tracks have been parsed yet.
*/
2015-10-06 22:39:51 +02:00
inline ParsingStatus MediaFileInfo::tracksParsingStatus() const
2015-04-22 19:22:01 +02:00
{
2015-10-06 22:39:51 +02:00
return m_tracksParsingStatus;
2015-04-22 19:22:01 +02:00
}
2015-07-15 00:10:24 +02:00
/*!
* \brief Returns the number of tracks that could be parsed.
*
* parseTracks() needs to be called before. Otherwise this
* method always returns zero.
*
* \sa parseTracks()
*/
inline size_t MediaFileInfo::trackCount() const
{
return m_singleTrack ? 1 : 0 + m_container->trackCount();
}
2015-04-22 19:22:01 +02:00
/*!
* \brief Returns whether the chapters have been parsed yet.
*/
2015-10-06 22:39:51 +02:00
inline ParsingStatus MediaFileInfo::chaptersParsingStatus() const
2015-04-22 19:22:01 +02:00
{
2015-10-06 22:39:51 +02:00
return m_chaptersParsingStatus;
2015-04-22 19:22:01 +02:00
}
/*!
* \brief Returns whether the attachments have been parsed yet.
*/
2015-10-06 22:39:51 +02:00
inline ParsingStatus MediaFileInfo::attachmentsParsingStatus() const
2015-04-22 19:22:01 +02:00
{
2015-10-06 22:39:51 +02:00
return m_attachmentsParsingStatus;
2015-04-22 19:22:01 +02:00
}
/*!
* \brief Returns an indication whether an ID3v1 tag is assigned.
*/
inline bool MediaFileInfo::hasId3v1Tag() const
{
return m_id3v1Tag != nullptr;
}
/*!
* \brief Returns an indication whether an ID3v2 tag is assigned.
*/
inline bool MediaFileInfo::hasId3v2Tag() const
{
return m_id3v2Tags.size();
}
/*!
* \brief Returns an indication whether a tag of any format is assigned.
*/
inline bool MediaFileInfo::hasAnyTag() const
{
return hasId3v1Tag() || hasId3v2Tag() || (m_container && m_container->tagCount());
}
/*!
* \brief Returns a pointer to the assigned ID3v1 tag or nullptr if none is assigned.
*
* \remarks The MediaFileInfo keeps the ownership over the returned
* pointer. The returned ID3v1 tag will be destroyed when the
* MediaFileInfo gets invalidated.
*/
inline Id3v1Tag *MediaFileInfo::id3v1Tag() const
{
return m_id3v1Tag.get();
}
/*!
* \brief Returns pointers to the assigned ID3v2 tags.
*
* \remarks The MediaFileInfo keeps the ownership over the returned
* pointers. The returned ID3v2 tags will be destroyed when the
* MediaFileInfo gets invalidated.
*/
inline const std::vector<std::unique_ptr<Id3v2Tag> > &MediaFileInfo::id3v2Tags() const
{
return m_id3v2Tags;
}
/*!
* \brief Returns the container for the current file.
*
* If there is not corresponding subclass of AbstractContainer for the
* container format or the container has not been parsed yet using
* the parseContainerFormat() method nullptr will be returned.
*
* \sa parseContainerFormat()
* \sa AbstractContainer
*/
inline AbstractContainer *MediaFileInfo::container() const
{
return m_container.get();
}
/*!
* \brief Returns an indication whether forcing a full parse is enabled.
*
* If enabled the parser will analyse the file structure as deep as possible.
* This might cause long parsing times for big files.
*
* \sa setForceFullParse()
*/
inline bool MediaFileInfo::isForcingFullParse() const
{
return m_forceFullParse;
}
/*!
* \brief Sets whether forcing a full parse is enabled.
* \remarks The setting is applied next time parsing. The current parsing results are not mutated.
* \sa isForcingFullParse()
*/
inline void MediaFileInfo::setForceFullParse(bool forceFullParse)
{
m_forceFullParse = forceFullParse;
}
}
#endif // MEDIAINFO_H