diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs index 00d8b55a..f4074ad1 100644 --- a/Vocaluxe/Base/CConfig.cs +++ b/Vocaluxe/Base/CConfig.cs @@ -37,6 +37,7 @@ namespace Vocaluxe.Base // Debug public static EDebugLevel DebugLevel = EDebugLevel.TR_CONFIG_OFF; + public static EOffOn SaveModifiedSongs = EOffOn.TR_CONFIG_OFF; // Graphics #if WIN @@ -169,6 +170,7 @@ namespace Vocaluxe.Base return; xmlReader.TryGetEnumValue("//root/Debug/DebugLevel", ref DebugLevel); + xmlReader.TryGetEnumValue("//root/Debug/SaveModifiedSongs", ref SaveModifiedSongs); #region Graphics xmlReader.TryGetEnumValue("//root/Graphics/Renderer", ref Renderer); @@ -328,6 +330,9 @@ namespace Vocaluxe.Base writer.WriteComment("DebugLevel: " + CHelper.ListStrings(Enum.GetNames(typeof(EDebugLevel)))); writer.WriteElementString("DebugLevel", Enum.GetName(typeof(EDebugLevel), DebugLevel)); + writer.WriteComment("SaveModifiedSongs: " + CHelper.ListStrings(Enum.GetNames(typeof(EOffOn)))); + writer.WriteElementString("SaveModifiedSongs", Enum.GetName(typeof(EOffOn), SaveModifiedSongs)); + writer.WriteEndElement(); #endregion Debug diff --git a/Vocaluxe/Base/CMain.cs b/Vocaluxe/Base/CMain.cs index 8a40c555..84523016 100644 --- a/Vocaluxe/Base/CMain.cs +++ b/Vocaluxe/Base/CMain.cs @@ -60,6 +60,11 @@ namespace Vocaluxe.Base class CBconfig : IConfig { + public EOffOn GetSaveModifiedSongs() + { + return CConfig.SaveModifiedSongs; + } + public void SetBackgroundMusicVolume(int newVolume) { CConfig.BackgroundMusicVolume = newVolume; diff --git a/VocaluxeLib/IBasic.cs b/VocaluxeLib/IBasic.cs index c6893634..6543482a 100644 --- a/VocaluxeLib/IBasic.cs +++ b/VocaluxeLib/IBasic.cs @@ -29,6 +29,8 @@ namespace VocaluxeLib { public interface IConfig { + EOffOn GetSaveModifiedSongs(); + void SetBackgroundMusicVolume(int newVolume); int GetBackgroundMusicVolume(); diff --git a/VocaluxeLib/Songs/CBaseNote.cs b/VocaluxeLib/Songs/CBaseNote.cs index 1c81038b..45043aa7 100644 --- a/VocaluxeLib/Songs/CBaseNote.cs +++ b/VocaluxeLib/Songs/CBaseNote.cs @@ -48,6 +48,9 @@ namespace VocaluxeLib.Songs #region Properties public int StartBeat { get; set; } + /// + /// Last beat of this note. First valid beat for a note after that is at EndBeat+1 + /// public int EndBeat { get { return StartBeat + _Duration - 1; } diff --git a/VocaluxeLib/Songs/CSong.cs b/VocaluxeLib/Songs/CSong.cs index ece23c2c..688d2d28 100644 --- a/VocaluxeLib/Songs/CSong.cs +++ b/VocaluxeLib/Songs/CSong.cs @@ -20,7 +20,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using System.Text.RegularExpressions; using VocaluxeLib.Draw; namespace VocaluxeLib.Songs @@ -73,7 +72,7 @@ namespace VocaluxeLib.Songs public SMedley Medley; - public bool CalculateMedley = true; + private bool _CalculateMedley = true; public float PreviewStart; public int ShortEnd; @@ -197,7 +196,7 @@ namespace VocaluxeLib.Songs FadeOutTime = song.Medley.FadeOutTime }; - CalculateMedley = song.CalculateMedley; + _CalculateMedley = song._CalculateMedley; PreviewStart = song.PreviewStart; ShortEnd = song.ShortEnd; @@ -261,6 +260,12 @@ namespace VocaluxeLib.Songs return loader.ReadNotes(); } + public bool Save(string filePath) + { + var writer = new CSongWriter(this); + return writer.SaveFile(filePath); + } + public string GetMP3() { return Path.Combine(Folder, MP3FileName); @@ -381,7 +386,7 @@ namespace VocaluxeLib.Songs if (Medley.Source == EMedleySource.Tag) return; - if (!CalculateMedley) + if (!_CalculateMedley) return; List series = _GetSeries(); diff --git a/VocaluxeLib/Songs/CSongLoader.cs b/VocaluxeLib/Songs/CSongLoader.cs index f93a2368..98cc839b 100644 --- a/VocaluxeLib/Songs/CSongLoader.cs +++ b/VocaluxeLib/Songs/CSongLoader.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -295,7 +294,7 @@ namespace VocaluxeLib.Songs break; case "CALCMEDLEY": if (value.ToUpper() == "OFF") - _Song.CalculateMedley = false; + _Song._CalculateMedley = false; break; case "RELATIVE": if (value.ToUpper() == "YES") @@ -518,6 +517,7 @@ namespace VocaluxeLib.Songs _LogError("Wrong or missing number after \"P\""); return false; } + currentBeat = 0; lastNote = null; break; case ':': @@ -625,6 +625,7 @@ namespace VocaluxeLib.Songs { _LogWarning("Missing line break length"); changesMade.NoLengthBreakCt++; + currentBeat = beat; } else currentBeat += length; @@ -694,6 +695,11 @@ namespace VocaluxeLib.Songs { string msg = "Automatic changes have been made to " + filePath + " Please check result!\r\n" + changesMade; CBase.Log.LogError("Warning:" + msg); + if (CBase.Config.GetSaveModifiedSongs() == EOffOn.TR_CONFIG_ON) + { + string name = Path.GetFileNameWithoutExtension(_Song.FileName); + _Song.Save(Path.Combine(_Song.Folder, name + ".fix.txt")); + } } return true; } diff --git a/VocaluxeLib/Songs/CSongWriter.cs b/VocaluxeLib/Songs/CSongWriter.cs index 59d1cbe1..a108c685 100644 --- a/VocaluxeLib/Songs/CSongWriter.cs +++ b/VocaluxeLib/Songs/CSongWriter.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; namespace VocaluxeLib.Songs { @@ -17,19 +15,19 @@ namespace VocaluxeLib.Songs _Song = song; } - private void _WriteHeaderEntry(StreamWriter sw, string id, T value) + private void _WriteHeaderEntry(TextWriter sw, string id, T value) { if (!value.Equals(default(T))) sw.WriteLine("#" + id.ToUpper() + ":" + value); } - private void _WriteHeaderEntry(StreamWriter sw, string id, bool value) + private void _WriteHeaderEntry(TextWriter sw, string id, bool value) { if (value) _WriteHeaderEntry(sw, id, "YES"); } - private void _WriteHeaderEntry(StreamWriter sw, string id, IList value) + private void _WriteHeaderEntrys(TextWriter sw, string id, IList value) { if (value != null && value.Count > 0) { @@ -38,7 +36,7 @@ namespace VocaluxeLib.Songs } } - private void _WriteHeader(StreamWriter sw) + private void _WriteHeader(TextWriter sw) { _WriteHeaderEntry(sw, "ENCODING", _Song.Encoding); _WriteHeaderEntry(sw, "CREATOR", _Song.Creator); @@ -48,7 +46,7 @@ namespace VocaluxeLib.Songs { string comment = _Song._Comment.Replace("\r\n", "\n").Replace('\r', '\n'); char[] splitChar = {'\n'}; - _WriteHeaderEntry(sw, "COMMENT", comment.Split(splitChar)); + _WriteHeaderEntrys(sw, "COMMENT", comment.Split(splitChar)); } _WriteHeaderEntry(sw, "TITLE", _Song.Title); _WriteHeaderEntry(sw, "ARTIST", _Song.Artist); @@ -56,9 +54,9 @@ namespace VocaluxeLib.Songs _WriteHeaderEntry(sw, "TITLE-ON-SORTING", _Song.TitleSorting); if (!_Song.Artist.Equals(_Song.ArtistSorting)) _WriteHeaderEntry(sw, "ARTIST-ON-SORTING", _Song.ArtistSorting); - _WriteHeaderEntry(sw, "EDITION", _Song.Editions); - _WriteHeaderEntry(sw, "GENRE", _Song.Genres); - _WriteHeaderEntry(sw, "LANGUAGE", _Song.Languages); + _WriteHeaderEntrys(sw, "EDITION", _Song.Editions); + _WriteHeaderEntrys(sw, "GENRE", _Song.Genres); + _WriteHeaderEntrys(sw, "LANGUAGE", _Song.Languages); _WriteHeaderEntry(sw, "ALBUM", _Song.Album); _WriteHeaderEntry(sw, "YEAR", _Song.Year); _WriteHeaderEntry(sw, "MP3", _Song.MP3FileName); @@ -73,7 +71,7 @@ namespace VocaluxeLib.Songs _WriteHeaderEntry(sw, "PREVIEWSTART", _Song.PreviewStart); _WriteHeaderEntry(sw, "START", _Song.Start); _WriteHeaderEntry(sw, "END", _Song.Finish); - if (!_Song.CalculateMedley) + if (!_Song._CalculateMedley) _WriteHeaderEntry(sw, "CALCMEDLEY", "OFF"); if (_Song.Medley.Source == EMedleySource.Tag) { @@ -88,6 +86,68 @@ namespace VocaluxeLib.Songs foreach (string addLine in _Song.UnknownTags) sw.WriteLine(addLine); } + + private void _WriteNotes(TextWriter sw) + { + for (int i = 0; i < _Song.Notes.VoiceCount; i++) + { + CVoice voice = _Song.Notes.GetVoice(i); + if (_Song.Notes.VoiceCount > 1) + sw.WriteLine("P" + Math.Pow(2, i)); + bool firstLine = true; + int currentBeat = 0; + foreach (CSongLine line in voice.Lines) + { + if (!firstLine) + { + string lineTxt = "- " + (line.StartBeat - currentBeat); + if (_Song.Relative) + { + lineTxt += " " + (line.FirstNoteBeat - currentBeat); + currentBeat = line.FirstNoteBeat; + } + sw.WriteLine(lineTxt); + } + else + firstLine = false; + foreach (CSongNote note in line.Notes) + { + string tag; + switch (note.Type) + { + case ENoteType.Normal: + tag = ":"; + break; + case ENoteType.Golden: + tag = "*"; + break; + case ENoteType.Freestyle: + tag = "F"; + break; + default: + throw new NotImplementedException("Note type " + note.Type); + } + sw.WriteLine(tag + " " + (note.StartBeat - currentBeat) + " " + note.Duration + " " + note.Tone + " " + note.Text); + } + } + } + } + + public bool SaveFile(string filePath) + { + try + { + TextWriter sw = new StreamWriter(filePath, false, _Song.Encoding); + _WriteHeader(sw); + _WriteNotes(sw); + } + catch (Exception e) + { + CBase.Log.LogError("Unhandled exception while writing " + filePath + ": " + e); + return false; + } + return true; + } } } } \ No newline at end of file