1 /***************************************************************************
2     copyright            : (C) 2002 - 2008 by Scott Wheeler
3     email                : wheeler@kde.org
4  ***************************************************************************/
5 
6 /***************************************************************************
7  *   This library is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU Lesser General Public License version   *
9  *   2.1 as published by the Free Software Foundation.                     *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful, but   *
12  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the Free Software   *
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
19  *   02110-1301  USA                                                       *
20  *                                                                         *
21  *   Alternatively, this file is available under the Mozilla Public        *
22  *   License Version 1.1.  You may obtain a copy of the License at         *
23  *   http://www.mozilla.org/MPL/                                           *
24  ***************************************************************************/
25 
26 #ifndef TAGLIB_OGGPAGE_H
27 #define TAGLIB_OGGPAGE_H
28 
29 #include "taglib_export.h"
30 #include "tbytevectorlist.h"
31 
32 namespace TagLib {
33 
34   namespace Ogg {
35 
36     class File;
37     class PageHeader;
38 
39     //! An implementation of Ogg pages
40 
41     /*!
42      * This is an implementation of the pages that make up an Ogg stream.
43      * This handles parsing pages and breaking them down into packets and handles
44      * the details of packets spanning multiple pages and pages that contain
45      * multiple packets.
46      *
47      * In most Xiph.org formats the comments are found in the first few packets,
48      * this however is a reasonably complete implementation of Ogg pages that
49      * could potentially be useful for non-meta data purposes.
50      */
51 
52     class TAGLIB_EXPORT Page
53     {
54     public:
55       /*!
56        * Read an Ogg page from the \a file at the position \a pageOffset.
57        */
58       Page(File *file, long pageOffset);
59 
60       virtual ~Page();
61 
62       /*!
63        * Returns the page's position within the file (in bytes).
64        */
65       long fileOffset() const;
66 
67       /*!
68        * Returns a pointer to the header for this page.  This pointer will become
69        * invalid when the page is deleted.
70        */
71       const PageHeader *header() const;
72 
73       /*!
74        * Returns the index of the page within the Ogg stream.  This helps make it
75        * possible to determine if pages have been lost.
76        *
77        * \see setPageSequenceNumber()
78        */
79       int pageSequenceNumber() const;
80 
81       /*!
82        * Sets the page's position in the stream to \a sequenceNumber.
83        *
84        * \see pageSequenceNumber()
85        */
86       void setPageSequenceNumber(int sequenceNumber);
87 
88       /*!
89        * Returns a copy of the page with \a sequenceNumber set as sequence number.
90        *
91        * \see header()
92        * \see PageHeader::setPageSequenceNumber()
93        *
94        * \deprecated Always returns null.
95        */
96       Page* getCopyWithNewPageSequenceNumber(int sequenceNumber);
97 
98       /*!
99        * Returns the index of the first packet wholly or partially contained in
100        * this page.
101        *
102        * \see setFirstPacketIndex()
103        */
104       int firstPacketIndex() const;
105 
106       /*!
107        * Sets the index of the first packet in the page.
108        *
109        * \see firstPacketIndex()
110        */
111       void setFirstPacketIndex(int index);
112 
113       /*!
114        * When checking to see if a page contains a given packet this set of flags
115        * represents the possible values for that packets status in the page.
116        *
117        * \see containsPacket()
118        */
119       enum ContainsPacketFlags {
120         //! No part of the packet is contained in the page
121         DoesNotContainPacket = 0x0000,
122         //! The packet is wholly contained in the page
123         CompletePacket       = 0x0001,
124         //! The page starts with the given packet
125         BeginsWithPacket     = 0x0002,
126         //! The page ends with the given packet
127         EndsWithPacket       = 0x0004
128       };
129 
130       /*!
131        * Checks to see if the specified \a packet is contained in the current
132        * page.
133        *
134        * \see ContainsPacketFlags
135        */
136       ContainsPacketFlags containsPacket(int index) const;
137 
138       /*!
139        * Returns the number of packets (whole or partial) in this page.
140        */
141       unsigned int packetCount() const;
142 
143       /*!
144        * Returns a list of the packets in this page.
145        *
146        * \note Either or both the first and last packets may be only partial.
147        * \see PageHeader::firstPacketContinued()
148        */
149       ByteVectorList packets() const;
150 
151       /*!
152        * Returns the size of the page in bytes.
153        */
154       int size() const;
155 
156       ByteVector render() const;
157 
158       /*!
159        * Defines a strategy for pagination, or grouping pages into Ogg packets,
160        * for use with pagination methods.
161        *
162        * \note Yes, I'm aware that this is not a canonical "Strategy Pattern",
163        * the term was simply convenient.
164        */
165       enum PaginationStrategy {
166         /*!
167          * Attempt to put the specified set of packets into a single Ogg packet.
168          * If the sum of the packet data is greater than will fit into a single
169          * Ogg page -- 65280 bytes -- this will fall back to repagination using
170          * the recommended page sizes.
171          */
172         SinglePagePerGroup,
173         /*!
174          * Split the packet or group of packets into pages that conform to the
175          * sizes recommended in the Ogg standard.
176          */
177         Repaginate
178       };
179 
180       /*!
181        * Pack \a packets into Ogg pages using the \a strategy for pagination.
182        * The page number indicator inside of the rendered packets will start
183        * with \a firstPage and be incremented for each page rendered.
184        * \a containsLastPacket should be set to true if \a packets contains the
185        * last page in the stream and will set the appropriate flag in the last
186        * rendered Ogg page's header.  \a streamSerialNumber should be set to
187        * the serial number for this stream.
188        *
189        * \note The "absolute granule position" is currently always zeroed using
190        * this method as this suffices for the comment headers.
191        *
192        * \warning The pages returned by this method must be deleted by the user.
193        * You can use List<T>::setAutoDelete(true) to set these pages to be
194        * automatically deleted when this list passes out of scope.
195        *
196        * \see PaginationStrategy
197        * \see List::setAutoDelete()
198        */
199       static List<Page *> paginate(const ByteVectorList &packets,
200                                    PaginationStrategy strategy,
201                                    unsigned int streamSerialNumber,
202                                    int firstPage,
203                                    bool firstPacketContinued = false,
204                                    bool lastPacketCompleted = true,
205                                    bool containsLastPacket = false);
206 
207     protected:
208       /*!
209        * Creates an Ogg packet based on the data in \a packets.  The page number
210        * for each page will be set to \a pageNumber.
211        */
212       Page(const ByteVectorList &packets,
213            unsigned int streamSerialNumber,
214            int pageNumber,
215            bool firstPacketContinued = false,
216            bool lastPacketCompleted = true,
217            bool containsLastPacket = false);
218 
219     private:
220       Page(const Page &);
221       Page &operator=(const Page &);
222 
223       class PagePrivate;
224       PagePrivate *d;
225     };
226   }
227 }
228 #endif
229