00001 #include <iostream>
00002 #include <sys/stat.h>
00003 using namespace std;
00004
00005 #include "metaioflacvorbiscomment.h"
00006 #include "metaiovorbiscomment.h"
00007 #include "metadata.h"
00008
00009
00010 #include <mythtv/mythcontext.h>
00011
00012 MetaIOFLACVorbisComment::MetaIOFLACVorbisComment(void)
00013 : MetaIO(".flac")
00014 {
00015 }
00016
00017 MetaIOFLACVorbisComment::~MetaIOFLACVorbisComment(void)
00018 {
00019 }
00020
00021
00022
00032 bool MetaIOFLACVorbisComment::write(Metadata* mdata, bool exclusive)
00033 {
00034 exclusive = exclusive;
00035
00036
00037 if (!mdata)
00038 return false;
00039
00040 FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
00041 if (!FLAC__metadata_chain_read(chain, mdata->Filename().local8Bit())
00042 && !FLAC__metadata_chain_read(chain, mdata->Filename().ascii()))
00043 {
00044 FLAC__metadata_chain_delete(chain);
00045 return false;
00046 }
00047
00048 bool found_vc_block = false;
00049 FLAC__StreamMetadata *block = 0;
00050 FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
00051
00052 FLAC__metadata_iterator_init(iterator, chain);
00053
00054 do {
00055 block = FLAC__metadata_iterator_get_block(iterator);
00056 if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
00057 found_vc_block = true;
00058 } while (!found_vc_block && FLAC__metadata_iterator_next(iterator));
00059
00060 if (!found_vc_block)
00061 {
00062 block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
00063
00064 while (FLAC__metadata_iterator_next(iterator))
00065 ;
00066
00067 if (!FLAC__metadata_iterator_insert_block_after(iterator, block))
00068 {
00069 FLAC__metadata_chain_delete(chain);
00070 FLAC__metadata_iterator_delete(iterator);
00071 return false;
00072 }
00073
00074 FLAC__ASSERT(FLAC__metadata_iterator_get_block(iterator) == block);
00075 }
00076
00077 FLAC__ASSERT(0 != block);
00078 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
00079
00080
00081
00082 if (block->data.vorbis_comment.comments > 0)
00083 FLAC__metadata_object_vorbiscomment_resize_comments(block, 0);
00084
00085
00086 setComment(block, MYTH_VORBISCOMMENT_ARTIST, mdata->Artist());
00087
00088 if (mdata->Compilation())
00089 {
00090
00091 setComment(block, MYTH_VORBISCOMMENT_MUSICBRAINZ_ALBUMARTISTID,
00092 MYTH_MUSICBRAINZ_ALBUMARTIST_UUID);
00093
00094 if (!mdata->CompilationArtist().isEmpty())
00095 {
00096 setComment(block, MYTH_VORBISCOMMENT_COMPILATIONARTIST,
00097 mdata->CompilationArtist());
00098 }
00099
00100 }
00101
00102 setComment(block, MYTH_VORBISCOMMENT_ALBUM, mdata->Album());
00103 setComment(block, MYTH_VORBISCOMMENT_TITLE, mdata->Title());
00104 setComment(block, MYTH_VORBISCOMMENT_GENRE, mdata->Genre());
00105
00106 char text[128];
00107 if (0 != mdata->Track())
00108 {
00109 snprintf(text, 128, "%d", mdata->Track());
00110 setComment(block, MYTH_VORBISCOMMENT_TRACK, text);
00111 }
00112
00113 if (0 != mdata->Year())
00114 {
00115 snprintf(text, 128, "%d", mdata->Year());
00116 setComment(block, MYTH_VORBISCOMMENT_DATE, text);
00117 }
00118
00119 FLAC__metadata_chain_write(chain, false, false);
00120
00121 FLAC__metadata_chain_delete(chain);
00122 FLAC__metadata_iterator_delete(iterator);
00123
00124 return true;
00125 }
00126
00127
00128
00135 Metadata* MetaIOFLACVorbisComment::read(QString filename)
00136 {
00137 QString artist = "", compilation_artist = "", album = "", title = "", genre = "";
00138 int year = 0, tracknum = 0, length = 0;
00139 bool compilation = false;
00140
00141 FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
00142 if (!FLAC__metadata_chain_read(chain, filename.local8Bit())
00143 && !FLAC__metadata_chain_read(chain, filename.ascii()))
00144 {
00145 FLAC__metadata_chain_delete(chain);
00146 return NULL;
00147 }
00148
00149 bool found_vc_block = false;
00150 FLAC__StreamMetadata *block = 0;
00151 FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
00152
00153 FLAC__metadata_iterator_init(iterator, chain);
00154
00155 block = FLAC__metadata_iterator_get_block(iterator);
00156
00157 FLAC__ASSERT(0 != block);
00158 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
00159
00160 length = getTrackLength(block);
00161
00162 do {
00163 block = FLAC__metadata_iterator_get_block(iterator);
00164 if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
00165 found_vc_block = true;
00166 } while (!found_vc_block && FLAC__metadata_iterator_next(iterator));
00167
00168 if (!found_vc_block)
00169 {
00170 FLAC__metadata_chain_delete(chain);
00171 FLAC__metadata_iterator_delete(iterator);
00172 return NULL;
00173 }
00174
00175 FLAC__ASSERT(0 != block);
00176 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
00177
00178 title = getComment(block, MYTH_VORBISCOMMENT_TITLE);
00179
00180 if (title.isEmpty())
00181 {
00182 readFromFilename(filename, artist, album, title, genre, tracknum);
00183 }
00184 else
00185 {
00186 artist = getComment(block, MYTH_VORBISCOMMENT_ARTIST);
00187 compilation_artist = getComment(block,
00188 MYTH_VORBISCOMMENT_COMPILATIONARTIST);
00189 album = getComment(block, MYTH_VORBISCOMMENT_ALBUM);
00190 genre = getComment(block, MYTH_VORBISCOMMENT_GENRE);
00191 tracknum = getComment(block, MYTH_VORBISCOMMENT_TRACK).toInt();
00192 year = getComment(block, MYTH_VORBISCOMMENT_DATE).toInt();
00193
00194 QString tmp = getComment(block,
00195 MYTH_VORBISCOMMENT_MUSICBRAINZ_ALBUMARTISTID);
00196 compilation = (MYTH_MUSICBRAINZ_ALBUMARTIST_UUID == tmp);
00197
00198 }
00199
00200 FLAC__metadata_chain_delete(chain);
00201 FLAC__metadata_iterator_delete(iterator);
00202
00203 Metadata *retdata = new Metadata(filename, artist, compilation_artist, album,
00204 title, genre, year, tracknum, length);
00205
00206 retdata->setCompilation(compilation);
00207
00208 return retdata;
00209 }
00210
00211
00212
00219 int MetaIOFLACVorbisComment::getTrackLength(QString filename)
00220 {
00221 FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
00222 if (!FLAC__metadata_chain_read(chain, filename.local8Bit()) &&
00223 !FLAC__metadata_chain_read(chain, filename.ascii()))
00224 {
00225 FLAC__metadata_chain_delete(chain);
00226 return 0;
00227 }
00228
00229 FLAC__StreamMetadata *block = 0;
00230 FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
00231
00232 FLAC__metadata_iterator_init(iterator, chain);
00233
00234 block = FLAC__metadata_iterator_get_block(iterator);
00235
00236 FLAC__ASSERT(0 != block);
00237 FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO);
00238
00239 int length = getTrackLength(block);
00240
00241 FLAC__metadata_chain_delete(chain);
00242 FLAC__metadata_iterator_delete(iterator);
00243
00244 return length;
00245 }
00246
00247
00248
00257 inline int MetaIOFLACVorbisComment::getTrackLength(FLAC__StreamMetadata* pBlock)
00258 {
00259 if (!pBlock)
00260 return 0;
00261
00262 return pBlock->data.stream_info.total_samples /
00263 (pBlock->data.stream_info.sample_rate / 1000);
00264 }
00265
00266
00274 QString MetaIOFLACVorbisComment::getComment(FLAC__StreamMetadata* pBlock,
00275 const char* pLabel)
00276 {
00277 FLAC__StreamMetadata_VorbisComment_Entry *entry;
00278 entry = pBlock->data.vorbis_comment.comments;
00279
00280 QString qlabel = pLabel;
00281 QString retstr = "";
00282 for (unsigned int i = 0; i < pBlock->data.vorbis_comment.num_comments; i++)
00283 {
00284 char *fieldname = new char[(entry + i)->length + 1];
00285 fieldname[(entry + i)->length] = 0;
00286 strncpy(fieldname, (char *)((entry + i)->entry), (entry + i)->length);
00287 QString entrytext = fieldname;
00288 delete [] fieldname;
00289 int loc;
00290
00291
00292
00293 if ((loc = entrytext.find("=")) &&
00294 (loc == (int)qlabel.length()) &&
00295 entrytext.lower().left(qlabel.length()) == qlabel.lower())
00296 {
00297 return QString::fromUtf8(entrytext.right(entrytext.length() - loc - 1));
00298 }
00299 }
00300
00301 return "";
00302 }
00303
00304
00305
00314 void MetaIOFLACVorbisComment::setComment(FLAC__StreamMetadata* pBlock,
00315 const char* pLabel,
00316 const QString& rData)
00317 {
00318 if (rData.length() < 1)
00319 return;
00320
00321 QString test = getComment(pBlock, pLabel);
00322
00323 QString thenewentry = QString(pLabel).upper() + "=" + rData;
00324 QCString utf8str = thenewentry.utf8();
00325 int thenewentrylen = utf8str.length();
00326
00327 FLAC__StreamMetadata_VorbisComment_Entry entry;
00328
00329 entry.length = thenewentrylen;
00330 entry.entry = (unsigned char *)utf8str.data();
00331
00332 FLAC__metadata_object_vorbiscomment_insert_comment(pBlock,
00333 pBlock->data.vorbis_comment.num_comments,
00334 entry, true);
00335 }