Example #1
0
        private static void ResetTreeLevel(BeatmapTreeLevel level)
        {
            if (level.Beatmaps.Count > 0)
            {
                //The full path is present so we should dispose of some beatmaps first.
                level.Beatmaps.ForEach(b => Remove(b));

                //Find unique sets
                Dictionary <string, int> setCheck = new Dictionary <string, int>();

                foreach (Beatmap b in level.Beatmaps)
                {
                    if (b.AudioPresent)
                    {
                        setCheck[b.ContainingFolderAbsolute] = 1;
                    }
                    else
                    {
                        TotalAudioOnly--;
                    }
                }

                //Alter some counts.
                TotalUniqueSets -= setCheck.Count;
            }

            if (level.Children.Count > 0)
            {
                level.Children.ForEach(ResetTreeLevel); //propagate down
            }
        }
Example #2
0
 internal BeatmapTreeItem(BeatmapTreeLevel treelevel, int level)
 {
     TreeLevel = treelevel;
     Level     = level;
     PopulateSprites();
     Children = new List <BeatmapTreeItem>();
 }
Example #3
0
        /// <summary>
        /// Get the BeatmapTreeLevel for specified path. Create if not existing.
        /// </summary>
        /// <returns></returns>
        internal static BeatmapTreeLevel GetTreeLevel(string path, bool ignoreExisting = false)
        {
            //check for file existence to avoid directories which could be perceived as filenames causing a problem
            if (path.EndsWith(".osz") && File.Exists(path))
            {
                path = Path.GetDirectoryName(path);
            }

            if (path.StartsWith(BeatmapManager.SongsDirectory))
            {
                path = path.Replace(BeatmapManager.SongsDirectory, string.Empty).TrimStart('\\');
            }

            path = GeneralHelper.PathSanitise(path).TrimStart(Path.DirectorySeparatorChar);

            BeatmapTreeLevel level = Root;

            if (path.Length == 0)
            {
                return(level);
            }

            string[] folders = path.Split(Path.DirectorySeparatorChar);

            if (ignoreExisting && folders.Length < 2) //not in a subfolder
            {
                BeatmapTreeLevel tl = new BeatmapTreeLevel(Path.Combine(BeatmapManager.SongsDirectory, path), level);
                level.Children.Add(tl);
                return(tl);
            }

            switch (folders[folders.Length - 1])
            {
            case "Failed":
            case "SubmissionCache":
                //ignored folders.
                return(null);
            }

            string builtPath = BeatmapManager.SongsDirectory;

            for (int i = 0; i < folders.Length; i++)
            {
                BeatmapTreeLevel tl = level.Children.Find(c => c.Name == folders[i]);

                builtPath = Path.Combine(builtPath, folders[i]);

                if (tl == null)
                {
                    //create one because it doesn't exist.
                    level.Children.Add(tl = new BeatmapTreeLevel(builtPath, level));
                }

                level = tl;
            }

            return(level);
        }
Example #4
0
        internal BeatmapTreeLevel(string name, BeatmapTreeLevel parent, List <Beatmap> beatmaps)
        {
            Name     = name;
            Children = new List <BeatmapTreeLevel>();
            Beatmaps = beatmaps;
            Parent   = parent;

            BeatmapTreeLevel test = this;

            while (test.Parent != null)
            {
                Level++;
                test = test.Parent;
            }
        }
Example #5
0
        internal BeatmapTreeLevel(string fullPath, BeatmapTreeLevel parent)
        {
            string[] pathElements = fullPath.Split(Path.DirectorySeparatorChar);
            Name     = pathElements[pathElements.Length - 1];
            FullPath = fullPath;
            Children = new List <BeatmapTreeLevel>();
            Beatmaps = new List <Beatmap>();
            Parent   = parent;

            BeatmapTreeLevel test = this;

            while (test.Parent != null)
            {
                Level++;
                test = test.Parent;
            }
        }
        internal static bool Initialize(bool force = false)
        {
            //First check we have performed an initial load.
            //If not, try reading from osu!.db, else initialise the list.
            if (Beatmaps != null && Beatmaps.Count != 0 && !force)
            {
                return(false);
            }


            BeatmapsByChecksum = new Dictionary <string, Beatmap>();
            BeatmapsById       = new Dictionary <int, Beatmap>();

            InitialLoadComplete = false;
            Root = new BeatmapTreeLevel(BeatmapManager.SongsDirectory, null);

            databaseDeserialize();

            InitializeMonitor();
            return(true);
        }
