Example #1
0
        // ReSharper disable InconsistentNaming
        private static void Main(string[] args)
        // ReSharper restore InconsistentNaming
        {
#if !DEBUG
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
#endif
            AppDomain.CurrentDomain.AssemblyResolve += _AssemblyResolver;
            COSFunctions.AddEnvironmentPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libs\\unmanaged\\"));
            #if ARCH_X86
            COSFunctions.AddEnvironmentPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libs\\unmanaged\\x86\\"));
#endif
#if ARCH_X64
            COSFunctions.AddEnvironmentPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libs\\unmanaged\\x64\\"));
#endif


            // Close program if there is another instance running
            if (!_EnsureSingleInstance())
            {
                return;
            }
#if !DEBUG
            try
            {
                _Run(args);
            }
            catch (Exception e)
            {
                CLog.Fatal(e, "Unhandled error: {ErrorMessage}", CLog.Params(e.Message));
            }
#else
            _Run(args);
#endif
            _CloseProgram();
        }
Example #2
0
        /// <summary>
        ///     Loads the currently selected theme trying all others if current theme failed loading<br />
        ///     Therefore CConfig.Theme/Skin might be changed!<br />
        ///     Closes the program on failure!
        /// </summary>
        public static void Load()
        {
            CTheme theme = _Themes.FirstOrDefault(th => th is CBaseTheme && th.Name == CConfig.Config.Theme.Theme) ?? _Themes.FirstOrDefault(th => th is CBaseTheme);

            while (theme != null)
            {
                if (theme.Load())
                {
                    break;
                }
                theme.Unload();
                CLog.Error("Failed to load theme {ThemeName}! Removing...", CLog.Params(theme.Name, theme), true);
                _Themes.Remove(theme);
                theme = _Themes.FirstOrDefault(th => th is CBaseTheme);
            }
            CurrentThemes.Add(-1, theme);
            if (theme == null)
            {
                CLog.Fatal("No themes found! Cannot continue!");
            }
            else
            {
                CConfig.Config.Theme.Theme = theme.Name;
                CConfig.Config.Theme.Skin  = theme.CurrentSkin.Name;
                int[] ids = _Themes.Select(th => th.PartyModeID).Distinct().ToArray();
                foreach (int id in ids.Where(id => id >= 0))
                {
                    LoadPartymodeTheme(id);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Uploads a log to a new anonymous gist.
        /// </summary>
        /// <param name="log">The log that should be uploaded.</param>
        /// <param name="lastError">The error message displayed to the user (if available).</param>
        /// <returns>The link to the uploaded file.</returns>
        private async Task <string> _UploadLogToGist(string log, string lastError = "not available")
        {
            string json = JsonConvert.SerializeObject(new CGistCreateData()
            {
                Description = $"An { (_Crash ? "crash" : "error") } log submission for { _VocaluxeVersionTag }",
                Public      = false,
                Files       = new Dictionary <string, CGistFileData>()
                {
                    {
                        "Vocaluxe.log",
                        new CGistFileData()
                        {
                            Content = log
                        }
                    },
                    {
                        "LastError.txt",
                        new CGistFileData()
                        {
                            Content = lastError
                        }
                    }
                }
            });

            var    content        = new StringContent(json, Encoding.UTF8, "application/json");
            string responseString = "";

            try
            {
                var response = await _Client.PostAsync("https://api.github.com/gists", content);

                responseString = await response.Content.ReadAsStringAsync();
            }
            catch (HttpRequestException e)
            {
                CLog.Error(e, "Couldn't upload log", show: true, propertyValues: CLog.Params(json));
            }

            return(_GetGistUrlRegex.Match(responseString)?.Groups[1]?.Value ?? "");
        }
Example #4
0
        public override bool Init()
        {
            string oldDBFilePath = Path.Combine(CSettings.DataFolder, CSettings.FileNameOldHighscoreDB);

            if (File.Exists(oldDBFilePath))
            {
                if (File.Exists(_FilePath))
                {
                    if (!_CreateOrConvert(oldDBFilePath))
                    {
                        CLog.Fatal("Cannot init Highscore DB: Error opening old database: {DBFile}" + CLog.Params(oldDBFilePath));
                        return(false);
                    }
                    if (!_CreateOrConvert(_FilePath))
                    {
                        CLog.Fatal("Cannot init Highscore DB: Error opening database: {DBFile}", CLog.Params(_FilePath));
                        return(false);
                    }
                    if (!_ImportData(oldDBFilePath))
                    {
                        CLog.Fatal("Cannot init Highscore DB: Error importing data");
                        return(false);
                    }
                }
                else
                {
                    File.Copy(oldDBFilePath, _FilePath);
                    if (!_CreateOrConvert(_FilePath))
                    {
                        CLog.Fatal("Cannot init Highscore DB: Error opening database: {DBFile}" + CLog.Params(_FilePath));
                        return(false);
                    }
                }
                File.Delete(oldDBFilePath);
            }
            else if (!_CreateOrConvert(_FilePath))
            {
                CLog.Fatal("Cannot init Highscore DB: Error opening database: {DBFile}", CLog.Params(_FilePath));
                return(false);
            }
            return(true);
        }
Example #5
0
        private static void _Run(string[] args)
        {
            Application.DoEvents();

            try
            {
                // Create data folder
                Directory.CreateDirectory(CSettings.DataFolder);

                // Init Log
                CLog.Init(CSettings.FolderNameLogs,
                          CSettings.FileNameMainLog,
                          CSettings.FileNameSongLog,
                          CSettings.FileNameCrashMarker,
                          CSettings.GetFullVersionText(),
                          CReporter.ShowReporterFunc,
                          ELogLevel.Information);

                if (!CProgrammHelper.CheckRequirements())
                {
                    return;
                }
                CProgrammHelper.Init();

                using (CBenchmark.Time("Init Program"))
                {
                    CMain.Init();
                    Application.DoEvents();

                    // Init Language
                    using (CBenchmark.Time("Init Language"))
                    {
                        if (!CLanguage.Init())
                        {
                            throw new CLoadingException("Language");
                        }
                    }

                    Application.DoEvents();

                    // load config
                    using (CBenchmark.Time("Init Config"))
                    {
                        CConfig.LoadCommandLineParams(args);
                        CConfig.UseCommandLineParamsBefore();
                        CConfig.Init();
                        CConfig.UseCommandLineParamsAfter();
                    }

                    // Create folders
                    CSettings.CreateFolders();

                    _SplashScreen = new CSplashScreen();
                    Application.DoEvents();

                    // Init Draw
                    using (CBenchmark.Time("Init Draw"))
                    {
                        if (!CDraw.Init())
                        {
                            throw new CLoadingException("drawing");
                        }
                    }

                    Application.DoEvents();

                    // Init Playback
                    using (CBenchmark.Time("Init Playback"))
                    {
                        if (!CSound.Init())
                        {
                            throw new CLoadingException("playback");
                        }
                    }

                    Application.DoEvents();

                    // Init Record
                    using (CBenchmark.Time("Init Record"))
                    {
                        if (!CRecord.Init())
                        {
                            throw new CLoadingException("record");
                        }
                    }

                    Application.DoEvents();

                    // Init VideoDecoder
                    using (CBenchmark.Time("Init Videodecoder"))
                    {
                        if (!CVideo.Init())
                        {
                            throw new CLoadingException("video");
                        }
                    }

                    Application.DoEvents();

                    // Init Database
                    using (CBenchmark.Time("Init Database"))
                    {
                        if (!CDataBase.Init())
                        {
                            throw new CLoadingException("database");
                        }
                    }

                    Application.DoEvents();

                    //Init Webcam
                    using (CBenchmark.Time("Init Webcam"))
                    {
                        if (!CWebcam.Init())
                        {
                            throw new CLoadingException("webcam");
                        }
                    }

                    Application.DoEvents();

                    // Init Background Music
                    using (CBenchmark.Time("Init Background Music"))
                    {
                        CBackgroundMusic.Init();
                    }

                    Application.DoEvents();

                    // Init Profiles
                    using (CBenchmark.Time("Init Profiles"))
                    {
                        CProfiles.Init();
                    }

                    Application.DoEvents();

                    // Init Fonts
                    using (CBenchmark.Time("Init Fonts"))
                    {
                        if (!CFonts.Init())
                        {
                            throw new CLoadingException("fonts");
                        }
                    }

                    Application.DoEvents();

                    // Theme System
                    using (CBenchmark.Time("Init Theme"))
                    {
                        if (!CThemes.Init())
                        {
                            throw new CLoadingException("theme");
                        }
                    }

                    using (CBenchmark.Time("Load Theme"))
                    {
                        CThemes.Load();
                    }

                    Application.DoEvents();

                    // Load Cover
                    using (CBenchmark.Time("Init Cover"))
                    {
                        if (!CCover.Init())
                        {
                            throw new CLoadingException("covertheme");
                        }
                    }

                    Application.DoEvents();

                    // Init Screens
                    using (CBenchmark.Time("Init Screens"))
                    {
                        CGraphics.Init();
                    }

                    Application.DoEvents();

                    // Init Server
                    using (CBenchmark.Time("Init Server"))
                    {
                        CVocaluxeServer.Init();
                    }

                    Application.DoEvents();

                    // Init Input
                    using (CBenchmark.Time("Init Input"))
                    {
                        CController.Init();
                        CController.Connect();
                    }

                    Application.DoEvents();

                    // Init Game
                    using (CBenchmark.Time("Init Game"))
                    {
                        CGame.Init();
                        CProfiles.Update();
                        CConfig.UsePlayers();
                    }

                    Application.DoEvents();

                    // Init Party Modes
                    using (CBenchmark.Time("Init Party Modes"))
                    {
                        if (!CParty.Init())
                        {
                            throw new CLoadingException("Party Modes");
                        }
                    }

                    Application.DoEvents();
                    //Only reasonable point to call GC.Collect() because initialization may cause lots of garbage
                    //Rely on GC doing its job afterwards and call Dispose methods where appropriate
                    GC.Collect();
                }
            }
            catch (Exception e)
            {
                CLog.Error(e, "Error on start up: {ExceptionMessage}", CLog.Params(e.Message), show: true);
                if (_SplashScreen != null)
                {
                    _SplashScreen.Close();
                }
                _CloseProgram();
                return;
            }
            Application.DoEvents();

            // Start Main Loop
            if (_SplashScreen != null)
            {
                _SplashScreen.Close();
            }

            CDraw.MainLoop();
        }
Example #6
0
        private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
        {
            var e = (Exception)args.ExceptionObject;

            CLog.Fatal(e, "Unhandled exception: {ExceptionMessage}", CLog.Params(e.Message));
        }
Example #7
0
        public virtual void LoadTheme(string xmlPath)
        {
            ThemePath = xmlPath;

            string file = Path.Combine(xmlPath, ThemeName + ".xml");

            try
            {
                CXmlDeserializer deserializer = new CXmlDeserializer(new CLoadThemeErrorHandler());
                Theme = deserializer.Deserialize <SThemeScreen>(file);

                foreach (SThemeBackground bg in Theme.Backgrounds)
                {
                    _AddBackground(new CBackground(bg, PartyModeID), bg.Name);
                }

                foreach (SThemeButton bt in Theme.Buttons)
                {
                    _AddButton(new CButton(bt, PartyModeID), bt.Name);
                }

                foreach (SThemeEqualizer eq in Theme.Equalizers)
                {
                    _AddEqualizer(new CEqualizer(eq, PartyModeID), eq.Name);
                }

                foreach (SThemeLyrics ly in Theme.Lyrics)
                {
                    _AddLyric(new CLyric(ly, PartyModeID), ly.Name);
                }

                foreach (SThemeNameSelection ns in Theme.NameSelections)
                {
                    _AddNameSelection(new CNameSelection(ns, PartyModeID), ns.Name);
                }

                foreach (SThemeParticleEffect pe in Theme.ParticleEffects)
                {
                    _AddParticleEffect(new CParticleEffect(pe, PartyModeID), pe.Name);
                }

                foreach (SThemePlaylist pl in Theme.Playlists)
                {
                    _AddPlaylist(new CPlaylist(pl, PartyModeID), pl.Name);
                }

                foreach (SThemeProgressBar pb in Theme.ProgressBars)
                {
                    _AddProgressBar(new CProgressBar(pb, PartyModeID), pb.Name);
                }

                foreach (SThemeScreenSetting ss in Theme.ScreenSettings)
                {
                    _AddScreenSetting(new CScreenSetting(ss, PartyModeID), ss.Name);
                }

                foreach (SThemeSelectSlide sl in Theme.SelectSlides)
                {
                    _AddSelectSlide(new CSelectSlide(sl, PartyModeID), sl.Name);
                }

                foreach (SThemeSingBar sb in Theme.SingNotes)
                {
                    _AddSingNote(new CSingNotes(sb, PartyModeID), sb.Name);
                }

                foreach (SThemeSongMenu sm in Theme.SongMenus)
                {
                    _AddSongMenu(CSongMenuFactory.CreateSongMenu(sm, PartyModeID), sm.Name);
                }

                foreach (SThemeStatic st in Theme.Statics)
                {
                    _AddStatic(new CStatic(st, PartyModeID), st.Name);
                }

                foreach (SThemeText te in Theme.Texts)
                {
                    _AddText(new CText(te, PartyModeID), te.Name);
                }

                if (_ScreenVersion != Theme.Informations.ScreenVersion)
                {
                    string msg = "Can't load screen file of screen \"" + ThemeName + "\", ";
                    if (Theme.Informations.ScreenVersion < _ScreenVersion)
                    {
                        msg += "the file ist outdated! ";
                    }
                    else
                    {
                        msg += "the file is for newer program versions! ";
                    }

                    msg += "Current screen version is " + _ScreenVersion;
                    CLog.Error(msg);
                }
                foreach (IThemeable el in _Elements.Select(_GetElement).OfType <IThemeable>())
                {
                    el.LoadSkin();
                }
            }
            catch (Exception e)
            {
                CLog.Fatal(e, "Error while reading {ThemeName}.xml", CLog.Params(ThemeName), true);
            }
        }
Example #8
0
            public bool ReadHeader(bool useSetEncoding = false)
            {
                string filePath = Path.Combine(_Song.Folder, _Song.FileName);

                if (!File.Exists(filePath))
                {
                    return(false);
                }

                _Song.Languages.Clear();
                _Song.Genres.Clear();
                _Song.UnknownTags.Clear();
                _Song.BackgroundFileNames.Clear();
                _Song._Comment          = "";
                _Song.ManualEncoding    = false;
                _Song.Medley.Source     = EDataSource.None;
                _Song._CalculateMedley  = true;
                _Song.Preview.Source    = EDataSource.None;
                _Song.ShortEnd.Source   = EDataSource.None;
                _Song.Start             = 0;
                _Song.VideoGap          = 0;
                _Song.Preview.StartTime = 0;

                var          headerFlags = new EHeaderFlags();
                StreamReader sr          = null;

                _LineNr = 0;
                try
                {
                    sr = new StreamReader(filePath, _Song.Encoding, true);
                    while (!sr.EndOfStream)
                    {
                        string line = sr.ReadLine();
                        _LineNr++;
                        if (line == "")
                        {
                            continue;
                        }
                        if (!line[0].Equals('#'))
                        {
                            break;
                        }

                        int pos = line.IndexOf(":", StringComparison.Ordinal);

                        if (pos <= 1)
                        {
                            _Song.UnknownTags.Add(line);
                            continue;
                        }
                        string identifier = line.Substring(1, pos - 1).Trim().ToUpper();
                        if (identifier.Contains(" "))
                        {
                            _Song.UnknownTags.Add(line);
                            continue;
                        }
                        string value = line.Substring(pos + 1).Trim();

                        if (value == "")
                        {
                            _Song.UnknownTags.Add(line);
                            CLog.CSongLog.Warning("[{SongFileName}] Empty value skipped", CLog.Params(_Song.FileName));
                            continue;
                        }

                        switch (identifier)
                        {
                        case "ENCODING":
                            Encoding newEncoding = value.GetEncoding();
                            _Song.ManualEncoding = true;
                            if (!newEncoding.Equals(sr.CurrentEncoding))
                            {
                                if (useSetEncoding)
                                {
                                    CLog.CSongLog.Warning("[{SongFileName}] Duplicate encoding ignored", CLog.Params(_Song.FileName));
                                    continue;
                                }
                                sr.Dispose();
                                sr             = null;
                                _Song.Encoding = newEncoding;
                                return(ReadHeader(true));
                            }
                            break;

                        case "TITLE":
                            _Song.Title  = value;
                            headerFlags |= EHeaderFlags.Title;
                            break;

                        case "ARTIST":
                            _Song.Artist = value;
                            headerFlags |= EHeaderFlags.Artist;
                            break;

                        case "TITLE-ON-SORTING":
                            _Song.TitleSorting = value;
                            break;

                        case "ARTIST-ON-SORTING":
                            _Song.ArtistSorting = value;
                            break;

                        case "CREATOR":
                        case "AUTHOR":
                        case "AUTOR":
                            _Song.Creator = value;
                            break;

                        case "VERSION":
                            _Song.Version = value;
                            break;

                        case "SOURCE":
                        case "YOUTUBE":
                            _Song.Source = value;
                            break;

                        case "LENGTH":
                            _Song.Length = value;
                            break;

                        case "MP3":
                            if (File.Exists(Path.Combine(_Song.Folder, value)))
                            {
                                _Song.MP3FileName = value;
                                headerFlags      |= EHeaderFlags.MP3;
                            }
                            else
                            {
                                CLog.CSongLog.Error("[{SongFileName}] Can't find audio file: {AudioFile}", CLog.Params(_Song.FileName, Path.Combine(_Song.Folder, value)));
                                return(false);
                            }
                            break;

                        case "BPM":
                            if (CHelper.TryParse(value, out _Song.BPM))
                            {
                                _Song.BPM   *= _BPMFactor;
                                headerFlags |= EHeaderFlags.BPM;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid BPM value: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "EDITION":
                            if (value.Length > 1)
                            {
                                _Song.Editions.Add(value);
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid edition: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "GENRE":
                            if (value.Length > 1)
                            {
                                _Song.Genres.Add(value);
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid genre: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "ALBUM":
                            _Song.Album = value;
                            break;

                        case "YEAR":
                            int num;
                            if (value.Length == 4 && int.TryParse(value, out num) && num > 0)
                            {
                                _Song.Year = value;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid year: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "LANGUAGE":
                            if (value.Length > 1)
                            {
                                _Song.Languages.Add(_UnifyLanguage(value));
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid language: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "COMMENT":
                            if (!String.IsNullOrEmpty(_Song._Comment))
                            {
                                _Song._Comment += "\r\n";
                            }
                            _Song._Comment += value;
                            break;

                        case "GAP":
                            if (CHelper.TryParse(value, out _Song.Gap))
                            {
                                _Song.Gap /= 1000f;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid gap: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "COVER":
                            if (File.Exists(Path.Combine(_Song.Folder, value)))
                            {
                                _Song.CoverFileName = value;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Can't find cover file: {MissingFile}", CLog.Params(_Song.FileName, Path.Combine(_Song.Folder, value)));
                            }
                            break;

                        case "BACKGROUND":
                            if (File.Exists(Path.Combine(_Song.Folder, value)))
                            {
                                _Song.BackgroundFileNames.Add(value);
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Can't find background file: {MissingFile}", CLog.Params(_Song.FileName, Path.Combine(_Song.Folder, value)));
                            }
                            break;

                        case "VIDEO":
                            if (File.Exists(Path.Combine(_Song.Folder, value)))
                            {
                                _Song.VideoFileName = value;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Can't find video file: {MissingFile}", CLog.Params(_Song.FileName, Path.Combine(_Song.Folder, value)));
                            }
                            break;

                        case "VIDEOGAP":
                            if (!CHelper.TryParse(value, out _Song.VideoGap))
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid videogap: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "VIDEOASPECT":
                            if (!CHelper.TryParse(value, out _Song.VideoAspect, true))
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid videoaspect: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "START":
                            if (!CHelper.TryParse(value, out _Song.Start))
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid start: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "END":
                            if (CHelper.TryParse(value, out _Song.Finish))
                            {
                                _Song.Finish /= 1000f;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid end: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "PREVIEWSTART":
                            if (CHelper.TryParse(value, out _Song.Preview.StartTime) && _Song.Preview.StartTime >= 0f)
                            {
                                _Song.Preview.Source = EDataSource.Tag;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid previewstart: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "PREVIEW":
                            if (CHelper.TryParse(value, out _Song.Preview.StartTime) && _Song.Preview.StartTime >= 0f)
                            {
                                //This is stored in ms not like PREVIEWSTART!
                                _Song.Preview.StartTime /= 1000f;
                                _Song.Preview.Source     = EDataSource.Tag;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid previewstart: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "MEDLEYSTARTBEAT":
                            if (int.TryParse(value, out _Song.Medley.StartBeat))
                            {
                                headerFlags |= EHeaderFlags.MedleyStartBeat;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid medleystartbeat: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "MEDLEYENDBEAT":
                            if (int.TryParse(value, out _Song.Medley.EndBeat))
                            {
                                headerFlags |= EHeaderFlags.MedleyEndBeat;
                            }
                            else
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Invalid medleyendbeat: {Value}", CLog.Params(_Song.FileName, value));
                            }
                            break;

                        case "ENDSHORT":
                            if ((headerFlags & EHeaderFlags.BPM) != 0)
                            {
                                int endTime;
                                if (int.TryParse(value, out endTime) || endTime < 0)
                                {
                                    _Song.ShortEnd.EndBeat = (int)CBase.Game.GetBeatFromTime(endTime / 1000f, _Song.BPM, _Song.Gap);
                                    _Song.ShortEnd.Source  = EDataSource.Tag;
                                }
                                else
                                {
                                    CLog.CSongLog.Warning("[{SongFileName}] Invalid shortendbeat: {Value}", CLog.Params(_Song.FileName, value));
                                }
                            }
                            break;

                        case "CALCMEDLEY":
                            if (value.ToUpper() == "OFF")
                            {
                                _Song._CalculateMedley = false;
                            }
                            break;

                        case "RELATIVE":
                            if (value.ToUpper() == "YES")
                            {
                                _Song.Relative = true;
                            }
                            break;

                        case "RESOLUTION":
                        case "NOTESGAP":
                            //Outdated/not used
                            _Song.UnknownTags.Add(line);
                            break;

                        default:
                            if (identifier.StartsWith("DUETSINGER"))
                            {
                                identifier = identifier.Substring(10);
                                if (!identifier.StartsWith("P"))     // fix for missing "P"
                                {
                                    identifier = "P" + identifier;
                                }
                            }
                            if (identifier.StartsWith("P"))
                            {
                                int player;
                                if (int.TryParse(identifier.Substring(1).Trim(), out player))
                                {
                                    foreach (int curPlayer in player.GetSetBits())
                                    {
                                        _Song.Notes.VoiceNames[curPlayer] = value;
                                    }
                                }
                            }
                            else
                            {
                                _Song.UnknownTags.Add(line);
                                CLog.CSongLog.Warning("[{SongFileName}] Unknown tag: #{Identifier}", CLog.Params(_Song.FileName, identifier));
                            }

                            break;
                        }
                    } //end of while

                    if (sr.EndOfStream)
                    {
                        //No other data then header
                        CLog.CSongLog.Error("[{SongFileName}] Lyrics/Notes missing", CLog.Params(_Song.FileName));

                        return(false);
                    }

                    if ((headerFlags & EHeaderFlags.Title) == 0)
                    {
                        CLog.CSongLog.Error("[{SongFileName}] Title tag missing", CLog.Params(_Song.FileName));
                        return(false);
                    }

                    if ((headerFlags & EHeaderFlags.Artist) == 0)
                    {
                        CLog.CSongLog.Error("[{SongFileName}] Artist tag missing", CLog.Params(_Song.FileName));
                        return(false);
                    }

                    if ((headerFlags & EHeaderFlags.MP3) == 0)
                    {
                        CLog.CSongLog.Error("[{SongFileName}] MP3 tag missing", CLog.Params(_Song.FileName));
                        return(false);
                    }

                    if ((headerFlags & EHeaderFlags.BPM) == 0)
                    {
                        CLog.CSongLog.Error("[{SongFileName}] BPM tag missing", CLog.Params(_Song.FileName));
                        return(false);
                    }

                    #region check medley tags
                    if ((headerFlags & EHeaderFlags.MedleyStartBeat) != 0 && (headerFlags & EHeaderFlags.MedleyEndBeat) != 0)
                    {
                        if (_Song.Medley.StartBeat > _Song.Medley.EndBeat)
                        {
                            CLog.CSongLog.Error("[{SongFileName}] MedleyStartBeat is bigger than MedleyEndBeat in file: {StartBeat} > {EndBeat}", CLog.Params(_Song.FileName, _Song.Medley.StartBeat > _Song.Medley.EndBeat));
                            headerFlags = headerFlags - EHeaderFlags.MedleyStartBeat - EHeaderFlags.MedleyEndBeat;
                        }
                    }

                    if (_Song.Preview.Source == EDataSource.None)
                    {
                        //PreviewStart is not set or <=0
                        _Song.Preview.StartTime = (headerFlags & EHeaderFlags.MedleyStartBeat) != 0 ? CBase.Game.GetTimeFromBeats(_Song.Medley.StartBeat, _Song.BPM) : 0f;
                        // ReSharper disable CompareOfFloatsByEqualityOperator
                        _Song.Preview.Source = _Song.Preview.StartTime == 0 ? EDataSource.None : EDataSource.Calculated;
                        // ReSharper restore CompareOfFloatsByEqualityOperator
                    }

                    if ((headerFlags & EHeaderFlags.MedleyStartBeat) != 0 && (headerFlags & EHeaderFlags.MedleyEndBeat) != 0)
                    {
                        _Song.Medley.Source      = EDataSource.Tag;
                        _Song.Medley.FadeInTime  = CBase.Settings.GetDefaultMedleyFadeInTime();
                        _Song.Medley.FadeOutTime = CBase.Settings.GetDefaultMedleyFadeOutTime();
                    }
                    #endregion check medley tags
                }
                catch (Exception e)
                {
                    if (sr != null)
                    {
                        sr.Dispose();
                    }
                    CLog.CSongLog.Error(e, "[{SongFileName}] Error reading txt header with Message: {ExceptionMessage}", CLog.Params(e.Message, _Song.FileName));
                    return(false);
                }
                _Song.Encoding = sr.CurrentEncoding;
                sr.Dispose();
                _Song._CheckFiles();

                CBase.DataBase.GetDataBaseSongInfos(_Song.Artist, _Song.Title, out _Song.NumPlayed, out _Song.DateAdded, out _Song.DataBaseSongID);

                //Before saving this tags to .txt: Check, if ArtistSorting and Artist are equal, then don't save this tag.
                if (String.IsNullOrEmpty(_Song.ArtistSorting))
                {
                    _Song.ArtistSorting = _Song.Artist;
                }

                if (String.IsNullOrEmpty(_Song.TitleSorting))
                {
                    _Song.TitleSorting = _Song.Title;
                }

                return(true);
            }
Example #9
0
            /// <summary>
            ///     Read notes. First try to read notes normally (assume standard)<br />
            ///     If there are more than _MaxZeroNoteCt with length &lt; 1,  try to read notes adding 1 to length<br />
            ///     Then if there are more than _MaxOverlapNoteCt fallback to first version ignoring notes with length &lt; 1
            /// </summary>
            /// <param name="forceReload"></param>
            /// <returns></returns>
            public bool ReadNotes(bool forceReload = false)
            {
                //Skip loading if already done and no reload is forced
                if (_Song.NotesLoaded && !forceReload)
                {
                    return(true);
                }

                string filePath = Path.Combine(_Song.Folder, _Song.FileName);

                if (!File.Exists(filePath))
                {
                    CLog.CSongLog.Error("[{SongFileName}] The file songfile does not exist", CLog.Params(_Song.FileName));
                    return(false);
                }

                int       currentBeat = 0;     //Used for relative songs
                CSongNote lastNote    = null;  //Holds last parsed note. Get's reset on player change
                bool      endFound    = false; // True if end tag was found

                int player = 1;

                _LineNr = 0;

                char[] trimChars  = { ' ', ':' };
                char[] splitChars = { ' ' };

                var changesMade = new CAutoChanges();

                StreamReader sr = null;

                try
                {
                    sr = new StreamReader(filePath, _Song.Encoding, true);

                    _Song.Notes.Reset();

                    //Search for Note Beginning
                    while (!sr.EndOfStream && !endFound)
                    {
                        string line = sr.ReadLine();
                        _LineNr++;

                        if (String.IsNullOrEmpty(line))
                        {
                            continue;
                        }

                        char tag = line[0];
                        //Remove tag and potential space
                        line = (line.Length >= 2 && line[1] == ' ') ? line.Substring(2) : line.Substring(1);

                        int beat, length;
                        switch (tag)
                        {
                        case '#':
                            continue;

                        case 'E':
                            endFound = true;
                            break;

                        case 'P':
                            line = line.Trim(trimChars);

                            if (!int.TryParse(line, out player))
                            {
                                CLog.CSongLog.Error("[{SongFileName}] Wrong or missing number after \"P\" (in line {LineNr})", CLog.Params(_Song.FileName, _LineNr));
                                return(false);
                            }
                            currentBeat = 0;
                            lastNote    = null;
                            break;

                        case ':':
                        case '*':
                        case 'F':
                        case 'R':       // Read R (RAP) and G (Golden RAP) notes as Freestyle notes currently. Final implementation needed!
                        case 'G':       // Read R (RAP) and G (Golden RAP) notes as Freestyle notes currently. Final implementation needed!
                            string[] noteData = line.Split(splitChars, 4);
                            if (noteData.Length < 4)
                            {
                                if (noteData.Length == 3)
                                {
                                    CLog.CSongLog.Warning("[{SongFileName}] Ignored note without text (in line {LineNr})", CLog.Params(_Song.FileName, _LineNr));
                                    changesMade.NoTextNoteCt++;
                                    continue;
                                }
                                CLog.CSongLog.Error("[{SongFileName}] Invalid note found (in line {LineNr}): {noteData}", CLog.Params(_Song.FileName, _LineNr, noteData));
                                sr.Dispose();
                                return(false);
                            }
                            int tone;
                            if (!int.TryParse(noteData[0], out beat) || !int.TryParse(noteData[1], out length) || !int.TryParse(noteData[2], out tone))
                            {
                                CLog.CSongLog.Error("[{SongFileName}] Invalid note found (non-numeric values) (in line {LineNr}): {noteData}", CLog.Params(_Song.FileName, _LineNr, noteData));
                                sr.Dispose();
                                return(false);
                            }
                            string text = noteData[3].TrimMultipleWs();
                            if (text == "")
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Ignored note without text (in line {LineNr})", CLog.Params(_Song.FileName, _LineNr));
                                changesMade.NoTextNoteCt++;
                                continue;
                            }
                            if (_CurrentReadMode == ENoteReadMode.ZeroBased)
                            {
                                length++;
                            }
                            if (length < 1)
                            {
                                changesMade.ZeroLengthNoteCt++;
                                if (_CurrentReadMode == ENoteReadMode.Normal && changesMade.ZeroLengthNoteCt > _MaxZeroNoteCt && changesMade.OverlapNoteCt <= _MaxOverlapNoteCt)
                                {
                                    CLog.CSongLog.Warning("[{SongFileName}] Found more than {MaxZeroNoteCt} notes with length < 1. Trying alternative read mode.", CLog.Params(_Song.FileName, _MaxZeroNoteCt));
                                    _CurrentReadMode = ENoteReadMode.ZeroBased;
                                    sr.Dispose();
                                    return(ReadNotes(true));
                                }
                                CLog.CSongLog.Warning("[{SongFileName}] Ignored note with length < 1 (in line {LineNr})", CLog.Params(_Song.FileName, _LineNr));
                            }
                            else
                            {
                                ENoteType noteType;

                                if (tag.Equals('*'))
                                {
                                    noteType = ENoteType.Golden;
                                }
                                else if (tag.Equals('F') || tag.Equals('R') || tag.Equals('G'))      // Read R (RAP) and G (Golden RAP) notes as Freestyle notes currently. Final implementation needed!
                                {
                                    noteType = ENoteType.Freestyle;
                                }
                                else
                                {
                                    noteType = ENoteType.Normal;
                                }

                                if (_Song.Relative)
                                {
                                    beat += currentBeat;
                                }

                                bool ignored = false;
                                foreach (int curPlayer in player.GetSetBits())
                                {
                                    //Create the note here as we want independent instances in the lines. Otherwhise we can't modify them later
                                    lastNote = new CSongNote(beat, length, tone, text, noteType);
                                    if (!_AddNote(curPlayer, lastNote))
                                    {
                                        if (!ignored)
                                        {
                                            ignored = true;
                                            changesMade.OverlapNoteCt++;
                                            if (changesMade.OverlapNoteCt > _MaxOverlapNoteCt && _CurrentReadMode == ENoteReadMode.ZeroBased)
                                            {
                                                CLog.CSongLog.Warning("[{SongFileName}] Found more than {MaxOverlapNoteCt} overlapping notes. Using standard mode.", CLog.Params(_Song.FileName, _MaxOverlapNoteCt));
                                                _CurrentReadMode = ENoteReadMode.OneBased;
                                                sr.Dispose();
                                                return(ReadNotes(true));
                                            }
                                        }
                                        CLog.CSongLog.Warning("[{SongFileName}] Ignored note for player {CurrentPlayerNumber} because it overlaps with other note (in line {LineNr})", CLog.Params(_Song.FileName, (curPlayer + 1), _LineNr));
                                    }
                                }
                            }
                            break;

                        case '-':
                            string[] lineBreakData = line.Split(splitChars);
                            if (lineBreakData.Length < 1)
                            {
                                CLog.CSongLog.Error("[{SongFileName}] Invalid line break found (No beat) (in line {LineNr}): {LineBreakData}", CLog.Params(_Song.FileName, _LineNr, lineBreakData));
                                sr.Dispose();
                                return(false);
                            }
                            if (!int.TryParse(lineBreakData[0], out beat))
                            {
                                CLog.CSongLog.Error("[{SongFileName}] Invalid line break found (Non-numeric value) (in line {LineNr}): {LineBreakData}", CLog.Params(_Song.FileName, _LineNr, lineBreakData));
                                sr.Dispose();
                                return(false);
                            }

                            if (_Song.Relative)
                            {
                                beat += currentBeat;
                                if (lineBreakData.Length < 2 || !int.TryParse(lineBreakData[1], out length))
                                {
                                    CLog.CSongLog.Warning("[{SongFileName}] Missing line break length (in line {LineNr}):{LineBreakData}", CLog.Params(_Song.FileName, _LineNr, lineBreakData));
                                    changesMade.NoLengthBreakCt++;
                                    currentBeat = beat;
                                }
                                else
                                {
                                    currentBeat += length;
                                }
                            }

                            if (lastNote != null && beat <= lastNote.EndBeat)
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Line break is before previous note end. Adjusted. (in line {LineNr})", CLog.Params(_Song.FileName, _LineNr));

                                changesMade.AjustedBreakCt++;
                                if (_Song.Relative)
                                {
                                    currentBeat += lastNote.EndBeat - beat + 1;
                                }
                                beat = lastNote.EndBeat + 1;
                            }

                            if (beat < 1)
                            {
                                CLog.CSongLog.Warning("[{SongFileName}] Ignored line break because position is < 1 (in line {LineNr})", CLog.Params(_Song.FileName, _LineNr));
                                changesMade.InvalidPosBreakCt++;
                            }
                            else
                            {
                                foreach (int curPlayer in player.GetSetBits())
                                {
                                    if (!_NewSentence(curPlayer, beat))
                                    {
                                        CLog.CSongLog.Warning("[{SongFileName}] Ignored line break for player {CurPlayerNr} (Overlapping or duplicate) (in line {LineNr})", CLog.Params(_Song.FileName, (curPlayer + 1), _LineNr));
                                    }
                                }
                            }
                            break;

                        default:
                            CLog.CSongLog.Error("[{SongFileName}] Unexpected or missing character ({Tag})", CLog.Params(_Song.FileName, tag));
                            return(false);
                        }
                    }

                    for (int i = 0; i < _Song.Notes.VoiceCount; i++)
                    {
                        CVoice voice      = _Song.Notes.GetVoice(i);
                        int    emptyLines = voice.RemoveEmptyLines();
                        if (emptyLines > 0)
                        {
                            CLog.CSongLog.Warning("[{SongFileName}] Removed {NumEmptyLines} empty lines from P .This often indicates a problem with the line breaks in the file", CLog.Params(_Song.FileName, emptyLines));
                        }
                        voice.UpdateTimings();
                    }
                }
                catch (Exception e)
                {
                    CLog.CSongLog.Error(e, "[{SongFileName}] An unhandled exception occured: {ExceptionMessage}", CLog.Params(_Song.FileName, e.Message));
                    if (sr != null)
                    {
                        sr.Dispose();
                    }
                    return(false);
                }
                sr.Dispose();
                try
                {
                    _Song._CalcMedley();
                    _Song._CheckPreview();
                    _Song._FindShortEnd();
                    _Song.NotesLoaded = true;
                    if (_Song.IsDuet)
                    {
                        _Song._CheckDuet();
                    }
                }
                catch (Exception e)
                {
                    CLog.CSongLog.Error(e, "[{SongFileName}] An unhandled exception occured: {ExceptionMessage}", CLog.Params(_Song.FileName, e.Message));
                    return(false);
                }

                if (changesMade.IsModified)
                {
                    CLog.Warning("Automatic changes have been made to {FilePath} Please check result!\r\n{ChangesMade}", CLog.Params(filePath, changesMade));
                    if (CBase.Config.GetSaveModifiedSongs() == EOffOn.TR_CONFIG_ON)
                    {
                        string name = Path.GetFileNameWithoutExtension(_Song.FileName);
                        _Song.Save(Path.Combine(_Song.Folder, name + ".fix"));
                    }
                }
                return(true);
            }