/// <summary> /// Clear all the tags /// </summary> /// <param name="track"></param> /// <returns></returns> public static TrackData ClearTag(TrackData track) { track.Artist = ""; track.AlbumArtist = ""; track.Album = ""; track.BPM = 0; track.ID3Comments.Clear(); track.Frames.Clear(); track.Compilation = false; track.Composer = ""; track.Conductor = ""; track.Copyright = ""; track.DiscNumber = 0; track.DiscCount = 0; track.Genre = ""; track.Grouping = ""; track.LyricsFrames.Clear(); track.Pictures.Clear(); track.Title = ""; track.TrackNumber = 0; track.TrackCount = 0; track.Year = 0; track.Ratings.Clear(); return track; }
public override bool Execute(ref TrackData track, int rowIndex) { if (track.NumPics > 0) { track.Pictures.Clear(); return true; } return false; }
public override bool Execute(ref TrackData track, int rowIndex) { if (track.Comment != "") { track.ID3Comments.Clear(); return true; } return false; }
public override bool Execute(ref TrackData track, int rowIndex) { if (_pic == null || _pic.Data == null) { return false; } track.Pictures.Clear(); track.Pictures.Add(_pic); return true; }
public override bool Execute(ref TrackData track, int rowIndex) { if (!SaveTrack(track, rowIndex)) { bErrors = true; } // returning false here, since we are setting the Track Status in Save Track // and don't want to have it cvhanged again in calling routine return false; }
public override bool Execute(ref TrackData track, int rowIndex) { TracksGrid.SetProgressBar(100); int stream = Bass.BASS_StreamCreateFile(track.FullFileName, 0, 0, BASSFlag.BASS_STREAM_DECODE); if (stream == 0) { Log.Error("BPM: Could not create stream for {0}. {1}", track.FullFileName, Bass.BASS_ErrorGetCode()); return false; } _bpmProc = BpmProgressProc; double len = Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetLength(stream)); float bpm = BassFx.BASS_FX_BPM_DecodeGet(stream, 0.0, len, 0, BASSFXBpm.BASS_FX_BPM_BKGRND | BASSFXBpm.BASS_FX_FREESOURCE | BASSFXBpm.BASS_FX_BPM_MULT2, _bpmProc, IntPtr.Zero); track.BPM = Convert.ToInt32(bpm); BassFx.BASS_FX_BPM_Free(stream); TracksGrid.MainForm.progressBar1.Value = 0; return true; }
public override bool Execute(ref TrackData track, int rowIndex) { if (track.IsMp3) { Util.SendProgress(string.Format("Validating file {0}", track.FileName)); string strError; track.MP3ValidationError = MP3Val.ValidateMp3File(track.FullFileName, out strError); if (track.MP3ValidationError != Util.MP3Error.NoError) { TracksGrid.SetColorMP3Errors(rowIndex, track.MP3ValidationError); track.Status = 3; TracksGrid.View.Rows[rowIndex].Cells[0].ToolTipText = strError; } else { TracksGrid.View.Rows[rowIndex].Cells[0].ToolTipText = ""; } } // We don't want to mark thze file as changed, since no change occured in the Tags return false; }
/// <summary> /// Does the actual save of the track /// </summary> /// <param name = "track"></param> /// <returns></returns> private bool SaveTrack(TrackData track, int rowIndex) { try { if (track.Changed) { Util.SendProgress(string.Format("Saving file {0}", track.FullFileName)); log.Debug("Save: Saving track: {0}", track.FullFileName); // The track to be saved, may be currently playing. If this is the case stop playnack to free the file if (track.FullFileName == _main.Player.CurrentSongPlaying) { log.Debug("Save: Song is played in Player. Stop playback to free the file"); _main.Player.Stop(); } if (Options.MainSettings.CopyArtist && track.AlbumArtist == "") { track.AlbumArtist = track.Artist; } if (Options.MainSettings.UseCaseConversion) { CaseConversion.CaseConversion convert = new CaseConversion.CaseConversion(_main, true); convert.CaseConvert(track, rowIndex); convert.Dispose(); } // Save the file string errorMessage = ""; if (Track.SaveFile(track, ref errorMessage)) { // If we are in Database mode, we should also update the MediaPortal Database if (_main.TreeView.DatabaseMode) { UpdateMusicDatabase(track); } if (RenameFile(track)) { // rename was ok, so get the new file into the binding list string ext = Path.GetExtension(track.FileName); string newFileName = Path.Combine(Path.GetDirectoryName(track.FullFileName), String.Format("{0}{1}", Path.GetFileNameWithoutExtension(track.FileName), ext)); track = Track.Create(newFileName); Options.Songlist[rowIndex] = track; } // Check, if we need to create a folder.jpg if (!System.IO.File.Exists(Path.Combine(Path.GetDirectoryName(track.FullFileName), "folder.jpg")) && Options.MainSettings.CreateFolderThumb) { SavePicture(track); } track.Status = 0; tracksGrid.Rows[rowIndex].Cells[0].ToolTipText = ""; track.Changed = false; tracksGrid.Rows[rowIndex].Tag = ""; Options.Songlist[rowIndex] = track; SetGridRowColors(rowIndex); } else { track.Status = 2; AddErrorMessage(tracksGrid.Rows[rowIndex], errorMessage); } } } catch (Exception ex) { Options.Songlist[rowIndex].Status = 2; AddErrorMessage(tracksGrid.Rows[rowIndex], ex.Message); log.Error("Save: Error Saving data for row {0}: {1} {2}", rowIndex, ex.Message, ex.StackTrace); return false; } return true; }
/// <summary> /// Rename the file if necessary /// Called by Save and SaveAll /// </summary> /// <param name = "track"></param> private bool RenameFile(TrackData track) { string originalFileName = Path.GetFileName(track.FullFileName); if (originalFileName != track.FileName) { string ext = Path.GetExtension(track.FileName); string filename = Path.GetFileNameWithoutExtension(track.FileName); string path = Path.GetDirectoryName(track.FullFileName); string newFileName = Path.Combine(path, string.Format("{0}{1}", filename, ext)); // Check, if the New file name already exists // Don't change the newfilename, when only the Case change happened in filename int i = 1; if (System.IO.File.Exists(newFileName) && originalFileName.ToLowerInvariant() != track.FileName.ToLowerInvariant()) { newFileName = Path.Combine(path, string.Format("{0} ({1}){2}", filename, i, ext)); while (System.IO.File.Exists(newFileName)) { i++; newFileName = Path.Combine(path, string.Format("{0} ({1}){2}", filename, i, ext)); } } System.IO.File.Move(track.FullFileName, newFileName); log.Debug("Save: Renaming track: {0} Newname: {1}", track.FullFileName, newFileName); return true; } return false; }
private bool ApplyTagFilter(TrackData track) { if (!_main.TreeView.ActiveFilter.UseTagFilter) { return true; } List<TreeViewTagFilter> filter = _main.TreeView.ActiveFilter.TagFilter; List<bool> results = new List<bool>(filter.Count); bool numericCompare = false; // For year, bpm, etc. int index = 0; int searchNumber = 0; string searchstring = ""; foreach (TreeViewTagFilter tagfilter in filter) { switch (tagfilter.Field) { case "artist": searchstring = track.Artist; break; case "albumartist": searchstring = track.AlbumArtist; break; case "album": searchstring = track.Album; break; case "title": searchstring = track.Title; break; case "genre": searchstring = track.Genre; break; case "comment": searchstring = track.Comment; break; case "composer": searchstring = track.Composer; break; case "conductor": searchstring = track.Conductor; break; // Tags with are checked for existence or non-existence case "picture": searchstring = track.Pictures.Count > 0 ? "True" : "False"; break; case "lyrics": searchstring = track.Lyrics != null ? "True" : "False"; break; // Numeric Tags case "track": numericCompare = true; searchNumber = (int)track.TrackNumber; break; case "numtracks": numericCompare = true; searchNumber = (int)track.TrackCount; break; case "disc": numericCompare = true; searchNumber = (int)track.DiscNumber; break; case "numdiscs": numericCompare = true; searchNumber = (int)track.DiscCount; break; case "year": numericCompare = true; searchNumber = track.Year; break; case "rating": numericCompare = true; searchNumber = track.Rating; break; case "bpm": numericCompare = true; searchNumber = track.BPM; break; case "bitrate": numericCompare = true; searchNumber = Convert.ToInt16(track.BitRate); break; case "samplerate": numericCompare = true; searchNumber = Convert.ToInt16(track.SampleRate); break; case "channels": numericCompare = true; searchNumber = Convert.ToInt16(track.Channels); break; } // Now check the filter value, if we have a negation string searchValue = tagfilter.FilterValue; bool negation = false; if (searchValue.Length > 0 && searchValue[0] == '!') { searchValue = searchValue.Substring(1); negation = true; } bool match = false; if (numericCompare) { try { searchValue = searchValue.Trim(); if (searchValue == "") searchValue = "0"; if (searchValue.StartsWith("<=")) { searchValue = searchValue.Substring(2); match = searchNumber <= Int32.Parse(searchValue); } else if (searchValue.StartsWith(">=")) { searchValue = searchValue.Substring(2); match = searchNumber >= Int32.Parse(searchValue); } else if (searchValue.StartsWith("<")) { searchValue = searchValue.Substring(1); match = searchNumber < Int32.Parse(searchValue); } else if (searchValue.StartsWith(">")) { searchValue = searchValue.Substring(1); match = searchNumber > Int32.Parse(searchValue); } else if (searchValue.StartsWith("=")) { searchValue = searchValue.Substring(1); match = searchNumber == Int32.Parse(searchValue); } else { match = searchNumber == Int32.Parse(searchValue); } } catch (FormatException) { match = false; } } else { match = Regex.IsMatch(searchstring, MakeRegexp(searchValue)); } if (negation) { match = !match; } results.Insert(index, match); index++; } index = 0; bool ok = false; foreach (bool result in results) { if (index + 1 == results.Count) { if (index == 0) { ok = result; } break; } bool nextresult = results[index + 1]; if (filter[index].FilterOperator == "and") { ok = result && nextresult; } else { ok = result || nextresult; } if (!ok) { break; } } return ok; }
/// <summary> /// Read the Tags from the File /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static TrackData Create(string fileName) { TrackData track = new TrackData(); TagLib.File file = null; bool error = false; try { TagLib.ByteVector.UseBrokenLatin1Behavior = true; file = TagLib.File.Create(fileName); } catch (CorruptFileException) { log.Warn("File Read: Ignoring track {0} - Corrupt File!", fileName); error = true; } catch (UnsupportedFormatException) { log.Warn("File Read: Ignoring track {0} - Unsupported format!", fileName); error = true; } catch (FileNotFoundException) { log.Warn("File Read: Ignoring track {0} - Physical file no longer existing!", fileName); error = true; } catch (Exception ex) { log.Error("File Read: Error processing file: {0} {1}", fileName, ex.Message); error = true; } if (error) { return null; } TagLib.Id3v2.Tag id3v2tag = null; try { if (file.MimeType.Substring(file.MimeType.IndexOf("/") + 1) == "mp3") { id3v2tag = file.GetTag(TagTypes.Id3v2, false) as TagLib.Id3v2.Tag; } } catch (Exception ex) { log.Error("File Read: Error retrieving id3tag: {0} {1}", fileName, ex.Message); return null; } #region Set Common Values FileInfo fi = new FileInfo(fileName); try { track.Id = new Guid(); track.FullFileName = fileName; track.FileName = Path.GetFileName(fileName); track.Readonly = fi.IsReadOnly; track.TagType = file.MimeType.Substring(file.MimeType.IndexOf("/") + 1); } catch (Exception ex) { log.Error("File Read: Error setting Common tags: {0} {1}", fileName, ex.Message); return null; } #endregion #region Set Tags try { // Artist track.Artist = String.Join(";", file.Tag.Performers); if (track.Artist.Contains("AC;DC")) { track.Artist = track.Artist.Replace("AC;DC", "AC/DC"); } track.AlbumArtist = String.Join(";", file.Tag.AlbumArtists); if (track.AlbumArtist.Contains("AC;DC")) { track.AlbumArtist = track.AlbumArtist.Replace("AC;DC", "AC/DC"); } track.Album = file.Tag.Album ?? ""; track.BPM = (int)file.Tag.BeatsPerMinute; track.Compilation = id3v2tag == null ? false : id3v2tag.IsCompilation; track.Composer = string.Join(";", file.Tag.Composers); track.Conductor = file.Tag.Conductor ?? ""; track.Copyright = file.Tag.Copyright ?? ""; track.DiscNumber = file.Tag.Disc; track.DiscCount = file.Tag.DiscCount; track.Genre = string.Join(";", file.Tag.Genres); track.Grouping = file.Tag.Grouping ?? ""; track.Title = file.Tag.Title ?? ""; track.TrackNumber = file.Tag.Track; track.TrackCount = file.Tag.TrackCount; track.Year = (int)file.Tag.Year; // Pictures foreach (IPicture picture in file.Tag.Pictures) { MPTagThat.Core.Common.Picture pic = new MPTagThat.Core.Common.Picture { Type = picture.Type, MimeType = picture.MimeType, Description = picture.Description }; pic.Data = pic.ImageFromData(picture.Data.Data); track.Pictures.Add(pic); } // Comments if (track.TagType == "mp3" && id3v2tag != null) { foreach (CommentsFrame commentsframe in id3v2tag.GetFrames<CommentsFrame>()) { track.ID3Comments.Add(new Comment(commentsframe.Description, commentsframe.Language, commentsframe.Text)); } } else { track.Comment = file.Tag.Comment; } // Lyrics track.Lyrics = file.Tag.Lyrics; if (track.TagType == "mp3" && id3v2tag != null) { foreach (UnsynchronisedLyricsFrame lyricsframe in id3v2tag.GetFrames<UnsynchronisedLyricsFrame>()) { // Only add non-empty Frames if (lyricsframe.Text != "") { track.LyricsFrames.Add(new Lyric(lyricsframe.Description, lyricsframe.Language, lyricsframe.Text)); } } } // Rating if (track.TagType == "mp3") { TagLib.Id3v2.PopularimeterFrame popmFrame = null; // First read in all POPM Frames found if (id3v2tag != null) { foreach (PopularimeterFrame popmframe in id3v2tag.GetFrames<PopularimeterFrame>()) { // Only add valid POPM Frames if (popmframe.User != "" && popmframe.Rating > 0) { track.Ratings.Add(new PopmFrame(popmframe.User, (int)popmframe.Rating, (int)popmframe.PlayCount)); } } popmFrame = TagLib.Id3v2.PopularimeterFrame.Get(id3v2tag, "MPTagThat", false); if (popmFrame != null) { track.Rating = popmFrame.Rating; } } if (popmFrame == null) { // Now check for Ape Rating TagLib.Ape.Tag apetag = file.GetTag(TagTypes.Ape, true) as TagLib.Ape.Tag; TagLib.Ape.Item apeItem = apetag.GetItem("RATING"); if (apeItem != null) { string rating = apeItem.ToString(); try { track.Rating = Convert.ToInt32(rating); } catch (Exception) { } } } } else { if (track.TagType == "ape") { TagLib.Ape.Tag apetag = file.GetTag(TagTypes.Ape, true) as TagLib.Ape.Tag; TagLib.Ape.Item apeItem = apetag.GetItem("RATING"); if (apeItem != null) { string rating = apeItem.ToString(); try { track.Rating = Convert.ToInt32(rating); } catch (Exception) { } } } } } catch (Exception ex) { log.Error("Exception setting Tags for file: {0}. {1}", fileName, ex.Message); } #endregion #region Set Properties try { track.DurationTimespan = file.Properties.Duration; int fileLength = (int) (fi.Length/1024); track.FileSize = fileLength.ToString(); track.BitRate = file.Properties.AudioBitrate.ToString(); track.SampleRate = file.Properties.AudioSampleRate.ToString(); track.Channels = file.Properties.AudioChannels.ToString(); track.Version = file.Properties.Description; track.CreationTime = string.Format("{0:yyyy-MM-dd HH:mm:ss}", fi.CreationTime); track.LastWriteTime = string.Format("{0:yyyy-MM-dd HH:mm:ss}", fi.LastWriteTime); } catch (Exception ex) { log.Error("Exception setting Properties for file: {0}. {1}", fileName, ex.Message); } #endregion // Now copy all Text frames of an ID3 V2 try { if (track.TagType == "mp3" && id3v2tag != null) { foreach (TagLib.Id3v2.Frame frame in id3v2tag.GetFrames()) { string id = frame.FrameId.ToString(); if (!track.StandardFrames.Contains(id) && track.ExtendedFrames.Contains(id)) { track.Frames.Add(new Frame(id, "", frame.ToString())); } else if (!track.StandardFrames.Contains(id) && !track.ExtendedFrames.Contains(id)) { if (frame.GetType() == typeof (UserTextInformationFrame)) { track.UserFrames.Add(new Frame(id, (frame as UserTextInformationFrame).Description ?? "", (frame as UserTextInformationFrame).Text.Length == 0 ? "" : (frame as UserTextInformationFrame).Text[0])); } else if (frame.GetType() == typeof (PrivateFrame)) { track.UserFrames.Add(new Frame(id, (frame as PrivateFrame).Owner ?? "", (frame as PrivateFrame).PrivateData == null ? "" : (frame as PrivateFrame).PrivateData.ToString())); } else if (frame.GetType() == typeof (UniqueFileIdentifierFrame)) { track.UserFrames.Add(new Frame(id, (frame as UniqueFileIdentifierFrame).Owner ?? "", (frame as UniqueFileIdentifierFrame).Identifier == null ? "" : (frame as UniqueFileIdentifierFrame).Identifier.ToString())); } else if (frame.GetType() == typeof (UnknownFrame)) { track.UserFrames.Add(new Frame(id, "", (frame as UnknownFrame).Data == null ? "" : (frame as UnknownFrame).Data.ToString())); } else { track.UserFrames.Add(new Frame(id, "", frame.ToString())); } } } track.ID3Version = id3v2tag.Version; } } catch (Exception ex) { log.Error("Exception getting User Defined frames for file: {0}. {1}", fileName, ex.Message); } return track; }
/// <summary> /// Organise Files /// </summary> /// <param name = "parameter"></param> private void Organise(string parameter) { log.Trace(">>>"); DataGridView tracksGrid = _main.TracksGridView.View; _directories = new Dictionary<string, string>(); // First do an automatic save of all pending changes _main.TracksGridView.SaveAll(false); bool bError = false; string targetFolder = cbRootDir.Text; int trackCount = tracksGrid.SelectedRows.Count; SetProgressBar(trackCount); foreach (DataGridViewRow row in tracksGrid.Rows) { if (!row.Selected) continue; Application.DoEvents(); _main.progressBar1.Value += 1; if (_progressCancelled) { ResetProgressBar(); return; } track = Options.Songlist[row.Index]; // Replace the Parameter Value with the Values from the track string resolvedParmString = Util.ReplaceParametersWithTrackValues(parameter, track); if (_scriptAssembly != null) // Do we have a script selected { try { IScript script = (IScript)_scriptAssembly.CreateInstance("Script"); targetFolder = script.Invoke(track); if (targetFolder == "") { // Fall back to standard folder, if something happened in the script targetFolder = cbRootDir.Text; } } catch (Exception ex) { log.Error("Script Execution failed: {0}", ex.Message); } } string directoryName = ""; if (resolvedParmString.Contains(@"\")) { directoryName = Path.GetDirectoryName(resolvedParmString); } directoryName = Path.Combine(targetFolder, directoryName); try { // Now check the validity of the directory if (!Directory.Exists(directoryName)) { try { Directory.CreateDirectory(directoryName); } catch (Exception e1) { bError = true; log.Debug("Error creating folder: {0} {1]", directoryName, e1.Message); Options.Songlist[row.Index].Status = 2; _main.TracksGridView.AddErrorMessage(row, String.Format("{0}: {1} {2}", localisation.ToString("message", "Error"), directoryName, e1.Message)); continue; // Process next row } } // Store the directory of the current file in the dictionary, so that we may copy later all non-music files string dir = Path.GetDirectoryName(track.FullFileName); if (!_directories.ContainsKey(dir)) { _directories.Add(dir, directoryName); } // Now construct the new File Name string newFilename = resolvedParmString; int lastBackSlash = resolvedParmString.LastIndexOf(@"\"); if (lastBackSlash > -1) { newFilename = resolvedParmString.Substring(lastBackSlash + 1); } newFilename += track.FileExt; newFilename = Path.Combine(directoryName, newFilename); try { if (!ckOverwriteFiles.Checked) { if (File.Exists(newFilename)) { bError = true; log.Debug("File exists: {0}", newFilename); Options.Songlist[row.Index].Status = 2; _main.TracksGridView.AddErrorMessage(row, string.Format("{0}: {1}", newFilename, localisation.ToString("organise", "FileExists"))); continue; } } // If new file name validates to be the same as the old file, i.e. it goes into the source folder // then continue, as this would lead in the source file to be deleted first and then there's nothing, which could be copied if (newFilename.ToLowerInvariant() == track.FullFileName.ToLowerInvariant()) { bError = true; log.Debug("Old File and New File same: {0}", newFilename); Options.Songlist[row.Index].Status = 2; _main.TracksGridView.AddErrorMessage(row, string.Format("{0}: {1}", newFilename, localisation.ToString("organise", "SameFile"))); continue; } if (ckCopyFiles.Checked) { FileSystem.CopyFile(track.FullFileName, newFilename, ckOverwriteFiles.Checked); Options.Songlist[row.Index].Status = 0; } else { FileSystem.MoveFile(track.FullFileName, newFilename, ckOverwriteFiles.Checked); Options.Songlist[row.Index].Status = 0; } } catch (Exception e2) { bError = true; log.Error("Error Copy/Move File: {0} {1}", track.FullFileName, e2.Message); Options.Songlist[row.Index].Status = 2; _main.TracksGridView.AddErrorMessage(row, String.Format("{0}: {1}", localisation.ToString("message", "Error"), e2.Message)); } } catch (Exception ex) { bError = true; log.Error("Error Organising Files: {0} stack: {1}", ex.Message, ex.StackTrace); Options.Songlist[row.Index].Status = 2; _main.TracksGridView.AddErrorMessage(row, String.Format("{0}: {1} {2}", localisation.ToString("message", "Error"), directoryName, ex.Message)); } } // Now that we have Moved/Copied the individual Files, we will copy / move the Pictures, etc. if (ckCopyNonMusicFiles.Checked) { foreach (string dir in _directories.Keys) { string[] files = Directory.GetFiles(dir); foreach (string file in files) { // ignore audio files, we've processed them before if (Util.IsAudio(file)) continue; string newFilename = Path.Combine(_directories[dir], Path.GetFileName(file)); try { if (!ckOverwriteFiles.Checked) { if (File.Exists(newFilename)) { log.Debug("File exists: {0}", newFilename); continue; } } if (ckCopyFiles.Checked) { FileSystem.CopyFile(file, newFilename, UIOption.AllDialogs, UICancelOption.DoNothing); } else { FileSystem.MoveFile(file, newFilename, UIOption.AllDialogs, UICancelOption.DoNothing); } } catch (Exception ex) { log.Error("Error Copy/Move File: {0} {1}", file, ex.Message); } } } } ResetProgressBar(); // Delete empty folders,if we didn't get any error if (!ckCopyFiles.Checked && !bError) { foreach (string dir in _directories.Keys) { DeleteSubFolders(dir); DeleteParentFolders(dir); } string currentSelectedFolder = _main.CurrentDirectory; // Go up 1 level in the directory structure to find an existing folder int i = 0; while (i < 10) { if (Directory.Exists(currentSelectedFolder)) break; currentSelectedFolder = currentSelectedFolder.Substring(0, currentSelectedFolder.LastIndexOf("\\")); i++; // Max of 10 levels, to avoid possible infinity loop } _main.CurrentDirectory = currentSelectedFolder; _main.TreeView.RefreshFolders(); _main.RefreshTrackList(); } tracksGrid.Refresh(); tracksGrid.Parent.Refresh(); log.Trace("<<<"); }
/// <summary> /// Loop through all the selected rows and set the Preview /// </summary> /// <param name = "parameters"></param> private void Tag2FileNamePreview(string parameters) { log.Trace(">>>"); enumerateStartValue = (int)numericUpDownStartAt.Value; enumerateNumberDigits = (int)numericUpDownNumberDigits.Value; int index = -1; foreach (DataGridViewRow row in _main.TracksGridView.View.Rows) { if (!row.Selected) continue; index++; try { track = _main.TracksGridView.TrackList[row.Index]; trackPreview = _previewForm.Tracks[index]; trackPreview.NewFileName = ReplaceParametersWithValues(parameters); } catch (Exception) {} } _previewForm.Refresh(); log.Trace("<<<"); }
/// <summary> /// Execute the Command /// </summary> /// <param name="track"></param> /// <param name="rowIndex"></param> /// <returns></returns> public virtual bool Execute(ref TrackData track, int rowIndex) { return false; }
/// <summary> /// Convert File Name to Tag /// </summary> /// <param name = "parameters"></param> private void FileName2Tag(List<ParameterPart> parameters) { log.Trace(">>>"); bool bErrors = false; DataGridView tracksGrid = _main.TracksGridView.View; foreach (DataGridViewRow row in tracksGrid.Rows) { if (!row.Selected) continue; try { _main.TracksGridView.Changed = true; _main.TracksGridView.SetBackgroundColorChanged(row.Index); track = _main.TracksGridView.TrackList[row.Index]; track.Changed = true; ReplaceParametersWithValues(parameters, false); } catch (Exception ex) { log.Error("Error applying changes from Filename To Tag: {0} stack: {1}", ex.Message, ex.StackTrace); _main.TracksGridView.TrackList[row.Index].Status = 2; _main.TracksGridView.AddErrorMessage(row, localisation.ToString("TagAndRename", "InvalidParm")); bErrors = true; } } _main.TracksGridView.Changed = bErrors; // check, if we still have changed items in the list foreach (TrackData track in _main.TracksGridView.TrackList) { if (track.Changed) _main.TracksGridView.Changed = true; } tracksGrid.Refresh(); tracksGrid.Parent.Refresh(); log.Trace("<<<"); }
/// <summary> /// Rename the file if necessary /// Called by Save and SaveAll /// </summary> /// <param name = "track"></param> private bool RenameFile(TrackData track) { string originalFileName = Path.GetFileName(track.FullFileName); if (originalFileName != track.FileName) { string ext = Path.GetExtension(track.FileName); string newFileName = Path.Combine(Path.GetDirectoryName(track.FullFileName), String.Format("{0}{1}", Path.GetFileNameWithoutExtension(track.FileName), ext)); System.IO.File.Move(track.FullFileName, newFileName); log.Debug("Save: Renaming track: {0} Newname: {1}", track.FullFileName, newFileName); return true; } return false; }
/// <summary> /// Sets the Color for Tracks, that contain errors found by mp3val /// </summary> /// <param name = "index"></param> public void SetColorMP3Errors(int index, TrackData.MP3Error error) { if (error == TrackData.MP3Error.Fixable || error == TrackData.MP3Error.Fixed) { tracksGrid.Rows[index].DefaultCellStyle.BackColor = ServiceScope.Get<IThemeManager>().CurrentTheme.FixableErrorBackColor; tracksGrid.Rows[index].DefaultCellStyle.ForeColor = ServiceScope.Get<IThemeManager>().CurrentTheme.FixableErrorForeColor; } else if (error == TrackData.MP3Error.NonFixable) { tracksGrid.Rows[index].DefaultCellStyle.BackColor = ServiceScope.Get<IThemeManager>().CurrentTheme.NonFixableErrorBackColor; tracksGrid.Rows[index].DefaultCellStyle.ForeColor = ServiceScope.Get<IThemeManager>().CurrentTheme.NonFixableErrorForeColor; } if (error == TrackData.MP3Error.Fixed) { SetStatusColumnOk(tracksGrid.Rows[index]); } }
/// <summary> /// Do Case Conversion for the given track. /// Called internally by the Convert button and by the Save clause, if set in Preferences /// </summary> /// <param name = "track"></param> public void CaseConvert(TrackData track, int rowIndex) { bool bErrors = false; // Convert the Filename if (checkBoxConvertFileName.Checked) { string fileName = ConvertCase(Path.GetFileNameWithoutExtension(track.FileName)); // Now check the length of the filename if (fileName.Length > 255) { log.Debug("Filename too long: {0}", fileName); track.Status = 2; _main.TracksGridView.AddErrorMessage(_main.TracksGridView.View.Rows[rowIndex], String.Format("{0}: {1}", localisation.ToString("tag2filename", "NameTooLong"), fileName)); bErrors = true; } if (!bErrors) { // Now that we have a correct Filename track.FileName = string.Format("{0}{1}", fileName, Path.GetExtension(track.FileName)); track.Changed = true; _main.TracksGridView.Changed = true; _main.TracksGridView.SetBackgroundColorChanged(rowIndex); Options.Songlist[rowIndex] = track; } } // Convert the Tags if (checkBoxConvertTags.Checked) { string strConv = ""; bool bChanged = false; if (checkBoxArtist.Checked) { strConv = track.Artist; bChanged = (strConv = ConvertCase(strConv)) != track.Artist ? true : false || bChanged; if (bChanged) track.Artist = strConv; } if (checkBoxAlbumArtist.Checked) { strConv = track.AlbumArtist; bChanged = (strConv = ConvertCase(strConv)) != track.AlbumArtist ? true : false || bChanged; if (bChanged) track.AlbumArtist = strConv; } if (checkBoxAlbum.Checked) { strConv = track.Album; bChanged = (strConv = ConvertCase(strConv)) != track.Album ? true : false || bChanged; if (bChanged) track.Album = strConv; } if (checkBoxTitle.Checked) { strConv = track.Title; bChanged = (strConv = ConvertCase(strConv)) != track.Title ? true : false || bChanged; if (bChanged) track.Title = strConv; } if (checkBoxComment.Checked) { strConv = track.Comment; bChanged = (strConv = ConvertCase(strConv)) != track.Comment ? true : false || bChanged; if (bChanged) track.Comment = strConv; } if (bChanged) { track.Changed = true; _main.TracksGridView.Changed = true; _main.TracksGridView.SetBackgroundColorChanged(rowIndex); Options.Songlist[rowIndex] = track; } } }
/// <summary> /// Add the Track to the Conversion Grid /// </summary> /// <param name = "track"></param> public void AddToConvert(TrackData track) { if (track == null) return; ConversionData convdata = new ConversionData(); convdata.Track = track; bindingList.Add(convdata); }
public override bool Execute(ref TrackData track, int rowIndex) { string inputFile = track.FullFileName; string outFile = Util.ReplaceParametersWithTrackValues(Options.MainSettings.RipFileNameFormat, track); outFile = Path.Combine(_conversionData.RootFolder, outFile); string directoryName = Path.GetDirectoryName(outFile); // Now check the validity of the directory if (directoryName != null && !Directory.Exists(directoryName)) { try { Directory.CreateDirectory(directoryName); } catch (Exception e1) { Log.Error("Error creating folder: {0} {1]", directoryName, e1.Message); // Send the message _msg.MessageData["action"] = "error"; _msg.MessageData["error"] = _localisation.ToString("message", "Error"); _msg.MessageData["tooltip"] = String.Format("{0}: {1}", _localisation.ToString("message", "Error"), e1.Message); _msg.MessageData["rowindex"] = rowIndex; _queue.Send(_msg); return false; } } IAudioEncoder audioEncoder = new AudioEncoder(); outFile = audioEncoder.SetEncoder(_conversionData.Encoder, outFile); // Send message with new Filename _msg.MessageData["action"] = "newfilename"; _msg.MessageData["filename"] = outFile; _msg.MessageData["rowindex"] = rowIndex; _queue.Send(_msg); if (inputFile == outFile) { _msg.MessageData["action"] = "error"; _msg.MessageData["error"] = _localisation.ToString("message", "Error"); _msg.MessageData["tooltip"] = String.Format("{0}: {1}", inputFile, _localisation.ToString("Conversion", "SameFile")); _msg.MessageData["rowindex"] = rowIndex; _queue.Send(_msg); Log.Error("No conversion for {0}. Output would overwrite input", inputFile); return false; } int stream = Bass.BASS_StreamCreateFile(inputFile, 0, 0, BASSFlag.BASS_STREAM_DECODE); if (stream == 0) { _msg.MessageData["action"] = "error"; _msg.MessageData["error"] = _localisation.ToString("message", "Error"); _msg.MessageData["tooltip"] = String.Format("{0}: {1}", inputFile, _localisation.ToString("Conversion", "OpenFileError")); _msg.MessageData["rowindex"] = rowIndex; _queue.Send(_msg); Log.Error("Error creating stream for file {0}. Error: {1}", inputFile, Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode())); return false; } Log.Info("Convert file {0} -> {1}", inputFile, outFile); if (audioEncoder.StartEncoding(stream, rowIndex) != BASSError.BASS_OK) { _msg.MessageData["action"] = "error"; _msg.MessageData["error"] = _localisation.ToString("message", "Error"); _msg.MessageData["tooltip"] = String.Format("{0}: {1}", inputFile, _localisation.ToString("Conversion", "EncodingFileError")); _msg.MessageData["rowindex"] = rowIndex; _queue.Send(_msg); Log.Error("Error starting Encoder for File {0}. Error: {1}", inputFile, Enum.GetName(typeof(BASSError), Bass.BASS_ErrorGetCode())); Bass.BASS_StreamFree(stream); return false; } _msg.MessageData["action"] = "progress"; _msg.MessageData["percent"] = 100.0; _msg.MessageData["rowindex"] = rowIndex; _queue.Send(_msg); Bass.BASS_StreamFree(stream); try { // Now Tag the encoded File File tagInFile = File.Create(inputFile); File tagOutFile = File.Create(outFile); tagOutFile.Tag.AlbumArtists = tagInFile.Tag.AlbumArtists; tagOutFile.Tag.Album = tagInFile.Tag.Album; tagOutFile.Tag.Genres = tagInFile.Tag.Genres; tagOutFile.Tag.Year = tagInFile.Tag.Year; tagOutFile.Tag.Performers = tagInFile.Tag.Performers; tagOutFile.Tag.Track = tagInFile.Tag.Track; tagOutFile.Tag.TrackCount = tagInFile.Tag.TrackCount; tagOutFile.Tag.Title = tagInFile.Tag.Title; tagOutFile.Tag.Comment = tagInFile.Tag.Comment; tagOutFile.Tag.Composers = tagInFile.Tag.Composers; tagOutFile.Tag.Conductor = tagInFile.Tag.Conductor; tagOutFile.Tag.Copyright = tagInFile.Tag.Copyright; tagOutFile.Tag.Disc = tagInFile.Tag.Disc; tagOutFile.Tag.DiscCount = tagInFile.Tag.DiscCount; tagOutFile.Tag.Lyrics = tagInFile.Tag.Lyrics; tagOutFile.Tag.Pictures = tagInFile.Tag.Pictures; tagOutFile = Util.FormatID3Tag(tagOutFile); tagOutFile.Save(); Log.Info("Finished converting file {0} -> {1}", inputFile, outFile); return true; } catch (Exception ex) { Log.Error("Error tagging encoded file {0}. Error: {1}", outFile, ex.Message); } return false; }
/// <summary> /// Do Case Conversion for the given track. /// Called internally by the Convert button and by the Save clause, if set in Preferences /// </summary> /// <param name = "track"></param> public void CaseConvert(TrackData track, int rowIndex) { bool bErrors = false; // Convert the Filename if (checkBoxConvertFileName.Checked) { string fileName = ConvertCase(Path.GetFileNameWithoutExtension(track.FileName)); // Now check the length of the filename if (fileName.Length > 255) { log.Debug("Filename too long: {0}", fileName); _main.TracksGridView.TrackList[rowIndex].Status = 2; _main.TracksGridView.AddErrorMessage(_main.TracksGridView.View.Rows[rowIndex], String.Format("{0}: {1}", localisation.ToString("tag2filename", "NameTooLong"), fileName)); bErrors = true; } // Check, if we would generate duplicate file names foreach (DataGridViewRow file in _main.TracksGridView.View.Rows) { // Don't compare the file with itself if (rowIndex == file.Index) continue; TrackData filedata = _main.TracksGridView.TrackList[file.Index]; if (filedata.FileName.ToLowerInvariant() == fileName.ToLowerInvariant()) { log.Debug("New Filename already exists: {0}", fileName); _main.TracksGridView.TrackList[rowIndex].Status = 2; _main.TracksGridView.AddErrorMessage(_main.TracksGridView.View.Rows[rowIndex], String.Format("{0}: {1}", localisation.ToString("tag2filename", "FileExists"), fileName)); bErrors = true; break; } } if (!bErrors) { // Now that we have a correct Filename and no duplicates accept the changes track.FileName = string.Format("{0}{1}", fileName, Path.GetExtension(track.FileName)); track.Changed = true; _main.TracksGridView.Changed = true; _main.TracksGridView.SetBackgroundColorChanged(rowIndex); } } // Convert the Tags if (checkBoxConvertTags.Checked) { string strConv = ""; bool bChanged = false; if (checkBoxArtist.Checked) { strConv = track.Artist; bChanged = (strConv = ConvertCase(strConv)) != track.Artist ? true : false || bChanged; if (bChanged) track.Artist = strConv; } if (checkBoxAlbumArtist.Checked) { strConv = track.AlbumArtist; bChanged = (strConv = ConvertCase(strConv)) != track.AlbumArtist ? true : false || bChanged; if (bChanged) track.AlbumArtist = strConv; } if (checkBoxAlbum.Checked) { strConv = track.Album; bChanged = (strConv = ConvertCase(strConv)) != track.Album ? true : false || bChanged; if (bChanged) track.Album = strConv; } if (checkBoxTitle.Checked) { strConv = track.Title; bChanged = (strConv = ConvertCase(strConv)) != track.Title ? true : false || bChanged; if (bChanged) track.Title = strConv; } if (checkBoxComment.Checked) { strConv = track.Comment; bChanged = (strConv = ConvertCase(strConv)) != track.Comment ? true : false || bChanged; if (bChanged) track.Comment = strConv; } if (bChanged) { track.Changed = true; _main.TracksGridView.Changed = true; _main.TracksGridView.SetBackgroundColorChanged(rowIndex); } } }
private void UpdateMusicDatabase(TrackData track) { string db = Options.MainSettings.MediaPortalDatabase; if (!System.IO.File.Exists(db)) { return; } string[] tracks = track.Track.Split('/'); int trackNumber = 0; if (tracks[0] != "") { trackNumber = Convert.ToInt32(tracks[0]); } int trackTotal = 0; if (tracks.Length > 1) { trackTotal = Convert.ToInt32(tracks[1]); } string[] discs = track.Disc.Split('/'); int discNumber = 0; if (discs[0] != "") { discNumber = Convert.ToInt32(discs[0]); } int discTotal = 0; if (discs.Length > 1) { discTotal = Convert.ToInt32(discs[1]); } string originalFileName = Path.GetFileName(track.FullFileName); string newFileName = ""; newFileName = track.FullFileName; /* if (originalFileName != track.FileName) { string ext = Path.GetExtension(track.File.Name); newFileName = Path.Combine(Path.GetDirectoryName(track.File.Name), String.Format("{0}{1}", Path.GetFileNameWithoutExtension(track.FileName), ext)); } else { newFileName = track.FullFileName; } */ string sql = String.Format( @"update tracks set strArtist = '{0}', strAlbumArtist = '{1}', strAlbum = '{2}', strGenre = '{3}', strTitle = '{4}', iTrack = {5}, iNumTracks = {6}, iYear = {7}, iRating = {8}, iDisc = {9}, iNumDisc = {10}, strLyrics = '{11}', strPath = '{12}' where strPath = '{13}'", Util.RemoveInvalidChars(FormatMultipleEntry(track.Artist)), Util.RemoveInvalidChars(FormatMultipleEntry(track.AlbumArtist)), Util.RemoveInvalidChars(track.Album), Util.RemoveInvalidChars(FormatMultipleEntry(track.Genre)), Util.RemoveInvalidChars(track.Title), trackNumber, trackTotal, track.Year, track.Rating, discNumber, discTotal, Util.RemoveInvalidChars(track.Lyrics), Util.RemoveInvalidChars(newFileName), Util.RemoveInvalidChars(track.FullFileName) ); string connection = string.Format(@"Data Source={0}", db); try { SQLiteConnection conn = new SQLiteConnection(connection); conn.Open(); using (SQLiteCommand cmd = new SQLiteCommand()) { cmd.Connection = conn; cmd.CommandType = CommandType.Text; cmd.CommandText = sql; int result = cmd.ExecuteNonQuery(); } conn.Close(); } catch (Exception ex) { log.Error("Database Update: Error executing sql: {0}", ex.Message); } }
/// <summary> /// Adds a Track to the data grid /// </summary> /// <param name = "track"></param> private void AddTrack(TrackData track) { if (track == null) return; if (dataGridViewBurn.InvokeRequired) { ThreadSafeAddTracksDelegate d = AddTrack; dataGridViewBurn.Invoke(d, new object[] {track}); return; } bindingList.Add(track); }
/// <summary> /// Read the Tags from the File /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static TrackData Create(string fileName) { TrackData track = new TrackData(); TagLib.File file = null; bool error = false; try { TagLib.ByteVector.UseBrokenLatin1Behavior = true; file = TagLib.File.Create(fileName); } catch (CorruptFileException) { log.Warn("File Read: Ignoring track {0} - Corrupt File!", fileName); error = true; } catch (UnsupportedFormatException) { log.Warn("File Read: Ignoring track {0} - Unsupported format!", fileName); error = true; } catch (FileNotFoundException) { log.Warn("File Read: Ignoring track {0} - Physical file no longer existing!", fileName); error = true; } catch (Exception ex) { log.Error("File Read: Error processing file: {0} {1}", fileName, ex.Message); error = true; } if (error) { return(null); } TagLib.Id3v2.Tag id3v2tag = null; try { if (file.MimeType.Substring(file.MimeType.IndexOf("/") + 1) == "mp3") { id3v2tag = file.GetTag(TagTypes.Id3v2, false) as TagLib.Id3v2.Tag; } } catch (Exception ex) { log.Error("File Read: Error retrieving id3tag: {0} {1}", fileName, ex.Message); return(null); } #region Set Common Values FileInfo fi = new FileInfo(fileName); try { track.Id = Guid.NewGuid(); track.FullFileName = fileName; track.FileName = Path.GetFileName(fileName); track.Readonly = fi.IsReadOnly; track.TagType = file.MimeType.Substring(file.MimeType.IndexOf("/") + 1); } catch (Exception ex) { log.Error("File Read: Error setting Common tags: {0} {1}", fileName, ex.Message); return(null); } #endregion #region Set Tags try { // Artist track.Artist = String.Join(";", file.Tag.Performers); if (track.Artist.Contains("AC;DC")) { track.Artist = track.Artist.Replace("AC;DC", "AC/DC"); } track.ArtistSortName = String.Join(";", file.Tag.PerformersSort); if (track.ArtistSortName.Contains("AC;DC")) { track.ArtistSortName = track.ArtistSortName.Replace("AC;DC", "AC/DC"); } track.AlbumArtist = String.Join(";", file.Tag.AlbumArtists); if (track.AlbumArtist.Contains("AC;DC")) { track.AlbumArtist = track.AlbumArtist.Replace("AC;DC", "AC/DC"); } track.AlbumArtistSortName = String.Join(";", file.Tag.AlbumArtistsSort); if (track.AlbumArtistSortName.Contains("AC;DC")) { track.AlbumArtistSortName = track.AlbumArtistSortName.Replace("AC;DC", "AC/DC"); } track.Album = file.Tag.Album ?? ""; track.AlbumSortName = file.Tag.AlbumSort ?? ""; track.BPM = (int)file.Tag.BeatsPerMinute; track.Compilation = id3v2tag == null ? false : id3v2tag.IsCompilation; track.Composer = string.Join(";", file.Tag.Composers); track.Conductor = file.Tag.Conductor ?? ""; track.Copyright = file.Tag.Copyright ?? ""; track.DiscNumber = file.Tag.Disc; track.DiscCount = file.Tag.DiscCount; track.Genre = string.Join(";", file.Tag.Genres); track.Grouping = file.Tag.Grouping ?? ""; track.Title = file.Tag.Title ?? ""; track.TitleSortName = file.Tag.TitleSort ?? ""; track.ReplayGainTrack = file.Tag.ReplayGainTrack ?? ""; track.ReplayGainTrackPeak = file.Tag.ReplayGainTrackPeak ?? ""; track.ReplayGainAlbum = file.Tag.ReplayGainAlbum ?? ""; track.ReplayGainAlbumPeak = file.Tag.ReplayGainAlbumPeak ?? ""; track.TrackNumber = file.Tag.Track; track.TrackCount = file.Tag.TrackCount; track.Year = (int)file.Tag.Year; // Pictures foreach (IPicture picture in file.Tag.Pictures) { MPTagThat.Core.Common.Picture pic = new MPTagThat.Core.Common.Picture { Type = picture.Type, MimeType = picture.MimeType, Description = picture.Description }; pic.Data = picture.Data.Data; track.Pictures.Add(pic); } // Comments if (track.IsMp3 && id3v2tag != null) { foreach (CommentsFrame commentsframe in id3v2tag.GetFrames <CommentsFrame>()) { track.ID3Comments.Add(new Comment(commentsframe.Description, commentsframe.Language, commentsframe.Text)); } } else { track.Comment = file.Tag.Comment; } // Lyrics track.Lyrics = file.Tag.Lyrics; if (track.IsMp3 && id3v2tag != null) { foreach (UnsynchronisedLyricsFrame lyricsframe in id3v2tag.GetFrames <UnsynchronisedLyricsFrame>()) { // Only add non-empty Frames if (lyricsframe.Text != "") { track.LyricsFrames.Add(new Lyric(lyricsframe.Description, lyricsframe.Language, lyricsframe.Text)); } } } // Rating if (track.IsMp3) { TagLib.Id3v2.PopularimeterFrame popmFrame = null; // First read in all POPM Frames found if (id3v2tag != null) { foreach (PopularimeterFrame popmframe in id3v2tag.GetFrames <PopularimeterFrame>()) { // Only add valid POPM Frames if (popmframe.User != "" && popmframe.Rating > 0) { track.Ratings.Add(new PopmFrame(popmframe.User, (int)popmframe.Rating, (int)popmframe.PlayCount)); } } popmFrame = TagLib.Id3v2.PopularimeterFrame.Get(id3v2tag, "MPTagThat", false); if (popmFrame != null) { track.Rating = popmFrame.Rating; } } if (popmFrame == null) { // Now check for Ape Rating TagLib.Ape.Tag apetag = file.GetTag(TagTypes.Ape, true) as TagLib.Ape.Tag; TagLib.Ape.Item apeItem = apetag.GetItem("RATING"); if (apeItem != null) { string rating = apeItem.ToString(); try { track.Rating = Convert.ToInt32(rating); } catch (Exception) { } } } } else if (track.TagType == "ape") { TagLib.Ape.Tag apetag = file.GetTag(TagTypes.Ape, true) as TagLib.Ape.Tag; TagLib.Ape.Item apeItem = apetag.GetItem("RATING"); if (apeItem != null) { string rating = apeItem.ToString(); try { track.Rating = Convert.ToInt32(rating); } catch (Exception) { } } } else if (track.TagType == "ogg" || track.TagType == "flac") { XiphComment xiph = file.GetTag(TagLib.TagTypes.Xiph, false) as XiphComment; string[] rating = xiph.GetField("RATING"); if (rating.Length > 0) { try { track.Rating = Convert.ToInt32(rating[0]); } catch (Exception) { } } } } catch (Exception ex) { log.Error("Exception setting Tags for file: {0}. {1}", fileName, ex.Message); } #endregion #region Set Properties try { track.DurationTimespan = file.Properties.Duration; int fileLength = (int)(fi.Length / 1024); track.FileSize = fileLength.ToString(); track.BitRate = file.Properties.AudioBitrate.ToString(); track.SampleRate = file.Properties.AudioSampleRate.ToString(); track.Channels = file.Properties.AudioChannels.ToString(); track.Version = file.Properties.Description; track.CreationTime = string.Format("{0:yyyy-MM-dd HH:mm:ss}", fi.CreationTime); track.LastWriteTime = string.Format("{0:yyyy-MM-dd HH:mm:ss}", fi.LastWriteTime); } catch (Exception ex) { log.Error("Exception setting Properties for file: {0}. {1}", fileName, ex.Message); } #endregion // Now copy all Text frames of an ID3 V2 try { if (track.IsMp3 && id3v2tag != null) { foreach (TagLib.Id3v2.Frame frame in id3v2tag.GetFrames()) { string id = frame.FrameId.ToString(); if (!Util.StandardFrames.Contains(id) && Util.ExtendedFrames.Contains(id)) { track.Frames.Add(new Frame(id, "", frame.ToString())); } else if (!Util.StandardFrames.Contains(id) && !Util.ExtendedFrames.Contains(id)) { if ((Type)frame.GetType() == typeof(UserTextInformationFrame)) { // Don't add Replaygain frames, as they are handled in taglib tags if (!Util.IsReplayGain((frame as UserTextInformationFrame).Description)) { track.UserFrames.Add(new Frame(id, (frame as UserTextInformationFrame).Description ?? "", (frame as UserTextInformationFrame).Text.Length == 0 ? "" : (frame as UserTextInformationFrame).Text[0])); } } else if ((Type)frame.GetType() == typeof(PrivateFrame)) { track.UserFrames.Add(new Frame(id, (frame as PrivateFrame).Owner ?? "", (frame as PrivateFrame).PrivateData == null ? "" : (frame as PrivateFrame).PrivateData.ToString())); } else if ((Type)frame.GetType() == typeof(UniqueFileIdentifierFrame)) { track.UserFrames.Add(new Frame(id, (frame as UniqueFileIdentifierFrame).Owner ?? "", (frame as UniqueFileIdentifierFrame).Identifier == null ? "" : (frame as UniqueFileIdentifierFrame).Identifier.ToString())); } else if ((Type)frame.GetType() == typeof(UnknownFrame)) { track.UserFrames.Add(new Frame(id, "", (frame as UnknownFrame).Data == null ? "" : (frame as UnknownFrame).Data.ToString())); } else { track.UserFrames.Add(new Frame(id, "", frame.ToString())); } } } track.ID3Version = id3v2tag.Version; } } catch (Exception ex) { log.Error("Exception getting User Defined frames for file: {0}. {1}", fileName, ex.Message); } return(track); }
/// <summary> /// Do Preprocessing of the Tracks /// </summary> /// <param name="track"></param> /// <returns></returns> public virtual bool PreProcess(TrackData track) { return false; }
/// <summary> /// Convert File Name to Tag /// </summary> /// <param name = "parameters"></param> private void Tag2FileName(string parameter) { log.Trace(">>>"); bool bErrors = false; DataGridView tracksGrid = _main.TracksGridView.View; enumerateStartValue = (int)numericUpDownStartAt.Value; enumerateNumberDigits = (int)numericUpDownNumberDigits.Value; foreach (DataGridViewRow row in tracksGrid.Rows) { if (!row.Selected) continue; string fileName = parameter; track = _main.TracksGridView.TrackList[row.Index]; try { fileName = ReplaceParametersWithValues(parameter); // Now check the length of the filename if (fileName.Length > 255) { log.Debug("Filename too long: {0}", fileName); _main.TracksGridView.SetStatusColumnError(row); _main.TracksGridView.AddErrorMessage(row, String.Format("{0}: {1}", localisation.ToString("tag2filename", "NameTooLong"), fileName)); continue; // Process next row } // Check, if we would generate duplicate file names foreach (DataGridViewRow file in tracksGrid.Rows) { TrackData filedata = _main.TracksGridView.TrackList[file.Index]; if (filedata.FileName.ToLowerInvariant() == fileName.ToLowerInvariant()) { log.Debug("New Filename already exists: {0}", fileName); _main.TracksGridView.SetStatusColumnError(row); _main.TracksGridView.AddErrorMessage(row, String.Format("{0}: {1}", localisation.ToString("tag2filename", "FileExists"), fileName)); bErrors = true; break; } } if (bErrors) { bErrors = false; continue; } string ext = Path.GetExtension(track.FileName); // Now that we have a correct Filename and no duplicates accept the changes track.FileName = string.Format("{0}{1}", fileName, ext); track.Changed = true; _main.TracksGridView.Changed = true; _main.TracksGridView.SetBackgroundColorChanged(row.Index); } catch (Exception ex) { log.Error("Error Renaming File: {0} stack: {1}", ex.Message, ex.StackTrace); _main.TracksGridView.SetStatusColumnError(row); _main.TracksGridView.AddErrorMessage(row, String.Format("{0}: {1}", localisation.ToString("tag2filename", "Rename"), fileName)); bErrors = true; } } _main.TracksGridView.Changed = bErrors; // check, if we still have changed items in the list foreach (TrackData track in _main.TracksGridView.TrackList) { if (track.Changed) _main.TracksGridView.Changed = true; } tracksGrid.Refresh(); tracksGrid.Parent.Refresh(); log.Trace("<<<"); }
/// <summary> /// Replace the given Parameter string with the values from the Track /// </summary> /// <param name = "parameter"></param> /// <param name = "track"></param> /// <returns></returns> public static string ReplaceParametersWithTrackValues(string parameter, TrackData track) { string replacedString = parameter.Trim(new[] {'\\'}); try { if (replacedString.IndexOf("<A>") > -1) replacedString = replacedString.Replace("<A>", track.Artist.Replace(';', '_').Trim()); if (replacedString.IndexOf("<T>") > -1) replacedString = replacedString.Replace("<T>", track.Title.Trim()); if (replacedString.IndexOf("<B>") > -1) replacedString = replacedString.Replace("<B>", track.Album.Trim()); if (replacedString.IndexOf("<Y>") > -1) replacedString = replacedString.Replace("<Y>", track.Year.ToString().Trim()); if (replacedString.IndexOf("<K>") > -1) { string[] str = track.Track.Split('/'); replacedString = replacedString.Replace("<K>", str[0]); } if (replacedString.IndexOf("<k>") > -1) { string[] str = track.Track.Split('/'); replacedString = replacedString.Replace("<k>", str[1]); } if (replacedString.IndexOf("<D>") > -1) { string[] str = track.Disc.Split('/'); replacedString = replacedString.Replace("<D>", str[0]); } if (replacedString.IndexOf("<d>") > -1) { string[] str = track.Disc.Split('/'); replacedString = replacedString.Replace("<d>", str[1]); } if (replacedString.IndexOf("<G>") > -1) { string[] str = track.Genre.Split(';'); replacedString = replacedString.Replace("<G>", str[0].Trim()); } if (replacedString.IndexOf("<O>") > -1) replacedString = replacedString.Replace("<O>", track.AlbumArtist.Replace(';', '_').Trim()); if (replacedString.IndexOf("<C>") > -1) replacedString = replacedString.Replace("<C>", track.Comment.Trim()); if (replacedString.IndexOf("<U>") > -1) replacedString = replacedString.Replace("<U>", track.Grouping.Trim()); if (replacedString.IndexOf("<N>") > -1) replacedString = replacedString.Replace("<N>", track.Conductor.Trim()); if (replacedString.IndexOf("<R>") > -1) replacedString = replacedString.Replace("<R>", track.Composer.Replace(';', '_').Trim()); if (replacedString.IndexOf("<S>") > -1) replacedString = replacedString.Replace("<S>", track.SubTitle.Trim()); if (replacedString.IndexOf("<E>") > -1) replacedString = replacedString.Replace("<E>", track.BPM.ToString()); if (replacedString.IndexOf("<M>") > -1) replacedString = replacedString.Replace("<M>", track.Interpreter.Trim()); if (replacedString.IndexOf("<I>") > -1) replacedString = replacedString.Replace("<I>", track.BitRate); int index = replacedString.IndexOf("<A:"); if (index > -1) { replacedString = ReplaceStringWithLengthIndicator(index, replacedString, track.Artist.Replace(';', '_').Trim()); } index = replacedString.IndexOf("<O:"); if (index > -1) { replacedString = ReplaceStringWithLengthIndicator(index, replacedString, track.AlbumArtist.Replace(';', '_').Trim()); } index = replacedString.IndexOf("<K:"); if (index > -1) { string[] str = track.Track.Split('/'); replacedString = ReplaceStringWithLengthIndicator(index, replacedString, str[0]); } index = replacedString.IndexOf("<k:"); if (index > -1) { string[] str = track.Track.Split('/'); replacedString = ReplaceStringWithLengthIndicator(index, replacedString, str[1]); } index = replacedString.IndexOf("<D:"); if (index > -1) { string[] str = track.Disc.Split('/'); replacedString = ReplaceStringWithLengthIndicator(index, replacedString, str[0]); } index = replacedString.IndexOf("<d:"); if (index > -1) { string[] str = track.Disc.Split('/'); replacedString = ReplaceStringWithLengthIndicator(index, replacedString, str[1]); } // Empty Values would create invalid folders replacedString = replacedString.Replace(@"\\", @"\_\"); // If the directory name starts with a backslash, we've got an empty value on the beginning if (replacedString.IndexOf("\\") == 0) replacedString = "_" + replacedString; // We might have an empty value on the end of the path, which is indicated by a slash. // replace it with underscore if (replacedString.LastIndexOf("\\") == replacedString.Length - 1) replacedString += "_"; replacedString = MakeValidFolderName(replacedString); } catch (Exception) { return ""; } return replacedString; }
/// <summary> /// Save the Picture of the track as folder.jpg /// </summary> /// <param name = "track"></param> public void SavePicture(TrackData track) { if (track.NumPics > 0) { string fileName = Path.Combine(Path.GetDirectoryName(track.FullFileName), "folder.jpg"); try { Image img = Picture.ImageFromData(track.Pictures[0].Data); // Need to make a copy, otherwise we have a GDI+ Error Bitmap bCopy = new Bitmap(img); bCopy.Save(fileName, ImageFormat.Jpeg); } catch (Exception ex) { log.Error("Exception Saving picture: {0} {1}", fileName, ex.Message); } } }
/// <summary> /// Save the Modified file /// </summary> /// <param name="track"></param> /// <param name="errorMessage"></param> /// <returns></returns> public static bool SaveFile(TrackData track, ref string errorMessage) { errorMessage = ""; if (!track.Changed) { return(true); } if (track.Readonly && !Options.MainSettings.ChangeReadOnlyAttributte && (Options.ReadOnlyFileHandling == 0 || Options.ReadOnlyFileHandling == 2)) { Form dlg = new ReadOnlyDialog(track.FullFileName); DialogResult dlgResult = dlg.ShowDialog(); switch (dlgResult) { case DialogResult.Yes: Options.ReadOnlyFileHandling = 0; // Yes break; case DialogResult.OK: Options.ReadOnlyFileHandling = 1; // Yes to All break; case DialogResult.No: Options.ReadOnlyFileHandling = 2; // No break; case DialogResult.Cancel: Options.ReadOnlyFileHandling = 3; // No to All break; } } if (track.Readonly) { if (!Options.MainSettings.ChangeReadOnlyAttributte && Options.ReadOnlyFileHandling > 1) { errorMessage = "File is readonly"; return(false); } try { System.IO.File.SetAttributes(track.FullFileName, System.IO.File.GetAttributes(track.FullFileName) & ~FileAttributes.ReadOnly); track.Readonly = false; } catch (Exception ex) { log.Error("File Save: Can't reset Readonly attribute: {0} {1}", track.FullFileName, ex.Message); errorMessage = ServiceScope.Get <ILocalisation>().ToString("message", "ErrorResetAttr"); return(false); } } TagLib.File file = null; bool error = false; try { TagLib.ByteVector.UseBrokenLatin1Behavior = true; file = TagLib.File.Create(track.FullFileName); } catch (CorruptFileException) { log.Warn("File Read: Ignoring track {0} - Corrupt File!", track.FullFileName); errorMessage = ServiceScope.Get <ILocalisation>().ToString("message", "CorruptFile"); error = true; } catch (UnsupportedFormatException) { log.Warn("File Read: Ignoring track {0} - Unsupported format!", track.FullFileName); errorMessage = ServiceScope.Get <ILocalisation>().ToString("message", "UnsupportedFormat"); error = true; } catch (FileNotFoundException) { log.Warn("File Read: Ignoring track {0} - Physical file no longer existing!", track.FullFileName); errorMessage = ServiceScope.Get <ILocalisation>().ToString("message", "NonExistingFile"); error = true; } catch (Exception ex) { log.Error("File Read: Error processing file: {0} {1}", track.FullFileName, ex.Message); errorMessage = string.Format(ServiceScope.Get <ILocalisation>().ToString("message", "ErrorReadingFile"), ex.Message); error = true; } if (file == null || error) { log.Error("File Read: Error processing file.: {0}", track.FullFileName); return(false); } try { // Get the ID3 Frame for ID3 specifc frame handling TagLib.Id3v1.Tag id3v1tag = null; TagLib.Id3v2.Tag id3v2tag = null; if (track.IsMp3) { id3v1tag = file.GetTag(TagTypes.Id3v1, true) as TagLib.Id3v1.Tag; id3v2tag = file.GetTag(TagTypes.Id3v2, true) as TagLib.Id3v2.Tag; } // Remove Tags, if they have been removed in TagEdit Panel foreach (TagLib.TagTypes tagType in track.TagsRemoved) { file.RemoveTags(tagType); } #region Main Tags string[] splitValues = track.Artist.Split(new[] { ';', '|' }); file.Tag.Performers = splitValues; splitValues = track.AlbumArtist.Split(new[] { ';', '|' }); file.Tag.AlbumArtists = splitValues; file.Tag.Album = track.Album.Trim(); file.Tag.BeatsPerMinute = (uint)track.BPM; if (track.Comment != "") { file.Tag.Comment = ""; if (track.IsMp3) { id3v1tag.Comment = track.Comment; foreach (Comment comment in track.ID3Comments) { CommentsFrame commentsframe = CommentsFrame.Get(id3v2tag, comment.Description, comment.Language, true); commentsframe.Text = comment.Text; commentsframe.Description = comment.Description; commentsframe.Language = comment.Language; } } else { file.Tag.Comment = track.Comment; } } else { file.Tag.Comment = ""; } if (track.IsMp3) { id3v2tag.IsCompilation = track.Compilation; } file.Tag.Disc = track.DiscNumber; file.Tag.DiscCount = track.DiscCount; splitValues = track.Genre.Split(new[] { ';', '|' }); file.Tag.Genres = splitValues; file.Tag.Title = track.Title; file.Tag.Track = track.TrackNumber; file.Tag.TrackCount = track.TrackCount; file.Tag.Year = (uint)track.Year; file.Tag.ReplayGainTrack = track.ReplayGainTrack; file.Tag.ReplayGainTrackPeak = track.ReplayGainTrackPeak; file.Tag.ReplayGainAlbum = track.ReplayGainAlbum; file.Tag.ReplayGainAlbumPeak = track.ReplayGainAlbumPeak; #endregion #region Detailed Information splitValues = track.Composer.Split(new[] { ';', '|' }); file.Tag.Composers = splitValues; file.Tag.Conductor = track.Conductor; file.Tag.Copyright = track.Copyright; file.Tag.Grouping = track.Grouping; splitValues = track.ArtistSortName.Split(new[] { ';', '|' }); file.Tag.PerformersSort = splitValues; splitValues = track.AlbumArtistSortName.Split(new[] { ';', '|' }); file.Tag.AlbumArtistsSort = splitValues; file.Tag.AlbumSort = track.AlbumSortName; file.Tag.TitleSort = track.TitleSortName; #endregion #region Picture List <TagLib.Picture> pics = new List <TagLib.Picture>(); foreach (Picture pic in track.Pictures) { TagLib.Picture tagPic = new TagLib.Picture(); try { byte[] byteArray = pic.Data; ByteVector data = new ByteVector(byteArray); tagPic.Data = data; tagPic.Description = pic.Description; tagPic.MimeType = "image/jpg"; tagPic.Type = pic.Type; pics.Add(tagPic); } catch (Exception ex) { log.Error("Error saving Picture: {0}", ex.Message); } file.Tag.Pictures = pics.ToArray(); } // Clear the picture if (track.Pictures.Count == 0) { file.Tag.Pictures = pics.ToArray(); } #endregion #region Lyrics if (track.Lyrics != null && track.Lyrics != "") { file.Tag.Lyrics = track.Lyrics; if (track.IsMp3) { foreach (Lyric lyric in track.LyricsFrames) { UnsynchronisedLyricsFrame lyricframe = UnsynchronisedLyricsFrame.Get(id3v2tag, lyric.Description, lyric.Language, true); lyricframe.Text = lyric.Text; lyricframe.Description = lyric.Description; lyricframe.Language = lyric.Language; } } else { file.Tag.Lyrics = track.Lyrics; } } else { file.Tag.Lyrics = ""; } #endregion #region Ratings if (track.IsMp3) { if (track.Ratings.Count > 0) { foreach (PopmFrame rating in track.Ratings) { PopularimeterFrame popmFrame = PopularimeterFrame.Get(id3v2tag, rating.User, true); popmFrame.Rating = Convert.ToByte(rating.Rating); popmFrame.PlayCount = Convert.ToUInt32(rating.PlayCount); } } else { id3v2tag.RemoveFrames("POPM"); } } else if (track.TagType == "ogg" || track.TagType == "flac") { if (track.Ratings.Count > 0) { XiphComment xiph = file.GetTag(TagLib.TagTypes.Xiph, true) as XiphComment; xiph.SetField("RATING", track.Rating.ToString()); } } #endregion #region Non- Standard Taglib and User Defined Frames if (Options.MainSettings.ClearUserFrames) { foreach (Frame frame in track.UserFrames) { ByteVector frameId = new ByteVector(frame.Id); if (frame.Id == "TXXX") { id3v2tag.SetUserTextAsString(frame.Description, ""); } else { id3v2tag.SetTextFrame(frameId, ""); } } } List <Frame> allFrames = new List <Frame>(); allFrames.AddRange(track.Frames); // The only way to avoid duplicates of User Frames is to delete them by assigning blank values to them if (track.SavedUserFrames != null && !Options.MainSettings.ClearUserFrames) { // Clean the previously saved Userframes, to avoid duplicates foreach (Frame frame in track.SavedUserFrames) { ByteVector frameId = new ByteVector(frame.Id); if (frame.Id == "TXXX") { id3v2tag.SetUserTextAsString(frame.Description, ""); } else { id3v2tag.SetTextFrame(frameId, ""); } } allFrames.AddRange(track.UserFrames); } foreach (Frame frame in allFrames) { ByteVector frameId = new ByteVector(frame.Id); // The only way to avoid duplicates of User Frames is to delete them by assigning blank values to them if (frame.Id == "TXXX") { if (frame.Description != "") { id3v2tag.SetUserTextAsString(frame.Description, ""); id3v2tag.SetUserTextAsString(frame.Description, frame.Value); } } else { id3v2tag.SetTextFrame(frameId, ""); id3v2tag.SetTextFrame(frameId, frame.Value); } } #endregion // Now, depending on which frames the user wants to save, we will remove the other Frames file = Util.FormatID3Tag(file); // Set the encoding for ID3 Tags if (track.IsMp3) { TagLib.Id3v2.Tag.ForceDefaultEncoding = true; switch (Options.MainSettings.CharacterEncoding) { case 0: TagLib.Id3v2.Tag.DefaultEncoding = StringType.Latin1; break; case 1: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF16; break; case 2: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF16BE; break; case 3: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF8; break; case 4: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF16LE; break; } } // Save the file file.Save(); } catch (Exception ex) { log.Error("File Save: Error processing file: {0} {1}", track.FullFileName, ex.Message); errorMessage = ServiceScope.Get <ILocalisation>().ToString("message", "ErrorSave"); error = true; } if (error) { return(false); } return(true); }
/// <summary> /// Adds a Track to the data grid /// </summary> /// <param name = "track"></param> private void AddTrack(TrackData track) { if (track == null) return; if (tracksGrid.InvokeRequired) { ThreadSafeAddTracksDelegate d = AddTrack; tracksGrid.Invoke(d, new object[] { track }); return; } // Validate the MP3 File if (Options.MainSettings.MP3Validate && track.IsMp3) { string strError = ""; track.MP3ValidationError = MP3Val.ValidateMp3File(track.FullFileName, out strError); track.MP3ValidationErrorText = strError; } Options.Songlist.Add(track); }
/// <summary> /// Loop through all the selected rows and set the Preview /// </summary> /// <param name = "parameters"></param> private void OrganiseFilesPreview(string parameters) { log.Trace(">>>"); int index = -1; foreach (DataGridViewRow row in _main.TracksGridView.View.Rows) { if (!row.Selected) continue; index++; try { track = Options.Songlist[row.Index]; trackPreview = _previewForm.Tracks[index]; trackPreview.NewFullFileName = Util.ReplaceParametersWithTrackValues(parameters, track); } catch (Exception) {} } _previewForm.Refresh(); log.Trace("<<<"); }
/// <summary> /// Save the Modified file /// </summary> /// <param name="track"></param> /// <param name="errorMessage"></param> /// <returns></returns> public static bool SaveFile(TrackData track, ref string errorMessage) { errorMessage = ""; if (!track.Changed) { return true; } if (track.Readonly && !Options.MainSettings.ChangeReadOnlyAttributte && (Options.ReadOnlyFileHandling == 0 || Options.ReadOnlyFileHandling == 2)) { Form dlg = new ReadOnlyDialog(track.FullFileName); DialogResult dlgResult = dlg.ShowDialog(); switch (dlgResult) { case DialogResult.Yes: Options.ReadOnlyFileHandling = 0; // Yes break; case DialogResult.OK: Options.ReadOnlyFileHandling = 1; // Yes to All break; case DialogResult.No: Options.ReadOnlyFileHandling = 2; // No break; case DialogResult.Cancel: Options.ReadOnlyFileHandling = 3; // No to All break; } } if (track.Readonly) { if (!Options.MainSettings.ChangeReadOnlyAttributte && Options.ReadOnlyFileHandling > 1) { errorMessage = "File is readonly"; return false; } try { System.IO.File.SetAttributes(track.FullFileName, System.IO.File.GetAttributes(track.FullFileName) & ~FileAttributes.ReadOnly); track.Readonly = false; } catch (Exception ex) { log.Error("File Save: Can't reset Readonly attribute: {0} {1}", track.FullFileName, ex.Message); errorMessage = ServiceScope.Get<ILocalisation>().ToString("message", "ErrorResetAttr"); return false; } } TagLib.File file = null; bool error = false; try { TagLib.ByteVector.UseBrokenLatin1Behavior = true; file = TagLib.File.Create(track.FullFileName); } catch (CorruptFileException) { log.Warn("File Read: Ignoring track {0} - Corrupt File!", track.FullFileName); errorMessage = ServiceScope.Get<ILocalisation>().ToString("message", "CorruptFile"); error = true; } catch (UnsupportedFormatException) { log.Warn("File Read: Ignoring track {0} - Unsupported format!", track.FullFileName); errorMessage = ServiceScope.Get<ILocalisation>().ToString("message", "UnsupportedFormat"); error = true; } catch (FileNotFoundException) { log.Warn("File Read: Ignoring track {0} - Physical file no longer existing!", track.FullFileName); errorMessage = ServiceScope.Get<ILocalisation>().ToString("message", "NonExistingFile"); error = true; } catch (Exception ex) { log.Error("File Read: Error processing file: {0} {1}", track.FullFileName, ex.Message); errorMessage = string.Format(ServiceScope.Get<ILocalisation>().ToString("message", "ErrorReadingFile"), ex.Message); error = true; } if (file == null || error) { log.Error("File Read: Error processing file.: {0}", track.FullFileName); return false; } try { // Get the ID3 Frame for ID3 specifc frame handling TagLib.Id3v1.Tag id3v1tag = null; TagLib.Id3v2.Tag id3v2tag = null; if (track.TagType.ToLower() == "mp3") { id3v1tag = file.GetTag(TagTypes.Id3v1, true) as TagLib.Id3v1.Tag; id3v2tag = file.GetTag(TagTypes.Id3v2, true) as TagLib.Id3v2.Tag; } // Remove Tags, if they have been removed in TagEdit Panel foreach (TagLib.TagTypes tagType in track.TagsRemoved) { file.RemoveTags(tagType); } #region Main Tags string[] splitValues = track.Artist.Split(new[] { ';', '|' }); file.Tag.Performers = splitValues; splitValues = track.AlbumArtist.Split(new[] { ';', '|' }); file.Tag.AlbumArtists = splitValues; file.Tag.Album = track.Album.Trim(); file.Tag.BeatsPerMinute = (uint)track.BPM; if (track.Comment != "") { file.Tag.Comment = ""; if (track.TagType.ToLower() == "mp3") { id3v1tag.Comment = track.Comment; foreach (Comment comment in track.ID3Comments) { CommentsFrame commentsframe = CommentsFrame.Get(id3v2tag, comment.Description, comment.Language, true); commentsframe.Text = comment.Text; commentsframe.Description = comment.Description; commentsframe.Language = comment.Language; } } else file.Tag.Comment = track.Comment; } else { file.Tag.Comment = ""; } if (track.TagType.ToLower() == "mp3") { id3v2tag.IsCompilation = track.Compilation; } file.Tag.Disc = track.DiscNumber; file.Tag.DiscCount = track.DiscCount; splitValues = track.Genre.Split(new[] { ';', '|' }); file.Tag.Genres = splitValues; file.Tag.Title = track.Title; file.Tag.Track = track.TrackNumber; file.Tag.TrackCount = track.TrackCount; file.Tag.Year = (uint)track.Year; #endregion #region Detailed Information splitValues = track.Composer.Split(new[] { ';', '|' }); file.Tag.Composers = splitValues; file.Tag.Conductor = track.Conductor; file.Tag.Copyright = track.Copyright; file.Tag.Grouping = track.Grouping; #endregion #region Picture List<TagLib.Picture> pics = new List<TagLib.Picture>(); foreach (Picture pic in track.Pictures) { ImageConverter imgConverter = new ImageConverter(); TagLib.Picture tagPic = new TagLib.Picture(); try { byte[] byteArray = Picture.ImageToByte(pic.Data); ByteVector data = new ByteVector(byteArray); tagPic.Data = data; tagPic.Description = pic.Description; tagPic.MimeType = pic.MimeType; tagPic.Type = pic.Type; pics.Add(tagPic); } catch (Exception ex) { log.Error("Error saving Picture: {0}", ex.Message); } file.Tag.Pictures = pics.ToArray(); } // Clear the picture if (track.Pictures.Count == 0) { file.Tag.Pictures = pics.ToArray(); } #endregion #region Lyrics if (track.Lyrics != null && track.Lyrics != "") { file.Tag.Lyrics = track.Lyrics; if (track.TagType.ToLower() == "mp3") { foreach (Lyric lyric in track.LyricsFrames) { UnsynchronisedLyricsFrame lyricframe = UnsynchronisedLyricsFrame.Get(id3v2tag, lyric.Description, lyric.Language, true); lyricframe.Text = lyric.Text; lyricframe.Description = lyric.Description; lyricframe.Language = lyric.Language; } } else file.Tag.Lyrics = track.Lyrics; } else { file.Tag.Lyrics = ""; } #endregion #region Ratings if (track.TagType.ToLower() == "mp3") { if (track.Ratings.Count > 0) { foreach (PopmFrame rating in track.Ratings) { PopularimeterFrame popmFrame = PopularimeterFrame.Get(id3v2tag, rating.User, true); popmFrame.Rating = Convert.ToByte(rating.Rating); popmFrame.PlayCount = Convert.ToUInt32(rating.PlayCount); } } else id3v2tag.RemoveFrames("POPM"); } #endregion #region Non- Standard Taglib and User Defined Frames if (Options.MainSettings.ClearUserFrames) { foreach (Frame frame in track.UserFrames) { ByteVector frameId = new ByteVector(frame.Id); if (frame.Id == "TXXX") { id3v2tag.SetUserTextAsString(frame.Description, ""); } else { id3v2tag.SetTextFrame(frameId, ""); } } } // The only way to avoid duplicates of User Frames is to delete them by assigning blank values to them if (track.SavedUserFrames != null && !Options.MainSettings.ClearUserFrames) { foreach (Frame frame in track.SavedUserFrames) { ByteVector frameId = new ByteVector(frame.Id); if (frame.Id == "TXXX") { id3v2tag.SetUserTextAsString(frame.Description, ""); } else { id3v2tag.SetTextFrame(frameId, ""); } } List<Frame> allFrames = new List<Frame>(); allFrames.AddRange(track.Frames); allFrames.AddRange(track.UserFrames); foreach (Frame frame in allFrames) { ByteVector frameId = new ByteVector(frame.Id); if (frame.Id == "TXXX") { if (frame.Description != "") { id3v2tag.SetUserTextAsString(frame.Description, frame.Value); } } else { id3v2tag.SetTextFrame(frameId, frame.Value); } } } #endregion // Now, depending on which frames the user wants to save, we will remove the other Frames file = Util.FormatID3Tag(file); // Set the encoding for ID3 Tags if (track.TagType.ToLower() == "mp3") { TagLib.Id3v2.Tag.ForceDefaultEncoding = true; switch (Options.MainSettings.CharacterEncoding) { case 0: TagLib.Id3v2.Tag.DefaultEncoding = StringType.Latin1; break; case 1: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF16; break; case 2: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF16BE; break; case 3: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF8; break; case 4: TagLib.Id3v2.Tag.DefaultEncoding = StringType.UTF16LE; break; } } // Save the file file.Save(); } catch (Exception ex) { log.Error("File Save: Error processing file: {0} {1}", track.FullFileName, ex.Message); errorMessage = ServiceScope.Get<ILocalisation>().ToString("message", "ErrorSave"); error = true; } if (error) { return false; } return true; }