Tag Parser  6.4.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 MEDIA_GENERICCONTAINER_H
2 #define MEDIA_GENERICCONTAINER_H
3 
4 #include "./abstractcontainer.h"
5 
6 #include <algorithm>
7 #include <memory>
8 #include <vector>
9 #include <memory>
10 
11 namespace Media {
12 
23 template <class FileInfoType, class TagType, class TrackType, class ElementType>
25 {
26  friend FileInfoType;
27 
28 public:
29  GenericContainer(FileInfoType &fileInfo, uint64 startOffset);
31 
32  void validateElementStructure(NotificationList &gatheredNotifications, uint64 *paddingSize = nullptr);
33  FileInfoType &fileInfo() const;
34  ElementType *firstElement() const;
35  const std::vector<std::unique_ptr<ElementType> > &additionalElements() const;
36  std::vector<std::unique_ptr<ElementType> > &additionalElements();
37  TagType *tag(std::size_t index);
38  std::size_t tagCount() const;
39  TrackType *track(std::size_t index);
40  TrackType *trackById(uint64 id);
41  std::size_t trackCount() const;
42  const std::vector<std::unique_ptr<TagType> > &tags() const;
43  std::vector<std::unique_ptr<TagType> > &tags();
44  const std::vector<std::unique_ptr<TrackType> > &tracks() const;
45  std::vector<std::unique_ptr<TrackType> > &tracks();
46 
47  TagType *createTag(const TagTarget &target = TagTarget());
48  bool removeTag(Tag *tag);
49  void removeAllTags();
50  bool addTrack(TrackType *track);
51  bool removeTrack(AbstractTrack *track);
52  void removeAllTracks();
53  void reset();
54 
55  typedef FileInfoType fileInfoType;
56  typedef TagType tagType;
58  typedef ElementType elementType;
59 
60 protected:
61  std::unique_ptr<ElementType> m_firstElement;
62  std::vector<std::unique_ptr<ElementType> > m_additionalElements;
63  std::vector<std::unique_ptr<TagType> > m_tags;
64  std::vector<std::unique_ptr<TrackType> > m_tracks;
65 
66 private:
67  FileInfoType *m_fileInfo;
68 };
69 
73 template <class FileInfoType, class TagType, class TrackType, class ElementType>
75  AbstractContainer(fileInfo.stream(), startOffset),
76  m_fileInfo(&fileInfo)
77 {}
78 
85 template <class FileInfoType, class TagType, class TrackType, class ElementType>
87 {}
88 
99 template <class FileInfoType, class TagType, class TrackType, class ElementType>
101 {
102  parseHeader();
103  if(m_firstElement) {
104  m_firstElement->validateSubsequentElementStructure(gatheredNotifications, paddingSize);
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(), [tag] (const std::unique_ptr<TagType> &existingTag) -> bool {
286  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 &track : m_tracks) {
323  if(track->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 {
370  AbstractContainer::reset();
371  m_firstElement.reset();
372  m_additionalElements.clear();
373  m_tracks.clear();
374  m_tags.clear();
375 }
376 
377 } // namespace Media
378 
379 #endif // MEDIA_GENERICCONTAINER_H
bool isEmpty() const
Returns an indication whether the target is empty.
Definition: tagtarget.h:177
The GenericContainer class helps parsing header, track, tag and chapter information of a file...
std::vector< std::unique_ptr< TrackType > > m_tracks
TrackType
Specifies the track type.
Definition: abstracttrack.h:28
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
Definition: abstracttrack.h:40
std::vector< std::unique_ptr< ElementType > > m_additionalElements
The Tag class is used to store, read and write tag information.
Definition: tag.h:98
GenericContainer(FileInfoType &fileInfo, uint64 startOffset)
Constructs a new container for the specified fileInfo at the specified startOffset.
The AbstractContainer class provides an interface and common functionality to parse and make a certai...
std::vector< std::unique_ptr< TagType > > m_tags
std::list< Notification > NotificationList
Definition: notification.h:39
TagType
Specifies the tag type.
Definition: tag.h:21
The TagTarget class specifies the target of a tag.
Definition: tagtarget.h:31
Contains all classes and functions of the TagInfo library.
Definition: exceptions.h:9
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
std::unique_ptr< ElementType > m_firstElement