55 #include <sbILibraryUtils.h>
60 #include "sbIPropertyArray.h"
65 #include <nsComponentManagerUtils.h>
67 #include <nsIMIMEService.h>
68 #include <nsIBinaryInputStream.h>
69 #include <nsIIOService.h>
70 #include <nsIProtocolHandler.h>
71 #include <nsIStandardURL.h>
72 #include <nsICharsetDetector.h>
73 #include <nsICharsetConverterManager.h>
74 #include <nsIUnicodeDecoder.h>
75 #include <nsIContentSniffer.h>
76 #include <nsNetUtil.h>
77 #include <nsServiceManagerUtils.h>
78 #include <nsStringGlue.h>
81 #include <nsUnicharUtils.h>
86 #include <oggflacfile.h>
89 #include <urllinkframe.h>
92 #include <vorbisfile.h>
93 #include <uniquefileidentifierframe.h>
94 #include <textidentificationframe.h>
95 #include <tpropertymap.h>
105 #define WRITE_PROPERTY(tmp_result, SB_PROPERTY, taglibName) \
107 tmp_result = mpMetadataPropertyArray->GetPropertyValue( \
108 NS_LITERAL_STRING(SB_PROPERTY), propertyValue); \
109 if (NS_SUCCEEDED(tmp_result)) { \
110 TagLib::String key = TagLib::String(taglibName, \
111 TagLib::String::UTF8); \
112 TagLib::String value = TagLib::String( \
113 NS_ConvertUTF16toUTF8(propertyValue).BeginReading(), \
114 TagLib::String::UTF8); \
115 properties->erase(key); \
116 if (!value.isEmpty()) { \
117 TagLib::StringList valueList = \
118 TagLib::StringList(value); \
119 properties->insert(key, valueList); \
123 #define GET_PROPERTY(taglibid) \
124 properties[TagLib::String(taglibid)].toString(", ")
125 #define TAGLIB1_PROPERTIES_WORKAROUND(pTag) \
127 if (dynamic_cast<TagLib::APE::Tag*>(pTag)){ \
128 properties.merge(dynamic_cast<TagLib::APE::Tag*>(pTag) \
131 if (dynamic_cast<TagLib::ASF::Tag*>(pTag)){ \
132 properties.merge(dynamic_cast<TagLib::ASF::Tag*>(pTag) \
135 if (dynamic_cast<TagLib::ID3v1::Tag*>(pTag)){ \
136 properties.merge(dynamic_cast<TagLib::ID3v1::Tag*>(pTag)\
139 if (dynamic_cast<TagLib::ID3v2::Tag*>(pTag)){ \
140 properties.merge(dynamic_cast<TagLib::ID3v2::Tag*>(pTag)\
143 if (dynamic_cast<TagLib::MP4::Tag*>(pTag)){ \
144 properties.merge(dynamic_cast<TagLib::MP4::Tag*>(pTag) \
147 if (dynamic_cast<TagLib::Ogg::XiphComment*>(pTag)){ \
149 dynamic_cast<TagLib::Ogg::XiphComment*>(pTag) \
157 #define SB_GN_PROP_EXTENDEDDATA "http://gracenote.com/pos/1.0#extendedData"
158 #define SB_GN_PROP_TAGID "http://gracenote.com/pos/1.0#tagId"
161 #define MAX_MPEG_IMAGE_SIZE 16777216 // MPEG (ID3v2)
170 static PRLogModuleInfo* gLog = nsnull;
171 #define LOG(args) PR_BEGIN_MACRO \
173 gLog = PR_NewLogModule("sbMetadataHandlerTaglib"); \
175 PR_LOG(gLog, PR_LOG_DEBUG, args); \
183 #define GUESS_CHARSET_MIN_CHAR_COUNT 256
185 PRLock* sbMetadataHandlerTaglib::sTaglibLock = nsnull;
196 nsICharsetDetectionObserver)
228 NS_IMETHODIMP sbMetadataHandlerTaglib::Vote(
229 const nsAString &
url,
239 if ( (_url.Find(
".flac", PR_TRUE) != -1)
240 || (_url.Find(
".mpc", PR_TRUE) != -1)
241 || (_url.Find(
".mp3", PR_TRUE) != -1)
242 || (_url.Find(
".m4a", PR_TRUE) != -1)
243 || (_url.Find(
".m4p", PR_TRUE) != -1)
244 || (_url.Find(
".m4v", PR_TRUE) != -1)
245 || (_url.Find(
".m4r", PR_TRUE) != -1)
246 || (_url.Find(
".aac", PR_TRUE) != -1)
247 || (_url.Find(
".mp4", PR_TRUE) != -1)
248 || (_url.Find(
".wv", PR_TRUE) != -1)
249 || (_url.Find(
".spx", PR_TRUE) != -1)
250 || (_url.Find(
".tta", PR_TRUE) != -1)
251 || (_url.Find(
".oga", PR_TRUE) != -1)
252 || (_url.Find(
".ogm", PR_TRUE) != -1)
253 || (_url.Find(
".ogg", PR_TRUE) != -1)
254 || (_url.Find(
".wma", PR_TRUE) != -1)
255 || (_url.Find(
".wmv", PR_TRUE) != -1))
261 else if ( (_url.Find(
".avi", PR_TRUE) != -1)
262 || (_url.Find(
".wav", PR_TRUE) != -1))
270 nsCOMPtr<nsIIOService>
ios = do_GetIOService(&rv);
271 NS_ENSURE_SUCCESS(rv, rv);
272 nsCOMPtr<nsIProtocolHandler> protocolHandler;
275 rv = ios->ExtractScheme(NS_ConvertUTF16toUTF8(_url), scheme);
276 if (NS_SUCCEEDED(rv)) {
277 rv = ios->GetProtocolHandler(scheme.BeginReading(),
278 getter_AddRefs(protocolHandler));
282 LOG((
"sbMetadataHandlerTaglib::Vote - can't handle scheme %s\n",
283 scheme.BeginReading()));
290 LOG((
"sbMetadataHandlerTaglib::Vote - voting to %d\n", vote));
296 sbMetadataHandlerTaglib::GetRequiresMainThread(PRBool *_retval)
298 NS_ENSURE_ARG_POINTER(_retval);
299 NS_ENSURE_STATE(mpChannel);
302 nsCOMPtr<nsIURI>
uri;
303 rv = mpChannel->GetURI(getter_AddRefs(uri));
304 NS_ENSURE_SUCCESS(rv, rv);
306 PRBool isFileURI = PR_FALSE;
307 rv = uri->SchemeIs(
"file" , &isFileURI );
308 NS_ENSURE_SUCCESS(rv, rv);
314 *_retval = !isFileURI;
329 NS_IMETHODIMP sbMetadataHandlerTaglib::Read(
332 nsresult rv = NS_ERROR_FAILURE;
333 nsAutoLock lock(sTaglibLock);
337 rv = ReadInternal(pReadCount);
339 NS_ERROR(
"sbMetadataHandlerTaglib::Read caught an exception!");
340 rv = NS_ERROR_FAILURE;
346 nsresult sbMetadataHandlerTaglib::ReadInternal(
349 nsCOMPtr<nsIStandardURL> pStandardURL;
350 nsCOMPtr<nsIURI> pURI;
351 nsCOMPtr<nsIFile> pFile;
354 nsAutoString filePath;
355 PRUint32 unsignedReadCount = 0;
356 PRInt32 readCount = 0;
357 nsresult result =
NS_OK;
360 mCompleted = PR_FALSE;
363 mpTagLibChannelFileIOManager =
365 (
"@songbirdnest.com/Songbird/sbTagLibChannelFileIOManager;1",
369 if (NS_SUCCEEDED(result))
371 mpMetadataPropertyArray =
374 result = mpMetadataPropertyArray->SetStrict(PR_FALSE);
375 NS_ENSURE_SUCCESS(result, result);
380 result = NS_ERROR_NOT_INITIALIZED;
382 if (NS_SUCCEEDED(result))
383 result = mpURL->GetSpec(urlSpec);
384 if (NS_SUCCEEDED(result))
385 result = mpURL->GetScheme(urlScheme);
387 LOG((
"sbMetadataHandlerTaglib::ReadInternal - spec is %s\n",
388 urlSpec.BeginReading()));
393 if (urlScheme.Equals(NS_LITERAL_CSTRING(
"file")))
396 if (NS_SUCCEEDED(result))
398 PRBool useSpec = PR_TRUE;
399 #if XP_UNIX && !XP_MACOSX
400 if (StringBeginsWith(urlSpec, NS_LITERAL_CSTRING(
"file://"))) {
401 nsCString
path(Substring(urlSpec, NS_ARRAY_LENGTH(
"file://") - 1));
402 LOG((
"looking at path %s\n",
path.get()));
404 nsCOMPtr<nsILocalFile> localFile =
405 do_CreateInstance(
"@mozilla.org/file/local;1", &result);
406 if (NS_FAILED(result) || !localFile)
408 nsCOMPtr<nsINetUtil> netUtil =
409 do_CreateInstance(
"@mozilla.org/network/util;1", &result);
410 if (NS_FAILED(result)) {
411 LOG((
"failed to get netutil\n"));
414 nsCString unescapedPath;
415 result = netUtil->UnescapeString(
path, 0, unescapedPath);
416 if (NS_FAILED(result)) {
417 LOG((
"failed to unescape path\n"));
420 result = localFile->SetPersistentDescriptor(unescapedPath);
421 if (NS_FAILED(result)) {
422 LOG((
"failed to set persistent descriptor %s\n", unescapedPath.get()));
426 result = localFile->GetPersistentDescriptor(
path);
427 if (NS_SUCCEEDED(result)) {
428 LOG((
"file path is %s\n",
path.get()));
431 PRBool fileExists = PR_FALSE;
432 result = localFile->Exists(&fileExists);
433 if (NS_FAILED(result) || !fileExists) {
434 LOG((
"file does not exist, falling back"));
437 pFile = do_QueryInterface(localFile, &result);
438 if (NS_SUCCEEDED(result) && pFile)
444 result = mpFileProtocolHandler->GetFileFromURLSpec
446 getter_AddRefs(pFile));
449 if (NS_SUCCEEDED(result)) {
450 #if XP_UNIX && !XP_MACOSX
451 result = pFile->GetNativePath(mMetadataPath);
453 nsString metadataPathU16;
454 result = pFile->GetPath(metadataPathU16);
455 if (NS_SUCCEEDED(result)) {
456 CopyUTF16toUTF8(metadataPathU16, mMetadataPath);
460 LOG((
"using metadata path %s", mMetadataPath.get()));
463 if (NS_SUCCEEDED(result)) {
464 result = ReadMetadata();
466 if (NS_FAILED(result)) {
474 if (NS_SUCCEEDED(result) && !mCompleted)
478 do_CreateInstance(
"@songbirdnest.com/Songbird/SeekableChannel;1",
483 if (NS_SUCCEEDED(result))
487 PR_AtomicIncrement((PRInt32 *) &sNextChannelID);
488 mMetadataPath.AssignLiteral(
"metadata_channel://");
489 mMetadataPath.AppendInt(sNextChannelID);
490 mMetadataChannelID = mMetadataPath;
493 result = mpTagLibChannelFileIOManager->AddChannel
499 if (NS_SUCCEEDED(result))
500 mpSeekableChannel->Open(mpChannel,
this);
503 if (NS_SUCCEEDED(result))
508 if (NS_SUCCEEDED(result) && mCompleted) {
509 result = mpMetadataPropertyArray->GetLength(&unsignedReadCount);
510 readCount = (PRInt32)unsignedReadCount;
514 if (!NS_SUCCEEDED(result))
521 *pReadCount = readCount;
542 NS_IMETHODIMP sbMetadataHandlerTaglib::Write(
543 PRInt32 *pWriteCount)
545 nsresult rv = NS_ERROR_FAILURE;
546 nsAutoLock lock(sTaglibLock);
549 rv = WriteInternal(pWriteCount);
551 NS_ERROR(
"sbMetadataHandlerTaglib::Write caught an exception!");
557 nsresult sbMetadataHandlerTaglib::WriteInternal(
558 PRInt32 *pWriteCount)
560 nsCOMPtr<nsIStandardURL> pStandardURL;
561 nsCOMPtr<nsIURI> pURI;
562 nsCOMPtr<nsIFile> pFile;
565 nsAutoString filePath;
566 nsresult result =
NS_OK;
570 mCompleted = PR_FALSE;
573 NS_ENSURE_TRUE(mpMetadataPropertyArray, NS_ERROR_NOT_INITIALIZED);
576 mpTagLibChannelFileIOManager =
578 (
"@songbirdnest.com/Songbird/sbTagLibChannelFileIOManager;1",
582 NS_ENSURE_STATE(mpURL);
583 if (NS_SUCCEEDED(result))
584 result = mpURL->GetSpec(urlSpec);
585 if (NS_SUCCEEDED(result))
586 result = mpURL->GetScheme(urlScheme);
588 if (!urlScheme.EqualsLiteral(
"file"))
590 LOG((
"%s: can't write to scheme %s", __FUNCTION__, urlScheme.get()));
591 return NS_ERROR_NOT_IMPLEMENTED;
595 if (NS_SUCCEEDED(result))
597 result = mpFileProtocolHandler->GetFileFromURLSpec(
599 getter_AddRefs(pFile)
603 if (NS_SUCCEEDED(result)) {
604 #if XP_UNIX && !XP_MACOSX
605 result = pFile->GetNativePath(mMetadataPath);
607 nsCOMPtr<sbILibraryUtils> libUtils =
608 do_GetService(
"@songbirdnest.com/Songbird/library/Manager;1", &result);
609 NS_ENSURE_SUCCESS(result, result);
610 nsCOMPtr<nsIFile> canonicalFile;
611 result = libUtils->GetCanonicalPath(pFile,
612 getter_AddRefs(canonicalFile));
613 NS_ENSURE_SUCCESS(result, result);
615 canonicalFile.forget(getter_AddRefs(pFile));
617 nsString metadataPathU16;
618 result = pFile->GetPath(metadataPathU16);
619 if (NS_SUCCEEDED(result)) {
620 CopyUTF16toUTF8(metadataPathU16, mMetadataPath);
626 result = mpURL->GetFileExtension(fileExt);
627 NS_ENSURE_SUCCESS(result, result);
628 ToLowerCase(fileExt);
632 if (fileExt.Equals(NS_LITERAL_CSTRING(
"m4v")) ||
633 fileExt.Equals(NS_LITERAL_CSTRING(
"mp4")) ||
634 fileExt.Equals(NS_LITERAL_CSTRING(
"asf")) ||
635 fileExt.Equals(NS_LITERAL_CSTRING(
"wmv")) ||
636 fileExt.Equals(NS_LITERAL_CSTRING(
"mov")) ||
637 fileExt.Equals(NS_LITERAL_CSTRING(
"wm")) ||
638 fileExt.Equals(NS_LITERAL_CSTRING(
"ogx")) ||
639 fileExt.Equals(NS_LITERAL_CSTRING(
"ogm")) ||
640 fileExt.Equals(NS_LITERAL_CSTRING(
"ogv"))
647 if (NS_SUCCEEDED(result)) {
652 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
654 nsACString &filePath = mMetadataPath;
657 TagLib::FileRef f(filePath.BeginReading());
658 NS_ENSURE_TRUE(f.file(), NS_ERROR_FAILURE);
659 NS_ENSURE_TRUE(f.file()->isOpen(), NS_ERROR_FAILURE);
660 NS_ENSURE_TRUE(f.file()->isValid(), NS_ERROR_FAILURE);
662 nsAutoString propertyValue;
669 if (fileExt.Equals(NS_LITERAL_CSTRING(
"mp3"))) {
670 LOG((
"Writing MP3 Metadata"));
671 TagLib::MPEG::File* MPEGFile =
672 static_cast<TagLib::MPEG::File*
>(f.file());
675 if (NS_SUCCEEDED(result) && MPEGFile->APETag()) {
676 result = WriteAPE(MPEGFile->APETag());
678 if (NS_SUCCEEDED(result) && MPEGFile->ID3v1Tag()) {
679 result = WriteID3v1(MPEGFile->ID3v1Tag());
681 if (NS_SUCCEEDED(result) && MPEGFile->ID3v2Tag()) {
682 result = WriteID3v2(MPEGFile->ID3v2Tag());
686 nsAutoString imageSpec;
687 tmp_result = mpMetadataPropertyArray->GetPropertyValue(
691 if (NS_SUCCEEDED(tmp_result)) {
693 WriteMP3Image(MPEGFile, imageType, imageSpec);
704 tmp_result = mpMetadataPropertyArray->GetPropertyValue(
709 if (NS_SUCCEEDED(tmp_result)) {
710 if (MPEGFile->ID3v2Tag()) {
717 NS_ConvertUTF16toUTF8(url).BeginReading(),
722 TagLib::ID3v2::Tag*
tag = MPEGFile->ID3v2Tag();
723 if(taglibURL.isEmpty()) {
724 tag->removeFrames(
"WOAF");
726 else if(!tag->frameList(
"WOAF").isEmpty()) {
727 TagLib::ID3v2::UrlLinkFrame* frame =
728 static_cast<TagLib::ID3v2::UrlLinkFrame*
>(
729 tag->frameList(
"WOAF").front());
730 frame->setUrl(taglibURL);
734 TagLib::ID3v2::UrlLinkFrame* frame =
735 new TagLib::ID3v2::UrlLinkFrame(
"WOAF");
736 tag->addFrame(frame);
737 frame->setUrl(taglibURL);
745 nsresult extendedDataResult;
746 tagResult = mpMetadataPropertyArray->GetPropertyValue(
748 extendedDataResult = mpMetadataPropertyArray->GetPropertyValue(
750 if (NS_SUCCEEDED(tagResult) || NS_SUCCEEDED(extendedDataResult)) {
751 AddGracenoteMetadataMP3(MPEGFile);
754 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"ogg")) ||
755 fileExt.Equals(NS_LITERAL_CSTRING(
"oga"))) {
756 LOG((
"Write OGG metadata"));
758 TagLib::Ogg::Vorbis::File* oggFile =
759 static_cast<TagLib::Ogg::Vorbis::File*
>(f.file());
762 if (NS_SUCCEEDED(result) && oggFile->tag()){
763 result = WriteXiphComment(oggFile->tag());
767 nsAutoString imageSpec;
768 tmp_result = mpMetadataPropertyArray->GetPropertyValue(
772 if (NS_SUCCEEDED(tmp_result)) {
774 WriteOGGImage(oggFile, imageType, imageSpec);
779 nsresult extendedDataResult;
780 tagResult = mpMetadataPropertyArray->GetPropertyValue(
782 extendedDataResult = mpMetadataPropertyArray->GetPropertyValue(
784 if (NS_SUCCEEDED(tagResult) || NS_SUCCEEDED(extendedDataResult)) {
785 AddGracenoteMetadataXiph(oggFile);
788 }
else if (fileExt.EqualsLiteral(
"mp4") ||
789 fileExt.EqualsLiteral(
"m4a") ||
790 fileExt.EqualsLiteral(
"m4v")) {
791 LOG((
"Writing MPEG-4 metadata"));
793 TagLib::MP4::File* mp4File =
static_cast<TagLib::MP4::File*
>(f.file());
796 if (NS_SUCCEEDED(result) && mp4File->tag()){
797 result = WriteMP4(mp4File->tag());
801 nsAutoString imageSpec;
802 tmp_result = mpMetadataPropertyArray->GetPropertyValue(
806 if (NS_SUCCEEDED(tmp_result)) {
808 WriteMP4Image(mp4File, imageType, imageSpec);
813 if (NS_SUCCEEDED(result)){
817 LOG((
"%s: failed to save!", __FUNCTION__));
818 result = NS_ERROR_FAILURE;
821 LOG((
"%s: failed to update tags!", __FUNCTION__));
828 mCompleted = PR_TRUE;
833 void sbMetadataHandlerTaglib::AddGracenoteMetadataMP3(
834 TagLib::MPEG::File* MPEGFile)
837 nsString propertyValue;
839 rv = mpMetadataPropertyArray->GetPropertyValue(
841 if (NS_SUCCEEDED(rv)) {
842 const TagLib::ByteVector UFID(
"UFID");
843 TagLib::ID3v2::Tag *tag2 = MPEGFile->ID3v2Tag(
true);
844 NS_ASSERTION(tag2,
"TagLib did not create id3v2 tag as asked!");
847 NS_LossyConvertUTF16toASCII propertyCValue(propertyValue);
848 TagLib::ByteVector identifier(propertyCValue.BeginReading(),
849 propertyCValue.Length());
852 const TagLib::ID3v2::FrameList& frames =
853 tag2->frameList(UFID);
854 TagLib::ID3v2::FrameList::ConstIterator it;
855 for (it = frames.begin(); it != frames.end(); ++it) {
856 NS_ASSERTION((*it)->frameID() == UFID,
857 "TagLib gave us the wrong frame!");
858 TagLib::ID3v2::UniqueFileIdentifierFrame* ufidFrame =
859 static_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*
>(*it);
860 if (!(ufidFrame->owner() ==
owner)) {
864 tag2->removeFrame(ufidFrame);
869 TagLib::ID3v2::FrameFactory* factory =
870 TagLib::ID3v2::FrameFactory::instance();
871 TagLib::ID3v2::UniqueFileIdentifierFrame* ufidFrame =
872 static_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*
>(
873 factory->createFrame(UFID));
874 ufidFrame->setOwner(
owner);
875 ufidFrame->setIdentifier(identifier);
876 tag2->addFrame(ufidFrame);
879 rv = mpMetadataPropertyArray->GetPropertyValue(
881 if (NS_SUCCEEDED(rv)) {
882 const TagLib::ByteVector TXXX(
"TXXX");
883 TagLib::ID3v2::Tag *tag2 = MPEGFile->ID3v2Tag(
true);
884 NS_ASSERTION(tag2,
"TagLib did not create id3v2 tag as asked!");
887 NS_LossyConvertUTF16toASCII propertyCValue(propertyValue);
891 const TagLib::ID3v2::FrameList& frames =
892 tag2->frameList(TXXX);
893 TagLib::ID3v2::FrameList::ConstIterator it;
894 for (it = frames.begin(); it != frames.end(); ++it) {
895 NS_ASSERTION((*it)->frameID() == TXXX,
896 "TagLib gave us the wrong frame!");
897 TagLib::ID3v2::UserTextIdentificationFrame* txxxFrame =
898 static_cast<TagLib::ID3v2::UserTextIdentificationFrame*
>(*it);
899 if (!(txxxFrame->description() == description)) {
903 tag2->removeFrame(txxxFrame);
908 TagLib::ID3v2::FrameFactory* factory =
909 TagLib::ID3v2::FrameFactory::instance();
910 TagLib::ID3v2::UserTextIdentificationFrame* txxxFrame =
911 static_cast<TagLib::ID3v2::UserTextIdentificationFrame*
>(
912 factory->createFrame(TXXX));
913 txxxFrame->setDescription(description);
914 txxxFrame->setText(text);
915 tag2->addFrame(txxxFrame);
919 void sbMetadataHandlerTaglib::AddGracenoteMetadataXiph(
920 TagLib::Ogg::Vorbis::File *oggFile)
923 nsString propertyValue;
925 TagLib::Ogg::XiphComment *xiphComment = oggFile->tag();
926 NS_ASSERTION(xiphComment,
"TagLib has no xiph comment!");
927 rv = mpMetadataPropertyArray->GetPropertyValue(
929 if (NS_SUCCEEDED(rv)) {
931 TagLib::String::UTF8);
932 xiphComment->addField(
"GracenoteFileID",
value);
934 rv = mpMetadataPropertyArray->GetPropertyValue(
936 if (NS_SUCCEEDED(rv)) {
938 TagLib::String::UTF8);
939 xiphComment->addField(
"GracenoteExtData",
value);
956 NS_IMETHODIMP sbMetadataHandlerTaglib::GetImageData(
958 nsACString &aMimeType,
963 NS_ENSURE_ARG_POINTER(aData);
965 LOG((
"sbMetadataHandlerTaglib::GetImageData\n"));
971 sbAlbumArt *cachedArt = nsnull;
972 for (PRUint32
i=0;
i < mCachedAlbumArt.Length();
i++) {
973 cachedArt = mCachedAlbumArt[
i];
974 NS_ENSURE_TRUE(cachedArt, NS_ERROR_UNEXPECTED);
975 if (cachedArt->type == aType) {
976 LOG((
"sbMetadataHandlerTaglib::GetImageData - found cached image\n"));
978 aMimeType.Assign(cachedArt->mimeType);
979 *aDataLen = cachedArt->dataLen;
980 *aData = cachedArt->data;
984 cachedArt->dataLen = 0;
985 cachedArt->data = nsnull;
986 mCachedAlbumArt.RemoveElementAt(
i);
1005 nsAutoLock lock(sTaglibLock);
1007 rv = GetImageDataInternal(aType, aMimeType, aDataLen, aData);
1009 NS_ERROR(
"sbMetadataHandlerTaglib::GetImageData caught an exception!");
1010 rv = NS_ERROR_FAILURE;
1015 nsresult sbMetadataHandlerTaglib::GetImageDataInternal(
1017 nsACString &aMimeType,
1021 nsCOMPtr<nsIFile> pFile;
1023 nsCString urlScheme;
1029 nsresult result =
NS_OK;
1032 NS_ENSURE_STATE(mpURL);
1033 result = mpURL->GetSpec(urlSpec);
1034 NS_ENSURE_SUCCESS(result, result);
1035 result = mpURL->GetScheme(urlScheme);
1036 NS_ENSURE_SUCCESS(result, result);
1038 if (urlScheme.EqualsLiteral(
"file"))
1041 result = mpURL->GetFileExtension(fileExt);
1042 NS_ENSURE_SUCCESS(result, result);
1043 ToLowerCase(fileExt);
1045 isMP3 = fileExt.Equals(NS_LITERAL_CSTRING(
"mp3"));
1046 isM4A = fileExt.Equals(NS_LITERAL_CSTRING(
"m4a"));
1047 isOGG = fileExt.Equals(NS_LITERAL_CSTRING(
"ogg")) ||
1048 fileExt.Equals(NS_LITERAL_CSTRING(
"oga"));
1049 isFLAC = fileExt.Equals(NS_LITERAL_CSTRING(
"flac"));
1050 if (!isMP3 && !isM4A && !isOGG && !isFLAC) {
1051 return NS_ERROR_NOT_IMPLEMENTED;
1055 result = mpFileProtocolHandler->GetFileFromURLSpec
1057 getter_AddRefs(pFile));
1058 NS_ENSURE_SUCCESS(result, result);
1062 result = pFile->GetPath(filePath);
1063 NS_ENSURE_SUCCESS(result, result);
1064 CopyUTF16toUTF8(filePath, mMetadataPath);
1066 result = pFile->GetNativePath(mMetadataPath);
1067 NS_ENSURE_SUCCESS(result, result);
1068 nsCString filePath = mMetadataPath;
1071 result = NS_ERROR_FILE_UNKNOWN_TYPE;
1073 nsAutoPtr<TagLib::MPEG::File> pTagFile;
1074 pTagFile =
new TagLib::MPEG::File(filePath.BeginReading());
1075 NS_ENSURE_STATE(pTagFile);
1078 if (pTagFile->ID3v2Tag()) {
1079 result = ReadImageID3v2(pTagFile->ID3v2Tag(), aType, aMimeType, aDataLen,
aData);
1082 nsAutoPtr<TagLib::MP4::File> pTagFile;
1083 pTagFile =
new TagLib::MP4::File(filePath.BeginReading());
1084 NS_ENSURE_STATE(pTagFile);
1087 if (pTagFile->tag()) {
1088 result = ReadImageITunes(
1089 static_cast<TagLib::MP4::Tag*>(pTagFile->tag()),
1090 aMimeType, aDataLen, aData);
1093 nsAutoPtr<TagLib::Ogg::Vorbis::File> pTagFile;
1096 pTagFile =
new TagLib::Ogg::Vorbis::File(NS_ConvertUTF16toUTF8(filePath).BeginReading());
1098 pTagFile =
new TagLib::Ogg::Vorbis::File(filePath.BeginReading());
1100 NS_ENSURE_STATE(pTagFile);
1103 if (pTagFile->tag()) {
1104 result = ReadImageOgg(
1105 static_cast<TagLib::Ogg::XiphComment*>(pTagFile->tag()),
1106 aType, aMimeType, aDataLen, aData);
1108 }
else if (isFLAC) {
1109 nsAutoPtr<TagLib::FLAC::File> pTagFile;
1110 pTagFile =
new TagLib::FLAC::File(filePath.BeginReading());
1111 NS_ENSURE_STATE(pTagFile);
1113 if(pTagFile->xiphComment()) {
1115 result = ReadImageFlac(pTagFile, aType, aMimeType, aDataLen, aData);
1119 result = NS_ERROR_NOT_IMPLEMENTED;
1124 NS_IMETHODIMP sbMetadataHandlerTaglib::SetImageData(
1126 const nsAString &aURL)
1129 LOG((
"sbMetadataHandlerTaglib::SetImageData\n"));
1130 nsAutoLock lock(sTaglibLock);
1133 rv = SetImageDataInternal(aType, aURL);
1135 NS_ERROR(
"sbMetadataHandlerTaglib::SetImageData caught an exception!");
1136 rv = NS_ERROR_FAILURE;
1141 nsresult sbMetadataHandlerTaglib::SetImageDataInternal(
1143 const nsAString &aURL)
1145 nsCOMPtr<nsIFile> pFile;
1147 nsCString urlScheme;
1149 nsresult result =
NS_OK;
1154 NS_ENSURE_STATE(mpURL);
1156 LOG((
"%s(%s)", __FUNCTION__, NS_ConvertUTF16toUTF8(aURL).
get()));
1159 result = mpURL->GetFileExtension(fileExt);
1160 NS_ENSURE_SUCCESS(result, result);
1162 ToLowerCase(fileExt);
1163 isMP3 = fileExt.EqualsLiteral(
"mp3");
1164 isOGG = fileExt.EqualsLiteral(
"ogg") ||
1165 fileExt.EqualsLiteral(
"oga");
1166 isMP4 = fileExt.EqualsLiteral(
"mp4") ||
1167 fileExt.EqualsLiteral(
"m4a");
1168 if (!isMP3 && !isOGG && !isMP4) {
1169 LOG((
"%s: file format not supported", __FUNCTION__));
1170 return NS_ERROR_NOT_IMPLEMENTED;
1173 result = mpURL->GetSpec(urlSpec);
1174 NS_ENSURE_SUCCESS(result, result);
1175 result = mpURL->GetScheme(urlScheme);
1176 NS_ENSURE_SUCCESS(result, result);
1178 if (urlScheme.EqualsLiteral(
"file"))
1181 result = mpFileProtocolHandler->GetFileFromURLSpec
1183 getter_AddRefs(pFile));
1184 NS_ENSURE_SUCCESS(result, result);
1188 result = pFile->GetPath(filePath);
1189 NS_ENSURE_SUCCESS(result, result);
1190 CopyUTF16toUTF8(filePath, mMetadataPath);
1192 result = pFile->GetNativePath(mMetadataPath);
1193 NS_ENSURE_SUCCESS(result, result);
1194 nsCString filePath = mMetadataPath;
1198 TagLib::FileRef f(filePath.BeginReading());
1199 NS_ENSURE_TRUE(f.file(), NS_ERROR_FAILURE);
1200 NS_ENSURE_TRUE(f.file()->isOpen(), NS_ERROR_FAILURE);
1201 NS_ENSURE_TRUE(f.file()->isValid(), NS_ERROR_FAILURE);
1205 result = WriteMP3Image(static_cast<TagLib::MPEG::File*>(f.file()),
1209 result = WriteOGGImage(static_cast<TagLib::Ogg::Vorbis::File*>(f.file()),
1213 result = WriteMP4Image(static_cast<TagLib::MP4::File*>(f.file()),
1218 if (NS_SUCCEEDED(result)) {
1223 LOG((
"%s: Failed to save", __FUNCTION__));
1224 result = NS_ERROR_FAILURE;
1228 LOG((
"%s: scheme not supported", __FUNCTION__));
1229 result = NS_ERROR_NOT_IMPLEMENTED;
1242 nsresult sbMetadataHandlerTaglib::RemoveAllImagesMP3(
1243 TagLib::MPEG::File* aMPEGFile,
1246 if (aMPEGFile->ID3v2Tag()) {
1247 TagLib::ID3v2::FrameList frameList= aMPEGFile->ID3v2Tag()->frameList(
"APIC");
1248 if (!frameList.isEmpty()){
1249 std::list<TagLib::ID3v2::Frame*>::const_iterator iter = frameList.begin();
1250 while (iter != frameList.end()) {
1251 TagLib::ID3v2::AttachedPictureFrame *frame =
1252 static_cast<TagLib::ID3v2::AttachedPictureFrame *
>( *iter );
1253 std::list<TagLib::ID3v2::Frame*>::const_iterator nextIter = iter;
1255 if (frame && frame->type() == imageType){
1257 aMPEGFile->ID3v2Tag()->removeFrame(*iter,
true);
1274 nsresult sbMetadataHandlerTaglib::RemoveAllImagesOGG(
1275 TagLib::Ogg::Vorbis::File* aOGGFile,
1278 if (aOGGFile->tag()) {
1279 StringList s_artworkList = aOGGFile->tag()->fieldListMap()[
"METADATA_BLOCK_PICTURE"];
1280 if(!s_artworkList.isEmpty()){
1281 for (StringList::Iterator it = s_artworkList.begin();
1282 it != s_artworkList.end();
1285 TagLib::FLAC::Picture *picture =
new TagLib::FLAC::Picture();
1286 String encodedData = *it;
1287 if (encodedData.isNull())
1291 std::string decodedData = base64_decode(encodedData.to8Bit());
1292 if (decodedData.empty())
1295 bv.setData(decodedData.data(), decodedData.size());
1296 if (!picture->parse(bv))
1302 if (picture->type() == imageType) {
1303 LOG((
"erasing artwork"));
1304 aOGGFile->tag()->removeField(
"METADATA_BLOCK_PICTURE", *it);
1323 nsresult sbMetadataHandlerTaglib::ReadImageFile(
const nsAString &imageSpec,
1324 PRUint8* &imageData,
1325 PRUint32 &imageDataSize,
1326 nsCString &imageMimeType)
1329 nsCOMPtr<nsIFile> imageFile;
1330 nsCOMPtr<nsIURI> imageURI;
1332 nsCString cImageSpec = NS_LossyConvertUTF16toASCII(imageSpec);
1335 nsAutoUnlock unlock(sTaglibLock);
1337 nsCOMPtr<nsIIOService> ioservice =
1339 NS_ENSURE_SUCCESS(rv, rv);
1342 rv = ioservice->NewURI(cImageSpec, nsnull, nsnull,
1343 getter_AddRefs(imageURI));
1344 NS_ENSURE_SUCCESS(rv, rv);
1347 rv = imageURI->SchemeIs(
"resource", &isResource);
1348 NS_ENSURE_SUCCESS(rv, rv);
1351 rv = mpResourceProtocolHandler->ResolveURI(imageURI, cImageSpec);
1352 NS_ENSURE_SUCCESS(rv, rv);
1356 rv = mpFileProtocolHandler->GetFileFromURLSpec(cImageSpec,
1357 getter_AddRefs(imageFile)
1359 NS_ENSURE_SUCCESS(rv, rv);
1362 nsCOMPtr<nsIMIMEService> mimeService =
1363 do_GetService(
"@mozilla.org/mime;1", &rv);
1364 NS_ENSURE_SUCCESS(rv, rv);
1365 rv = mimeService->GetTypeFromFile(imageFile, imageMimeType);
1366 NS_ENSURE_SUCCESS(rv, rv);
1369 nsCOMPtr<nsIFileInputStream> inputStream =
1370 do_CreateInstance(
"@mozilla.org/network/file-input-stream;1", &rv);
1371 NS_ENSURE_SUCCESS(rv, rv);
1373 rv = inputStream->Init(imageFile, 0x01, 0600, 0);
1374 NS_ENSURE_SUCCESS(rv, rv);
1376 nsCOMPtr<nsIBinaryInputStream> stream =
1377 do_CreateInstance(
"@mozilla.org/binaryinputstream;1", &rv);
1378 NS_ENSURE_SUCCESS(rv, rv);
1380 rv = stream->SetInputStream(inputStream);
1381 NS_ENSURE_SUCCESS(rv, rv);
1384 rv = inputStream->Available(&imageDataSize);
1385 NS_ENSURE_SUCCESS(rv, rv);
1388 rv = stream->ReadByteArray(imageDataSize, &imageData);
1389 NS_ENSURE_SUCCESS(rv, rv);
1403 nsresult sbMetadataHandlerTaglib::WriteMP3Image(TagLib::MPEG::File* aMPEGFile,
1405 const nsAString &imageSpec)
1409 if (!aMPEGFile->ID3v2Tag()) {
1411 return NS_ERROR_FAILURE;
1414 if (imageSpec.Length() <= 0) {
1416 rv = RemoveAllImagesMP3(aMPEGFile, imageType);
1419 PRUint32 imageDataSize = 0;
1420 nsCString imageMimeType;
1423 rv = ReadImageFile(imageSpec, imageData, imageDataSize, imageMimeType);
1424 NS_ENSURE_SUCCESS(rv, rv);
1431 return NS_ERROR_FAILURE;
1435 return NS_ERROR_FAILURE;
1439 TagLib::ID3v2::AttachedPictureFrame *pic =
1440 new TagLib::ID3v2::AttachedPictureFrame;
1442 TagLib::String::UTF8));
1443 pic->setType(TagLib::ID3v2::AttachedPictureFrame::Type(imageType));
1444 pic->setPicture(TagLib::ByteVector((
const char *)imageData, imageDataSize));
1447 rv = RemoveAllImagesMP3(aMPEGFile, imageType);
1448 NS_ENSURE_SUCCESS(rv, rv);
1451 aMPEGFile->ID3v2Tag()->addFrame(pic);
1466 nsresult sbMetadataHandlerTaglib::WriteOGGImage(
1467 TagLib::Ogg::Vorbis::File* aOGGFile,
1469 const nsAString &imageSpec)
1473 if (!aOGGFile->tag()) {
1474 return NS_ERROR_FAILURE;
1477 if (imageSpec.Length() <= 0) {
1479 rv = RemoveAllImagesOGG(aOGGFile, imageType);
1482 PRUint32 imageDataSize = 0;
1483 nsCString imageMimeType;
1486 rv = ReadImageFile(imageSpec, imageData, imageDataSize, imageMimeType);
1487 NS_ENSURE_SUCCESS(rv, rv);
1491 LOG((
"WriteOGGImage():: Creating new FLAC::Picture"));
1492 TagLib::FLAC::Picture *pic =
new TagLib::FLAC::Picture;
1494 TagLib::String::UTF8));
1495 pic->setType(TagLib::FLAC::Picture::Type(imageType));
1496 pic->setData(TagLib::ByteVector((
const char *)imageData, imageDataSize));
1499 LOG((
"WriteOGGImage():: Removing all images from OGG file"));
1500 rv = RemoveAllImagesOGG(aOGGFile, imageType);
1501 NS_ENSURE_SUCCESS(rv, rv);
1504 LOG((
"WriteOGGImage():: Setting the artwork"));
1505 ByteVector bv = pic->render();
1506 std::string encodedData = base64_encode((
const unsigned char *)bv.data(), bv.size());
1507 bv = ByteVector(encodedData.data(), encodedData.length());
1508 aOGGFile->tag()->addField(
"METADATA_BLOCK_PICTURE", bv.data());
1521 nsresult sbMetadataHandlerTaglib::WriteMP4Image(
1522 TagLib::MP4::File* aMP4File,
1524 const nsAString &imageSpec)
1526 LOG((
"%s: setting to image %s",
1528 NS_ConvertUTF16toUTF8(imageSpec).
get()));
1531 NS_ENSURE_TRUE(aMP4File->tag(), NS_ERROR_FAILURE);
1533 NS_ERROR_NOT_IMPLEMENTED);
1535 TagLib::ByteVector
data;
1537 if (imageSpec.IsEmpty()) {
1539 LOG((
"%s: clearing image", __FUNCTION__));
1543 PRUint32 imageDataSize = 0;
1544 nsCString imageMimeType;
1547 rv = ReadImageFile(imageSpec, imageData, imageDataSize, imageMimeType);
1548 NS_ENSURE_SUCCESS(rv, rv);
1550 LOG((
"%s: setting image to %u bytes", __FUNCTION__, imageDataSize));
1551 data.setData((
const char*)imageData, imageDataSize);
1554 TagLib::MP4::Tag* tag =
static_cast<TagLib::MP4::Tag*
>(aMP4File->tag());
1556 MP4::CoverArtList coverArtList;
1558 coverArtList.append(MP4::CoverArt(MP4::CoverArt::JPEG, data));
1559 tag->itemListMap()[
"covr"] = coverArtList;
1574 nsresult sbMetadataHandlerTaglib::ReadImageID3v2(TagLib::ID3v2::Tag *aTag,
1576 nsACString &aMimeType,
1580 NS_ENSURE_ARG_POINTER(aTag);
1581 NS_ENSURE_ARG_POINTER(aData);
1582 nsresult rv =
NS_OK;
1586 return NS_ERROR_FAILURE;
1592 TagLib::ID3v2::FrameList frameList = aTag->frameList(
"APIC");
1593 if (!frameList.isEmpty()){
1594 TagLib::ID3v2::AttachedPictureFrame *
p = nsnull;
1595 for (TagLib::uint frameIndex = 0;
1596 frameIndex < frameList.size();
1598 p =
static_cast<TagLib::ID3v2::AttachedPictureFrame *
>(frameList[frameIndex]);
1599 if (p->type() == aType && p->picture().size() > 0) {
1601 *aDataLen = p->picture().size();
1604 aMimeType.Assign(p->mimeType().toCString(), p->mimeType().length());
1608 *aData =
static_cast<PRUint8 *
>(nsMemory::Clone(p->picture().data(),
1610 NS_ENSURE_TRUE(*aData, NS_ERROR_OUT_OF_MEMORY);
1619 nsresult sbMetadataHandlerTaglib::ReadImageITunes(TagLib::MP4::Tag *aTag,
1620 nsACString &aMimeType,
1624 NS_ENSURE_ARG_POINTER(aTag);
1625 NS_ENSURE_ARG_POINTER(aData);
1626 NS_ENSURE_ARG_POINTER(aDataLen);
1627 nsCOMPtr<nsIThread> mainThread;
1628 nsresult rv =
NS_OK;
1633 MP4::ItemListMap::Iterator itr = aTag->itemListMap().begin();
1635 if (aTag->itemListMap().contains(
"covr")) {
1636 MP4::CoverArtList coverArtList = aTag->itemListMap()[
"covr"].toCoverArtList();
1638 if (coverArtList.size() == 0) {
1642 MP4::CoverArt ca = coverArtList[0];
1644 *aDataLen = coverArtList[0].data().size();
1647 static_cast<PRUint8 *
>(nsMemory::Clone(coverArtList[0].
data().
data(), *aDataLen));
1648 NS_ENSURE_TRUE(data, NS_ERROR_OUT_OF_MEMORY);
1654 nsAutoUnlock unlock(sTaglibLock);
1656 nsCOMPtr<nsIContentSniffer> contentSniffer =
1658 NS_ENSURE_SUCCESS(rv, rv);
1660 rv = contentSniffer->GetMIMETypeFromContent(NULL, data.
get(), *aDataLen,
1662 NS_ENSURE_SUCCESS(rv, rv);
1671 nsresult sbMetadataHandlerTaglib::ReadImageOgg(TagLib::Ogg::XiphComment *aTag,
1673 nsACString &aMimeType,
1677 NS_ENSURE_ARG_POINTER(aTag);
1678 NS_ENSURE_ARG_POINTER(aData);
1679 NS_ENSURE_ARG_POINTER(aDataLen);
1680 nsCOMPtr<nsIThread> mainThread;
1685 StringList artworkList = aTag->fieldListMap()[
"METADATA_BLOCK_PICTURE"];
1686 if(!artworkList.isEmpty()){
1687 for (StringList::Iterator it = artworkList.begin();
1688 it != artworkList.end();
1691 TagLib::FLAC::Picture* picture =
new TagLib::FLAC::Picture();
1692 String encodedData = *it;
1693 if (encodedData.isNull())
1697 std::string decodedData = base64_decode(encodedData.to8Bit());
1698 if (decodedData.empty())
1701 bv.setData(decodedData.data(), decodedData.size());
1702 if (!picture->parse(bv))
1707 if (picture->type() == aType) {
1708 *aDataLen = picture->data().size();
1709 aMimeType.Assign(picture->mimeType().toCString());
1710 *aData =
static_cast<PRUint8 *
>(
1711 nsMemory::Clone(picture->data().data(), *aDataLen));
1712 NS_ENSURE_TRUE(*aData, NS_ERROR_OUT_OF_MEMORY);
1721 nsresult sbMetadataHandlerTaglib::ReadImageFlac(TagLib::FLAC::File *pTagFile,
1723 nsACString &aMimeType,
1727 NS_ENSURE_ARG_POINTER(pTagFile);
1728 NS_ENSURE_ARG_POINTER(aData);
1729 NS_ENSURE_ARG_POINTER(aDataLen);
1730 nsCOMPtr<nsIThread> mainThread;
1731 TagLib::List<TagLib::FLAC::Picture*> artworkList;
1737 artworkList = pTagFile->pictureList();
1738 if(!artworkList.isEmpty()){
1740 TagLib::List<TagLib::FLAC::Picture*>::Iterator it = artworkList.begin();
1741 it != artworkList.end();
1744 TagLib::FLAC::Picture* picture = *it;
1745 if (picture->type() == aType) {
1746 *aDataLen = picture->data().size();
1747 aMimeType.Assign(picture->mimeType().toCString());
1748 *aData =
static_cast<PRUint8 *
>(
1749 nsMemory::Clone(picture->data().data(), *aDataLen));
1750 NS_ENSURE_TRUE(*aData, NS_ERROR_OUT_OF_MEMORY);
1770 NS_IMETHODIMP sbMetadataHandlerTaglib::OnChannelData(
1782 NS_IMETHODIMP sbMetadataHandlerTaglib::Close()
1785 mCachedAlbumArt.Clear();
1789 if (!mMetadataChannelID.IsEmpty())
1791 mpTagLibChannelFileIOManager->RemoveChannel(mMetadataChannelID);
1792 mMetadataChannelID.Truncate();
1796 if (mpSeekableChannel)
1798 mpSeekableChannel->Close();
1799 mpSeekableChannel = nsnull;
1813 NS_IMETHODIMP sbMetadataHandlerTaglib::GetProps(
1816 NS_ENSURE_ARG_POINTER(ppPropertyArray);
1817 NS_ENSURE_STATE(mpMetadataPropertyArray);
1818 NS_ADDREF(*ppPropertyArray = mpMetadataPropertyArray);
1822 NS_IMETHODIMP sbMetadataHandlerTaglib::SetProps(
1825 mpMetadataPropertyArray = ppPropertyArray;
1829 NS_IMETHODIMP sbMetadataHandlerTaglib::GetCompleted(
1832 NS_ENSURE_ARG_POINTER(pCompleted);
1833 *pCompleted = mCompleted;
1837 NS_IMETHODIMP sbMetadataHandlerTaglib::GetChannel(
1840 NS_ENSURE_ARG_POINTER(ppChannel);
1841 NS_IF_ADDREF(*ppChannel = mpChannel);
1845 NS_IMETHODIMP sbMetadataHandlerTaglib::SetChannel(
1848 mpChannel = pChannel;
1853 nsCOMPtr<nsIURI> pURI;
1854 nsresult result =
NS_OK;
1855 result = mpChannel->GetURI(getter_AddRefs(pURI));
1856 NS_ENSURE_SUCCESS(result, result);
1857 mpURL = do_QueryInterface(pURI, &result);
1858 NS_ENSURE_SUCCESS(result, result);
1883 NS_IMETHODIMP sbMetadataHandlerTaglib::OnChannelDataAvailable(
1886 PRBool channelCompleted;
1887 nsresult result =
NS_OK;
1897 mMetadataChannelRestart = PR_FALSE;
1901 nsAutoLock lock(sTaglibLock);
1908 result = mpSeekableChannel->GetCompleted(&channelCompleted);
1909 if (NS_SUCCEEDED(result) && channelCompleted)
1915 printf(
"1: OnChannelDataAvailable exception\n");
1937 mpTagLibChannelFileIOManager(nsnull),
1938 mpFileProtocolHandler(nsnull),
1939 mpResourceProtocolHandler(nsnull),
1940 mpMetadataPropertyArray(nsnull),
1942 mpSeekableChannel(nsnull),
1944 mMetadataChannelRestart(PR_FALSE),
1945 mCompleted(PR_FALSE)
1976 nsCOMPtr<nsIIOService> ioservice =
1977 do_GetService(
"@mozilla.org/network/io-service;1", &rv);
1978 NS_ENSURE_SUCCESS(rv, rv);
1980 nsCOMPtr<nsIProtocolHandler> fileHandler;
1981 rv = ioservice->GetProtocolHandler(
"file", getter_AddRefs(fileHandler));
1982 NS_ENSURE_SUCCESS(rv, rv);
1983 mpFileProtocolHandler = do_QueryInterface(fileHandler, &rv);
1984 NS_ENSURE_SUCCESS(rv, rv);
1986 nsCOMPtr<nsIProtocolHandler> resHandler;
1987 rv = ioservice->GetProtocolHandler(
"resource", getter_AddRefs(resHandler));
1988 NS_ENSURE_SUCCESS(rv, rv);
1989 mpResourceProtocolHandler = do_QueryInterface(resHandler, &rv);
1990 NS_ENSURE_SUCCESS(rv, rv);
1998 sbMetadataHandlerTaglib::sTaglibLock =
1999 nsAutoLock::NewLock(
"sbMetadataHandlerTaglib::sTaglibLock");
2000 NS_ENSURE_TRUE(sbMetadataHandlerTaglib::sTaglibLock, NS_ERROR_OUT_OF_MEMORY);
2008 if (sbMetadataHandlerTaglib::sTaglibLock) {
2009 nsAutoLock::DestroyLock(sbMetadataHandlerTaglib::sTaglibLock);
2023 PRUint32 sbMetadataHandlerTaglib::sNextChannelID = 0;
2071 void sbMetadataHandlerTaglib::ReadID3v2Tags(
2072 TagLib::ID3v2::Tag *pTag,
2073 const char *aCharset)
2075 TagLib::ID3v2::FrameListMap frameListMap;
2076 int numMetadataEntries;
2084 frameListMap = pTag->frameListMap();
2087 numMetadataEntries =
sizeof(
ID3v2Map) /
sizeof(ID3v2Map[0]);
2088 for (i = 0; i < numMetadataEntries; i++) {
2089 TagLib::ID3v2::FrameList frameList = frameListMap[ID3v2Map[
i][0]];
2090 if(!frameList.isEmpty()) {
2091 AddMetadataValue(ID3v2Map[i][1], frameList.front()->toString(), aCharset);
2096 TagLib::ID3v2::FrameList frameList = frameListMap[
"WOAF"];
2097 if (!frameList.isEmpty())
2099 TagLib::ID3v2::UrlLinkFrame* woaf =
2100 static_cast<TagLib::ID3v2::UrlLinkFrame*
>(frameList.front());
2111 nsCString urlScheme;
2112 nsresult result = mpURL->GetScheme(urlScheme);
2113 NS_ENSURE_SUCCESS(result,);
2115 if (urlScheme.Equals(NS_LITERAL_CSTRING(
"file"))) {
2116 sbAlbumArt *art =
new sbAlbumArt();
2117 NS_ENSURE_TRUE(art,);
2118 result = ReadImageID3v2(pTag,
2120 art->mimeType, &(art->dataLen), &(art->data));
2121 NS_ENSURE_SUCCESS(result,);
2123 nsAutoPtr<sbAlbumArt>* cacheSlot = mCachedAlbumArt.AppendElement();
2124 NS_ENSURE_TRUE(cacheSlot,);
2127 art =
new sbAlbumArt();
2128 NS_ENSURE_TRUE(art,);
2130 art->mimeType, &(art->dataLen), &(art->data));
2131 NS_ENSURE_SUCCESS(result,);
2133 cacheSlot = mCachedAlbumArt.AppendElement();
2134 NS_ENSURE_TRUE(cacheSlot,);
2171 void sbMetadataHandlerTaglib::ReadAPETags(
2172 TagLib::APE::Tag *pTag)
2174 TagLib::APE::ItemListMap itemListMap;
2175 int numMetadataEntries;
2184 itemListMap = pTag->itemListMap();
2187 numMetadataEntries =
sizeof(
APEMap) /
sizeof(APEMap[0]);
2188 for (i = 0; i < numMetadataEntries; i++) {
2189 TagLib::APE::Item item = itemListMap[APEMap[
i][0]];
2190 if (!item.isEmpty()) {
2191 AddMetadataValue(APEMap[i][1], item.toString(), nsnull);
2212 void sbMetadataHandlerTaglib::ReadXiphTags(
2213 TagLib::Ogg::XiphComment *pTag)
2215 nsresult result =
NS_OK;
2220 result = mpURL->SchemeIs(
"file", &isFileURI);
2221 NS_ENSURE_SUCCESS(result, );
2223 nsAutoPtr<sbAlbumArt> art(
new sbAlbumArt());
2224 NS_ENSURE_TRUE(art, );
2225 result = ReadImageOgg(
2228 art->mimeType, &(art->dataLen), &(art->data));
2229 NS_ENSURE_SUCCESS(result, );
2231 nsAutoPtr<sbAlbumArt>* cacheSlot = mCachedAlbumArt.AppendElement();
2232 NS_ENSURE_TRUE(cacheSlot, );
2235 art =
new sbAlbumArt();
2236 NS_ENSURE_TRUE(art, );
2237 result = ReadImageOgg(
2240 art->mimeType, &(art->dataLen), &(art->data));
2241 NS_ENSURE_SUCCESS(result, );
2243 cacheSlot = mCachedAlbumArt.AppendElement();
2244 NS_ENSURE_TRUE(cacheSlot, );
2262 nsresult sbMetadataHandlerTaglib::CheckChannelRestart()
2264 nsresult result =
NS_OK;
2266 if (!mMetadataChannelID.IsEmpty())
2269 mpTagLibChannelFileIOManager->GetChannelRestart(mMetadataChannelID,
2270 &mMetadataChannelRestart);
2271 NS_ENSURE_SUCCESS(result, result);
2272 if (!mMetadataChannelRestart) {
2274 result = mpTagLibChannelFileIOManager->GetChannelSize(mMetadataChannelID,
2276 NS_ENSURE_SUCCESS(result, result);
2283 result = NS_ERROR_FAILURE;
2299 nsresult sbMetadataHandlerTaglib::ReadMetadata()
2302 PRBool isValid = PR_FALSE;
2303 PRBool decodedFileExt = PR_FALSE;
2304 nsresult result =
NS_OK;
2307 result = mpURL->GetFileExtension(fileExt);
2308 if (NS_SUCCEEDED(result))
2309 ToLowerCase(fileExt);
2314 result = mpURL->GetSpec(spec);
2315 if (NS_SUCCEEDED(result)) {
2316 LOG((
"sbMetadataHandlerTaglib:: Reading metadata from %s\n", spec.get()));
2323 if (NS_SUCCEEDED(result))
2325 decodedFileExt = PR_TRUE;
2326 if (fileExt.Equals(NS_LITERAL_CSTRING(
"flac"))) {
2327 isValid = ReadFLACFile();
2328 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"mpc"))) {
2329 isValid = ReadMPCFile();
2330 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"mp3"))) {
2331 isValid = ReadMPEGFile();
2332 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"m4a")) ||
2333 fileExt.Equals(NS_LITERAL_CSTRING(
"m4r")) ||
2334 fileExt.Equals(NS_LITERAL_CSTRING(
"aac")) ||
2335 fileExt.Equals(NS_LITERAL_CSTRING(
"m4p"))) {
2336 isValid = ReadMP4File();
2337 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"m4v")) ||
2338 fileExt.Equals(NS_LITERAL_CSTRING(
"mp4"))) {
2339 isValid = ReadMP4File();
2342 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"ogg")) ||
2343 fileExt.Equals(NS_LITERAL_CSTRING(
"oga"))) {
2344 isValid = ReadOGAFile();
2345 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"ogv")) ||
2346 fileExt.Equals(NS_LITERAL_CSTRING(
"ogm")) ||
2347 fileExt.Equals(NS_LITERAL_CSTRING(
"ogx"))) {
2348 isValid = ReadOGGFile();
2351 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"wma"))) {
2352 isValid = ReadASFFile();
2353 }
else if (fileExt.Equals(NS_LITERAL_CSTRING(
"wmv"))) {
2354 isValid = ReadASFFile();
2359 decodedFileExt = PR_FALSE;
2365 if ( NS_SUCCEEDED(result)
2368 && !mMetadataChannelRestart)
2370 isValid = ReadMPEGFile();
2374 if (isValid && !mMetadataChannelRestart)
2378 if (!NS_SUCCEEDED(result))
2383 result = NS_ERROR_FAILURE;
2396 void sbMetadataHandlerTaglib::CompleteRead()
2399 mCompleted = PR_TRUE;
2413 nsresult sbMetadataHandlerTaglib::AddSeparatedNumbers(
2415 const char *baseProperty,
2416 const char *countProperty)
2420 TagLib::StringList
val = value.split(SEP);
2421 if (!val.isEmpty()){
2422 AddMetadataValue(baseProperty, (PRUint64) val[0].toInt());
2423 if (val.size() > 1){
2424 AddMetadataValue(countProperty, (PRUint64) val[1].toInt());
2446 PRBool sbMetadataHandlerTaglib::ReadFile(
2447 TagLib::File *pTagFile,
2448 const char *aCharset)
2451 TagLib::AudioProperties *pAudioProperties;
2454 if (!pTagFile || !pTagFile->isValid()) {
2458 pTag = pTagFile->tag();
2460 TagLib::PropertyMap properties = pTag->properties();
2464 if (dynamic_cast<TagLib::TagUnion*>(pTag)){
2466 if (tagUnion->
tag(2)){
2469 if (tagUnion->
tag(1)){
2472 if (tagUnion->
tag(0)){
2526 pAudioProperties = pTagFile->audioProperties();
2527 if (pAudioProperties)
2532 (PRUint64)pAudioProperties->length() * 1000000);
2546 nsresult sbMetadataHandlerTaglib::RunCharsetDetector(
2547 nsICharsetDetector* aDetector,
2550 NS_ENSURE_ARG_POINTER(aDetector);
2551 nsresult rv =
NS_OK;
2553 mLastConfidence = eNoAnswerYet;
2555 nsCOMPtr<nsICharsetDetectionObserver>
observer =
2556 do_QueryInterface( NS_ISUPPORTS_CAST(nsICharsetDetectionObserver*,
this) );
2557 NS_ASSERTION(observer,
"Um! We're supposed to be implementing this...");
2559 rv = aDetector->Init(observer);
2560 if (NS_SUCCEEDED(rv)) {
2564 const PRUint32 chunkSize = aContent.size();
2566 PRUint32 currentSize = 0;
2568 rv = aDetector->DoIt(raw.c_str(), chunkSize, &isDone);
2569 if (NS_FAILED(rv) || isDone) {
2572 currentSize += chunkSize;
2574 if (NS_SUCCEEDED(rv)) {
2575 rv = aDetector->Done();
2583 const char *aCharset,
2584 nsDetectionConfident aConf)
2586 mLastCharset.AssignLiteral(aCharset);
2587 mLastConfidence = aConf;
2593 CopyUTF8toUTF16(nsDependentCString(aString.toCString(
true)), aResult);
2597 void sbMetadataHandlerTaglib::ConvertCharset(
2599 const char *aCharset,
2606 if (!aCharset || !*aCharset ||
2607 !strcmp(
"UTF-8", aCharset) ||
2608 !strcmp(
"us-ascii", aCharset))
2611 LOG((
"sbMetadataHandlerTaglib::ConvertCharset: not converting to \"%s\"",
2612 aCharset ? aCharset :
"(null)"
2621 if (strcmp(
"CP_ACP", aCharset) == 0) {
2623 int size = ::MultiByteToWideChar( CP_ACP,
2624 MB_ERR_INVALID_CHARS,
2631 PRUnichar *wstr =
reinterpret_cast< PRUnichar *
>( NS_Alloc( (size + 1) *
sizeof( PRUnichar ) ) );
2633 int read = MultiByteToWideChar( CP_ACP,
2634 MB_ERR_INVALID_CHARS,
2639 NS_ASSERTION(size == read,
"Win32 Current Codepage conversion failed.");
2641 aResult.Assign(wstr, size);
2652 nsCOMPtr<nsICharsetConverterManager> converterManager =
2653 do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
2654 NS_ENSURE_SUCCESS(rv,
toMozString(aString, aResult));
2656 nsCOMPtr<nsIUnicodeDecoder> decoder;
2657 rv = converterManager->GetUnicodeDecoderRaw(aCharset, getter_AddRefs(decoder));
2658 NS_ENSURE_SUCCESS(rv,
toMozString(aString, aResult));
2660 PRInt32 dataLen = data.length();
2662 rv = decoder->GetMaxLength(data.c_str(), dataLen, &size);
2663 NS_ENSURE_SUCCESS(rv,
toMozString(aString, aResult));
2665 PRUnichar *wstr =
reinterpret_cast< PRUnichar *
>( NS_Alloc( (size + 1) *
sizeof( PRUnichar ) ) );
2666 rv = decoder->Convert(data.c_str(), &dataLen, wstr, &size);
2667 if (NS_SUCCEEDED(rv)) {
2668 aResult.Assign(wstr, size);
2671 NS_ENSURE_SUCCESS(rv,
toMozString(aString, aResult));
2685 PRBool sbMetadataHandlerTaglib::ReadFLACFile()
2687 nsAutoPtr<TagLib::FLAC::File> pTagFile;
2688 PRBool isValid = PR_TRUE;
2689 nsresult result =
NS_OK;
2693 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
2695 nsACString &filePath = mMetadataPath;
2699 pTagFile =
new TagLib::FLAC::File(filePath.BeginReading());
2701 result = NS_ERROR_OUT_OF_MEMORY;
2702 if (!pTagFile->isOpen())
2703 result = NS_ERROR_INVALID_ARG;
2704 if (NS_SUCCEEDED(result))
2705 result = CheckChannelRestart();
2708 if (NS_SUCCEEDED(result) && isValid)
2709 isValid = ReadFile(pTagFile);
2712 if (NS_SUCCEEDED(result) && isValid)
2713 ReadXiphTags(pTagFile->xiphComment());
2719 result = mpURL->SchemeIs(
"file", &isFileURI);
2720 NS_ENSURE_SUCCESS(result, PR_FALSE);
2723 mCachedAlbumArt.Clear();
2724 nsAutoPtr<sbAlbumArt> art(
new sbAlbumArt());
2725 NS_ENSURE_TRUE(art, PR_FALSE);
2726 result = ReadImageFlac(
2729 art->mimeType, &(art->dataLen), &(art->data));
2730 NS_ENSURE_SUCCESS(result, PR_FALSE);
2732 nsAutoPtr<sbAlbumArt>* cacheSlot = mCachedAlbumArt.AppendElement();
2733 NS_ENSURE_TRUE(cacheSlot, PR_FALSE);
2736 art =
new sbAlbumArt();
2737 NS_ENSURE_TRUE(art, PR_FALSE);
2738 result = ReadImageFlac(
2741 art->mimeType, &(art->dataLen), &(art->data));
2742 NS_ENSURE_SUCCESS(result, PR_FALSE);
2744 cacheSlot = mCachedAlbumArt.AppendElement();
2745 NS_ENSURE_TRUE(cacheSlot, PR_FALSE);
2750 if (NS_FAILED(result))
2765 PRBool sbMetadataHandlerTaglib::ReadMPCFile()
2767 nsAutoPtr<TagLib::MPC::File> pTagFile;
2768 PRBool isValid = PR_TRUE;
2769 nsresult result =
NS_OK;
2773 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
2775 nsACString &filePath = mMetadataPath;
2778 pTagFile =
new TagLib::MPC::File(filePath.BeginReading());
2780 result = NS_ERROR_OUT_OF_MEMORY;
2781 if (!pTagFile->isOpen())
2782 result = NS_ERROR_INVALID_ARG;
2783 if (NS_SUCCEEDED(result))
2784 result = CheckChannelRestart();
2787 if (NS_SUCCEEDED(result) && isValid)
2788 isValid = ReadFile(pTagFile);
2791 if (NS_SUCCEEDED(result) && isValid)
2792 ReadAPETags(pTagFile->APETag());
2795 if (NS_FAILED(result))
2810 PRBool sbMetadataHandlerTaglib::ReadMPEGFile()
2812 nsAutoPtr<TagLib::MPEG::File> pTagFile;
2813 PRBool isValid = PR_TRUE;
2814 nsresult result =
NS_OK;
2818 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
2820 nsACString &filePath = mMetadataPath;
2823 pTagFile =
new TagLib::MPEG::File(filePath.BeginReading());
2825 result = NS_ERROR_OUT_OF_MEMORY;
2826 if (!pTagFile->isOpen())
2827 result = NS_ERROR_INVALID_ARG;
2828 if (NS_SUCCEEDED(result))
2829 result = CheckChannelRestart();
2833 if (NS_SUCCEEDED(result)) {
2835 charset.AssignLiteral(
"UTF-8");
2839 if (NS_SUCCEEDED(result) && isValid)
2840 isValid = ReadFile(pTagFile, charset.BeginReading());
2843 if (NS_SUCCEEDED(result) && isValid)
2844 ReadID3v2Tags(pTagFile->ID3v2Tag(), charset.BeginReading());
2847 if (NS_SUCCEEDED(result) && isValid)
2848 ReadAPETags(pTagFile->APETag());
2851 if (NS_FAILED(result))
2866 PRBool sbMetadataHandlerTaglib::ReadASFFile()
2868 nsAutoPtr<TagLib::ASF::File> pTagFile;
2869 PRBool isValid = PR_TRUE;
2870 nsresult result =
NS_OK;
2874 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
2876 nsACString &filePath = mMetadataPath;
2879 pTagFile =
new TagLib::ASF::File(filePath.BeginReading());
2881 result = NS_ERROR_OUT_OF_MEMORY;
2882 if (!pTagFile->isOpen())
2883 result = NS_ERROR_INVALID_ARG;
2884 if (NS_SUCCEEDED(result))
2885 result = CheckChannelRestart();
2888 if (NS_SUCCEEDED(result) && isValid)
2889 isValid = ReadFile(pTagFile,
"");
2892 if (NS_FAILED(result))
2906 PRBool sbMetadataHandlerTaglib::ReadMP4File()
2908 nsAutoPtr<TagLib::MP4::File> pTagFile;
2909 PRBool isValid = PR_TRUE;
2910 nsresult result =
NS_OK;
2914 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
2916 nsACString &filePath = mMetadataPath;
2919 pTagFile =
new TagLib::MP4::File(filePath.BeginReading());
2921 result = NS_ERROR_OUT_OF_MEMORY;
2922 if (!pTagFile->isOpen())
2923 result = NS_ERROR_INVALID_ARG;
2924 if (NS_SUCCEEDED(result))
2925 result = CheckChannelRestart();
2928 if (NS_SUCCEEDED(result))
2929 isValid = ReadFile(pTagFile);
2931 if (NS_SUCCEEDED(result) && isValid) {
2935 result = mpURL->SchemeIs(
"file", &isFileURI);
2936 NS_ENSURE_SUCCESS(result, PR_FALSE);
2938 nsAutoPtr<sbAlbumArt> art(
new sbAlbumArt());
2939 NS_ENSURE_TRUE(art, PR_FALSE);
2940 result = ReadImageITunes(
2941 static_cast<TagLib::MP4::Tag*>(pTagFile->tag()),
2942 art->mimeType, &(art->dataLen), &(art->data));
2943 NS_ENSURE_SUCCESS(result, PR_FALSE);
2945 nsAutoPtr<sbAlbumArt>* cacheSlot = mCachedAlbumArt.AppendElement();
2946 NS_ENSURE_TRUE(cacheSlot, PR_FALSE);
2968 if (NS_SUCCEEDED(result)) {
2969 static const TagLib::ByteVector DRM_ATOMS[] = {
2970 TagLib::ByteVector(
"moov"),
2971 TagLib::ByteVector(
"trak"),
2972 TagLib::ByteVector(
"mdia"),
2973 TagLib::ByteVector(
"minf"),
2974 TagLib::ByteVector(
"stbl"),
2975 TagLib::ByteVector(
"stsd"),
2976 TagLib::ByteVector(
"drms"),
2977 TagLib::ByteVector(
"sinf"),
2978 TagLib::ByteVector(
"schi"),
2979 TagLib::ByteVector(
"priv"),
2985 static const size_t DRM_ATOM_COUNT =
sizeof(DRM_ATOMS)/
sizeof(TagLib::ByteVector);
2986 static const size_t ATOM_LEN_BYTES = 4;
2991 pTagFile->seek(lPos,TagLib::File::Beginning);
2993 while(pTagFile->tell() < pTagFile->length()) {
2996 atomLen = pTagFile->readBlock(ATOM_LEN_BYTES).toUInt();
2999 atomLen -= 2*ATOM_LEN_BYTES;
3000 if( pTagFile->readBlock(ATOM_LEN_BYTES) == DRM_ATOMS[idx] ) {
3006 pTagFile->seek(atomLen,TagLib::File::Current);
3010 (atomLen > 0) && (pTagFile->tell()+atomLen <= pTagFile->length())
3013 ByteVector moovBuffer = pTagFile->readBlock(atomLen);
3015 while( lPos < atomLen ) {
3017 lPos = moovBuffer.find(DRM_ATOMS[idx++],lPos);
3020 }
else if( idx == DRM_ATOM_COUNT ) {
3030 if (NS_FAILED(result))
3045 PRBool sbMetadataHandlerTaglib::ReadOGGFile()
3047 nsAutoPtr<TagLib::Vorbis::File> pTagFile;
3048 PRBool isValid = PR_TRUE;
3049 nsresult result =
NS_OK;
3053 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
3055 nsACString &filePath = mMetadataPath;
3058 pTagFile =
new TagLib::Vorbis::File(filePath.BeginReading());
3060 result = NS_ERROR_OUT_OF_MEMORY;
3061 if (!pTagFile->isOpen())
3062 result = NS_ERROR_INVALID_ARG;
3063 if (NS_SUCCEEDED(result))
3064 result = CheckChannelRestart();
3067 if (NS_SUCCEEDED(result))
3068 isValid = ReadFile(pTagFile);
3071 if (NS_SUCCEEDED(result) && isValid)
3072 ReadXiphTags(pTagFile->tag());
3075 if (NS_FAILED(result))
3089 PRBool sbMetadataHandlerTaglib::ReadOGAFile()
3091 nsAutoPtr<TagLib::Ogg::FLAC::File> pTagFile;
3092 PRBool isValid = PR_TRUE;
3093 nsresult result =
NS_OK;
3097 NS_ConvertUTF8toUTF16 filePath(mMetadataPath);
3099 nsACString &filePath = mMetadataPath;
3102 pTagFile =
new TagLib::Ogg::FLAC::File(filePath.BeginReading());
3104 result = NS_ERROR_OUT_OF_MEMORY;
3105 if (!pTagFile->isOpen())
3106 result = NS_ERROR_INVALID_ARG;
3107 if (NS_SUCCEEDED(result))
3108 result = CheckChannelRestart();
3111 if (NS_SUCCEEDED(result))
3112 isValid = ReadFile(pTagFile);
3124 if (NS_FAILED(result))
3140 nsresult sbMetadataHandlerTaglib::AddMetadataValue(
3143 const char *charset)
3145 nsresult result =
NS_OK;
3148 nsAutoString strValue;
3149 ConvertCharset(value, charset, strValue);
3150 result = mpMetadataPropertyArray->AppendProperty
3151 (NS_ConvertASCIItoUTF16(name),
3168 nsresult sbMetadataHandlerTaglib::AddMetadataValue(
3172 nsresult result =
NS_OK;
3183 result = mpMetadataPropertyArray->AppendProperty
3184 (NS_ConvertASCIItoUTF16(name),
3200 nsresult sbMetadataHandlerTaglib::AddMetadataValue(
3204 nsresult result =
NS_OK;
3215 result = mpMetadataPropertyArray->AppendProperty
3216 (NS_ConvertASCIItoUTF16(name),
3222 nsresult sbMetadataHandlerTaglib::AddMetadataValue(
3224 const nsAString &value)
3226 nsresult result =
NS_OK;
3228 if(value.IsEmpty()) {
3232 result = mpMetadataPropertyArray->AppendProperty(NS_ConvertASCIItoUTF16(name),
3257 nsresult sbMetadataHandlerTaglib::WriteBasic(
3258 TagLib::PropertyMap *properties)
3260 LOG((
"Writing Tag-unspecific values"));
3261 nsAutoString propertyValue;
3264 nsresult tmp_result;
3272 if (NS_SUCCEEDED(tmp_result)) {
3274 properties->erase(key);
3310 nsresult sbMetadataHandlerTaglib::WriteSeparatedNumbers(
3311 TagLib::PropertyMap *properties,
3313 const nsAString &baseProperty,
3314 const nsAString &countProperty)
3316 TagLib::StringList valueList;
3317 nsAutoString propertyValue;
3321 bool changed =
false;
3325 valueList = (*properties)[
target];
3326 if (!valueList.isEmpty()){
3327 TagLib::StringList old = valueList[0].split(SEP);
3328 if (!old.isEmpty()){
3330 if (old.size() > 1){
3336 nsresult tmp_result = mpMetadataPropertyArray->GetPropertyValue(
3337 baseProperty, propertyValue);
3338 if (NS_SUCCEEDED(tmp_result)) {
3341 NS_ConvertUTF16toUTF8(propertyValue).BeginReading(),
3342 TagLib::String::UTF8);
3343 if (value.isEmpty()){
3349 tmp_result = mpMetadataPropertyArray->GetPropertyValue(
3350 countProperty, propertyValue);
3351 if (NS_SUCCEEDED(tmp_result)) {
3354 NS_ConvertUTF16toUTF8(propertyValue).BeginReading(),
3355 TagLib::String::UTF8);
3356 if (value.isEmpty()){
3364 if (count != DEFAULT){
3368 properties->erase(target);
3369 if (base != DEFAULT){
3370 properties->insert(target, base);
3383 nsresult sbMetadataHandlerTaglib::WriteAPE(
3384 TagLib::APE::Tag *tag)
3386 LOG((
"Writing APE Tag"));
3387 nsresult result =
NS_OK;
3388 nsAutoString propertyValue;
3390 TagLib::PropertyMap prop = tag->properties();
3391 TagLib::PropertyMap* properties = ∝
3394 result = WriteBasic(properties);
3395 if (!NS_SUCCEEDED(result)) {
3400 result = WriteSeparatedNumbers(properties,
3404 if (!NS_SUCCEEDED(result)) {
3407 result = WriteSeparatedNumbers(properties,
3411 if (!NS_SUCCEEDED(result)) {
3416 nsresult tmp_result;
3419 tag->setProperties(prop);
3430 nsresult sbMetadataHandlerTaglib::WriteASF(
3431 TagLib::ASF::Tag *tag)
3433 LOG((
"Writing ASF Tag"));
3434 nsresult result =
NS_OK;
3435 nsAutoString propertyValue;
3437 TagLib::PropertyMap prop = tag->properties();
3438 TagLib::PropertyMap* properties = ∝
3441 result = WriteBasic(properties);
3442 if (!NS_SUCCEEDED(result)) {
3447 nsresult tmp_result;
3455 tag->setProperties(prop);
3466 nsresult sbMetadataHandlerTaglib::WriteID3v1(
3467 TagLib::ID3v1::Tag *tag)
3469 LOG((
"Writing ID3v1 Tag"));
3470 nsresult result =
NS_OK;
3471 nsAutoString propertyValue;
3473 TagLib::PropertyMap prop = tag->properties();
3474 TagLib::PropertyMap* properties = ∝
3477 result = WriteBasic(properties);
3478 if (!NS_SUCCEEDED(result)) {
3483 nsresult tmp_result;
3487 tag->setProperties(prop);
3498 nsresult sbMetadataHandlerTaglib::WriteID3v2(
3499 TagLib::ID3v2::Tag *tag)
3501 LOG((
"Writing ID3v2 Tag"));
3502 nsresult result =
NS_OK;
3504 nsAutoString propertyValue;
3506 TagLib::PropertyMap prop = tag->properties();
3507 TagLib::PropertyMap* properties = ∝
3510 result = WriteBasic(properties);
3511 if (!NS_SUCCEEDED(result)) {
3516 result = WriteSeparatedNumbers(properties,
3520 if (!NS_SUCCEEDED(result)) {
3523 result = WriteSeparatedNumbers(properties,
3527 if (!NS_SUCCEEDED(result)) {
3532 nsresult tmp_result;
3542 tag->setProperties(prop);
3553 nsresult sbMetadataHandlerTaglib::WriteMP4(
3554 TagLib::MP4::Tag *tag)
3556 LOG((
"Writing MP4 Tag"));
3557 nsresult result =
NS_OK;
3558 nsAutoString propertyValue;
3560 TagLib::PropertyMap prop = tag->properties();
3561 TagLib::PropertyMap* properties = ∝
3564 result = WriteBasic(properties);
3565 if (!NS_SUCCEEDED(result)) {
3570 nsresult tmp_result;
3577 tag->setProperties(prop);
3588 nsresult sbMetadataHandlerTaglib::WriteXiphComment(
3589 TagLib::Ogg::XiphComment *tag)
3591 LOG((
"Writing XiphComment"));
3592 nsresult result =
NS_OK;
3593 nsAutoString propertyValue;
3595 TagLib::PropertyMap prop = tag->properties();
3596 TagLib::PropertyMap* properties = ∝
3599 result = WriteBasic(properties);
3600 if (!NS_SUCCEEDED(result)) {
3605 result = WriteSeparatedNumbers(properties,
3609 if (!NS_SUCCEEDED(result)) {
3612 result = WriteSeparatedNumbers(properties,
3616 if (!NS_SUCCEEDED(result)) {
3621 nsresult tmp_result;
3624 tag->setProperties(prop);
3655 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3656 "abcdefghijklmnopqrstuvwxyz"
3659 std::string sbMetadataHandlerTaglib::base64_encode(
unsigned char const* bytes_to_encode,
3660 unsigned int in_len) {
3664 unsigned char char_array_3[3];
3665 unsigned char char_array_4[4];
3668 char_array_3[i++] = *(bytes_to_encode++);
3670 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
3671 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
3672 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
3673 char_array_4[3] = char_array_3[2] & 0x3f;
3675 for(i = 0; (i <4) ; i++)
3676 ret += base64_chars[char_array_4[i]];
3683 for(j = i; j < 3; j++)
3684 char_array_3[j] =
'\0';
3686 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
3687 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
3688 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
3689 char_array_4[3] = char_array_3[2] & 0x3f;
3691 for (j = 0; (j < i + 1); j++)
3692 ret += base64_chars[char_array_4[j]];
3704 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3705 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3706 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3707 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3708 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3709 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
3710 52, 53, 54, 55, 56, 57, 58, 59,
3711 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3712 0xff, 0, 1, 2, 3, 4, 5, 6,
3713 7, 8, 9, 10, 11, 12, 13, 14,
3714 15, 16, 17, 18, 19, 20, 21, 22,
3715 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
3716 0xff, 26, 27, 28, 29, 30, 31, 32,
3717 33, 34, 35, 36, 37, 38, 39, 40,
3718 41, 42, 43, 44, 45, 46, 47, 48,
3719 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
3720 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3721 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3722 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3723 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3724 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3725 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3726 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3727 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3728 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3729 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3730 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3731 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3732 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3733 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3734 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3735 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
3742 int in_len = encoded_string.size();
3743 if (in_len % 4 != 0) {
3750 unsigned char vals[4];
3752 vals[0] = base64lookup[(
unsigned char)encoded_string[i]];
3753 vals[1] = base64lookup[(
unsigned char)encoded_string[i+1]];
3754 vals[2] = base64lookup[(
unsigned char)encoded_string[i+2]];
3755 vals[3] = base64lookup[(
unsigned char)encoded_string[i+3]];
3760 if (vals[0] == 0xff || vals[1] == 0xff || vals[2] == 0xff ||
3766 if (vals[0] == 0xff || vals[1] == 0xff)
3768 if (vals[2] == 0xff || vals[3] == 0xff)
3770 if (encoded_string[i+3] !=
'=' ||
3771 (vals[2] == 0xff && encoded_string[i+2] !=
'='))
3774 ret += vals[0]<<2 | vals[1]>>4;
3775 if (vals[2] != 0xff)
3776 ret += (vals[1]&0x0F)<<4 | vals[2]>>2;
3782 ret += vals[0]<<2 | vals[1]>>4;
3783 ret += (vals[1]&0x0F)<<4 | vals[2]>>2;
3784 ret += (vals[2]&0x03)<<6 | vals[3];
#define SB_PROPERTY_TOTALDISCS
#define SB_PROPERTY_METADATAUUID
#define SB_PROPERTY_SAMPLERATE
#define SB_PROPERTY_LYRICS
#define SB_PROPERTY_CHANNELS
#define SB_PROPERTY_ALBUMARTISTNAME
#define SB_PROPERTY_RATING
#define SB_PROPERTY_ISDRMPROTECTED
#define SB_PROPERTY_CONDUCTORNAME
#define SB_PROPERTY_LYRICISTNAME
#define SB_PROPERTY_TOTALTRACKS
A seekable wrapper for an nsIChannel.
#define SB_PROPERTY_BITRATE
An interface to carry around arrays of nsIProperty instances Note that implementations of the interfa...
#define SB_PROPERTY_ORIGINPAGE
const sbCreateProxiedComponent do_ProxiedGetService(const nsCID &aCID, nsresult *error=0)
#define SB_PROPERTY_GENRE
#define SB_PROPERTY_CONTENTTYPE
_updateTextAndScrollDataForFrame aContent
this _dialogInput val(dateText)
#define SB_PROPERTY_SOFTWAREVENDOR
#define SB_PROPERTY_DURATION
#define SB_PROPERTY_COPYRIGHT
#define SB_PROPERTY_DISCNUMBER
#define SB_PROPERTY_ARTISTNAME
A listener interface for sbISeekableChannel.
BogusChannel prototype owner
Tag * tag(int index) const
#define SB_PROPERTY_RECORDLABELNAME
#define SB_PROPERTY_ALBUMNAME
#define SB_PROPERTY_LANGUAGE
#define SB_PROPERTY_COMPOSERNAME
#define SB_PROPERTY_TRACKNAME
#define SB_PROPERTY_COMMENT
dataSBGenres SBProperties tag
#define SB_PROPERTY_COPYRIGHTURL
#define SB_PROPERTY_SUBTITLE
_getSelectedPageStyle s i
#define SB_PROPERTY_PRIMARYIMAGEURL
_updateTextAndScrollDataForFrame aData
#define SB_PROPERTY_TRACKNUMBER