File indexing completed on 2024-05-19 04:56:31

0001 /**
0002  * \file oggfile.hpp
0003  * Handling of Ogg files.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 26 Sep 2005
0008  *
0009  * Copyright (C) 2005-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 <QList>
0030 #include "oggflacconfig.h"
0031 #include "taggedfile.h"
0032 
0033 
0034  /** List box item containing OGG file */
0035 class OggFile : public TaggedFile {
0036 public:
0037   /**
0038    * Constructor.
0039    *
0040    * @param idx index in tagged file system model
0041    */
0042   explicit OggFile(const QPersistentModelIndex& idx);
0043 
0044   /**
0045    * Destructor.
0046    */
0047   ~OggFile() override = default;
0048 
0049   /**
0050    * Get key of tagged file format.
0051    * @return "OggMetadata".
0052    */
0053   QString taggedFileKey() const override;
0054 
0055   /**
0056    * Get features supported.
0057    * @return bit mask with Feature flags set.
0058    */
0059   int taggedFileFeatures() const override;
0060 
0061   /**
0062    * Read tags from file.
0063    *
0064    * @param force true to force reading even if tags were already read.
0065    */
0066   void readTags(bool force) override;
0067 
0068   /**
0069    * Write tags to file and rename it if necessary.
0070    *
0071    * @param force   true to force writing even if file was not changed.
0072    * @param renamed will be set to true if the file was renamed,
0073    *                i.e. the file name is no longer valid, else *renamed
0074    *                is left unchanged
0075    * @param preserve true to preserve file time stamps
0076    *
0077    * @return true if ok, false if the file could not be written or renamed.
0078    */
0079   bool writeTags(bool force, bool* renamed, bool preserve) override;
0080 
0081   /**
0082    * Free resources allocated when calling readTags().
0083    *
0084    * @param force true to force clearing even if the tags are modified
0085    */
0086   void clearTags(bool force) override;
0087 
0088   /**
0089    * Remove frames.
0090    *
0091    * @param tagNr tag number
0092    * @param flt filter specifying which frames to remove
0093    */
0094   void deleteFrames(Frame::TagNumber tagNr, const FrameFilter& flt) override;
0095 
0096 
0097   /**
0098    * Check if tag information has already been read.
0099    *
0100    * @return true if information is available,
0101    *         false if the tags have not been read yet, in which case
0102    *         hasTag() does not return meaningful information.
0103    */
0104   bool isTagInformationRead() const override;
0105 
0106   /**
0107    * Check if file has a tag.
0108    *
0109    * @param tagNr tag number
0110    * @return true if a tag is available.
0111    * @see isTagInformationRead()
0112    */
0113   bool hasTag(Frame::TagNumber tagNr) const override;
0114 
0115   /**
0116    * Get technical detail information.
0117    *
0118    * @param info the detail information is returned here
0119    */
0120   void getDetailInfo(DetailInfo& info) const override;
0121 
0122   /**
0123    * Get duration of file.
0124    *
0125    * @return duration in seconds,
0126    *         0 if unknown.
0127    */
0128   unsigned getDuration() const override;
0129 
0130   /**
0131    * Get file extension including the dot.
0132    *
0133    * @return file extension ".ogg".
0134    */
0135   QString getFileExtension() const override;
0136 
0137   /**
0138    * Get the format of tag.
0139    *
0140    * @param tagNr tag number
0141    * @return "Vorbis".
0142    */
0143   QString getTagFormat(Frame::TagNumber tagNr) const override;
0144 
0145   /**
0146    * Get a specific frame from the tags.
0147    *
0148    * @param tagNr tag number
0149    * @param type  frame type
0150    * @param frame the frame is returned here
0151    *
0152    * @return true if ok.
0153    */
0154   bool getFrame(Frame::TagNumber tagNr, Frame::Type type, Frame& frame) const override;
0155 
0156   /**
0157    * Set a frame in the tags.
0158    *
0159    * @param tagNr tag number
0160    * @param frame frame to set
0161    *
0162    * @return true if ok.
0163    */
0164   bool setFrame(Frame::TagNumber tagNr, const Frame& frame) override;
0165 
0166   /**
0167    * Add a frame in the tags.
0168    *
0169    * @param tagNr tag number
0170    * @param frame frame to add
0171    *
0172    * @return true if ok.
0173    */
0174   bool addFrame(Frame::TagNumber tagNr, Frame& frame) override;
0175 
0176   /**
0177    * Delete a frame in the tags.
0178    *
0179    * @param tagNr tag number
0180    * @param frame frame to delete.
0181    *
0182    * @return true if ok.
0183    */
0184   bool deleteFrame(Frame::TagNumber tagNr, const Frame& frame) override;
0185 
0186   /**
0187    * Get all frames in tag.
0188    *
0189    * @param tagNr tag number
0190    * @param frames frame collection to set.
0191    */
0192   void getAllFrames(Frame::TagNumber tagNr, FrameCollection& frames) override;
0193 
0194   /**
0195    * Get a list of frame IDs which can be added.
0196    * @param tagNr tag number
0197    * @return list with frame IDs.
0198    */
0199   QStringList getFrameIds(Frame::TagNumber tagNr) const override;
0200 
0201 protected:
0202   /** Vorbis comment field. */
0203   class CommentField {
0204   public:
0205     /** Constructor. */
0206     CommentField(const QString& name = QString(),
0207                  const QString& value = QString())
0208       : m_name(name), m_value(value) {}
0209     /**
0210      * Get name.
0211      * @return name.
0212      */
0213     QString getName() const { return m_name; }
0214     /**
0215      * Get value.
0216      * @return value.
0217      */
0218     QString getValue() const { return m_value; }
0219     /**
0220      * Set value.
0221      * @param value value
0222      */
0223     void setValue(const QString& value) { m_value = value; }
0224 
0225   private:
0226     QString m_name;
0227     QString m_value;
0228   };
0229 
0230   /** Vorbis comment list. */
0231   class CommentList : public QList<CommentField> {
0232   public:
0233     /** Constructor. */
0234     CommentList() {}
0235     /** Destructor. */
0236     ~CommentList() {}
0237     /**
0238      * Get value.
0239      * @param name name
0240      * @return value, "" if not found.
0241      */
0242     QString getValue(const QString& name) const;
0243     /**
0244      * Set value.
0245      * @param name name
0246      * @param value value
0247      * @return true if value was changed.
0248      */
0249     bool setValue(const QString& name, const QString& value);
0250   };
0251 
0252   /**
0253    * Get text field.
0254    *
0255    * @param name name
0256    * @return value, "" if not found,
0257    *         QString::null if the tags have not been read yet.
0258    */
0259   QString getTextField(const QString& name) const;
0260 
0261   /**
0262    * Set text field.
0263    * If value is null or the tags have not been read yet, nothing is changed.
0264    * If value is different from the current value, changed is set.
0265    *
0266    * @param name name
0267    * @param value value, "" to remove, QString::null to do nothing
0268    * @param type frame type
0269    */
0270   void setTextField(const QString& name, const QString& value,
0271                     const Frame::ExtendedType& type);
0272 
0273 protected:
0274   /** true if file has been read. */
0275   bool m_fileRead;
0276   /** Comments of this file. */
0277   CommentList m_comments;
0278 
0279   /** Information about Ogg/Vorbis file. */
0280   struct FileInfo {
0281     /** Constructor. */
0282     FileInfo() : version(0), channels(0),
0283       sampleRate(0), bitrate(0), duration(0), valid(false) {}
0284 
0285     int version;     /**< vorbis encoder version */
0286     int channels;    /**< number of channels */
0287     long sampleRate; /**< sample rate in Hz */
0288     long bitrate;    /**< bitrate in bits/s */
0289     long duration;   /**< duration in seconds */
0290     bool valid;      /**< true if read() was successful */
0291   };
0292 
0293   /** Info about file. */
0294   FileInfo m_fileInfo;
0295 
0296 private:
0297   OggFile(const OggFile&);
0298   OggFile& operator=(const OggFile&);
0299 
0300 #ifdef HAVE_VORBIS
0301   /**
0302    * Read information about an Ogg/Vorbis file.
0303    * @param info file info to fill
0304    * @param fn file name
0305    * @return true if ok.
0306    */
0307   bool readFileInfo(FileInfo& info, const QString& fn) const;
0308 #endif // HAVE_VORBIS
0309 };