コード例 #1
0
ファイル: networkremote.cpp プロジェクト: BrummbQ/Clementine
void NetworkRemote::AcceptConnection() {
  if (!signals_connected_) {
    signals_connected_ = true;

    // Setting up the signals, but only once
    connect(incoming_data_parser_.get(), SIGNAL(SendClementineInfo()),
            outgoing_data_creator_.get(), SLOT(SendClementineInfo()));
    connect(incoming_data_parser_.get(), SIGNAL(SendFirstData(bool)),
            outgoing_data_creator_.get(), SLOT(SendFirstData(bool)));
    connect(incoming_data_parser_.get(), SIGNAL(SendAllPlaylists()),
            outgoing_data_creator_.get(), SLOT(SendAllPlaylists()));
    connect(incoming_data_parser_.get(), SIGNAL(SendAllActivePlaylists()),
            outgoing_data_creator_.get(), SLOT(SendAllActivePlaylists()));
    connect(incoming_data_parser_.get(), SIGNAL(SendPlaylistSongs(int)),
            outgoing_data_creator_.get(), SLOT(SendPlaylistSongs(int)));

    connect(app_->playlist_manager(), SIGNAL(ActiveChanged(Playlist*)),
            outgoing_data_creator_.get(), SLOT(ActiveChanged(Playlist*)));
    connect(app_->playlist_manager(), SIGNAL(PlaylistChanged(Playlist*)),
            outgoing_data_creator_.get(), SLOT(PlaylistChanged(Playlist*)));
    connect(app_->playlist_manager(), SIGNAL(PlaylistAdded(int,QString,bool)),
            outgoing_data_creator_.get(), SLOT(PlaylistAdded(int,QString,bool)));
    connect(app_->playlist_manager(), SIGNAL(PlaylistRenamed(int,QString)),
            outgoing_data_creator_.get(), SLOT(PlaylistRenamed(int,QString)));
    connect(app_->playlist_manager(), SIGNAL(PlaylistClosed(int)),
            outgoing_data_creator_.get(), SLOT(PlaylistClosed(int)));
    connect(app_->playlist_manager(), SIGNAL(PlaylistDeleted(int)),
            outgoing_data_creator_.get(), SLOT(PlaylistDeleted(int)));

    connect(app_->player(), SIGNAL(VolumeChanged(int)), outgoing_data_creator_.get(),
            SLOT(VolumeChanged(int)));
    connect(app_->player()->engine(), SIGNAL(StateChanged(Engine::State)),
            outgoing_data_creator_.get(), SLOT(StateChanged(Engine::State)));

    connect(app_->playlist_manager()->sequence(),
            SIGNAL(RepeatModeChanged(PlaylistSequence::RepeatMode)),
            outgoing_data_creator_.get(),
            SLOT(SendRepeatMode(PlaylistSequence::RepeatMode)));
    connect(app_->playlist_manager()->sequence(),
            SIGNAL(ShuffleModeChanged(PlaylistSequence::ShuffleMode)),
            outgoing_data_creator_.get(),
            SLOT(SendShuffleMode(PlaylistSequence::ShuffleMode)));

    connect(incoming_data_parser_.get(), SIGNAL(GetLyrics()),
            outgoing_data_creator_.get(), SLOT(GetLyrics()));

    connect(incoming_data_parser_.get(),
            SIGNAL(SendSongs(pb::remote::RequestDownloadSongs,RemoteClient*)),
            outgoing_data_creator_.get(),
            SLOT(SendSongs(pb::remote::RequestDownloadSongs,RemoteClient*)));
    connect(incoming_data_parser_.get(),
            SIGNAL(ResponseSongOffer(RemoteClient*, bool)),
            outgoing_data_creator_.get(),
            SLOT(ResponseSongOffer(RemoteClient*, bool)));

    connect(incoming_data_parser_.get(),
            SIGNAL(SendLibrary(RemoteClient*)),
            outgoing_data_creator_.get(),
            SLOT(SendLibrary(RemoteClient*)));
  }
コード例 #2
0
ファイル: Player.cpp プロジェクト: AllainFortier/lcdhost
QString CPlayer::replace_tokens(QString str, bool hidePlayingState)
{
    QString status_text = "";
    switch(GetState())
    {
    case PLAYER_STOPPED:
        if(GetPlayer()=="")
            status_text = "";
        else
            status_text = "Stopped";
        break;
    case PLAYER_PAUSED:
        status_text = "Paused";
        break;
    case PLAYER_PLAYING:
        status_text = (hidePlayingState? "" : "Playing");
        break;
    }

    replace_token(str,"title"    ,GetTitle());
    replace_token(str,"artist"   ,GetArtist());
    replace_token(str,"album"    ,GetAlbum());
    replace_token(str,"duration" ,GetDuration(),GetDuration());
    replace_token(str,"played"   ,GetPosition(),GetDuration());
    replace_token(str,"remaining",GetDuration() - GetPosition(),GetDuration());
    replace_token(str,"status"   ,status_text);
    replace_token(str,"player"   ,GetPlayer());
    replace_token(str,"file"     ,GetFilePath());
    replace_token(str,"shuffle"  ,(GetShuffle() ? "Shuffle" : ""));
    replace_token(str,"repeat"   ,(GetRepeat() ? "Repeat" : ""));
    replace_token(str,"rating"   ,QString::number(GetRating()));
    replace_token(str,"lyrics"   ,GetLyrics());
    return str;
}
コード例 #3
0
ファイル: incomingdataparser.cpp プロジェクト: Gu1/Clementine
void IncomingDataParser::Parse(const pb::remote::Message& msg) {
  close_connection_ = false;

  RemoteClient* client = qobject_cast<RemoteClient*>(sender());

  // Now check what's to do
  switch (msg.type()) {
    case pb::remote::CONNECT:
      ClientConnect(msg);
      break;
    case pb::remote::DISCONNECT:
      close_connection_ = true;
      break;
    case pb::remote::REQUEST_PLAYLISTS:
      SendPlaylists(msg);
      break;
    case pb::remote::REQUEST_PLAYLIST_SONGS:
      GetPlaylistSongs(msg);
      break;
    case pb::remote::SET_VOLUME:
      emit SetVolume(msg.request_set_volume().volume());
      break;
    case pb::remote::PLAY:
      emit Play();
      break;
    case pb::remote::PLAYPAUSE:
      emit PlayPause();
      break;
    case pb::remote::PAUSE:
      emit Pause();
      break;
    case pb::remote::STOP:
      emit Stop();
      break;
    case pb::remote::STOP_AFTER:
      emit StopAfterCurrent();
      break;
    case pb::remote::NEXT:
      emit Next();
      break;
    case pb::remote::PREVIOUS:
      emit Previous();
      break;
    case pb::remote::CHANGE_SONG:
      ChangeSong(msg);
      break;
    case pb::remote::SHUFFLE_PLAYLIST:
      emit ShuffleCurrent();
      break;
    case pb::remote::REPEAT:
      SetRepeatMode(msg.repeat());
      break;
    case pb::remote::SHUFFLE:
      SetShuffleMode(msg.shuffle());
      break;
    case pb::remote::SET_TRACK_POSITION:
      emit SeekTo(msg.request_set_track_position().position());
      break;
    case pb::remote::INSERT_URLS:
      InsertUrls(msg);
      break;
    case pb::remote::REMOVE_SONGS:
      RemoveSongs(msg);
      break;
    case pb::remote::OPEN_PLAYLIST:
      OpenPlaylist(msg);
      break;
    case pb::remote::CLOSE_PLAYLIST:
      ClosePlaylist(msg);
      break;
    case pb::remote::LOVE:
      emit Love();
      break;
    case pb::remote::BAN:
      emit Ban();
      break;
    case pb::remote::GET_LYRICS:
      emit GetLyrics();
      break;
    case pb::remote::DOWNLOAD_SONGS:
      emit SendSongs(msg.request_download_songs(), client);
      break;
    case pb::remote::SONG_OFFER_RESPONSE:
      emit ResponseSongOffer(client, msg.response_song_offer().accepted());
      break;
    case pb::remote::GET_LIBRARY:
      emit SendLibrary(client);
      break;
    case pb::remote::RATE_SONG:
      RateSong(msg);
      break;
    default:
      break;
  }
}
コード例 #4
0
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;
}