void cFCODatabaseFileIter::SeekToGenre(cGenre::Genre genreId) { for( SeekBegin(); ! Done(); Next() ) { if( GetGenre() == genreId ) return; } }
/* Sets a specified field of the given tag. */ void ID3V1_TAG::SetField(ID3V1_TAG_COMP type, const char* source, int charset) { if (!source) // cannot remove components of ID3V1 tags source = ""; char encoded[32]; switch( type ) { case ID3V1_TITLE: ch_convert( CH_CP_NONE, source, charset, encoded, sizeof( encoded ), 0); spacecopy( title, encoded, sizeof title ); break; case ID3V1_ARTIST: ch_convert( CH_CP_NONE, source, charset, encoded, sizeof( encoded ), 0); spacecopy( artist, encoded, sizeof artist ); break; case ID3V1_ALBUM: ch_convert( CH_CP_NONE, source, charset, encoded, sizeof( encoded ), 0); spacecopy( album, encoded, sizeof album ); break; case ID3V1_YEAR: ch_convert( CH_CP_NONE, source, charset, encoded, sizeof( encoded ), 0); spacecopy( year, encoded, sizeof year ); break; case ID3V1_COMMENT: ch_convert( CH_CP_NONE, source, charset, encoded, sizeof( encoded ), 0); spacecopy( comment, encoded, sizeof comment ); break; case ID3V1_TRACK: empty = 0; track = atol( source ); break; case ID3V1_GENRE: { int i; size_t l; if (*source == 0) genre = 0xFF; else if (sscanf(source, "#%i%n", &i, &l) == 1 && l == strlen(source)) genre = i; else genre = (unsigned char)GetGenre(source); break; } } }
/* GetIcyData() */ void CIcy::GetIcyData(ICYDATA* pIcyData) { memset(pIcyData,'\0',sizeof(ICYDATA)); if(m_nResponse==ICY_CODE_OK) { strcpyn(pIcyData->station,GetStationName(),ICY_MAX_STATION+1); strcpyn(pIcyData->genre,GetGenre(),ICY_MAX_GENRE+1); strcpyn(pIcyData->url,GetUrl(),ICY_MAX_URL+1); strcpyn(pIcyData->contenttype,GetContentType(),ICY_MAX_CONTENT+1); pIcyData->metaint = GetMetaInterval(); pIcyData->bitrate = GetBitRate(); strcpyn(pIcyData->notice,GetNotice(),ICY_MAX_NOTICE+1); strcpyn(pIcyData->noticeinfo,GetNoticeInfo(),ICY_MAX_NOTICE+1); pIcyData->code = m_nResponse; } }
int CGenreTable::SearchGenre( CUString strSearch ) const { int i; strSearch.TrimLeft(); strSearch.TrimRight(); for ( i = 0 ; i < (int)v_Entries.size(); i++ ) { if ( 0 == strSearch.CompareNoCase( GetGenre( i ) ) ) { return i; } } return -1; }
CUString CGenreTable::GetID3V1GenreString( int nID3TagIdx ) const { int i; CUString strRet; for ( i = 0 ; i < (int)v_Entries.size(); i++ ) { if ( nID3TagIdx == GetID3V1ID( i ) ) { return GetGenre( i ); } } strRet = g_language.GetString( IDS_UNKNOWN ); return strRet; }
int CGenreTable::AddEntry( INT nID3V1ID, const CUString& strGenre, const CUString& strCDDBGenre, bool bCanBeModified ) { bool bAdd = true; int i = 0; GENRETABLEENTRY newEntry; newEntry.nID3V1ID = nID3V1ID; newEntry.strGenre = strGenre; newEntry.bCanBeModified = bCanBeModified; newEntry.strCDDBGenre = strCDDBGenre; newEntry.strGenre.TrimLeft(); newEntry.strGenre.TrimRight(); newEntry.strCDDBGenre.TrimLeft(); newEntry.strCDDBGenre.TrimRight(); // check if entry is already in this list for ( i = 0 ; i < (int)v_Entries.size(); i++ ) { if ( GetID3V1ID( i ) == nID3V1ID && ( 0 == strGenre.CompareNoCase( GetGenre( i ) ) ) ) { bAdd = false; } } if ( true == bAdd ) { v_Entries.push_back( newEntry ); // Sort(); } return v_Entries.size(); }
bool FLACMetadata::WriteMetadata(CFErrorRef *error) { UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX)) return false; FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new(); // ENOMEM sux if(NULL == chain) return false; if(!FLAC__metadata_chain_read(chain, reinterpret_cast<const char *>(buf))) { // Attempt to provide a descriptive error message if(NULL != error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); switch(FLAC__metadata_chain_status(chain)) { case FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE: { CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a FLAC file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; break; } case FLAC__METADATA_CHAIN_STATUS_BAD_METADATA: { CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a FLAC file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file contains bad metadata."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; break; } default: { CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a FLAC file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; break; } } *error = CFErrorCreate(kCFAllocatorDefault, AudioMetadataErrorDomain, AudioMetadataFileFormatNotRecognizedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } FLAC__metadata_chain_delete(chain), chain = NULL; return false; } FLAC__metadata_chain_sort_padding(chain); FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); if(NULL == iterator) { FLAC__metadata_chain_delete(chain), chain = NULL; return false; } FLAC__metadata_iterator_init(iterator, chain); // Seek to the vorbis comment block if it exists while(FLAC__METADATA_TYPE_VORBIS_COMMENT != FLAC__metadata_iterator_get_block_type(iterator)) { if(!FLAC__metadata_iterator_next(iterator)) break; // Already at end } FLAC__StreamMetadata *block = NULL; // If there isn't a vorbis comment block add one if(FLAC__METADATA_TYPE_VORBIS_COMMENT != FLAC__metadata_iterator_get_block_type(iterator)) { // The padding block will be the last block if it exists; add the comment block before it if(FLAC__METADATA_TYPE_PADDING == FLAC__metadata_iterator_get_block_type(iterator)) FLAC__metadata_iterator_prev(iterator); block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); if(NULL == block) { FLAC__metadata_chain_delete(chain), chain = NULL; FLAC__metadata_iterator_delete(iterator), iterator = NULL; return false; } // Add our metadata if(!FLAC__metadata_iterator_insert_block_after(iterator, block)) { if(NULL != error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Unable to write metadata"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioMetadataErrorDomain, AudioMetadataInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } FLAC__metadata_chain_delete(chain), chain = NULL; FLAC__metadata_iterator_delete(iterator), iterator = NULL; return false; } } else block = FLAC__metadata_iterator_get_block(iterator); // Standard tags SetVorbisComment(block, "ALBUM", GetAlbumTitle()); SetVorbisComment(block, "ARTIST", GetArtist()); SetVorbisComment(block, "ALBUMARTIST", GetAlbumArtist()); SetVorbisComment(block, "COMPOSER", GetComposer()); SetVorbisComment(block, "GENRE", GetGenre()); SetVorbisComment(block, "DATE", GetReleaseDate()); SetVorbisComment(block, "DESCRIPTION", GetComment()); SetVorbisComment(block, "TITLE", GetTitle()); SetVorbisCommentNumber(block, "TRACKNUMBER", GetTrackNumber()); SetVorbisCommentNumber(block, "TRACKTOTAL", GetTrackTotal()); SetVorbisCommentBoolean(block, "COMPILATION", GetCompilation()); SetVorbisCommentNumber(block, "DISCNUMBER", GetDiscNumber()); SetVorbisCommentNumber(block, "DISCTOTAL", GetDiscTotal()); SetVorbisComment(block, "ISRC", GetISRC()); SetVorbisComment(block, "MCN", GetMCN()); // Additional metadata CFDictionaryRef additionalMetadata = GetAdditionalMetadata(); if(NULL != additionalMetadata) { CFIndex count = CFDictionaryGetCount(additionalMetadata); const void * keys [count]; const void * values [count]; CFDictionaryGetKeysAndValues(additionalMetadata, reinterpret_cast<const void **>(keys), reinterpret_cast<const void **>(values)); for(CFIndex i = 0; i < count; ++i) { CFIndex keySize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(reinterpret_cast<CFStringRef>(keys[i])), kCFStringEncodingASCII); char key [keySize + 1]; if(!CFStringGetCString(reinterpret_cast<CFStringRef>(keys[i]), key, keySize + 1, kCFStringEncodingASCII)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.FLAC"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); continue; } SetVorbisComment(block, key, reinterpret_cast<CFStringRef>(values[i])); } } // ReplayGain info SetVorbisCommentDouble(block, "REPLAYGAIN_REFERENCE_LOUDNESS", GetReplayGainReferenceLoudness(), CFSTR("%2.1f dB")); SetVorbisCommentDouble(block, "REPLAYGAIN_TRACK_GAIN", GetReplayGainReferenceLoudness(), CFSTR("%+2.2f dB")); SetVorbisCommentDouble(block, "REPLAYGAIN_TRACK_PEAK", GetReplayGainTrackGain(), CFSTR("%1.8f")); SetVorbisCommentDouble(block, "REPLAYGAIN_ALBUM_GAIN", GetReplayGainAlbumGain(), CFSTR("%+2.2f dB")); SetVorbisCommentDouble(block, "REPLAYGAIN_ALBUM_PEAK", GetReplayGainAlbumPeak(), CFSTR("%1.8f")); // Write the new metadata to the file if(!FLAC__metadata_chain_write(chain, true, false)) { if(NULL != error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Unable to write metadata"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioMetadataErrorDomain, AudioMetadataInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } FLAC__metadata_chain_delete(chain), chain = NULL; FLAC__metadata_iterator_delete(iterator), iterator = NULL; return false; } FLAC__metadata_chain_delete(chain), chain = NULL; FLAC__metadata_iterator_delete(iterator), iterator = NULL; MergeChangedMetadataIntoMetadata(); return true; }
void FillID3List(HWND hwndDlg, HWND hwndList, char *filename) { ID3Tag *tag; ID3Frame *frame; ID3Field *field; ID3_FrameID eFrameID; char info[1024]; int numFrames; int i; int iItem = 0; if ((tag = ID3Tag_New()) != NULL) { ID3Tag_Link(tag, filename); numFrames = ID3Tag_NumFrames(tag); for (i = 0; i < numFrames; i++) { iItem++; frame = ID3Tag_GetFrameNum(tag, i); eFrameID = ID3Frame_GetID(frame); switch (eFrameID) { case ID3FID_ALBUM: case ID3FID_BPM: case ID3FID_COMPOSER: case ID3FID_CONTENTTYPE: case ID3FID_COPYRIGHT: case ID3FID_DATE: case ID3FID_PLAYLISTDELAY: case ID3FID_ENCODEDBY: case ID3FID_LYRICIST: case ID3FID_FILETYPE: case ID3FID_TIME: case ID3FID_CONTENTGROUP: case ID3FID_TITLE: case ID3FID_SUBTITLE: case ID3FID_INITIALKEY: case ID3FID_LANGUAGE: case ID3FID_SONGLEN: case ID3FID_MEDIATYPE: case ID3FID_ORIGALBUM: case ID3FID_ORIGFILENAME: case ID3FID_ORIGLYRICIST: case ID3FID_ORIGARTIST: case ID3FID_ORIGYEAR: case ID3FID_FILEOWNER: case ID3FID_LEADARTIST: case ID3FID_BAND: case ID3FID_CONDUCTOR: case ID3FID_MIXARTIST: case ID3FID_PARTINSET: case ID3FID_PUBLISHER: case ID3FID_TRACKNUM: case ID3FID_RECORDINGDATES: case ID3FID_NETRADIOSTATION: case ID3FID_NETRADIOOWNER: case ID3FID_SIZE: case ID3FID_ISRC: case ID3FID_ENCODERSETTINGS: case ID3FID_YEAR: { LV_ITEM lvi; ID3ITEM *pItem = LocalAlloc(LPTR, sizeof(ID3ITEM)); /* Initialize LV_ITEM members that are common to all items. */ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; lvi.state = 0; lvi.stateMask = 0; lvi.pszText = LPSTR_TEXTCALLBACK; /* app. maintains text */ lvi.iImage = 0; lvi.iItem = iItem; lvi.iSubItem = 0; pItem->frameId = eFrameID; pItem->aCols[0] = GetFrameDesc(eFrameID); field = ID3Frame_GetField(frame, ID3FN_TEXT); ID3Field_GetASCII(field, info, 1024, 1); if (eFrameID == ID3FID_CONTENTTYPE) pItem->aCols[1] = GetGenre(info); else pItem->aCols[1] = DupString(info); lvi.lParam = (LPARAM)pItem; /* item data */ /* Add the item. */ ListView_InsertItem(hwndList, &lvi); break; } case ID3FID_USERTEXT: case ID3FID_COMMENT: /* Can also contain an extra language field (but not used now) */ case ID3FID_UNSYNCEDLYRICS: /* Can also contain an extra language field (but not used now) */ { LV_ITEM lvi; ID3ITEM *pItem = LocalAlloc(LPTR, sizeof(ID3ITEM)); /* Initialize LV_ITEM members that are common to all items. */ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; lvi.state = 0; lvi.stateMask = 0; lvi.pszText = LPSTR_TEXTCALLBACK; /* app. maintains text */ lvi.iImage = 0; lvi.iItem = iItem; lvi.iSubItem = 0; pItem->frameId = eFrameID; field = ID3Frame_GetField(frame, ID3FN_DESCRIPTION); ID3Field_GetASCII(field, info, 1024, 1); pItem->aCols[0] = DupString(info); field = ID3Frame_GetField(frame, ID3FN_TEXT); ID3Field_GetASCII(field, info, 1024, 1); pItem->aCols[1] = DupString(info); lvi.lParam = (LPARAM)pItem; /* item data */ /* Add the item. */ ListView_InsertItem(hwndList, &lvi); break; } case ID3FID_WWWAUDIOFILE: case ID3FID_WWWARTIST: case ID3FID_WWWAUDIOSOURCE: case ID3FID_WWWCOMMERCIALINFO: case ID3FID_WWWCOPYRIGHT: case ID3FID_WWWPUBLISHER: case ID3FID_WWWPAYMENT: case ID3FID_WWWRADIOPAGE: { LV_ITEM lvi; ID3ITEM *pItem = LocalAlloc(LPTR, sizeof(ID3ITEM)); /* Initialize LV_ITEM members that are common to all items. */ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; lvi.state = 0; lvi.stateMask = 0; lvi.pszText = LPSTR_TEXTCALLBACK; /* app. maintains text */ lvi.iImage = 0; lvi.iItem = iItem; lvi.iSubItem = 0; pItem->frameId = eFrameID; pItem->aCols[0] = GetFrameDesc(eFrameID); field = ID3Frame_GetField(frame, ID3FN_URL); ID3Field_GetASCII(field, info, 1024, 1); pItem->aCols[1] = DupString(info); lvi.lParam = (LPARAM)pItem; /* item data */ /* Add the item. */ ListView_InsertItem(hwndList, &lvi); break; } case ID3FID_WWWUSER: { LV_ITEM lvi; ID3ITEM *pItem = LocalAlloc(LPTR, sizeof(ID3ITEM)); /* Initialize LV_ITEM members that are common to all items. */ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE; lvi.state = 0; lvi.stateMask = 0; lvi.pszText = LPSTR_TEXTCALLBACK; /* app. maintains text */ lvi.iImage = 0; lvi.iItem = iItem; lvi.iSubItem = 0; pItem->frameId = eFrameID; field = ID3Frame_GetField(frame, ID3FN_DESCRIPTION); ID3Field_GetASCII(field, info, 1024, 1); pItem->aCols[0] = DupString(info); field = ID3Frame_GetField(frame, ID3FN_URL); ID3Field_GetASCII(field, info, 1024, 1); pItem->aCols[1] = DupString(info); lvi.lParam = (LPARAM)pItem; /* item data */ /* Add the item. */ ListView_InsertItem(hwndList, &lvi); break; } default: break; } } ID3Tag_Delete(tag); } }
/* Get the title from the file */ void GetID3FileTitle(char *filename, char *title, char *format) { ID3Tag *tag; ID3Frame *frame; ID3Field *field; char buffer[255]; int some_info = 0; char *in = format; char *out = title; char *bound = out + (MAX_PATH - 10 - 1); if ((tag = ID3Tag_New()) != NULL) { ID3Tag_Link(tag, filename); while (*in && out < bound) { switch (*in) { case '%': ++in; break; default: *out++ = *in++; continue; } /* handle % escape sequence */ switch (*in++) { case '0': if ((frame = ID3Tag_FindFrameWithID(tag, ID3FID_TRACKNUM)) != NULL) { int size; field = ID3Frame_GetField(frame, ID3FN_TEXT); size = ID3Field_GetASCII(field, buffer, 255, 1); lstrcpy(out, buffer); out += size; some_info = 1; } break; case '1': if ((frame = ID3Tag_FindFrameWithID(tag, ID3FID_LEADARTIST)) != NULL) { int size; field = ID3Frame_GetField(frame, ID3FN_TEXT); size = ID3Field_GetASCII(field, buffer, 255, 1); lstrcpy(out, buffer); out += size; some_info = 1; } break; case '2': if ((frame = ID3Tag_FindFrameWithID(tag, ID3FID_TITLE)) != NULL) { int size; field = ID3Frame_GetField(frame, ID3FN_TEXT); size = ID3Field_GetASCII(field, buffer, 255, 1); lstrcpy(out, buffer); out += size; some_info = 1; } break; case '3': if ((frame = ID3Tag_FindFrameWithID(tag, ID3FID_ALBUM)) != NULL) { int size; field = ID3Frame_GetField(frame, ID3FN_TEXT); size = ID3Field_GetASCII(field, buffer, 255, 1); lstrcpy(out, buffer); out += size; some_info = 1; } break; case '4': if ((frame = ID3Tag_FindFrameWithID(tag, ID3FID_YEAR)) != NULL) { int size; field = ID3Frame_GetField(frame, ID3FN_TEXT); size = ID3Field_GetASCII(field, buffer, 255, 1); lstrcpy(out, buffer); out += size; some_info = 1; } break; case '5': if ((frame = ID3Tag_FindFrameWithID(tag, ID3FID_COMMENT)) != NULL) { int size; field = ID3Frame_GetField(frame, ID3FN_TEXT); size = ID3Field_GetASCII(field, buffer, 255, 1); lstrcpy(out, buffer); out += size; some_info = 1; } break; case '6': if ((frame = ID3Tag_FindFrameWithID(tag, ID3FID_CONTENTTYPE)) != NULL) { int size; char *tmp; field = ID3Frame_GetField(frame, ID3FN_TEXT); size = ID3Field_GetASCII(field, buffer, 255, 1); tmp = GetGenre(buffer); lstrcpy(out, tmp); out += size; some_info = 1; } break; case '7': { char *p=filename+lstrlen(filename); int len = 0; while (*p != '\\' && p >= filename) { p--; len++; } lstrcpy(out, ++p); out += len; some_info = 1; break; } } } ID3Tag_Delete(tag); } if (!some_info) { char *p=filename+lstrlen(filename); while (*p != '\\' && p >= filename) p--; lstrcpy(title,++p); } }
bool MP4Metadata::WriteMetadata(CFErrorRef *error) { UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX)) return false; // Open the file for modification MP4FileHandle file = MP4Modify(reinterpret_cast<const char *>(buf)); if(MP4_INVALID_FILE_HANDLE == file) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG-4 file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not an MPEG file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioMetadataErrorDomain, AudioMetadataInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } return false; } // Read the tags const MP4Tags *tags = MP4TagsAlloc(); if(NULL == tags) { MP4Close(file), file = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } MP4TagsFetch(tags, file); // Album Title CFStringRef str = GetAlbumTitle(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetAlbum(tags, cString); } else MP4TagsSetAlbum(tags, NULL); // Artist str = GetArtist(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetArtist(tags, cString); } else MP4TagsSetArtist(tags, NULL); // Album Artist str = GetAlbumArtist(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetAlbumArtist(tags, cString); } else MP4TagsSetAlbumArtist(tags, NULL); // Genre str = GetGenre(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetGenre(tags, cString); } else MP4TagsSetGenre(tags, NULL); // Release date str = GetReleaseDate(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetReleaseDate(tags, cString); } else MP4TagsSetReleaseDate(tags, NULL); // Composer str = GetComposer(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetComposer(tags, cString); } else MP4TagsSetComposer(tags, NULL); // Comment str = GetComment(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetComments(tags, cString); } else MP4TagsSetComments(tags, NULL); // Track title str = GetTitle(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetName(tags, cString); } else MP4TagsSetName(tags, NULL); // Track number and total MP4TagTrack trackInfo; memset(&trackInfo, 0, sizeof(MP4TagTrack)); if(GetTrackNumber()) CFNumberGetValue(GetTrackNumber(), kCFNumberSInt32Type, &trackInfo.index); if(GetTrackTotal()) CFNumberGetValue(GetTrackTotal(), kCFNumberSInt32Type, &trackInfo.total); MP4TagsSetTrack(tags, &trackInfo); // Disc number and total MP4TagDisk discInfo; memset(&discInfo, 0, sizeof(MP4TagDisk)); if(GetDiscNumber()) CFNumberGetValue(GetDiscNumber(), kCFNumberSInt32Type, &discInfo.index); if(GetDiscTotal()) CFNumberGetValue(GetDiscTotal(), kCFNumberSInt32Type, &discInfo.total); MP4TagsSetDisk(tags, &discInfo); // Compilation if(GetCompilation()) { uint8_t comp = CFBooleanGetValue(GetCompilation()); MP4TagsSetCompilation(tags, &comp); } else MP4TagsSetCompilation(tags, NULL); // Lyrics str = GetLyrics(); if(str) { CFIndex cStringSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); char cString [cStringSize + 1]; if(!CFStringGetCString(str, cString, cStringSize + 1, kCFStringEncodingUTF8)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } MP4TagsSetLyrics(tags, cString); } else MP4TagsSetLyrics(tags, NULL); // Album art CFDataRef artData = GetFrontCoverArt(); if(artData) { MP4TagArtwork artwork; artwork.data = reinterpret_cast<void *>(const_cast<UInt8 *>(CFDataGetBytePtr(artData))); artwork.size = static_cast<uint32_t>(CFDataGetLength(artData)); artwork.type = MP4_ART_UNDEFINED; MP4TagsAddArtwork(tags, &artwork); } // Save our changes MP4TagsStore(tags, file); // Replay Gain // Reference loudness if(GetReplayGainReferenceLoudness()) { float f; if(!CFNumberGetValue(GetReplayGainReferenceLoudness(), kCFNumberFloatType, &f)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFStringGetCString() failed"); return false; } char value [8]; snprintf(value, sizeof(value), "%2.1f dB", f); MP4ItmfItem *item = MP4ItmfItemAlloc("----", 1); if(NULL != item) { item->mean = strdup("com.apple.iTunes"); item->name = strdup("replaygain_reference_loudness"); item->dataList.elements[0].typeCode = MP4_ITMF_BT_UTF8; item->dataList.elements[0].value = reinterpret_cast<uint8_t *>(strdup(value)); item->dataList.elements[0].valueSize = static_cast<uint32_t>(strlen(value)); } } else { MP4ItmfItemList *items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_reference_loudness"); if(items) { for(uint32_t i = 0; i < items->size; ++i) MP4ItmfRemoveItem(file, items->elements + i); } MP4ItmfItemListFree(items), items = NULL; } // Track gain if(GetReplayGainTrackGain()) { float f; if(!CFNumberGetValue(GetReplayGainTrackGain(), kCFNumberFloatType, &f)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFNumberGetValue() failed"); return false; } char value [10]; snprintf(value, sizeof(value), "%+2.2f dB", f); MP4ItmfItem *item = MP4ItmfItemAlloc("----", 1); if(NULL != item) { item->mean = strdup("com.apple.iTunes"); item->name = strdup("replaygain_track_gain"); item->dataList.elements[0].typeCode = MP4_ITMF_BT_UTF8; item->dataList.elements[0].value = reinterpret_cast<uint8_t *>(strdup(value)); item->dataList.elements[0].valueSize = static_cast<uint32_t>(strlen(value)); } } else { MP4ItmfItemList *items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_track_gain"); if(items) { for(uint32_t i = 0; i < items->size; ++i) MP4ItmfRemoveItem(file, items->elements + i); } MP4ItmfItemListFree(items), items = NULL; } // Track peak if(GetReplayGainTrackPeak()) { float f; if(!CFNumberGetValue(GetReplayGainTrackPeak(), kCFNumberFloatType, &f)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFNumberGetValue() failed"); return false; } char value [12]; snprintf(value, sizeof(value), "%1.8f", f); MP4ItmfItem *item = MP4ItmfItemAlloc("----", 1); if(NULL != item) { item->mean = strdup("com.apple.iTunes"); item->name = strdup("replaygain_track_peak"); item->dataList.elements[0].typeCode = MP4_ITMF_BT_UTF8; item->dataList.elements[0].value = reinterpret_cast<uint8_t *>(strdup(value)); item->dataList.elements[0].valueSize = static_cast<uint32_t>(strlen(value)); } } else { MP4ItmfItemList *items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_track_peak"); if(items) { for(uint32_t i = 0; i < items->size; ++i) MP4ItmfRemoveItem(file, items->elements + i); } MP4ItmfItemListFree(items), items = NULL; } // Album gain if(GetReplayGainAlbumGain()) { float f; if(!CFNumberGetValue(GetReplayGainAlbumGain(), kCFNumberFloatType, &f)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFNumberGetValue() failed"); return false; } char value [10]; snprintf(value, sizeof(value), "%+2.2f dB", f); MP4ItmfItem *item = MP4ItmfItemAlloc("----", 1); if(NULL != item) { item->mean = strdup("com.apple.iTunes"); item->name = strdup("replaygain_album_gain"); item->dataList.elements[0].typeCode = MP4_ITMF_BT_UTF8; item->dataList.elements[0].value = reinterpret_cast<uint8_t *>(strdup(value)); item->dataList.elements[0].valueSize = static_cast<uint32_t>(strlen(value)); } } else { MP4ItmfItemList *items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_album_gain"); if(items) { for(uint32_t i = 0; i < items->size; ++i) MP4ItmfRemoveItem(file, items->elements + i); } MP4ItmfItemListFree(items), items = NULL; } // Album peak if(GetReplayGainAlbumPeak()) { float f; if(!CFNumberGetValue(GetReplayGainAlbumPeak(), kCFNumberFloatType, &f)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioMetadata.MP4"); LOG4CXX_WARN(logger, "CFNumberGetValue() failed"); return false; } char value [12]; snprintf(value, sizeof(value), "%1.8f", f); MP4ItmfItem *item = MP4ItmfItemAlloc("----", 1); if(NULL != item) { item->mean = strdup("com.apple.iTunes"); item->name = strdup("replaygain_album_peak"); item->dataList.elements[0].typeCode = MP4_ITMF_BT_UTF8; item->dataList.elements[0].value = reinterpret_cast<uint8_t *>(strdup(value)); item->dataList.elements[0].valueSize = static_cast<uint32_t>(strlen(value)); } } else { MP4ItmfItemList *items = MP4ItmfGetItemsByMeaning(file, "com.apple.iTunes", "replaygain_album_peak"); if(items) { for(uint32_t i = 0; i < items->size; ++i) MP4ItmfRemoveItem(file, items->elements + i); } MP4ItmfItemListFree(items), items = NULL; } // Clean up MP4TagsFree(tags), tags = NULL; MP4Close(file), file = NULL; MergeChangedMetadataIntoMetadata(); return true; }