Example #7
0
 internal BeatmapTreeLevel(string name, BeatmapTreeLevel parent)
     :
     this(name, parent, new List <Beatmap>())
 {
 }
        internal static void ProcessBeatmaps(bool newFilesOnly = false, bool quickFolderChecks = false)
        {
            SongWatcher.EnableRaisingEvents = false;
            QuickFolderChecks = quickFolderChecks;

            //Doing a full pass over the song folder is an expensive operation.
            //We should only do so if it is requested, or if we can't find the local osu!.db
            if (!newFilesOnly)
            {
                //FULL PROCESS
                Logger.LogPrint(@"_______________ Full process initiated. _______________");

                //Mark every single beatmap as "not found" to begin with, then remove any remaining at the end which were not found.
                Beatmaps.ForEach(b =>
                {
                    b.DatabaseNotFound = true;
                    b.HeadersLoaded    = false;
                });

                Root.Children.Clear();
                Root.Beatmaps.Clear();

                TotalUniqueSets = 0;
                TotalAudioOnly  = 0;

                ProcessFolder(BeatmapManager.SongsDirectory);

                int removed = Beatmaps.RemoveAll(b => b.DatabaseNotFound);

                if (removed > 0)
                {
                    InvokeOnStatusUpdate(string.Format(LocalisationManager.GetString(OsuString.BeatmapManager_RemoveMissingMaps), removed));
                }

                ReloadDictionaries();

                InvokeOnStatusUpdate(string.Format(LocalisationManager.GetString(OsuString.BeatmapManager_LoadedMaps), Beatmaps.Count));
            }
            else
            {
                //PARTIAL PROCESS

                for (int j = 0; j < ChangedPackages.Count; j++)
                {
                    string package = ChangedPackages[j];

                    if (!File.Exists(package))
                    {
                        //Package is no longer with us :(

                        Logger.Log($@"{package} could not be loaded. It no longer exists.");

                        List <Beatmap> matches = Beatmaps.FindAll(b => b.ContainingFolderAbsolute == package);
                        matches.ForEach(b => Remove(b));

                        continue;
                    }
                    else
                    {
                        BeatmapTreeLevel level = GetTreeLevel(Path.GetDirectoryName(package));
                        if (level != null)
                        {
                            ProcessPackage(package, level);
                        }
                    }
                }

                //Special processing for importing new maps
                //Changed to for loop because foreach was getting modified internally.  not sure how this could happen.
                for (int j = 0; j < ChangedFolders.Count; j++)
                {
                    string folder = ChangedFolders[j];

                    bool folderStillExists = Directory.Exists(folder);

                    if (!folder.StartsWith(BeatmapManager.SongsDirectory))
                    {
                        ProcessBeatmaps();
                        return;
                    }

                    BeatmapTreeLevel level = GetTreeLevel(folder);

                    if (level == null)
                    {
                        continue;
                    }

                    if (level.Children.Count > 0 && folderStillExists)
                    {
                        //ignore this folder change for now?
                        //sure, unless it was deleted.
                        continue;
                    }

                    ResetTreeLevel(level);
                    if (folderStillExists)
                    {
                        ProcessTree(level);
                    }
                    else
                    {
                        if (level.Parent != null)
                        {
                            level.Parent.Children.Remove(level);
                        }
                    }
                }
            }

            if (Current != null && newFilesOnly)
            {
                SetCurrentFromFilename(Current.Filename, false);
            }

            InitialLoadComplete = true;

            SongWatcher.EnableRaisingEvents = true;
        }
        /// <summary>
        /// Process and load a single osz2 package.
        /// </summary>
        private static bool ProcessPackage(string filename, BeatmapTreeLevel treeLevel)
        {
            MapPackage package = Osz2Factory.TryOpen(filename);

            if (package == null)
            {
                NotificationManager.ShowMessage("Error reading " + Path.GetFileName(filename), Color.Red, 4000);
                return(false);
            }

            int mapsLoaded = 0;

            foreach (string file in package.MapFiles)
            {
                Beatmap b = new Beatmap {
                    Filename = file
                };

                if (InitialLoadComplete)
                {
                    int index = Beatmaps.BinarySearch(b);

                    if (index >= 0)
                    {
                        Beatmap found = Beatmaps[index];

                        if (found.InOszContainer)
                        {
                            found.DatabaseNotFound         = false;
                            found.BeatmapPresent           = true;
                            found.ContainingFolderAbsolute = filename;
                            found.InOszContainer           = true;

                            treeLevel.Beatmaps.Add(found);
                            mapsLoaded++;
                            continue;
                        }
                    }
                }

                b.BeatmapSetId = Convert.ToInt32(package.GetMetadata(MapMetaType.BeatmapSetID));
                b.BeatmapId    = package.GetIDByMap(file);

                b.ContainingFolderAbsolute = filename;
                b.InOszContainer           = true;
                b.AudioPresent             = true;
                b.BeatmapPresent           = true;

                b.ProcessHeaders();
                if (!b.HeadersLoaded)
                {
                    //failed?
                    continue;
                }

                b.NewFile = true;
                NewFilesList.Add(b);

                if (!b.AudioPresent && !b.BeatmapPresent)
                {
                    continue;
                }

                Add(b);
                lastAddedMap = b;
                treeLevel.Beatmaps.Add(b);
                mapsLoaded++;
            }

            Osz2Factory.CloseMapPackage(package);
            //package.Unlock();

            return(mapsLoaded > 0);
        }
        internal static void ProcessTree(BeatmapTreeLevel currentLevel)
        {
            if (currentLevel == null)
            {
                return;
            }

            //never process songs if we aren't the lead spectator.
            if (GameBase.Tournament && !GameBase.TournamentManager)
            {
                return;
            }

            //the number of stray .osu files found in this tree level.
            int strayBeatmapCount = 0;

            string folder = currentLevel.FullPath;

            if (currentLevel != Root)
            {
                InvokeOnStatusUpdate(folder.Replace(BeatmapManager.SongsDirectory, string.Empty).Trim('\\', '/'));
            }

#if !DEBUG
            try
            {
#endif

            bool isTopFolder = folder == BeatmapManager.SongsDirectory;

            if (!isTopFolder && InitialLoadComplete && (Current == null || Current.ContainingFolder == null || Current.ContainingFolderAbsolute != folder))
            {
                string relativeFolder = folder.Replace(SongsDirectory, string.Empty);
                bool   found          = false;

                //avoid hitting the filesystem at all wherever possible
                foreach (Beatmap fb in Beatmaps)
                {
                    if (fb.ContainingFolder != relativeFolder)
                    {
                        continue;
                    }

                    strayBeatmapCount++;
                    if (!fb.InOszContainer)
                    {
                        fb.DatabaseNotFound = false;

                        //we are matching based on filename here.
                        //the folder could have changed, and we need to update this change.
                        fb.ContainingFolderAbsolute = folder;

                        currentLevel.Beatmaps.Add(fb);

                        found = true;
                    }
                }

                if (found)
                {
                    TotalUniqueSets++;
                    return;
                }
            }

            //load osz2 packages
            foreach (string f in Directory.GetFiles(folder, "*.osz2"))
            {
                if (f == "LastUpload.osz2")
                {
                    break;
                }

                if (ProcessPackage(f, currentLevel))
                {
                    TotalUniqueSets++;
                }
            }

            //load osz directories
            foreach (string file in Directory.GetFiles(folder, "*.osu"))
            {
                strayBeatmapCount++;

                Beatmap b = new Beatmap {
                    Filename = Path.GetFileName(file)
                };

                if (InitialLoadComplete)
                {
                    int index = Beatmaps.BinarySearch(b);

                    if (index >= 0)
                    {
                        Beatmap found = Beatmaps[index];

                        //this condition is required to make sure we don't match an osz2 to a folder.
                        //this causes really weird results. this whole process could be improved to avoid this ugliness.
                        if (!found.InOszContainer)
                        {
                            found.DatabaseNotFound = false;
                            found.BeatmapPresent   = true;

                            //we are matching based on filename here.
                            //the folder could have changed, and we need to update this change.
                            found.ContainingFolderAbsolute = folder;

                            currentLevel.Beatmaps.Add(found);

                            continue;
                        }
                    }
                }

                b.ContainingFolderAbsolute = folder;
                try
                {
                    b.ProcessHeaders();
                }
                catch (UnauthorizedAccessException)
                {
                    Logger.Log($@"{b} could not be loaded. Insufficient permissions");
                    continue;
                }

                if (!b.AudioPresent && !b.BeatmapPresent)
                {
                    continue;
                }

                NewFilesList.Add(b);
                b.NewFile = true;

                Add(b);
                lastAddedMap = b;
                currentLevel.Beatmaps.Add(b);
            }

            if (strayBeatmapCount == 0 &&
                (currentLevel == Root ||
                 currentLevel.Parent == Root))
            {
                string   audioFilename = null;
                string[] files         = Directory.GetFiles(folder, @"*.mp3", SearchOption.TopDirectoryOnly);

                if (files.Length > 0)
                {
                    audioFilename = files[0];
                }

                if (audioFilename != null)
                {
                    Beatmap b = new Beatmap
                    {
                        AudioFilename            = Path.GetFileName(audioFilename),
                        Filename                 = Path.GetFileNameWithoutExtension(audioFilename) + @".osu",
                        DisplayTitle             = Path.GetFileName(audioFilename),
                        DisplayTitleNoArtist     = Path.GetFileName(audioFilename),
                        SortTitle                = Path.GetFileName(audioFilename),
                        AudioPresent             = true,
                        BeatmapPresent           = false,
                        ContainingFolderAbsolute = folder
                    };


                    int index = Add(b);

                    if (index >= 0)
                    {
                        Beatmaps[index].DatabaseNotFound = false;
                    }

                    currentLevel.Beatmaps.Add(b);

                    lastAddedMap = b;

                    TotalAudioOnly++;
                }
            }

            if (strayBeatmapCount > 0)
            {
                TotalUniqueSets++;
            }

            if (isTopFolder || strayBeatmapCount == 0)
            //Only process subfolders if they don't have any direct beatmaps contained in them.
            {
                foreach (string f in Directory.GetDirectories(folder))
                {
                    ProcessFolder(f);
                }
            }
#if !DEBUG
        }

        catch (Exception e)
        {
            TopMostMessageBox.Show("Error while processing " + folder + "\n" + e.ToString());
        }
#endif
        }
