Tag Parser
9.1.3
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
|
Go to the documentation of this file.
4 #include "../vorbis/vorbiscomment.h"
6 #include "../exceptions.h"
7 #include "../mediafileinfo.h"
8 #include "../mediaformat.h"
10 #include "resources/config.h"
12 #include <c++utilities/io/copy.h>
31 FlacStream::FlacStream(
MediaFileInfo &mediaFileInfo, std::uint64_t startOffset)
33 , m_mediaFileInfo(mediaFileInfo)
46 if (!m_vorbisComment) {
47 m_vorbisComment = make_unique<VorbisComment>();
49 return m_vorbisComment.get();
58 if (!m_vorbisComment) {
61 m_vorbisComment.reset();
67 static const string context(
"parsing raw FLAC header");
76 if (
m_reader.readUInt32BE() != 0x664C6143) {
86 header.parseHeader(buffer);
94 if (header.dataSize() >= 0x22) {
97 streamInfo.
parse(buffer);
104 diag.emplace_back(
DiagLevel::Critical,
"\"METADATA_BLOCK_STREAMINFO\" is truncated and will be ignored.", context);
111 if (!m_vorbisComment) {
112 m_vorbisComment = make_unique<VorbisComment>();
131 diag.emplace_back(
DiagLevel::Warning,
"\"METADATA_BLOCK_PICTURE\" contains no picture.", context);
134 if (!m_vorbisComment) {
136 m_vorbisComment = make_unique<VorbisComment>();
139 m_vorbisComment->fields().insert(make_pair(coverField.
id(), move(coverField)));
143 diag.emplace_back(
DiagLevel::Critical,
"\"METADATA_BLOCK_PICTURE\" is truncated and will be ignored.", context);
148 m_paddingSize += 4 + header.dataSize();
160 m_streamOffset =
static_cast<std::uint32_t
>(
m_istream->tellg());
176 istream &originalStream = m_mediaFileInfo.
stream();
177 originalStream.seekg(
static_cast<streamoff
>(
m_startOffset + 4));
181 BE::getBytes(
static_cast<std::uint32_t
>(0x664C6143u), copy.buffer());
184 std::streamoff lastStartOffset = -1;
191 originalStream.read(copy.buffer(), 4);
200 originalStream.seekg(header.
dataSize(), ios_base::cur);
204 originalStream.seekg(-4, ios_base::cur);
207 lastActuallyWrittenHeader = header;
209 }
while (!header.
isLast());
212 if (lastStartOffset >= 4
213 && ((!m_vorbisComment && !lastActuallyWrittenHeader.
isLast()) || (m_vorbisComment && lastActuallyWrittenHeader.
isLast()))) {
215 lastActuallyWrittenHeader.
setLast(!m_vorbisComment);
217 originalStream.seekg(lastActuallyWrittenHeader.
dataSize(), ios_base::cur);
221 if (!m_vorbisComment) {
222 return lastStartOffset >= 0 ? lastStartOffset : 0;
237 auto dataSize(
static_cast<std::uint64_t
>(endOffset) -
static_cast<std::uint64_t
>(lastStartOffset) - 4);
238 if (dataSize > 0xFFFFFF) {
240 diag.emplace_back(
DiagLevel::Critical,
"Vorbis Comment is too big and will be truncated.",
"write Vorbis Comment to FLAC stream");
242 header.
setDataSize(
static_cast<std::uint32_t
>(dataSize));
243 header.
setLast(!m_vorbisComment->hasField(coverId));
246 outputStream.seekp(
static_cast<streamoff
>(dataSize), ios_base::cur);
247 lastActuallyWrittenHeader = header;
251 return lastStartOffset;
254 const auto coverFields = m_vorbisComment->fields().equal_range(coverId);
255 for (
auto i = coverFields.first; i != coverFields.second;) {
263 header.
setLast(++i == coverFields.second);
268 lastStartOffset = lastCoverStartOffset;
269 lastActuallyWrittenHeader = header;
274 diag.emplace_back(
DiagLevel::Critical,
"Unable to serialize \"METADATA_BLOCK_PICTURE\" from assigned value.",
275 "write \"METADATA_BLOCK_PICTURE\" to FLAC stream");
282 if (!lastActuallyWrittenHeader.
isLast()) {
284 lastActuallyWrittenHeader.
setLast(
true);
289 return lastStartOffset;
298 CPP_UTILITIES_UNUSED(diag)
std::uint32_t m_samplingFrequency
std::streamoff makeHeader(std::ostream &stream, Diagnostics &diag)
Writes the FLAC metadata header to the specified outputStream.
void setTypeInfo(const TypeInfoType &typeInfo)
Sets the type info of the current TagField.
The Diagnostics class is a container for DiagMessage.
Contains all classes and functions of the TagInfo library.
TagValue & value()
Returns the value of the current TagField.
const IdentifierType & id() const
Returns the id of the current TagField.
std::uint64_t m_sampleCount
CppUtilities::BinaryReader m_reader
std::ostream & outputStream()
Returns the associated output stream.
void internalParseHeader(Diagnostics &diag) override
This method is internally called to parse header information. It needs to be implemented when subclas...
std::uint64_t size() const
Returns the size in bytes if known; otherwise returns 0.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
CppUtilities::TimeSpan m_duration
bool isEmpty() const
Returns whether an empty value is assigned.
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
std::uint16_t m_channelCount
FlacMetaDataBlockType
The FlacMetaDataBlockType enum specifies the type of FlacMetaDataBlockHeader.
CppUtilities::NativeFileStream & stream()
Returns the std::fstream for the current instance.
std::uint16_t m_bitsPerSample
The exception that is thrown when the data to be parsed holds no parsable information (e....
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
std::uint64_t m_startOffset
The exception that is thrown when the data to be parsed is truncated and therefore can not be parsed ...
The TagValue class wraps values of different types. It is meant to be assigned to a tag field.
VorbisComment * createVorbisComment()
Creates a new Vorbis comment for the stream.
std::uint64_t startOffset() const
Returns the start offset of the track in the associated stream.
void setId(const IdentifierType &id)
Sets the id of the current Tag Field.
static void makePadding(std::ostream &stream, std::uint32_t size, bool isLast, Diagnostics &diag)
Writes padding of the specified size to the specified stream.
bool removeVorbisComment()
Removes the assigned Vorbis comment if one is assigned; does nothing otherwise.