void testPicture() { ScopedFileCopy copy("empty", ".ogg"); string newname = copy.fileName(); { Vorbis::File f(newname.c_str()); FLAC::Picture *newpic = new FLAC::Picture(); newpic->setType(FLAC::Picture::BackCover); newpic->setWidth(5); newpic->setHeight(6); newpic->setColorDepth(16); newpic->setNumColors(7); newpic->setMimeType("image/jpeg"); newpic->setDescription("new image"); newpic->setData("JPEG data"); f.tag()->addPicture(newpic); f.save(); } { Vorbis::File f(newname.c_str()); List<FLAC::Picture *> lst = f.tag()->pictureList(); CPPUNIT_ASSERT_EQUAL((unsigned int)1, lst.size()); CPPUNIT_ASSERT_EQUAL((int)5, lst[0]->width()); CPPUNIT_ASSERT_EQUAL((int)6, lst[0]->height()); CPPUNIT_ASSERT_EQUAL((int)16, lst[0]->colorDepth()); CPPUNIT_ASSERT_EQUAL((int)7, lst[0]->numColors()); CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), lst[0]->mimeType()); CPPUNIT_ASSERT_EQUAL(String("new image"), lst[0]->description()); CPPUNIT_ASSERT_EQUAL(ByteVector("JPEG data"), lst[0]->data()); } }
void testReadPicture() { ScopedFileCopy copy("silence-44-s", ".flac"); string newname = copy.fileName(); FLAC::File f(newname.c_str()); List<FLAC::Picture *> lst = f.pictureList(); CPPUNIT_ASSERT_EQUAL((unsigned int)1, lst.size()); FLAC::Picture *pic = lst.front(); CPPUNIT_ASSERT_EQUAL(FLAC::Picture::FrontCover, pic->type()); CPPUNIT_ASSERT_EQUAL(1, pic->width()); CPPUNIT_ASSERT_EQUAL(1, pic->height()); CPPUNIT_ASSERT_EQUAL(24, pic->colorDepth()); CPPUNIT_ASSERT_EQUAL(0, pic->numColors()); CPPUNIT_ASSERT_EQUAL(String("image/png"), pic->mimeType()); CPPUNIT_ASSERT_EQUAL(String("A pixel."), pic->description()); CPPUNIT_ASSERT_EQUAL((unsigned int)150, pic->data().size()); }
void CTagLoaderTagLib::SetFlacArt(FLAC::File *flacFile, EmbeddedArt *art, CMusicInfoTag &tag) { FLAC::Picture *cover[2] = {}; List<FLAC::Picture *> pictures = flacFile->pictureList(); for (List<FLAC::Picture *>::ConstIterator i = pictures.begin(); i != pictures.end(); ++i) { FLAC::Picture *picture = *i; if (picture->type() == FLAC::Picture::FrontCover) cover[0] = picture; else // anything else is taken as second priority cover[1] = picture; } for (unsigned int i = 0; i < 2; i++) { if (cover[i]) { tag.SetCoverArtInfo(cover[i]->data().size(), cover[i]->mimeType().to8Bit(true)); if (art) art->set((const uint8_t*)cover[i]->data().data(), cover[i]->data().size(), cover[i]->mimeType().to8Bit(true)); return; // one is enough } } }
bool TagEditor::save() { if ( fRef ) { bool mustSave = false, result = false; if ( !isChecked() ) clearValues(); File &file = *fRef->file(); Tag &tag = getTag( *fRef, file ); if ( titleE->text() != tag.title().toCString( true ) ) { tag.setTitle( String( titleE->text().toUtf8().data(), String::UTF8 ) ); mustSave = true; } if ( artistE->text() != tag.artist().toCString( true ) ) { tag.setArtist( String( artistE->text().toUtf8().data(), String::UTF8 ) ); mustSave = true; } if ( albumE->text() != tag.album().toCString( true ) ) { tag.setAlbum( String( albumE->text().toUtf8().data(), String::UTF8 ) ); mustSave = true; } if ( commentE->text() != tag.comment().toCString( true ) ) { tag.setComment( String( commentE->text().toUtf8().data(), String::UTF8 ) ); mustSave = true; } if ( genreE->text() != tag.genre().toCString( true ) ) { tag.setGenre( String( genreE->text().toUtf8().data(), String::UTF8 ) ); mustSave = true; } if ( ( uint )yearB->value() != tag.year() ) { tag.setYear( yearB->value() ); mustSave = true; } if ( ( uint )trackB->value() != tag.track() ) { tag.setTrack( trackB->value() ); mustSave = true; } if ( isChecked() && ( pictureModificated || pictureBChecked != pictureB->isChecked() ) ) { const bool hasPicture = pictureB->isChecked() && !picture->isEmpty(); if ( instanceOf( file, MPEG::File ) || instanceOf( file, RIFF::AIFF::File ) ) { ID3v2::Tag *id3v2 = NULL; if ( instanceOf( file, MPEG::File ) ) id3v2 = ( ( MPEG::File & )file ).ID3v2Tag( hasPicture ); else if ( instanceOf( file, RIFF::AIFF::File ) ) id3v2 = ( ( RIFF::AIFF::File & )file ).tag(); if ( id3v2 ) { id3v2->removeFrames( "APIC" ); if ( hasPicture ) { ID3v2::AttachedPictureFrame *pictureFrame = new ID3v2::AttachedPictureFrame; pictureFrame->setType( ID3v2::AttachedPictureFrame::FrontCover ); pictureFrame->setMimeType( pictureMimeType.data() ); pictureFrame->setPicture( *picture ); id3v2->addFrame( pictureFrame ); } mustSave = true; } } else if ( instanceOf( file, FLAC::File ) ) { FLAC::File &flacF = ( FLAC::File & )file; flacF.removePictures(); if ( hasPicture ) { FLAC::Picture *flacPicture = new FLAC::Picture; flacPicture->setMimeType( pictureMimeType.data() ); flacPicture->setType( FLAC::Picture::FrontCover ); flacPicture->setData( *picture ); flacF.addPicture( flacPicture ); } mustSave = true; } else if ( instanceOf( file, MP4::File ) ) { MP4::ItemListMap &itemListMap = ( ( MP4::File & )file ).tag()->itemListMap(); if ( itemListMap.contains( "covr" ) ) itemListMap.erase( "covr" ); if ( hasPicture ) { MP4::CoverArt::Format format = ( MP4::CoverArt::Format )0; if ( pictureMimeType == "image/jpeg" ) format = MP4::CoverArt::JPEG; else if ( pictureMimeType == "image/png" ) format = MP4::CoverArt::PNG; #if TAGLIB18 else if ( pictureMimeType == "image/bmp" ) format = MP4::CoverArt::BMP; else if ( pictureMimeType == "image/gif" ) format = MP4::CoverArt::GIF; #endif if ( format ) { MP4::CoverArtList coverArtList; coverArtList.append( MP4::CoverArt( format, *picture ) ); itemListMap.insert( "covr", coverArtList ); } } mustSave = true; } else if ( isOgg( file ) ) { Ogg::XiphComment *xiphComment = getXiphComment( file ); if ( xiphComment ) { xiphComment->removeField( "METADATA_BLOCK_PICTURE" ); if ( hasPicture ) { FLAC::Picture flacPicture; flacPicture.setMimeType( pictureMimeType.data() ); flacPicture.setType( FLAC::Picture::FrontCover ); flacPicture.setData( *picture ); const ByteVector pict_data = flacPicture.render(); xiphComment->addField( "METADATA_BLOCK_PICTURE", QByteArray::fromRawData( pict_data.data(), pict_data.size() ).toBase64().data() ); } mustSave = true; } } } else if ( !isChecked() ) //Usuwanie wszystkich znanych tagów { mustSave = true; if ( instanceOf( file, MPEG::File ) ) ( ( MPEG::File & )file ).strip(); else if ( instanceOf( file, MPC::File ) ) ( ( MPC::File & )file ).strip(); else if ( instanceOf( file, WavPack::File ) ) ( ( WavPack::File & )file ).strip(); else if ( instanceOf( file, TrueAudio::File ) ) ( ( TrueAudio::File & )file ).strip(); else if ( instanceOf( file, APE::File ) ) ( ( APE::File & )file ).strip(); else if ( instanceOf( file, MP4::File ) ) ( ( MP4::File & )file ).tag()->itemListMap().clear(); else if ( instanceOf( file, ASF::File ) ) ( ( ASF::File & )file ).tag()->attributeListMap().clear(); else if ( isOgg( file ) ) removeXiphComment( getXiphComment( file ) ); else if ( instanceOf( file, FLAC::File ) ) { FLAC::File &flacF = ( FLAC::File & )file; flacF.removePictures(); #if TAGLIB19 if ( flacF.hasXiphComment() ) #endif removeXiphComment( flacF.xiphComment() ); } else if ( instanceOf( file, RIFF::AIFF::File ) ) { ID3v2::Tag *id3v2 = ( ( RIFF::AIFF::File & )file ).tag(); if ( id3v2 ) { ID3v2::FrameList frameList = id3v2->frameList(); for ( ID3v2::FrameList::ConstIterator it = frameList.begin() ; it != frameList.end() ; ++it ) id3v2->removeFrame( *it ); } } #if TAGLIB18 else if ( instanceOf( file, Mod::File ) || instanceOf( file, S3M::File ) || instanceOf( file, IT::File ) || instanceOf( file, XM::File ) ) { Mod::Tag *modTag = NULL; if ( instanceOf( file, Mod::File ) ) modTag = ( ( Mod::File & )file ).tag(); else if ( instanceOf( file, S3M::File ) ) modTag = ( ( S3M::File & )file ).tag(); else if ( instanceOf( file, IT::File ) ) modTag = ( ( IT::File & )file ).tag(); else if ( instanceOf( file, XM::File ) ) modTag = ( ( XM::File & )file ).tag(); if ( modTag ) modTag->setTrackerName( String::null ); } #endif } /* FLAC::File writer BUG workaround - remove ID3 tags */ if ( mustSave && instanceOf( file, FLAC::File ) ) { FLAC::File &flacF = ( FLAC::File & )file; #if TAGLIB19 if ( flacF.hasID3v1Tag() || flacF.hasID3v2Tag() ) #else if ( flacF.ID3v1Tag() || flacF.ID3v2Tag() ) #endif { const FileName fName = fRef->file()->name(); result = fRef->save(); delete fRef; fRef = NULL; if ( result ) result = MPEG::File( fName, false ).save( MPEG::File::NoTags ); mustSave = false; } } #if TAGLIB19 /* No ID3v2 in WAV, only InfoTag */ if ( mustSave && instanceOf( file, RIFF::WAV::File ) ) { RIFF::WAV::File &wavF = ( RIFF::WAV::File & )file; wavF.save( wavF.InfoTag()->isEmpty() ? RIFF::WAV::File::NoTags : RIFF::WAV::File::Info ); mustSave = false; } #endif return mustSave ? fRef->save() : ( fRef ? true : result ); } return false; }
bool TagEditor::open( const QString &fileName ) { clear(); #ifdef Q_OS_WIN fRef = new FileRef( ( const wchar_t * )fileName.utf16(), false ); #else fRef = new FileRef( fileName.toLocal8Bit(), false ); #endif if ( !fRef->isNull() && fRef->tag() ) { File &file = *fRef->file(); #if TAGLIB19 /* Copy ID3v2 to InfoTag */ if ( instanceOf( file, RIFF::WAV::File ) ) { const Tag &tag = *fRef->tag(); RIFF::Info::Tag &infoTag = *( ( RIFF::WAV::File & )file ).InfoTag(); if ( infoTag.isEmpty() && !tag.isEmpty() ) { infoTag.setTitle( tag.title() ); infoTag.setArtist( tag.artist() ); infoTag.setAlbum( tag.album() ); infoTag.setComment( tag.comment() ); infoTag.setGenre( tag.genre() ); infoTag.setYear( tag.year() ); infoTag.setTrack( tag.track() ); } } #endif const Tag &tag = getTag( *fRef, file ); bool hasTags = !tag.isEmpty(); setChecked( true ); if ( hasTags ) { titleE->setText( tag.title().toCString( true ) ); artistE->setText( tag.artist().toCString( true ) ); albumE->setText( tag.album().toCString( true ) ); commentE->setText( tag.comment().toCString( true ) ); genreE->setText( tag.genre().toCString( true ) ); yearB->setValue( tag.year() ); trackB->setValue( tag.track() ); } /* Covers */ if ( instanceOf( file, MPEG::File ) || instanceOf( file, RIFF::AIFF::File ) ) { pictureB->setEnabled( true ); if ( hasTags ) { ID3v2::Tag *id3v2 = NULL; if ( instanceOf( file, MPEG::File ) ) { MPEG::File &mpegF = ( MPEG::File & )file; #if TAGLIB19 if ( mpegF.hasID3v2Tag() ) #endif id3v2 = mpegF.ID3v2Tag(); } else if ( instanceOf( file, RIFF::AIFF::File ) ) id3v2 = ( ( RIFF::AIFF::File & )file ).tag(); if ( id3v2 ) { const ID3v2::FrameList &frameList = id3v2->frameList( "APIC" ); if ( !frameList.isEmpty() ) { ID3v2::AttachedPictureFrame &pictureFrame = *( ID3v2::AttachedPictureFrame * )frameList.front(); pictureMimeType = pictureFrame.mimeType().toCString(); *picture = pictureFrame.picture(); pictureB->setChecked( true ); pictureW->update(); } } } } else if ( instanceOf( file, FLAC::File ) ) { pictureB->setEnabled( true ); FLAC::File &flacF = ( FLAC::File & )file; if ( !flacF.pictureList().isEmpty() ) { FLAC::Picture &flacPicture = *flacF.pictureList().front(); pictureMimeType = flacPicture.mimeType().toCString(); *picture = flacPicture.data(); pictureB->setChecked( true ); pictureW->update(); hasTags = true; } } else if ( instanceOf( file, MP4::File ) ) { MP4::ItemListMap &itemListMap = ( ( MP4::File & )file ).tag()->itemListMap(); MP4::ItemListMap::ConstIterator it = itemListMap.find( "covr" ); pictureB->setEnabled( true ); if ( it != itemListMap.end() ) { MP4::CoverArtList coverArtList = it->second.toCoverArtList(); if ( !coverArtList.isEmpty() ) { MP4::CoverArt coverArt = coverArtList.front(); switch ( coverArt.format() ) { case MP4::CoverArt::JPEG: pictureMimeType = "image/jpeg"; break; case MP4::CoverArt::PNG: pictureMimeType = "image/png"; break; #if TAGLIB18 case MP4::CoverArt::BMP: pictureMimeType = "image/bmp"; break; case MP4::CoverArt::GIF: pictureMimeType = "image/gif"; break; #endif default: break; } if ( !pictureMimeType.isEmpty() ) { *picture = coverArt.data(); pictureB->setChecked( true ); pictureW->update(); hasTags = true; } } } } else if ( isOgg( file ) ) { const Ogg::XiphComment *xiphComment = getXiphComment( file ); if ( xiphComment ) { const Ogg::FieldListMap &fieldListMap = xiphComment->fieldListMap(); Ogg::FieldListMap::ConstIterator it = fieldListMap.find( "METADATA_BLOCK_PICTURE" ); pictureB->setEnabled( true ); if ( it != fieldListMap.end() && !it->second.isEmpty() ) { /* OGG picture and FLAC picture are the same except OGG picture is encoded into Base64 */ QByteArray pict_frame_decoded = QByteArray::fromBase64( it->second.front().toCString() ); FLAC::Picture flacPicture; if ( flacPicture.parse( ByteVector( pict_frame_decoded.data(), pict_frame_decoded.size() ) ) ) { pictureMimeType = flacPicture.mimeType().toCString(); *picture = flacPicture.data(); pictureB->setChecked( true ); pictureW->update(); } } } } pictureBChecked = pictureB->isChecked(); setChecked( hasTags ); return true; } delete fRef; fRef = NULL; return false; }
void FLAC::File::scan() { // Scan the metadata pages if(d->scanned) return; if(!isValid()) return; long nextBlockOffset; if(d->hasID3v2) nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize); else nextBlockOffset = find("fLaC"); if(nextBlockOffset < 0) { debug("FLAC::File::scan() -- FLAC stream not found"); setValid(false); return; } nextBlockOffset += 4; d->flacStart = nextBlockOffset; seek(nextBlockOffset); ByteVector header = readBlock(4); // Header format (from spec): // <1> Last-metadata-block flag // <7> BLOCK_TYPE // 0 : STREAMINFO // 1 : PADDING // .. // 4 : VORBIS_COMMENT // .. // <24> Length of metadata to follow char blockType = header[0] & 0x7f; bool isLastBlock = (header[0] & 0x80) != 0; uint length = header.mid(1, 3).toUInt(); // First block should be the stream_info metadata if(blockType != MetadataBlock::StreamInfo) { debug("FLAC::File::scan() -- invalid FLAC stream"); setValid(false); return; } d->streamInfoData = readBlock(length); d->blocks.append(new UnknownMetadataBlock(blockType, d->streamInfoData)); nextBlockOffset += length + 4; // Search through the remaining metadata while(!isLastBlock) { header = readBlock(4); blockType = header[0] & 0x7f; isLastBlock = (header[0] & 0x80) != 0; length = header.mid(1, 3).toUInt(); ByteVector data = readBlock(length); if(data.size() != length || length == 0) { debug("FLAC::File::scan() -- FLAC stream corrupted"); setValid(false); return; } MetadataBlock *block = 0; // Found the vorbis-comment if(blockType == MetadataBlock::VorbisComment) { if(!d->hasXiphComment) { d->xiphCommentData = data; d->hasXiphComment = true; } else { debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, using the first one"); } } else if(blockType == MetadataBlock::Picture) { FLAC::Picture *picture = new FLAC::Picture(); if(picture->parse(data)) { block = picture; } else { debug("FLAC::File::scan() -- invalid picture found, discarting"); delete picture; } } if(!block) { block = new UnknownMetadataBlock(blockType, data); } if(block->code() != MetadataBlock::Padding) { d->blocks.append(block); } else { delete block; } nextBlockOffset += length + 4; if(nextBlockOffset >= File::length()) { debug("FLAC::File::scan() -- FLAC stream corrupted"); setValid(false); return; } seek(nextBlockOffset); } // End of metadata, now comes the datastream d->streamStart = nextBlockOffset; d->streamLength = File::length() - d->streamStart; if(d->hasID3v1) d->streamLength -= 128; d->scanned = true; }
QMPlay_Tag::QMPlay_Tag( const char *_fileName ) { using namespace TagLib; fileName = _fileName; isNull = true; canWriteID3 = false; dontUse = false; isFLAC = fileName.right( 5 ) == ".flac"; if ( !isFLAC ) { QByteArray r4 = fileName.right( 4 ); if ( r4 == ".wav" ) { dontUse = true; return; } if ( r4 == ".mp3" ) canWriteID3 = true; } //General tags { Load_FileRef if ( !f->isNull() && f->tag() ) { Tag *tag = f->tag(); title = tag->title(); artist = tag->artist(); album = tag->album(); comment = tag->comment(); genre = tag->genre(); year = tag->year(); track = tag->track(); isNull = false; } delete f; } //ID3v2 picture if ( canWriteID3 ) { Load_MPEG_File ID3v2::Tag *id3v2 = f->ID3v2Tag(); if ( id3v2 && !id3v2->isEmpty() ) { ID3v2::FrameList pict = id3v2->frameList( "APIC" ); if ( !pict.isEmpty() ) { picture = ID3v2::AttachedPictureFrame( pict.front()->render() ).picture(); isNull = false; } } delete f; } //FLAC picture if ( isFLAC ) { Load_FLAC_File if ( f->pictureList().size() ) { FLAC::Picture *p = f->pictureList().front(); if ( p ) { picture = p->data(); isNull = false; } } delete f; } }
void QMPlay_Tag::save( bool clearID3 ) { if ( dontUse ) return; using namespace TagLib; //ID3v2 { Load_MPEG_File if ( !canWriteID3 || clearID3 ) f->save( MPEG::File::NoTags ); else { ID3v2::Tag *id3v2 = f->ID3v2Tag(); if ( id3v2 ) { ID3v2::FrameList pict = id3v2->frameList( "APIC" ); while ( pict.size() ) id3v2->removeFrame( pict[ 0 ] ); if ( !picture.isEmpty() ) { ID3v2::AttachedPictureFrame *pictFrame = new ID3v2::AttachedPictureFrame; pictFrame->setPicture( picture ); QString mimeType = "image/" + QImageReader( QDataStream( QByteArray( picture.data(), picture.size() ) ).device() ).format(); pictFrame->setMimeType( mimeType.toAscii().data() ); id3v2->addFrame( pictFrame ); } f->save(); } } delete f; } if ( isFLAC ) { Load_FLAC_File if ( f->pictureList().size() ) f->removePictures(); if ( !picture.isEmpty() ) { FLAC::Picture *pict = new FLAC::Picture; pict->setData( picture ); QString mimeType = "image/" + QImageReader( QDataStream( QByteArray( picture.data(), picture.size() ) ).device() ).format(); pict->setMimeType( mimeType.toAscii().data() ); f->addPicture( pict ); } f->save(); delete f; } //General tag { Load_FileRef if ( !f->isNull() && f->tag() ) { Tag *tag = f->tag(); tag->setTitle( title ); tag->setArtist( artist ); tag->setAlbum( album ); tag->setComment( comment ); tag->setGenre( genre ); tag->setYear( year ); tag->setTrack( track ); f->save(); } delete f; } }
void testReplacePicture() { ScopedFileCopy copy("silence-44-s", ".flac"); string newname = copy.fileName(); { FLAC::File f(newname.c_str()); List<FLAC::Picture *> lst = f.pictureList(); CPPUNIT_ASSERT_EQUAL((unsigned int)1, lst.size()); FLAC::Picture *newpic = new FLAC::Picture(); newpic->setType(FLAC::Picture::BackCover); newpic->setWidth(5); newpic->setHeight(6); newpic->setColorDepth(16); newpic->setNumColors(7); newpic->setMimeType("image/jpeg"); newpic->setDescription("new image"); newpic->setData("JPEG data"); f.removePictures(); f.addPicture(newpic); f.save(); } { FLAC::File f(newname.c_str()); List<FLAC::Picture *> lst = f.pictureList(); CPPUNIT_ASSERT_EQUAL((unsigned int)1, lst.size()); FLAC::Picture *pic = lst[0]; CPPUNIT_ASSERT_EQUAL(FLAC::Picture::BackCover, pic->type()); CPPUNIT_ASSERT_EQUAL(5, pic->width()); CPPUNIT_ASSERT_EQUAL(6, pic->height()); CPPUNIT_ASSERT_EQUAL(16, pic->colorDepth()); CPPUNIT_ASSERT_EQUAL(7, pic->numColors()); CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), pic->mimeType()); CPPUNIT_ASSERT_EQUAL(String("new image"), pic->description()); CPPUNIT_ASSERT_EQUAL(ByteVector("JPEG data"), pic->data()); } }