Example #11
0
        internal static void ProcessFolder(string folder, BeatmapTreeLevel parent)
        {
            BeatmapTreeLevel tl = new BeatmapTreeLevel(folder, parent);

            parent.Children.Add(tl);

            string[] oggs = Directory.GetFiles(folder, "*.ogg");
            string[] mp3s = Directory.GetFiles(folder, "*.mp3");

            string audioFilename = "";

            if (oggs.Length > 0)
            {
                audioFilename = oggs[0];
            }
            else if (mp3s.Length > 0)
            {
                audioFilename = mp3s[0];
            }

            int osuCount = 0;

            foreach (string file in Directory.GetFiles(folder, "*.osu"))
            {
                if (parent == BeatmapTreeManager.Root)
                {
                    try
                    {
                        string baseDir  = Directory.GetCurrentDirectory();
                        string songsDir = baseDir + "\\songs\\";

                        string newFolder = songsDir + Path.GetFileNameWithoutExtension(file);
                        if (!Directory.Exists(newFolder))
                        {
                            Directory.CreateDirectory(newFolder);
                        }

                        foreach (string f in Directory.GetFiles(folder))
                        {
                            File.Move(f, newFolder + "\\" + Path.GetFileName(f));
                        }
                    }
                    catch
                    {
                    }
                    MessageBox.Show(
                        "You have extracted a beatmap the wrong way!  Make sure you place the osz/zip file you downloaded inside the Songs directory, WITHOUT extracting it yourself.\nI have fixed it for you this time, but this will CAUSE PROBLEMS if more than one beatmap are present!");
                    parent.Children.Remove(tl);
                    ProcessFolder(folder, parent);
                    return;
                }

                osuCount++;

                if (ReadingDatabase)
                {
                    Beatmap found = BeatmapAvailable.Find(bm => bm.Filename == file);
                    if (found != null)
                    {
                        if (found.DateModified == new FileInfo(file).LastWriteTimeUtc)
                        {
                            //Hasn't changed - skip over
                            found.DatabaseNotFound = false;
                            tl.Beatmaps.Add(found);
                            continue;
                        }
                        else
                        {
                            //Has changed - do a full reload.
                            BeatmapAvailable.Remove(found);
                        }
                    }
                }

                Beatmap b = new Beatmap();
                b.ContainingFolder = folder;
                b.AudioFilename    = audioFilename;
                b.AudioPresent     = true;
                b.BeatmapPresent   = true;
                b.Filename         = file;

                ProcessHeaders(b);

                if (b.AudioPresent || b.BeatmapPresent)
                {
                    BeatmapAvailable.Add(b);
                    tl.Beatmaps.Add(b);
                }
            }

            if (osuCount == 0 && audioFilename.Length > 0)
            {
                Beatmap b = new Beatmap();
                b.AudioFilename        = audioFilename;
                b.Filename             = string.Format("{0}\\{1}.osu", folder, Path.GetFileNameWithoutExtension(audioFilename));
                b.DisplayTitle         = Path.GetFileName(audioFilename);
                b.DisplayTitleNoArtist = Path.GetFileName(audioFilename);
                b.SortTitle            = Path.GetFileName(audioFilename);
                b.GroupTitle           = Path.GetFileName(audioFilename);
                b.AudioPresent         = true;
                b.ContainingFolder     = folder;
                BeatmapAvailable.Add(b);
                tl.Beatmaps.Add(b);

                TotalAudioOnly++;
            }

            if (osuCount > 0)
            {
                TotalUniqueFolders++;
            }

            foreach (string f in Directory.GetDirectories(folder))
            {
                ProcessFolder(f, tl);
            }
        }