Tag Parser  10.0.1
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
genericcontainer.h
Go to the documentation of this file.
1 #ifndef TAG_PARSER_GENERICCONTAINER_H
2 #define TAG_PARSER_GENERICCONTAINER_H
3 
4 #include "./abstractcontainer.h"
5 
6 #include <algorithm>
7 #include <memory>
8 #include <vector>
9 
10 namespace TagParser {
11 
22 template <class FileInfoType, class TagType, class TrackType, class ElementType> class TAG_PARSER_EXPORT GenericContainer : public AbstractContainer {
23  friend FileInfoType;
24 
25 public:
26  GenericContainer(FileInfoType &fileInfo, std::uint64_t startOffset);
27  ~GenericContainer() override;
28 
29  void validateElementStructure(Diagnostics &diag, AbortableProgressFeedback &progress, std::uint64_t *paddingSize = nullptr);
30  FileInfoType &fileInfo() const;
31  ElementType *firstElement() const;
32  const std::vector<std::unique_ptr<ElementType>> &additionalElements() const;
33  std::vector<std::unique_ptr<ElementType>> &additionalElements();
34  TagType *tag(std::size_t index) override;
35  std::size_t tagCount() const override;
36  TrackType *track(std::size_t index) override;
37  TrackType *trackById(std::uint64_t id);
38  std::size_t trackCount() const override;
39  const std::vector<std::unique_ptr<TagType>> &tags() const;
40  std::vector<std::unique_ptr<TagType>> &tags();
41  const std::vector<std::unique_ptr<TrackType>> &tracks() const;
42  std::vector<std::unique_ptr<TrackType>> &tracks();
43 
44  TagType *createTag(const TagTarget &target = TagTarget()) override;
45  bool removeTag(Tag *tag) override;
46  void removeAllTags() override;
47  bool addTrack(TrackType *track);
48  bool removeTrack(AbstractTrack *track) override;
49  void removeAllTracks() override;
50  void reset() override;
51 
52  using ContainerFileInfoType = FileInfoType;
55  using ContainerElementType = ElementType;
56 
57 protected:
58  std::unique_ptr<ElementType> m_firstElement;
59  std::vector<std::unique_ptr<ElementType>> m_additionalElements;
60  std::vector<std::unique_ptr<TagType>> m_tags;
61  std::vector<std::unique_ptr<TrackType>> m_tracks;
62 
63 private:
64  FileInfoType *m_fileInfo;
65 };
66 
70 template <class FileInfoType, class TagType, class TrackType, class ElementType>
72  : AbstractContainer(fileInfo.stream(), startOffset)
73  , m_fileInfo(&fileInfo)
74 {
75 }
76 
83 template <class FileInfoType, class TagType, class TrackType, class ElementType>
85 {
86 }
87 
98 template <class FileInfoType, class TagType, class TrackType, class ElementType>
100  Diagnostics &diag, AbortableProgressFeedback &progress, std::uint64_t *paddingSize)
101 {
102  parseHeader(diag, progress);
103  if (m_firstElement) {
104  m_firstElement->validateSubsequentElementStructure(diag, paddingSize, &progress);
105  }
106 }
107 
113 template <class FileInfoType, class TagType, class TrackType, class ElementType>
115 {
116  return *m_fileInfo;
117 }
118 
131 template <class FileInfoType, class TagType, class TrackType, class ElementType>
133 {
134  return m_firstElement.get();
135 }
136 
144 template <class FileInfoType, class TagType, class TrackType, class ElementType>
145 inline const std::vector<std::unique_ptr<ElementType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::additionalElements() const
146 {
147  return m_additionalElements;
148 }
149 
157 template <class FileInfoType, class TagType, class TrackType, class ElementType>
159 {
160  return m_additionalElements;
161 }
162 
163 template <class FileInfoType, class TagType, class TrackType, class ElementType>
165 {
166  return m_tags[index].get();
167 }
168 
169 template <class FileInfoType, class TagType, class TrackType, class ElementType>
171 {
172  return m_tags.size();
173 }
174 
175 template <class FileInfoType, class TagType, class TrackType, class ElementType>
177 {
178  return m_tracks[index].get();
179 }
180 
181 template <class FileInfoType, class TagType, class TrackType, class ElementType>
183 {
184  for (auto &track : m_tracks) {
185  if (track->id() == id) {
186  return track.get();
187  }
188  }
189  return nullptr;
190 }
191 
192 template <class FileInfoType, class TagType, class TrackType, class ElementType>
194 {
195  return m_tracks.size();
196 }
197 
207 template <class FileInfoType, class TagType, class TrackType, class ElementType>
208 inline const std::vector<std::unique_ptr<TagType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tags() const
209 {
210  return m_tags;
211 }
212 
222 template <class FileInfoType, class TagType, class TrackType, class ElementType>
223 inline std::vector<std::unique_ptr<TagType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tags()
224 {
225  return m_tags;
226 }
227 
237 template <class FileInfoType, class TagType, class TrackType, class ElementType>
238 inline const std::vector<std::unique_ptr<TrackType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tracks() const
239 {
240  return m_tracks;
241 }
242 
252 template <class FileInfoType, class TagType, class TrackType, class ElementType>
253 inline std::vector<std::unique_ptr<TrackType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tracks()
254 {
255  return m_tracks;
256 }
257 
258 template <class FileInfoType, class TagType, class TrackType, class ElementType>
260 {
261  // check whether a tag matching the specified target is already assigned
262  if (!m_tags.empty()) {
263  if (!target.isEmpty() && m_tags.front()->supportsTarget()) {
264  for (auto &tag : m_tags) {
265  if (tag->target() == target) {
266  return tag.get();
267  }
268  }
269  } else {
270  return m_tags.front().get();
271  }
272  }
273 
274  // a new tag must be created
275  m_tags.emplace_back(std::make_unique<TagType>());
276  auto &tag = m_tags.back();
277  tag->setTarget(target);
278  return tag.get();
279 }
280 
281 template <class FileInfoType, class TagType, class TrackType, class ElementType>
283 {
284  if (auto size = m_tags.size()) {
285  m_tags.erase(std::remove_if(m_tags.begin(), m_tags.end(),
286  [tag](const std::unique_ptr<TagType> &existingTag) -> bool { return static_cast<Tag *>(existingTag.get()) == tag; }),
287  m_tags.end());
288  return size != m_tags.size();
289  }
290  return false;
291 }
292 
293 template <class FileInfoType, class TagType, class TrackType, class ElementType>
295 {
296  m_tags.clear();
297 }
298 
315 template <class FileInfoType, class TagType, class TrackType, class ElementType>
317 {
318  if (areTracksParsed() && supportsTrackModifications()) {
319  // ensure ID is unique
320  auto id = track->id();
321  ensureIdIsUnique:
322  for (const auto &existingTrack : m_tracks) {
323  if (existingTrack->id() == id) {
324  ++id;
325  goto ensureIdIsUnique;
326  }
327  }
328  track->setId(id);
329 
330  m_tracks.emplace_back(track);
331  return m_tracksAltered = true;
332  }
333  return false;
334 }
335 
336 template <class FileInfoType, class TagType, class TrackType, class ElementType>
338 {
339  bool removed = false;
340  if (areTracksParsed() && supportsTrackModifications() && !m_tracks.empty()) {
341  for (auto i = m_tracks.end() - 1, begin = m_tracks.begin();; --i) {
342  if (static_cast<AbstractTrack *>(i->get()) == track) {
343  i->release();
344  m_tracks.erase(i);
345  removed = true;
346  }
347  if (i == begin) {
348  break;
349  }
350  }
351  if (removed) {
352  m_tracksAltered = true;
353  }
354  }
355  return removed;
356 }
357 
358 template <class FileInfoType, class TagType, class TrackType, class ElementType>
360 {
361  if (areTracksParsed() && supportsTrackModifications() && m_tracks.size()) {
362  m_tracks.clear();
363  m_tracksAltered = true;
364  }
365 }
366 
367 template <class FileInfoType, class TagType, class TrackType, class ElementType>
369 {
371  m_firstElement.reset();
372  m_additionalElements.clear();
373  m_tracks.clear();
374  m_tags.clear();
375 }
376 
377 } // namespace TagParser
378 
379 #endif // TAG_PARSER_GENERICCONTAINER_H
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
The AbstractContainer class provides an interface and common functionality to parse and make a certai...
virtual void reset()
Discards all parsing results.
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
Definition: abstracttrack.h:65
The Diagnostics class is a container for DiagMessage.
Definition: diagnostics.h:156
The GenericContainer class helps parsing header, track, tag and chapter information of a file.
const std::vector< std::unique_ptr< TrackType > > & tracks() const
Returns the tracks of the file.
bool removeTrack(AbstractTrack *track) override
Removes the specified track to the container.
TagType * tag(std::size_t index) override
Returns the tag with the specified index.
void validateElementStructure(Diagnostics &diag, AbortableProgressFeedback &progress, std::uint64_t *paddingSize=nullptr)
Parses all elements the file consists of.
bool removeTag(Tag *tag) override
Removes the specified tag from the container.
TrackType * track(std::size_t index) override
Returns the track with the specified index.
void removeAllTags() override
Removes all tags attached to the container.
std::vector< std::unique_ptr< TrackType > > m_tracks
TagType * createTag(const TagTarget &target=TagTarget()) override
Creates and returns a tag for the specified target.
const std::vector< std::unique_ptr< TagType > > & tags() const
Returns the tags of the file.
GenericContainer(FileInfoType &fileInfo, std::uint64_t startOffset)
Constructs a new container for the specified fileInfo at the specified startOffset.
TrackType * trackById(std::uint64_t id)
bool addTrack(TrackType *track)
Adds the specified track to the container.
std::unique_ptr< ElementType > m_firstElement
FileInfoType & fileInfo() const
Returns the related file info.
~GenericContainer() override
Destroys the container.
std::vector< std::unique_ptr< ElementType > > m_additionalElements
void removeAllTracks() override
Removes all tracks from the container.
std::vector< std::unique_ptr< TrackType > > & tracks()
Returns the tracks of the file.
ElementType * firstElement() const
Returns the first element of the file if available; otherwiese returns nullptr.
std::vector< std::unique_ptr< TagType > > m_tags
std::size_t trackCount() const override
Returns the number of tracks the container holds.
std::vector< std::unique_ptr< TagType > > & tags()
Returns the tags of the file.
const std::vector< std::unique_ptr< ElementType > > & additionalElements() const
Returns all available additional elements.
void reset() override
Discards all parsing results.
std::size_t tagCount() const override
Returns the number of tags attached to the container.
std::vector< std::unique_ptr< ElementType > > & additionalElements()
Returns all available additional elements.
The TagTarget class specifies the target of a tag.
Definition: tagtarget.h:20
bool isEmpty() const
Returns an indication whether the target is empty.
Definition: tagtarget.h:168
The Tag class is used to store, read and write tag information.
Definition: tag.h:108
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10
TagType
Specifies the tag type.
Definition: tag.h:20
TrackType
The TrackType enum specifies the underlying file type of a track and the concrete class of the track ...
Definition: abstracttrack.h:31