MetadataHandlerTaglib.h
Go to the documentation of this file.
1 /*
2  *=BEGIN SONGBIRD GPL
3  *
4  * This file is part of the Songbird web player.
5  *
6  * Copyright(c) 2005-2009 POTI, Inc.
7  * http://www.songbirdnest.com
8  *
9  * This file may be licensed under the terms of of the
10  * GNU General Public License Version 2 (the ``GPL'').
11  *
12  * Software distributed under the License is distributed
13  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14  * express or implied. See the GPL for the specific language
15  * governing rights and limitations.
16  *
17  * You should have received a copy of the GPL along with this
18  * program. If not, go to http://www.gnu.org/licenses/gpl.html
19  * or write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  *=END SONGBIRD GPL
23  */
24 
25 #ifndef __METADATA_HANDLER_TAGLIB_H__
26 #define __METADATA_HANDLER_TAGLIB_H__
27 
28 /* *****************************************************************************
29  *******************************************************************************
30  *
31  * Taglib metadata handler.
32  *
33  *******************************************************************************
34  ******************************************************************************/
35 
41 /* *****************************************************************************
42  *
43  * Taglib metadata handler configuration.
44  *
45  ******************************************************************************/
46 
47 /*
48  * Taglib metadata handler XPCOM component definitions.
49  */
50 
51 #define SONGBIRD_METADATAHANDLERTAGLIB_CONTRACTID \
52  "@songbirdnest.com/Songbird/MetadataHandler/Taglib;1"
53 #define SONGBIRD_METADATAHANDLERTAGLIB_CLASSNAME \
54  "Songbird Taglib Metadata Handler Component"
55 #define SONGBIRD_METADATAHANDLERTAGLIB_CID \
56 { \
57  0x62f2be31, \
58  0x54cf, \
59  0x4728, \
60  { 0x84, 0xe8, 0x92, 0x3f, 0x52, 0x15, 0xb9, 0x2a } \
61 }
62 
63 /* *****************************************************************************
64  *
65  * Taglib metadata handler imported services.
66  *
67  ******************************************************************************/
68 
69 /* Mozilla imports. */
70 #include <nsCOMPtr.h>
71 #include <nsIChannel.h>
72 #include <nsICharsetDetectionObserver.h>
73 #include <nsIFileProtocolHandler.h>
74 #include <nsIResProtocolHandler.h>
75 #include <nsIURL.h>
76 #include <nsStringGlue.h>
77 #include <nsMemory.h>
78 #include <nsTArray.h>
79 #include <nsAutoPtr.h>
80 
81 /* Songbird imports. */
82 #include <sbIMetadataHandler.h>
83 #include <sbISeekableChannel.h>
84 #include <sbITagLibChannelFileIOManager.h>
85 
86 /* TagLib imports. */
87 #include <flacfile.h>
88 #include <fileref.h>
89 #include <mpegfile.h>
90 #include <asffile.h>
91 #include <vorbisfile.h>
92 #include <id3v1tag.h>
93 #include <id3v2tag.h>
94 #include <mp4file.h>
95 #include <mp4tag.h>
96 #include <apetag.h>
97 #include <tag.h>
98 #include <tfile.h>
99 #include <xiphcomment.h>
100 #include <attachedpictureframe.h>
101 
102 #include <nsAutoLock.h>
103 
104 /* *****************************************************************************
105  *
106  * Taglib metadata handler classes.
107  *
108  ******************************************************************************/
109 
110 /*
111  * sbMetadataHandlerTaglib class
112  */
113 
114 class nsICharsetDetector;
115 
118  public nsICharsetDetectionObserver
119 {
120  /*
121  * Taglib metadata handler configuration.
122  *
123  * MAX_SCAN_BYTES Maximum number of bytes to scan for tags.
124  *
125  * The taglib library scans files looking for various markers such as tag
126  * markers and frame markers. In order to prevent scanning the entirety of
127  * files that are corrupt or not of the expected format, the number of
128  * scanned bytes is limited to the value specified by MAX_SCAN_BYTES. If
129  * this value is set to 0, the entire file will be scanned until a valid
130  * marker is found.
131  */
132 
133  static const long MAX_SCAN_BYTES = 100000;
134 
135  /*
136  * mpTagLibChannelFileIOManager
137  * TagLib sbISeekableChannel file IO manager.
138  * mpFileProtocolHandler File protocol handler instance.
139  * mpMetadataPropertyArray Read metadata property values.
140  * mpChannel Metadata file channel.
141  * mpSeekableChannel Metadata channel.
142  * mpURL Metadata file channel URL.
143  * mMetadataChannelID Metadata channel ID.
144  * mMetadataChannelRestart True when metadata channel must be restarted.
145  * mCompleted True when metadata reading is complete.
146  * mMetadataPath Path used to access metadata. Always UTF-8.
147  * (This is atypical for Windows)
148  */
149 
150 private:
151  nsCOMPtr<sbITagLibChannelFileIOManager>
152  mpTagLibChannelFileIOManager;
153  nsCOMPtr<nsIFileProtocolHandler>
154  mpFileProtocolHandler;
155  nsCOMPtr<nsIResProtocolHandler>
156  mpResourceProtocolHandler;
157  nsCOMPtr<sbIMutablePropertyArray> mpMetadataPropertyArray;
158  nsCOMPtr<nsIChannel> mpChannel;
159  nsCOMPtr<sbISeekableChannel>
160  mpSeekableChannel;
161  nsCOMPtr<nsIURL> mpURL;
162  nsCString mMetadataChannelID;
163  PRBool mMetadataChannelRestart;
164  PRBool mCompleted;
165  nsCString mMetadataPath;
166 
167 
168  // When calling Read() keep a cache of any album art
169  // encountered, so that subsequent GetImageData calls
170  // do not have to reload the file.
171  // We keep the data rather than the Taglib::File
172  // because this lets us avoid the taglib lock.
173 
174  struct sbAlbumArt {
175  PRInt32 type;
176  nsCString mimeType;
177  PRUint32 dataLen;
178  PRUint8 *data;
179 
180  sbAlbumArt() : type(0), dataLen(0), data(nsnull) {
181  MOZ_COUNT_CTOR(sbAlbumArt);
182  };
183  ~sbAlbumArt() {
184  MOZ_COUNT_DTOR(sbAlbumArt);
185 
186  // If nobody has claimed the image by the time
187  // this object is destroyed, throw the image away
188  if (dataLen > 0 && data) {
189  NS_Free(data);
190  }
191  };
192  };
193 
194  nsTArray<nsAutoPtr<sbAlbumArt> > mCachedAlbumArt;
195 
196 
197  // Statics to help manage the single threading of taglib
198  static PRLock* sTaglibLock;
199 
200  /* Inherited interfaces. */
201 public:
203  NS_DECL_SBIMETADATAHANDLER
204  NS_DECL_SBISEEKABLECHANNELLISTENER
205 
206  /*
207  * Public taglib metadata handler services.
208  */
209 
211 
212  virtual ~sbMetadataHandlerTaglib();
213 
214  nsresult Init();
215 
216  static nsresult ModuleConstructor(nsIModule* aSelf);
217  static void ModuleDestructor(nsIModule* aSelf);
218 
219  /* nsICharsetDetectionObserver */
220  NS_IMETHOD Notify(const char* aCharset, nsDetectionConfident aConf);
221 
222  /*
223  * Private taglib metadata handler class services.
224  *
225  * sNextChannelID Next channel ID to use.
226  */
227 
228 private:
229  static PRUint32 sNextChannelID;
230 
231 private:
232  nsresult ReadInternal(
233  PRInt32 *pReadCount);
234  nsresult WriteInternal(
235  PRInt32 *pWriteCount);
236 
237  nsresult GetImageDataInternal(
238  PRInt32 aType,
239  nsACString &aMimeType,
240  PRUint32 *aDataLen,
241  PRUint8 **aData);
242 
243  nsresult SetImageDataInternal(
244  PRInt32 aType,
245  const nsAString &aURL);
246 
247  nsresult RemoveAllImagesMP3(
248  TagLib::MPEG::File *aMPEGFile,
249  PRInt32 imageType);
250 
251  nsresult RemoveAllImagesOGG(
252  TagLib::Ogg::Vorbis::File *aMPEGFile,
253  PRInt32 imageType);
254 
255  nsresult ReadImageFile(
256  const nsAString &imageSpec,
257  PRUint8* &imageData,
258  PRUint32 &imageDataSize,
259  nsCString &imageMimeType);
260 
261  nsresult WriteMP3Image(
262  TagLib::MPEG::File *aFile,
263  PRInt32 aType,
264  const nsAString &imageSpec);
265 
266  nsresult WriteOGGImage(
267  TagLib::Ogg::Vorbis::File *aFile,
268  PRInt32 aType,
269  const nsAString &imageSpec);
270 
271  nsresult WriteMP4Image(
272  TagLib::MP4::File *aFile,
273  PRInt32 aType,
274  const nsAString &imageSpec);
275 
276  nsresult ReadImageID3v2(
277  TagLib::ID3v2::Tag *aTag,
278  PRInt32 aType,
279  nsACString &aMimeType,
280  PRUint32 *aDataLen,
281  PRUint8 **aData);
282 
283  nsresult ReadImageITunes(
284  TagLib::MP4::Tag *aTag,
285  nsACString &aMimeType,
286  PRUint32 *aDataLen,
287  PRUint8 **aData);
288 
289  nsresult ReadImageOgg(
290  TagLib::Ogg::XiphComment *aTag,
291  PRInt32 aType,
292  nsACString &aMimeType,
293  PRUint32 *aDataLen,
294  PRUint8 **aData);
295 
296  nsresult ReadImageFlac(
297  TagLib::FLAC::File *pTagFile,
298  PRInt32 aType,
299  nsACString &aMimeType,
300  PRUint32 *aDataLen,
301  PRUint8 **aData);
302  /*
303  * Private taglib metadata handler ID3v2 services.
304  */
305  void ReadID3v2Tags(
306  TagLib::ID3v2::Tag *pTag,
307  const char *charset = 0);
308 
309  void AddGracenoteMetadataMP3(
310  TagLib::MPEG::File *MPEGFile);
311 
312  /*
313  * Private taglib metadata handler APE services.
314  */
315 
316 private:
317  void ReadAPETags(
318  TagLib::APE::Tag *pTag);
319 
320  /*
321  * Private taglib metadata handler Xiph services.
322  */
323 
324 private:
325  void ReadXiphTags(
326  TagLib::Ogg::XiphComment *pTag);
327 
328  void AddXiphTag(
329  TagLib::Ogg::FieldListMap &fieldListMap,
330  const char *fieldName,
331  const char *metadataName);
332 
333  void AddGracenoteMetadataXiph(
334  TagLib::Ogg::Vorbis::File *oggFile);
335 
336  /*
337  * Private taglib metadata handler MP4 services.
338  */
339 
340 private:
341  void ReadMP4Tags(
342  TagLib::MP4::Tag *pTag);
343 
344 
345  /*
346  * Private taglib metadata handler services.
347  */
348 
349 private:
350  // please be careful to call these appropriately.
351  // don't call release without first doing an acquire
352  // and don't try to acquire twice in a thread without releasing.
353  nsresult AcquireTaglibLock();
354  nsresult ReleaseTaglibLock();
355 
356  nsresult CheckChannelRestart();
357 
358  nsresult ReadMetadata();
359 
360  void GuessCharset(
361  TagLib::Tag *pTag,
362  nsACString& _retval);
363 
364  nsresult RunCharsetDetector(
365  nsICharsetDetector *aDetector,
367 
368  void ConvertCharset(
369  TagLib::String aString,
370  const char *aCharset,
371  nsAString& aResult);
372 
373  void CompleteRead();
374 
375  nsresult AddSeparatedNumbers(
377  const char *baseProperty,
378  const char *countProperty);
379 
380  PRBool ReadFile(
381  TagLib::File *pTagFile,
382  const char *aCharset = 0);
383 
384  PRBool ReadMPEGFile();
385 
386  PRBool ReadASFFile();
387 
388  PRBool ReadMP4File();
389 
390  PRBool ReadOGGFile();
391 
392  PRBool ReadOGAFile();
393 
394  PRBool ReadFLACFile();
395 
396  PRBool ReadMPCFile();
397 
398  nsresult AddMetadataValue(
399  const char *name,
400  TagLib::String value,
401  const char *charset);
402 
403  nsresult AddMetadataValue(
404  const char *name,
405  bool value);
406 
407  nsresult AddMetadataValue(
408  const char *name,
409  PRUint64 value);
410 
411  nsresult AddMetadataValue(
412  const char *name,
413  const nsAString &value);
414 
415  void FixTrackDiscNumber(
416  nsString numberKey,
417  nsString totalKey);
418 
419 private:
420  /*
421  * Functions to write Metadata to tags
422  */
423  nsresult WriteBasic(
424  TagLib::PropertyMap *properties);
425  nsresult WriteSeparatedNumbers(
426  TagLib::PropertyMap *properties,
428  const nsAString &baseProperty,
429  const nsAString &countProperty);
430  nsresult WriteAPE(
431  TagLib::APE::Tag *tag);
432  nsresult WriteASF(
433  TagLib::ASF::Tag *tag);
434  nsresult WriteID3v1(
435  TagLib::ID3v1::Tag *tag);
436  nsresult WriteID3v2(
437  TagLib::ID3v2::Tag *tag);
438  nsresult WriteMP4(
439  TagLib::MP4::Tag *tag);
440  nsresult WriteXiphComment(
441  TagLib::Ogg::XiphComment *tag);
442 
443  /*
444  * Private charset detector members
445  */
446 
447 private:
448  // these apply only to the last thing being detected
449  nsCString mLastCharset;
450  nsDetectionConfident mLastConfidence;
451 
452 private:
453  /*
454  * Base64 en-/decoding
455  */
456  std::string base64_decode(std::string const& encoded_string);
457  std::string base64_encode(unsigned char const* bytes_to_encode,
458  unsigned int in_len);
459 };
460 
461 
462 #endif /* __METADATA_HANDLER_TAGLIB_H__ */
NS_IMETHOD Notify(const char *aCharset, nsDetectionConfident aConf)
static void ModuleDestructor(nsIModule *aSelf)
static nsresult ModuleConstructor(nsIModule *aSelf)
_updateTextAndScrollDataForFrame aContent
An object capable of manipulating the metadata tags for a media file.
A listener interface for sbISeekableChannel.
countRef value
Definition: FeedWriter.js:1423
dataSBGenres SBProperties tag
Definition: tuner2.js:871
observe data
Definition: FeedWriter.js:1329
_updateTextAndScrollDataForFrame aData
converter charset
NS_DECL_ISUPPORTS NS_DECL_SBIMETADATAHANDLER NS_DECL_SBISEEKABLECHANNELLISTENER sbMetadataHandlerTaglib()