├── OsuPlayer.NativeLibs ├── _._ ├── image │ └── icon.png ├── docs │ └── README.md ├── runtimes │ ├── win-x64 │ │ └── native │ │ │ ├── bass.dll │ │ │ ├── bass_fx.dll │ │ │ ├── bassenc.dll │ │ │ └── bassenc_mp3.dll │ ├── win-x86 │ │ └── native │ │ │ ├── bass.dll │ │ │ ├── bass_fx.dll │ │ │ ├── bassenc.dll │ │ │ └── bassenc_mp3.dll │ ├── linux-x64 │ │ └── native │ │ │ ├── libbass.so │ │ │ ├── libbass_fx.so │ │ │ ├── libbassenc.so │ │ │ └── libbassenc_mp3.so │ ├── linux-x86 │ │ └── native │ │ │ ├── libbass.so │ │ │ ├── libbass_fx.so │ │ │ ├── libbassenc.so │ │ │ └── libbassenc_mp3.so │ └── osx-x64 │ │ └── native │ │ ├── libbass.dylib │ │ ├── libbass_fx.dylib │ │ ├── libbassenc.dylib │ │ └── libbassenc_mp3.dylib └── OsuPlayer.NativeLibs.csproj ├── OsuPlayer.IO ├── Realm.dll ├── Realm.Fody.dll ├── FodyWeavers.xml ├── DirectoryManager.cs ├── Storage │ ├── Config │ │ └── Config.cs │ ├── Equalizer │ │ └── EqStorage.cs │ ├── Playlists │ │ └── PlaylistStorage.cs │ └── Blacklist │ │ └── Blacklist.cs ├── Importer │ ├── IImportNotifications.cs │ ├── ISongSourceProvider.cs │ └── CollectionImporter.cs └── OsuPlayer.IO.csproj ├── OsuPlayer ├── Resources │ ├── x96.ico │ ├── defaultBg.jpg │ ├── playerLogo.png │ └── logo_outline.png ├── Modules │ ├── Audio │ │ └── Interfaces │ │ │ ├── ICommonFeatures.cs │ │ │ ├── IHasDiscordRpc.cs │ │ │ ├── IPlayModes.cs │ │ │ ├── IHasBlacklist.cs │ │ │ ├── ISettableAudioDevices.cs │ │ │ ├── IAudioEngine.cs │ │ │ ├── IHasPlaylists.cs │ │ │ ├── IHasEffects.cs │ │ │ ├── ICanOpenFiles.cs │ │ │ ├── IAudioControls.cs │ │ │ └── IPlayer.cs │ └── BitmapExtensions.cs ├── Usings.cs ├── Views │ ├── PartyViewModel.cs │ ├── TopBarViewModel.cs │ ├── StatisticsView.axaml.cs │ ├── PartyView.axaml.cs │ ├── PlayHistoryView.axaml.cs │ ├── UpdateViewModel.cs │ ├── Navigation │ │ └── NavigationFactory.cs │ ├── SearchView.axaml.cs │ ├── PartyView.axaml │ ├── CustomControls │ │ ├── AudioVisualizerView.axaml │ │ └── AudioVisualizerView.axaml.cs │ ├── HomeSubViews │ │ └── HomeUserPanelView.axaml.cs │ ├── UpdateView.axaml.cs │ ├── PlayHistoryViewModel.cs │ ├── HomeView.axaml.cs │ ├── UpdateView.axaml │ ├── TopBarView.axaml.cs │ └── ExportSongsView.axaml.cs ├── Windows │ ├── LoginWindowViewModel.cs │ ├── FullscreenWindow.axaml.cs │ ├── CreateProfileWindowViewModel.cs │ ├── FullscreenWindow.axaml │ ├── ExportSongsProcessWindowViewModel.cs │ └── FullscreenWindowViewModel.cs ├── Styles │ ├── FluentDark.axaml │ └── Accents │ │ └── AccentColors.axaml ├── App.axaml.cs ├── ValueConverters │ └── PlaylistValueConverter.cs └── UI Extensions │ ├── MessageBoxWindow.axaml.cs │ ├── MessageBoxViewModel.cs │ ├── MessageBox.cs │ └── MessageBoxWindow.axaml ├── .gitignore ├── .idea └── .idea.OsuPlayer │ └── .idea │ ├── dictionaries │ └── engel.xml │ ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml │ ├── encodings.xml │ ├── sqldialects.xml │ ├── vcs.xml │ ├── indexLayout.xml │ └── .gitignore ├── OsuPlayer.Data ├── Enums │ ├── DbCreationType.cs │ └── LogType.cs ├── OsuPlayer │ ├── Enums │ │ ├── PlayState.cs │ │ ├── ReleaseChannels.cs │ │ ├── RepeatMode.cs │ │ ├── ShuffleDirection.cs │ │ ├── PlayDirection.cs │ │ ├── StartupSong.cs │ │ ├── BackgroundMode.cs │ │ ├── SortingMode.cs │ │ └── FontWeights.cs │ ├── Classes │ │ ├── VersionModel.cs │ │ ├── AddToPlaylistContextMenuEntry.cs │ │ ├── AudioDevice.cs │ │ └── EqPreset.cs │ └── StorageModels │ │ ├── IStorableContainer.cs │ │ ├── BlacklistContainer.cs │ │ ├── EqContainer.cs │ │ ├── PlaylistContainer.cs │ │ └── Playlist.cs ├── DataModels │ ├── IDbReaderFactory.cs │ ├── Online │ │ ├── News.cs │ │ ├── Article.cs │ │ ├── UserColors.cs │ │ └── OnlineUserStatusModelExtended.cs │ ├── OsuCollection.cs │ ├── Extensions │ │ ├── HistoricalMapEntryComparer.cs │ │ └── HistoricalMapEntry.cs │ ├── Interfaces │ │ ├── IMapEntry.cs │ │ ├── IUser.cs │ │ ├── IDatabaseReader.cs │ │ └── IMapEntryBase.cs │ ├── RealmMapEntry.cs │ ├── ObservableSorter.cs │ └── DbMapEntry.cs ├── LazerModels │ ├── Files │ │ ├── INamedFile.cs │ │ ├── IHasRealmFiles.cs │ │ ├── IFileInfo.cs │ │ ├── RealmFile.cs │ │ ├── IHasNamedFiles.cs │ │ ├── IHasGuidPrimaryKey.cs │ │ ├── INamedFileUsage.cs │ │ └── RealmNamedFileUsage.cs │ ├── Beatmaps │ │ ├── BeatmapOnlineStatus.cs │ │ ├── ScoreRank.cs │ │ ├── IRulesetInfo.cs │ │ ├── BeatmapDifficulty.cs │ │ ├── IScoreInfo.cs │ │ ├── IBeatmapSetInfo.cs │ │ ├── IBeatmapInfo.cs │ │ └── BeatmapMetadata.cs │ ├── Interfaces │ │ ├── IUser.cs │ │ ├── IHasOnlineID.cs │ │ └── IMappingOperationOptions.cs │ ├── Extensions │ │ ├── ScoreInfoExtensions.cs │ │ ├── CollectionExtensions.cs │ │ ├── BeatmapInfoExtionsions.cs │ │ └── BeatmapMetadataInfoExtensions.cs │ ├── RealmUser.cs │ └── Collections │ │ └── BeatmapCollection.cs └── OsuPlayer.Data.csproj ├── OsuPlayer.Network ├── LastFm │ └── Responses │ │ ├── TokenResponse.cs │ │ └── SessionResponse.cs ├── Data │ └── OsuPlayerContributor.cs ├── Constants.cs ├── IWebRequest.cs ├── UpdateResponse.cs ├── API │ └── NorthFox │ │ ├── NorthFox.Event.cs │ │ ├── NorthFox.Activity.cs │ │ ├── NorthFox.ApiStatistics.cs │ │ ├── NorthFox.UserStatistics.cs │ │ ├── NorthFox.Beatmap.cs │ │ └── NorthFox.Badge.cs └── OsuPlayer.Network.csproj ├── OsuPlayer.Interfaces ├── Service │ ├── IOsuPlayerService.cs │ ├── ILoggingService.cs │ ├── IProfileManagerService.cs │ ├── IDiscordService.cs │ ├── IOsuPlayerApiService.cs │ ├── ILastFmApiService.cs │ ├── IHistoryProvider.cs │ ├── IShuffleServiceProvider.cs │ ├── ISortProvider.cs │ ├── Endpoint │ │ └── IOsuPlayerApiUserEndpoint.cs │ ├── IShuffleImpl.cs │ └── IStatisticsProvider.cs └── OsuPlayer.Interfaces.csproj ├── OsuPlayer.Extensions ├── StringExtensions.cs ├── EnumExtensions │ ├── KnownColorsExtensions.cs │ └── FontWeightExtensions.cs ├── FilePickerFileTypesExtensions.cs ├── DefaultImplAttr.cs ├── ValueConverters │ ├── OsuProfileConverter.cs │ ├── UsernameConverter.cs │ ├── SettingsUserConverter.cs │ ├── PlayPauseConverter.cs │ ├── IsCurrentSongInPlaylistConverter.cs │ ├── ShuffleConverter.cs │ ├── BeatmapModelFullSongNameConverter.cs │ ├── BeatmapModelLastPlayedConverter.cs │ ├── BeatmapModelMostPlayedConverter.cs │ ├── BeatmapModelTimesPlayedConverter.cs │ ├── DecimalFormatter.cs │ ├── IsCurrentSongOnBlacklistConverter.cs │ ├── LastFmToAuthConverter.cs │ ├── SourceListValueConverter.cs │ ├── IconNameToIconKindConverter.cs │ ├── VolumeConverter.cs │ ├── GridFormatter.cs │ └── RepeatConverter.cs ├── OsuPlayer.Extensions.csproj ├── ObjectExtensions │ └── BeatmapModelExtensions.cs └── UnhandledExceptionHandler.cs ├── OsuPlayer.Services ├── LoggingService.cs ├── ShuffleImpl │ ├── RngShuffler.cs │ └── BalancedShuffler.cs ├── OsuPlayer.Services.csproj ├── LastFmService.cs ├── ProfileManagerService.cs ├── HistoryService.cs ├── DbReaderFactory.cs ├── ShuffleService.cs ├── OsuSongSourceService.cs └── SortService.cs ├── OsuPlayer.CrashHandler ├── CrashHandlerMainWindowViewModel.cs ├── App.axaml ├── App.axaml.cs ├── Program.cs ├── CrashHandlerMainWindow.axaml.cs └── CrashHandlerMainWindow.axaml ├── OsuPlayer.Tests ├── NetworkTests │ └── PasswordManagerTests.cs ├── IOTests │ └── DirectoryManagerTests.cs ├── FormatTimeTests.cs ├── OsuPlayer.Tests.csproj └── ValueConverterTests │ ├── ShuffleConverterTests.cs │ ├── PlayPauseConverterTests.cs │ └── SourceListValueConverterTests.cs ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── dotnet.yml ├── OsuPlayer.Updater └── OsuPlayer.Updater.csproj ├── .run ├── OsuPlayer.Tests.run.xml ├── OsuPlayer.CrashHandler.run.xml ├── OsuPlayer With Environment Variables.run.xml ├── OsuPlayer _ Live API.run.xml ├── OsuPlayer _ Local API.run.xml └── OsuPlayer _ Sandbox API.run.xml └── LICENSE /OsuPlayer.NativeLibs/_._: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /OsuPlayer.IO/Realm.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.IO/Realm.dll -------------------------------------------------------------------------------- /OsuPlayer.IO/Realm.Fody.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.IO/Realm.Fody.dll -------------------------------------------------------------------------------- /OsuPlayer/Resources/x96.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer/Resources/x96.ico -------------------------------------------------------------------------------- /OsuPlayer/Resources/defaultBg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer/Resources/defaultBg.jpg -------------------------------------------------------------------------------- /OsuPlayer/Resources/playerLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer/Resources/playerLogo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | /packages/ 4 | riderModule.iml 5 | /_ReSharper.Caches/ 6 | OsuPlayer.sln.DotSettings.user 7 | .name -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/image/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/image/icon.png -------------------------------------------------------------------------------- /OsuPlayer/Resources/logo_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer/Resources/logo_outline.png -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/dictionaries/engel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /OsuPlayer.Data/Enums/DbCreationType.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.Enums; 2 | 3 | public enum DbCreationType 4 | { 5 | OsuDb, 6 | Realm 7 | } -------------------------------------------------------------------------------- /OsuPlayer.Network/LastFm/Responses/TokenResponse.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Network.LastFm.Responses; 2 | 3 | public record TokenResponse(string Token); -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/PlayState.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | public enum PlayState 4 | { 5 | Playing, 6 | Paused 7 | } -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/docs/README.md: -------------------------------------------------------------------------------- 1 | All rights belong to the respective owners at https://www.un4seen.com/. 2 | 3 | Contains the bass libraries for win and linux. -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x64/native/bass.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x64/native/bass.dll -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x86/native/bass.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x86/native/bass.dll -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x64/native/bass_fx.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x64/native/bass_fx.dll -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x64/native/bassenc.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x64/native/bassenc.dll -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x86/native/bass_fx.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x86/native/bass_fx.dll -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x86/native/bassenc.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x86/native/bassenc.dll -------------------------------------------------------------------------------- /OsuPlayer.IO/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbass.so -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbass.so -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbass.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbass.dylib -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbass_fx.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbass_fx.so -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbassenc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbassenc.so -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbass_fx.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbass_fx.so -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbassenc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbassenc.so -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbass_fx.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbass_fx.dylib -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbassenc.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbassenc.dylib -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x64/native/bassenc_mp3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x64/native/bassenc_mp3.dll -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/win-x86/native/bassenc_mp3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/win-x86/native/bassenc_mp3.dll -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/ReleaseChannels.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | public enum ReleaseChannels 4 | { 5 | Stable = 0, 6 | PreReleases = 1 7 | } -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbassenc_mp3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x64/native/libbassenc_mp3.so -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbassenc_mp3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/linux-x86/native/libbassenc_mp3.so -------------------------------------------------------------------------------- /OsuPlayer.Network/LastFm/Responses/SessionResponse.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Network.LastFm.Responses; 2 | 3 | public record SessionResponse(string? Name, string Key, int Subscriber); -------------------------------------------------------------------------------- /OsuPlayer.Data/Enums/LogType.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Services; 2 | 3 | public enum LogType 4 | { 5 | Info, 6 | Success, 7 | Warning, 8 | Error, 9 | Debug 10 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/RepeatMode.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | public enum RepeatMode 4 | { 5 | NoRepeat, 6 | Playlist, 7 | SingleSong 8 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/ShuffleDirection.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | public enum ShuffleDirection 4 | { 5 | Backwards = -1, 6 | Forward = 1 7 | } -------------------------------------------------------------------------------- /OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbassenc_mp3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Founntain/osuplayer/HEAD/OsuPlayer.NativeLibs/runtimes/osx-x64/native/libbassenc_mp3.dylib -------------------------------------------------------------------------------- /OsuPlayer.Network/Data/OsuPlayerContributor.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media.Imaging; 2 | 3 | namespace OsuPlayer.Network.Data; 4 | 5 | public record OsuPlayerContributor(string Name, Bitmap? Avatar); -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/PlayDirection.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | public enum PlayDirection 4 | { 5 | Backwards = -1, 6 | Normal = 0, 7 | Forward = 1 8 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/StartupSong.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | public enum StartupSong 4 | { 5 | FirstSong = 0, 6 | LastPlayed = 1, 7 | RandomSong = 2 8 | } -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/sqldialects.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/IOsuPlayerService.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Interfaces.Service; 2 | 3 | public interface IOsuPlayerService 4 | { 5 | protected abstract string ServiceName { get; } 6 | protected abstract string ServiceTag(); 7 | } -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/ILoggingService.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Services; 2 | 3 | namespace OsuPlayer.Interfaces.Service; 4 | 5 | public interface ILoggingService 6 | { 7 | public void Log(string message, LogType logType = LogType.Info, object? data = null); 8 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Extensions; 2 | 3 | public static class StringExtensions 4 | { 5 | public static string? IsNullOrWhiteSpaceWithFallback(this string? str, string? fallback) => string.IsNullOrWhiteSpace(str) ? fallback : str; 6 | } -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /OsuPlayer.IO/DirectoryManager.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.IO; 2 | 3 | public static class DirectoryManager 4 | { 5 | public static void GenerateMissingDirectories() 6 | { 7 | if (!Directory.Exists("data")) 8 | Directory.CreateDirectory("data"); 9 | } 10 | } -------------------------------------------------------------------------------- /OsuPlayer.Network/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Network; 2 | 3 | /// 4 | /// Global constants for the application 5 | /// 6 | public static class Constants 7 | { 8 | public static bool OfflineMode { get; set; } 9 | public static bool Localhost { get; set; } = false; 10 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Classes/VersionModel.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Classes; 2 | 3 | public sealed class VersionModel 4 | { 5 | public DateTime Version { get; set; } 6 | 7 | public new string ToString() 8 | { 9 | return Version.ToString("yyyy.Mdd.Hmm.s"); 10 | } 11 | } -------------------------------------------------------------------------------- /OsuPlayer.Network/IWebRequest.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Network; 2 | 3 | public interface IWebRequest 4 | { 5 | public Task GetRequest(string route, TRequest? data = default); 6 | public Task PostRequest(string route, TRequest? data = default); 7 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/ICommonFeatures.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Modules.Audio.Interfaces; 2 | 3 | /// 4 | /// This interface is used to provide a common feature set used by the audio component. 5 | /// 6 | public interface ICommonFeatures : IAudioControls, ISettableAudioDevices, IHasEffects 7 | { 8 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/StorageModels/IStorableContainer.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.StorageModels; 2 | 3 | /// 4 | /// This interface represents a implementing type which is given to 5 | /// 6 | public interface IStorableContainer 7 | { 8 | public IStorableContainer Init(); 9 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/IDbReaderFactory.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.DataModels.Interfaces; 2 | using OsuPlayer.Data.Enums; 3 | 4 | namespace OsuPlayer.Data.DataModels; 5 | 6 | public interface IDbReaderFactory 7 | { 8 | public DbCreationType Type { get; set; } 9 | 10 | public IDatabaseReader CreateDatabaseReader(string path); 11 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/IProfileManagerService.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.DataModels; 2 | 3 | namespace OsuPlayer.Interfaces.Service; 4 | 5 | public interface IProfileManagerService 6 | { 7 | public User? User { get; set; } 8 | 9 | public Task Login(string username, string password); 10 | public Task Login(string token); 11 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/BackgroundMode.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | public enum BackgroundMode 4 | { 5 | // SolidColor = WindowTransparencyLevel.None, 6 | // AcrylicBlur = WindowTransparencyLevel.AcrylicBlur, 7 | // Mica = WindowTransparencyLevel.Mica 8 | SolidColor, 9 | AcrylicBlur, 10 | Mica, 11 | } -------------------------------------------------------------------------------- /.idea/.idea.OsuPlayer/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /contentModel.xml 6 | /modules.xml 7 | /projectSettingsUpdater.xml 8 | /.idea.OsuPlayer.iml 9 | # Editor-based HTTP Client requests 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/INamedFile.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Files; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public interface INamedFile 6 | { 7 | string Filename { get; set; } 8 | 9 | RealmFile File { get; set; } 10 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/EnumExtensions/KnownColorsExtensions.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media; 2 | using OsuPlayer.Data.OsuPlayer.Enums; 3 | 4 | namespace OsuPlayer.Extensions.EnumExtensions; 5 | 6 | public static class KnownColorsExtensions 7 | { 8 | public static Color ToColor(this KnownColors color) 9 | { 10 | return Color.FromUInt32((uint) color); 11 | } 12 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/FilePickerFileTypesExtensions.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform.Storage; 2 | 3 | namespace OsuPlayer.Extensions; 4 | 5 | public class FilePickerFileTypesExtensions { 6 | public static FilePickerFileType OsuDb { get; } = new("osu! db files") 7 | { 8 | Patterns = new[] { "osu!.db", "client.realm", }, 9 | MimeTypes = null 10 | }; 11 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/IHasDiscordRpc.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Modules.Audio.Interfaces; 2 | 3 | /// 4 | /// This interface provides discord rpc capabilities. 5 | /// 6 | public interface IHasDiscordRpc 7 | { 8 | /// 9 | /// Disposes the discord client. 10 | /// 11 | public void DisposeDiscordClient(); 12 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/IDiscordService.cs: -------------------------------------------------------------------------------- 1 | using DiscordRPC; 2 | 3 | namespace OsuPlayer.Interfaces.Service; 4 | 5 | public interface IDiscordService 6 | { 7 | public void Initialize(); 8 | public void DeInitialize(); 9 | public Task UpdatePresence(string details, string state, int beatmapSetId = 0, Assets? assets = null, TimeSpan? durationLeft = null); 10 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/IHasRealmFiles.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Files; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public interface IHasRealmFiles 6 | { 7 | IList Files { get; } 8 | 9 | string Hash { get; set; } 10 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Enums/SortingMode.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | /// 4 | /// An enum representing possible sorting modes for the song list 5 | /// 6 | /// Available sorting modes: Title, Artist, SetId 7 | /// 8 | /// 9 | public enum SortingMode 10 | { 11 | Title = 0, 12 | Artist = 1, 13 | SetId = 2 14 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/StorageModels/BlacklistContainer.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global 2 | 3 | namespace OsuPlayer.Data.OsuPlayer.StorageModels; 4 | 5 | public class BlacklistContainer : IStorableContainer 6 | { 7 | public HashSet Songs { get; set; } = new(); 8 | 9 | public IStorableContainer Init() 10 | { 11 | return this; 12 | } 13 | } -------------------------------------------------------------------------------- /OsuPlayer.Services/LoggingService.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Interfaces.Service; 2 | 3 | namespace OsuPlayer.Services; 4 | 5 | public class LoggingService : OsuPlayerService, ILoggingService 6 | { 7 | public override string ServiceName => "LOGGING_SERVICE"; 8 | 9 | public void Log(string message, LogType logType = LogType.Info, object? data = null) => LogToConsole(message, logType, data); 10 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/IPlayModes.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.OsuPlayer.Enums; 2 | 3 | namespace OsuPlayer.Modules.Audio.Interfaces; 4 | 5 | /// 6 | /// This interface provides different play modes for the player. 7 | /// 8 | public interface IPlayModes 9 | { 10 | public Bindable IsShuffle { get; } 11 | public Bindable RepeatMode { get; } 12 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/IFileInfo.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Files; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public interface IFileInfo 6 | { 7 | /// 8 | /// SHA-256 hash of the file content. 9 | /// 10 | string Hash { get; } 11 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Classes/AddToPlaylistContextMenuEntry.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.Classes; 2 | 3 | public class AddToPlaylistContextMenuEntry 4 | { 5 | public string Name { get; set; } 6 | public Action Action { get; set; } 7 | 8 | public AddToPlaylistContextMenuEntry(string name, Action action) 9 | { 10 | Name = name; 11 | Action = action; 12 | } 13 | } -------------------------------------------------------------------------------- /OsuPlayer/Usings.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using System.IO; 3 | global using System.Linq; 4 | global using System.Collections.Generic; 5 | global using System.Collections.ObjectModel; 6 | global using Nein.Extensions.Bindables; 7 | global using OsuPlayer.IO.Storage.Config; 8 | global using OsuPlayer.Modules.Audio; 9 | using System.Runtime.CompilerServices; 10 | 11 | [assembly: InternalsVisibleTo("OsuPlayer.Tests")] -------------------------------------------------------------------------------- /OsuPlayer/Views/PartyViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | using Nein.Base; 3 | using ReactiveUI; 4 | 5 | namespace OsuPlayer.Views; 6 | 7 | public class PartyViewModel : BaseViewModel 8 | { 9 | public PartyViewModel() 10 | { 11 | Activator = new ViewModelActivator(); 12 | this.WhenActivated(disposables => { Disposable.Create(() => { }).DisposeWith(disposables); }); 13 | } 14 | } -------------------------------------------------------------------------------- /OsuPlayer/Views/TopBarViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | using Nein.Base; 3 | using ReactiveUI; 4 | 5 | namespace OsuPlayer.Views; 6 | 7 | public class TopBarViewModel : BaseViewModel 8 | { 9 | public TopBarViewModel() 10 | { 11 | Activator = new ViewModelActivator(); 12 | this.WhenActivated(disposables => { Disposable.Create(() => { }).DisposeWith(disposables); }); 13 | } 14 | } -------------------------------------------------------------------------------- /OsuPlayer.CrashHandler/CrashHandlerMainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using Nein.Base; 2 | using ReactiveUI; 3 | 4 | namespace OsuPlayer.CrashHandler; 5 | 6 | public class CrashHandlerMainWindowViewModel : BaseWindowViewModel 7 | { 8 | private string _crashLog = string.Empty; 9 | 10 | public string CrashLog 11 | { 12 | get => _crashLog; 13 | set => this.RaiseAndSetIfChanged(ref _crashLog, value); 14 | } 15 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/RealmFile.cs: -------------------------------------------------------------------------------- 1 | using Realms; 2 | 3 | namespace OsuPlayer.Data.LazerModels.Files; 4 | 5 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 6 | // See the LICENCE file in the repository root for full licence text. 7 | [MapTo("File")] 8 | public class RealmFile : RealmObject, IFileInfo 9 | { 10 | [PrimaryKey] 11 | public string Hash { get; set; } = string.Empty; 12 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/IHasNamedFiles.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Files; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public interface IHasNamedFiles 6 | { 7 | /// 8 | /// All files used by this model. 9 | /// 10 | IEnumerable Files { get; } 11 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/IHasGuidPrimaryKey.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using Realms; 3 | 4 | namespace OsuPlayer.Data.LazerModels.Files; 5 | 6 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 7 | // See the LICENCE file in the repository root for full licence text. 8 | public interface IHasGuidPrimaryKey 9 | { 10 | [JsonIgnore] 11 | [PrimaryKey] 12 | Guid ID { get; } 13 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/DefaultImplAttr.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Extensions; 2 | 3 | /// 4 | /// This attribute defines the default implementation of a service to use if no other is specified explicitly. 5 | /// 6 | public class DefaultImplAttr : Attribute 7 | { 8 | /// 9 | /// Creates a new instance of the class. 10 | /// 11 | public DefaultImplAttr() 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /OsuPlayer/Views/StatisticsView.axaml.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | using Nein.Base; 3 | 4 | namespace OsuPlayer.Views; 5 | 6 | public partial class StatisticsView : ReactiveControl 7 | { 8 | public StatisticsView() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private void Block(CompositeDisposable disposables) 14 | { 15 | Disposable.Create(() => { }).DisposeWith(disposables); 16 | } 17 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/IOsuPlayerApiService.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Api.Data.API.EntityModels; 2 | using OsuPlayer.Interfaces.Service.Endpoint; 3 | 4 | namespace OsuPlayer.Interfaces.Service; 5 | 6 | public interface IOsuPlayerApiService 7 | { 8 | public IOsuPlayerApiUserEndpoint User { get; set; } 9 | 10 | public Task LoginAndSaveAuthToken(string username, string password); 11 | public Task LoginWithTokenAndSaveNewToken(string token); 12 | } -------------------------------------------------------------------------------- /OsuPlayer.IO/Storage/Config/Config.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.OsuPlayer.StorageModels; 2 | 3 | namespace OsuPlayer.IO.Storage.Config; 4 | 5 | public class Config : Storable 6 | { 7 | private static ConfigContainer? _configContainer; 8 | 9 | public override string Path => System.IO.Path.Combine("data", "config.json"); 10 | 11 | public Config() 12 | { 13 | _configContainer ??= Read(); 14 | 15 | Container = _configContainer; 16 | } 17 | } -------------------------------------------------------------------------------- /OsuPlayer.IO/Storage/Equalizer/EqStorage.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.OsuPlayer.StorageModels; 2 | 3 | namespace OsuPlayer.IO.Storage.Equalizer; 4 | 5 | public class EqStorage : Storable 6 | { 7 | private static EqContainer? _eqContainer; 8 | 9 | public override string Path => System.IO.Path.Combine("data", "eqPresets.json"); 10 | 11 | public EqStorage() 12 | { 13 | _eqContainer ??= Read(); 14 | 15 | Container = _eqContainer; 16 | } 17 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/Online/News.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace OsuPlayer.Data.DataModels.Online; 4 | 5 | public sealed class News 6 | { 7 | public DateTime CreationTime { get; set; } 8 | 9 | public string CreationTimeString => 10 | $"Written on {CreationTime.ToString("dddd HH:mm, dd MMMM yyyy", new CultureInfo("en-us"))} by {Creator}"; 11 | 12 | public string Creator { get; set; } 13 | public string Title { get; set; } 14 | public string Content { get; set; } 15 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Beatmaps/BeatmapOnlineStatus.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Beatmaps; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public enum BeatmapOnlineStatus 6 | { 7 | None = -3, 8 | 9 | Graveyard = -2, 10 | 11 | WIP = -1, 12 | 13 | Pending = 0, 14 | 15 | Ranked = 1, 16 | 17 | Approved = 2, 18 | 19 | Qualified = 3, 20 | 21 | Loved = 4 22 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/Online/Article.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace OsuPlayer.Data.DataModels.Online; 4 | 5 | public sealed class Article 6 | { 7 | public DateTime CreationTime { get; set; } 8 | 9 | public string CreationTimeString => 10 | $"Written on {CreationTime.ToString("dddd HH:mm, dd MMMM yyyy", new CultureInfo("en-us"))} by {Creator}"; 11 | 12 | public string Creator { get; set; } 13 | public string Title { get; set; } 14 | public string Content { get; set; } 15 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/INamedFileUsage.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Files; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public interface INamedFileUsage 6 | { 7 | /// 8 | /// The underlying file on disk. 9 | /// 10 | IFileInfo File { get; } 11 | 12 | /// 13 | /// The filename for this usage. 14 | /// 15 | string Filename { get; } 16 | } -------------------------------------------------------------------------------- /OsuPlayer.Tests/NetworkTests/PasswordManagerTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using OsuPlayer.Network.Security; 3 | 4 | namespace OsuPlayer.Tests.NetworkTests; 5 | 6 | public class PasswordManagerTests 7 | { 8 | [TestCase("", false)] 9 | [TestCase("Test", false)] 10 | [TestCase("Test123!_?", true)] 11 | public void PasswordManagerTest(string pw, bool expected) 12 | { 13 | var result = PasswordManager.CheckIfPasswordMeetsRequirements(pw); 14 | 15 | Assert.That(result, Is.EqualTo(expected)); 16 | } 17 | } -------------------------------------------------------------------------------- /OsuPlayer.Tests/IOTests/DirectoryManagerTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using NUnit.Framework; 3 | using OsuPlayer.IO; 4 | 5 | namespace OsuPlayer.Tests.IOTests; 6 | 7 | public class DirectoryManagerTests 8 | { 9 | [Test] 10 | public void GenerateMissingDirectories() 11 | { 12 | Assert.DoesNotThrow(() => 13 | { 14 | if (Directory.Exists("data")) 15 | Directory.Delete("data", true); 16 | }); 17 | 18 | Assert.DoesNotThrow(DirectoryManager.GenerateMissingDirectories); 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer.CrashHandler/App.axaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/ILastFmApiService.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Interfaces.Service; 2 | 3 | public interface ILastFmApiService 4 | { 5 | public void SetApiKeyAndSecret(string apiKey, string secret); 6 | public Task Scrobble(string title, string artist); 7 | public bool LoadSessionKey(); 8 | public Task LoadSessionKeyAsync(); 9 | public bool IsAuthorized(); 10 | public Task GetAuthToken(); 11 | public void AuthorizeToken(); 12 | public Task GetSessionKey(); 13 | public Task SaveSessionKeyAsync(); 14 | } -------------------------------------------------------------------------------- /OsuPlayer/Views/PartyView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Interactivity; 3 | using Material.Icons; 4 | using Material.Icons.Avalonia; 5 | using Nein.Extensions; 6 | 7 | namespace OsuPlayer.Views; 8 | 9 | public partial class PartyView : UserControl 10 | { 11 | public PartyView() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | private void Button_OnClick(object? sender, RoutedEventArgs e) 17 | { 18 | GeneralExtensions.OpenUrl("https://github.com/osu-player/osuplayer/issues/70"); 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/OsuCollection.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.DataModels; 2 | 3 | /// 4 | /// Represents a collection from osu! 5 | /// 6 | public class OsuCollection 7 | { 8 | public string Name { get; set; } = string.Empty; 9 | public List BeatmapHashes { get; private set; } = new(); 10 | 11 | public OsuCollection() 12 | { 13 | } 14 | 15 | public OsuCollection(string name, List beatmapHashes) 16 | { 17 | Name = name; 18 | BeatmapHashes = beatmapHashes; 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer.Network/UpdateResponse.cs: -------------------------------------------------------------------------------- 1 | using Octokit; 2 | 3 | namespace OsuPlayer.Network; 4 | 5 | /// 6 | /// A data structure for an update. 7 | /// 8 | public sealed class UpdateResponse 9 | { 10 | public bool IsNewVersionAvailable { get; set; } 11 | public bool IsPrerelease { get; set; } 12 | public string? HtmlUrl { get; set; } 13 | public string? Version { get; set; } 14 | public string? PatchNotes { get; set; } 15 | public DateTimeOffset? ReleaseDate { get; set; } 16 | public IReadOnlyList? Assets { get; set; } 17 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/IHistoryProvider.cs: -------------------------------------------------------------------------------- 1 | using Nein.Extensions.Bindables; 2 | using OsuPlayer.Data.DataModels.Extensions; 3 | using OsuPlayer.Data.DataModels.Interfaces; 4 | 5 | namespace OsuPlayer.Interfaces.Service; 6 | 7 | /// 8 | /// This interface provides historic capabilities 9 | /// 10 | public interface IHistoryProvider 11 | { 12 | public HistoricalMapEntryComparer Comparer { get; } 13 | public BindableList History { get; } 14 | 15 | void AddOrUpdateMapEntry(IMapEntryBase mapEntry); 16 | void ClearHistory(); 17 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/Extensions/HistoricalMapEntryComparer.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.DataModels.Extensions; 2 | 3 | public class HistoricalMapEntryComparer : IEqualityComparer 4 | { 5 | public bool Equals(HistoricalMapEntry? x, HistoricalMapEntry? y) 6 | { 7 | if (x == null && y == null) return true; 8 | if (x == null || y == null) return false; 9 | 10 | return x.MapEntry.Hash == y.MapEntry.Hash; 11 | } 12 | 13 | public int GetHashCode(HistoricalMapEntry obj) 14 | { 15 | return obj.MapEntry.GetHashCode(); 16 | } 17 | } -------------------------------------------------------------------------------- /OsuPlayer/Windows/LoginWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using Nein.Base; 2 | using ReactiveUI; 3 | 4 | namespace OsuPlayer.Windows; 5 | 6 | public class LoginWindowViewModel : BaseWindowViewModel 7 | { 8 | private string _password = string.Empty; 9 | private string _username = string.Empty; 10 | 11 | public string Username 12 | { 13 | get => _username; 14 | set => this.RaiseAndSetIfChanged(ref _username, value); 15 | } 16 | 17 | public string Password 18 | { 19 | get => _password; 20 | set => this.RaiseAndSetIfChanged(ref _password, value); 21 | } 22 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/Interfaces/IMapEntry.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.DataModels.Interfaces; 2 | 3 | public interface IMapEntry : IMapEntryBase 4 | { 5 | public string AudioFileName { get; } 6 | public string FolderName { get; } 7 | public string FolderPath { get; } 8 | public string FullPath { get; } 9 | 10 | /// 11 | /// Gets the background image of this 12 | /// 13 | /// the path of the background found. Returns null if the map doesn't have a background 14 | public Task FindBackground(); 15 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/IHasBlacklist.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace OsuPlayer.Modules.Audio.Interfaces; 4 | 5 | /// 6 | /// This interface provides blacklist capability. 7 | /// 8 | public interface IHasBlacklist 9 | { 10 | public Bindable BlacklistSkip { get; } 11 | 12 | public event PropertyChangedEventHandler? BlacklistChanged; 13 | 14 | /// 15 | /// Triggers if the blacklist got changed 16 | /// 17 | /// 18 | public void TriggerBlacklistChanged(PropertyChangedEventArgs e); 19 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Interfaces/IUser.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Interfaces; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public interface IUser : IHasOnlineID, IEquatable 6 | { 7 | string Username { get; } 8 | 9 | bool IsBot { get; } 10 | 11 | bool IEquatable.Equals(IUser? other) 12 | { 13 | if (other == null) 14 | return false; 15 | 16 | return OnlineID == other.OnlineID && Username == other.Username; 17 | } 18 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/OsuProfileConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | 4 | namespace OsuPlayer.Extensions.ValueConverters; 5 | 6 | public class OsuProfileConverter : IValueConverter 7 | { 8 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 9 | { 10 | return !string.IsNullOrWhiteSpace(value?.ToString()); 11 | } 12 | 13 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/IShuffleServiceProvider.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Interfaces.Service; 2 | 3 | /// 4 | /// This interface provides a service provider for shuffle implementations. 5 | /// 6 | public interface IShuffleServiceProvider 7 | { 8 | public List ShuffleAlgorithms { get; } 9 | public IShuffleImpl? ShuffleImpl { get; } 10 | 11 | /// 12 | /// Sets the shuffle algorithm. 13 | /// 14 | /// The to set. 15 | public void SetShuffleImpl(IShuffleImpl? algorithm); 16 | } -------------------------------------------------------------------------------- /OsuPlayer.CrashHandler/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace OsuPlayer.CrashHandler; 6 | 7 | public class App : Application 8 | { 9 | public override void Initialize() 10 | { 11 | AvaloniaXamlLoader.Load(this); 12 | } 13 | 14 | public override void OnFrameworkInitializationCompleted() 15 | { 16 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) desktop.MainWindow = new CrashHandlerMainWindow(); 17 | 18 | base.OnFrameworkInitializationCompleted(); 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/ISortProvider.cs: -------------------------------------------------------------------------------- 1 | using DynamicData; 2 | using Nein.Extensions.Bindables; 3 | using OsuPlayer.Data.DataModels; 4 | using OsuPlayer.Data.DataModels.Interfaces; 5 | using OsuPlayer.Data.OsuPlayer.Enums; 6 | 7 | namespace OsuPlayer.Interfaces.Service; 8 | 9 | public interface ISortProvider 10 | { 11 | public IObservable>? SortedSongs { get; set; } 12 | public Bindable SortingModeBindable { get; } 13 | public ObservableSorter SortingModeObservable { get; } 14 | 15 | public IComparable CustomSorter(IMapEntryBase map, SortingMode sortingMode); 16 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/ISettableAudioDevices.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.OsuPlayer.Classes; 2 | 3 | namespace OsuPlayer.Modules.Audio.Interfaces; 4 | 5 | /// 6 | /// This interface provides changeable audio device capability. 7 | /// 8 | public interface ISettableAudioDevices 9 | { 10 | public List AvailableAudioDevices { get; } 11 | 12 | /// 13 | /// Set the audio device to use as the output. 14 | /// 15 | /// The to use 16 | public void SetDevice(AudioDevice? audioDevice); 17 | } -------------------------------------------------------------------------------- /OsuPlayer/Styles/FluentDark.axaml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OsuPlayer/Windows/FullscreenWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Markup.Xaml; 2 | using Nein.Base; 3 | using Nein.Extensions; 4 | using OsuPlayer.Modules.Audio.Interfaces; 5 | using Splat; 6 | 7 | namespace OsuPlayer.Windows; 8 | 9 | public partial class FullscreenWindow : ReactiveWindow 10 | { 11 | public FullscreenWindow() 12 | { 13 | InitializeComponent(); 14 | 15 | DataContext = new FullscreenWindowViewModel(Locator.Current.GetRequiredService()); 16 | } 17 | 18 | private void InitializeComponent() 19 | { 20 | AvaloniaXamlLoader.Load(this); 21 | } 22 | } -------------------------------------------------------------------------------- /OsuPlayer/Views/PlayHistoryView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Input; 2 | using Nein.Base; 3 | 4 | namespace OsuPlayer.Views; 5 | 6 | public partial class PlayHistoryView : ReactiveControl 7 | { 8 | public PlayHistoryView() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | private async void HistoryListBox_OnDoubleTapped(object? sender, TappedEventArgs e) 14 | { 15 | var mapEntryFromHash = ViewModel.SongSourceProvider.GetMapEntryFromHash(ViewModel.SelectedHistoricalMapEntry?.MapEntry.Hash); 16 | 17 | await ViewModel.Player.TryPlaySongAsync(mapEntryFromHash); 18 | } 19 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/UsernameConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | 4 | namespace OsuPlayer.Extensions.ValueConverters; 5 | 6 | public class UsernameConverter : IValueConverter 7 | { 8 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 9 | { 10 | return string.IsNullOrWhiteSpace(value?.ToString()) ? "Not logged in" : value; 11 | } 12 | 13 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | } -------------------------------------------------------------------------------- /OsuPlayer/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Markup.Xaml; 4 | using OsuPlayer.Windows; 5 | using Splat; 6 | 7 | namespace OsuPlayer; 8 | 9 | public class App : Application 10 | { 11 | public override void Initialize() 12 | { 13 | AvaloniaXamlLoader.Load(this); 14 | } 15 | 16 | public override void OnFrameworkInitializationCompleted() 17 | { 18 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) desktop.MainWindow = Locator.Current.GetService(); 19 | 20 | base.OnFrameworkInitializationCompleted(); 21 | } 22 | } -------------------------------------------------------------------------------- /OsuPlayer/Views/UpdateViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | using Nein.Base; 3 | using OsuPlayer.Network; 4 | using ReactiveUI; 5 | 6 | namespace OsuPlayer.Views; 7 | 8 | public class UpdateViewModel : BaseViewModel 9 | { 10 | private UpdateResponse? _update; 11 | 12 | public UpdateResponse? Update 13 | { 14 | get => _update; 15 | set => this.RaiseAndSetIfChanged(ref _update, value); 16 | } 17 | 18 | public UpdateViewModel() 19 | { 20 | Activator = new ViewModelActivator(); 21 | 22 | this.WhenActivated(disposables => { Disposable.Create(() => { }).DisposeWith(disposables); }); 23 | } 24 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Extensions/ScoreInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.LazerModels.Beatmaps; 2 | 3 | namespace OsuPlayer.Data.LazerModels.Extensions; 4 | 5 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 6 | // See the LICENCE file in the repository root for full licence text. 7 | public static class ScoreInfoExtensions 8 | { 9 | /// 10 | /// A user-presentable display title representing this score. 11 | /// 12 | public static string GetDisplayTitle(this IScoreInfo scoreInfo) 13 | { 14 | return $"{scoreInfo.User.Username} playing {scoreInfo.Beatmap.GetDisplayTitle()}"; 15 | } 16 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/IAudioEngine.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace OsuPlayer.Modules.Audio.Interfaces; 4 | 5 | /// 6 | /// This interface wraps all sub-interfaces used by the audio engine. 7 | /// 8 | public interface IAudioEngine : ICanOpenFiles, ICommonFeatures 9 | { 10 | public delegate Task ChannelReachedEndHandler(); 11 | 12 | public Bindable ChannelLength { get; } 13 | public Bindable ChannelPosition { get; } 14 | public Bindable PlaybackSpeed { get; } 15 | public ChannelReachedEndHandler ChannelReachedEnd { set; } 16 | 17 | public float[] GetVisualizationData(); 18 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/Online/UserColors.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media; 2 | 3 | namespace OsuPlayer.Data.DataModels.Online; 4 | 5 | /// 6 | /// A list of all available role colors 7 | /// 8 | public static class UserColors 9 | { 10 | public static Brush Staff => new SolidColorBrush(Color.FromRgb(46, 224, 94)); 11 | public static Brush Developer => new SolidColorBrush(Color.FromRgb(255, 0, 152)); 12 | public static Brush Tester => new SolidColorBrush(Color.FromRgb(0, 191, 255)); 13 | public static Brush Donator => new SolidColorBrush(Color.FromRgb(255, 215, 0)); 14 | public static Brush User => new SolidColorBrush(Color.FromRgb(255, 255, 255)); 15 | } -------------------------------------------------------------------------------- /OsuPlayer.IO/Storage/Playlists/PlaylistStorage.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.OsuPlayer.StorageModels; 2 | 3 | namespace OsuPlayer.IO.Storage.Playlists; 4 | 5 | /// 6 | /// The PlaylistStorage reads and writes playlist data to the playlists.json file located in the data folder. 7 | /// 8 | public sealed class PlaylistStorage : Storable 9 | { 10 | private static PlaylistContainer? _playlistContainer; 11 | 12 | public override string Path => System.IO.Path.Combine("data", "playlists.json"); 13 | 14 | public PlaylistStorage() 15 | { 16 | _playlistContainer ??= Read(); 17 | 18 | Container = _playlistContainer; 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Beatmaps/ScoreRank.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace OsuPlayer.Data.LazerModels.Beatmaps; 4 | 5 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 6 | // See the LICENCE file in the repository root for full licence text. 7 | public enum ScoreRank 8 | { 9 | [Description(@"D")] 10 | D, 11 | 12 | [Description(@"C")] 13 | C, 14 | 15 | [Description(@"B")] 16 | B, 17 | 18 | [Description(@"A")] 19 | A, 20 | 21 | [Description(@"S")] 22 | S, 23 | 24 | [Description(@"S+")] 25 | SH, 26 | 27 | [Description(@"SS")] 28 | X, 29 | 30 | [Description(@"SS+")] 31 | XH 32 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Extensions/CollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.LazerModels.Extensions; 2 | 3 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 4 | // See the LICENCE file in the repository root for full licence text. 5 | public static class CollectionExtensions 6 | { 7 | public static void AddRange(this ICollection collection, IEnumerable items) 8 | { 9 | // List has a potentially more optimal path to adding a range. 10 | if (collection is List list) 11 | list.AddRange(items); 12 | else 13 | foreach (var obj in items) 14 | collection.Add(obj); 15 | } 16 | } -------------------------------------------------------------------------------- /OsuPlayer.IO/Storage/Blacklist/Blacklist.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.DataModels.Interfaces; 2 | using OsuPlayer.Data.OsuPlayer.StorageModels; 3 | 4 | namespace OsuPlayer.IO.Storage.Blacklist; 5 | 6 | public sealed class Blacklist : Storable 7 | { 8 | private static BlacklistContainer? _blacklistContainer; 9 | 10 | public override string? Path => System.IO.Path.Combine("data", "blacklist.json"); 11 | 12 | public Blacklist() 13 | { 14 | _blacklistContainer ??= Read(); 15 | 16 | Container = _blacklistContainer; 17 | } 18 | 19 | public bool Contains(IMapEntryBase? map) 20 | { 21 | return Container.Songs.Contains(map?.Hash); 22 | } 23 | } -------------------------------------------------------------------------------- /OsuPlayer/Views/Navigation/NavigationFactory.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using FluentAvalonia.UI.Controls; 3 | 4 | namespace OsuPlayer.Views.Navigation; 5 | 6 | public class NavigationFactory : INavigationPageFactory 7 | { 8 | public Control GetPage(Type srcType) 9 | { 10 | return null; 11 | } 12 | 13 | public Control GetPageFromObject(object target) 14 | { 15 | switch (target) 16 | { 17 | case HomeViewModel: 18 | return new HomeView(); 19 | case PlaylistViewModel: 20 | return new PlaylistView(); 21 | default: 22 | throw new ArgumentException(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/StorageModels/EqContainer.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.OsuPlayer.Classes; 2 | 3 | namespace OsuPlayer.Data.OsuPlayer.StorageModels; 4 | 5 | public class EqContainer : IStorableContainer 6 | { 7 | public Guid? LastUsedEqId { get; set; } 8 | 9 | public List? EqPresets { get; set; } 10 | 11 | public IStorableContainer Init() 12 | { 13 | EqPresets ??= new List(); 14 | EqPresets.Add(EqPreset.Flat); 15 | EqPresets.Add(EqPreset.Custom); 16 | EqPresets.Add(EqPreset.Classic); 17 | EqPresets.Add(EqPreset.LaptopSpeaker); 18 | 19 | LastUsedEqId ??= EqPresets.First().Id; 20 | 21 | return this; 22 | } 23 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/SettingsUserConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using OsuPlayer.Api.Data.API.EntityModels; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class SettingsUserConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | if (value is UserModel user) 12 | return user.Name; 13 | 14 | return "Not logged in"; 15 | } 16 | 17 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | } -------------------------------------------------------------------------------- /OsuPlayer.IO/Importer/IImportNotifications.cs: -------------------------------------------------------------------------------- 1 | using Nein.Extensions.Bindables; 2 | 3 | namespace OsuPlayer.IO.Importer; 4 | 5 | /// 6 | /// This interface provides a way to receive import notifications 7 | /// 8 | public interface IImportNotifications 9 | { 10 | public Bindable SongsLoading { get; } 11 | 12 | /// 13 | /// Is called when importing songs started 14 | /// 15 | public void OnImportStarted(); 16 | 17 | /// 18 | /// Is called when importing songs finished 19 | /// 20 | /// Indicates whether the import was successful or not 21 | public void OnImportFinished(bool success); 22 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/IHasPlaylists.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using OsuPlayer.Data.OsuPlayer.StorageModels; 3 | 4 | namespace OsuPlayer.Modules.Audio.Interfaces; 5 | 6 | /// 7 | /// This interface provides playlist capability. 8 | /// 9 | public interface IHasPlaylists 10 | { 11 | public Bindable SelectedPlaylist { get; } 12 | public Bindable PlaylistEnableOnPlay { get; } 13 | 14 | public event PropertyChangedEventHandler? PlaylistChanged; 15 | 16 | /// 17 | /// Triggers if the playlist got changed 18 | /// 19 | /// 20 | public void TriggerPlaylistChanged(PropertyChangedEventArgs e); 21 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[REQUEST] " 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/PlayPauseConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Material.Icons; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class PlayPauseConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | if (value is bool val) return val ? MaterialIconKind.Pause : MaterialIconKind.PlayArrow; 12 | 13 | return MaterialIconKind.QuestionMark; 14 | } 15 | 16 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 17 | { 18 | throw new NotImplementedException(); 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/IsCurrentSongInPlaylistConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Material.Icons; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class IsCurrentSongInPlaylistConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | var x = value != null && (bool) value; 12 | 13 | return x ? MaterialIconKind.Heart : MaterialIconKind.HeartOutline; 14 | } 15 | 16 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 17 | { 18 | throw new NotImplementedException(); 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/ShuffleConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Material.Icons; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class ShuffleConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | if (value is bool val) return val ? MaterialIconKind.Shuffle : MaterialIconKind.ShuffleDisabled; 12 | 13 | return MaterialIconKind.QuestionMark; 14 | } 15 | 16 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 17 | { 18 | throw new NotImplementedException(); 19 | } 20 | } -------------------------------------------------------------------------------- /OsuPlayer/Styles/Accents/AccentColors.axaml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | #B200FF 6 | #9f05e1 7 | #8f06cb 8 | #7c05af 9 | #be29ff 10 | #c849ff 11 | #d676ff 12 | -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/Online/OnlineUserStatusModelExtended.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Api.Data.API.EntityModels; 2 | using OsuPlayer.Api.Data.API.Enums; 3 | 4 | namespace OsuPlayer.Data.DataModels.Online; 5 | 6 | public sealed class OnlineUserStatusModelExtended : UserOnlineStatusModel 7 | { 8 | public string Status => GetStatusDisplay(); 9 | 10 | public string GetStatusDisplay() 11 | { 12 | switch (StatusType) 13 | { 14 | case UserOnlineStatusType.Listening: 15 | return $"Listening to {Song}"; 16 | case UserOnlineStatusType.InParty: 17 | return $"Dancing in a party to {Song}"; 18 | default: 19 | return "Idle"; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /OsuPlayer.Network/API/NorthFox/NorthFox.Event.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Api.Data.API.EntityModels; 2 | 3 | namespace OsuPlayer.Network.API.NorthFox; 4 | 5 | public class NorthFoxEventEndpoint 6 | { 7 | private readonly AbstractApiBase _apiBase; 8 | 9 | public NorthFoxEventEndpoint(AbstractApiBase apiBase) 10 | { 11 | _apiBase = apiBase; 12 | } 13 | 14 | #region GET Requests 15 | 16 | public async Task?> GetAllEvents() 17 | { 18 | return await _apiBase.Get("Event"); 19 | } 20 | 21 | public async Task GetEvent(Guid uniqueId) 22 | { 23 | return await _apiBase.GetById("Event", uniqueId); 24 | } 25 | 26 | #endregion 27 | } -------------------------------------------------------------------------------- /OsuPlayer.Updater/OsuPlayer.Updater.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0; net8.0-windows10.0.17763.0 6 | enable 7 | enable 8 | true 9 | 10 | 11 | 12 | ..\OsuPlayer\bin\Debug\ 13 | 14 | 15 | 16 | ..\OsuPlayer\bin\Release\ 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/IHasEffects.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Modules.Audio.Interfaces; 2 | 3 | /// 4 | /// This interface provides audio effects capability. 5 | /// 6 | public interface IHasEffects 7 | { 8 | public BindableArray EqGains { get; } 9 | public bool IsEqEnabled { get; set; } 10 | 11 | /// 12 | /// Sets the playback speed (including pitch) 13 | /// 14 | /// The speed to set 15 | public void SetPlaybackSpeed(double speed); 16 | 17 | /// 18 | /// Triggers a Method change. Usually this should only be called when toggling pitch or other FX settings 19 | /// 20 | public void UpdatePlaybackMethod(); 21 | } -------------------------------------------------------------------------------- /OsuPlayer.Network/API/NorthFox/NorthFox.Activity.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Api.Data.API.EntityModels; 2 | 3 | namespace OsuPlayer.Network.API.NorthFox; 4 | 5 | public class NorthFoxActivityEndpoint 6 | { 7 | private readonly AbstractApiBase _apiBase; 8 | 9 | public NorthFoxActivityEndpoint(AbstractApiBase apiBase) 10 | { 11 | _apiBase = apiBase; 12 | } 13 | 14 | #region GET Requests 15 | 16 | public async Task?> GetAllActivities() 17 | { 18 | return await _apiBase.Get("Activity"); 19 | } 20 | 21 | public async Task GetActivity(Guid uniqueId) 22 | { 23 | return await _apiBase.GetById("Activity", uniqueId); 24 | } 25 | 26 | #endregion 27 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/BeatmapModelFullSongNameConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using OsuPlayer.Api.Data.API.EntityModels; 4 | using OsuPlayer.Extensions.ObjectExtensions; 5 | 6 | namespace OsuPlayer.Extensions.ValueConverters; 7 | 8 | public class BeatmapModelFullSongNameConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | return value is not BeatmapModel beatmapModel ? string.Empty : beatmapModel.FullSongName(); 13 | } 14 | 15 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/BeatmapModelLastPlayedConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using OsuPlayer.Api.Data.API.EntityModels; 4 | using OsuPlayer.Extensions.ObjectExtensions; 5 | 6 | namespace OsuPlayer.Extensions.ValueConverters; 7 | 8 | public class BeatmapModelLastPlayedConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | return value is not BeatmapModel beatmapModel ? string.Empty : beatmapModel.LastPlayedString(); 13 | } 14 | 15 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/BeatmapModelMostPlayedConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using OsuPlayer.Api.Data.API.EntityModels; 4 | using OsuPlayer.Extensions.ObjectExtensions; 5 | 6 | namespace OsuPlayer.Extensions.ValueConverters; 7 | 8 | public class BeatmapModelMostPlayedConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | return value is not BeatmapModel beatmapModel ? string.Empty : beatmapModel.MostPlayedString(); 13 | } 14 | 15 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/BeatmapModelTimesPlayedConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using OsuPlayer.Api.Data.API.EntityModels; 4 | using OsuPlayer.Extensions.ObjectExtensions; 5 | 6 | namespace OsuPlayer.Extensions.ValueConverters; 7 | 8 | public class BeatmapModelTimesPlayedConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | return value is not BeatmapModel beatmapModel ? string.Empty : beatmapModel.TimesPlayedString(); 13 | } 14 | 15 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/DecimalFormatter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | 4 | namespace OsuPlayer.Extensions.ValueConverters; 5 | 6 | public class DecimalFormatter : IValueConverter 7 | { 8 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 9 | { 10 | if (targetType != typeof(string)) return null; 11 | 12 | if (value is not IFormattable number) return ""; 13 | 14 | var format = number.ToString("N0", CultureInfo.CurrentCulture); 15 | 16 | return format; 17 | } 18 | 19 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/IsCurrentSongOnBlacklistConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Material.Icons; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class IsCurrentSongOnBlacklistConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | if (value is not bool x) 12 | return MaterialIconKind.QuestionMark; 13 | 14 | return x ? MaterialIconKind.HeartBroken : MaterialIconKind.HeartBrokenOutline; 15 | } 16 | 17 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | } -------------------------------------------------------------------------------- /OsuPlayer.Network/API/NorthFox/NorthFox.ApiStatistics.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Api.Data.API.Models; 2 | 3 | namespace OsuPlayer.Network.API.NorthFox; 4 | 5 | public class NorthFoxApiStatisticsEndpoint 6 | { 7 | private readonly AbstractApiBase _apiBase; 8 | 9 | public NorthFoxApiStatisticsEndpoint(AbstractApiBase apiBase) 10 | { 11 | _apiBase = apiBase; 12 | } 13 | 14 | #region GET Requests 15 | 16 | public async Task GetApiStatistics() 17 | { 18 | return await _apiBase.GetRequestAsync("ApiStatistics", "get"); 19 | } 20 | 21 | public async Task GetStorageAmount() 22 | { 23 | return await _apiBase.GetRequestAsync("ApiStatistics", "getStorageAmount"); 24 | } 25 | 26 | #endregion 27 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/RealmUser.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.LazerModels.Interfaces; 2 | using Realms; 3 | 4 | namespace OsuPlayer.Data.LazerModels; 5 | 6 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 7 | // See the LICENCE file in the repository root for full licence text. 8 | public class RealmUser : EmbeddedObject, IUser, IEquatable 9 | { 10 | public int OnlineID { get; set; } = 1; 11 | 12 | public string Username { get; set; } = string.Empty; 13 | 14 | public bool IsBot => false; 15 | 16 | public bool Equals(RealmUser other) 17 | { 18 | if (ReferenceEquals(null, other)) return false; 19 | if (ReferenceEquals(this, other)) return true; 20 | 21 | return OnlineID == other.OnlineID && Username == other.Username; 22 | } 23 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/LastFmToAuthConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Avalonia.Media; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class LastFmToAuthConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | var isAuthorized = value != null && (bool) value; 12 | 13 | return isAuthorized 14 | ? new SolidColorBrush(Color.FromRgb(0, 200, 0)) 15 | : new SolidColorBrush(Color.FromRgb(255, 204, 34)); 16 | } 17 | 18 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } -------------------------------------------------------------------------------- /OsuPlayer/Windows/CreateProfileWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using Nein.Base; 2 | using ReactiveUI; 3 | 4 | namespace OsuPlayer.Windows; 5 | 6 | public class CreateProfileWindowViewModel : BaseWindowViewModel 7 | { 8 | private bool _isTosChecked; 9 | private string _password = string.Empty; 10 | private string _username = string.Empty; 11 | 12 | public string Username 13 | { 14 | get => _username; 15 | set => this.RaiseAndSetIfChanged(ref _username, value); 16 | } 17 | 18 | public string Password 19 | { 20 | get => _password; 21 | set => this.RaiseAndSetIfChanged(ref _password, value); 22 | } 23 | 24 | public bool IsTosChecked 25 | { 26 | get => _isTosChecked; 27 | set => this.RaiseAndSetIfChanged(ref _isTosChecked, value); 28 | } 29 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] " 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. Windows, OSX or Linux] 28 | - Version [e.g. 22] 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/ICanOpenFiles.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Modules.Audio.Interfaces; 2 | 3 | /// 4 | /// This interface provides method(s) regarding opening and closing audio files. 5 | /// 6 | public interface ICanOpenFiles 7 | { 8 | /// 9 | /// Opens an audio file and creates a stream handle containing the decoded audio stream to play 10 | /// 11 | /// the path to the audio file to be opened 12 | /// true if opening succeeded, false else 13 | /// if the sync handle could not be created 14 | public bool OpenFile(string path); 15 | 16 | /// 17 | /// Closes the current audio file stream handle 18 | /// 19 | public void CloseFile(); 20 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/StorageModels/PlaylistContainer.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Data.OsuPlayer.StorageModels; 2 | 3 | /// 4 | /// A playlist container with a list 5 | /// 6 | public class PlaylistContainer : IStorableContainer 7 | { 8 | public IList? Playlists { get; set; } 9 | 10 | /// 11 | /// Indicates an init of the creating a new empty favorites 12 | /// 13 | /// the current object 14 | public IStorableContainer Init() 15 | { 16 | Playlists = new List 17 | { 18 | new() 19 | { 20 | Name = "Favorites" 21 | } 22 | }; 23 | return this; 24 | } 25 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/SourceListValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using DynamicData; 4 | using OsuPlayer.Data.OsuPlayer.StorageModels; 5 | 6 | namespace OsuPlayer.Extensions.ValueConverters; 7 | 8 | public class SourceListValueConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | return value switch 13 | { 14 | null => new List(), 15 | SourceList val => val.Items.ToList(), 16 | _ => new List() 17 | }; 18 | } 19 | 20 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer/Classes/AudioDevice.cs: -------------------------------------------------------------------------------- 1 | using ManagedBass; 2 | 3 | namespace OsuPlayer.Data.OsuPlayer.Classes; 4 | 5 | /// 6 | /// Wrapper class for 7 | /// 8 | public sealed class AudioDevice 9 | { 10 | private DeviceInfo DeviceInfo { get; } 11 | public string DeviceName => DeviceInfo.Name; 12 | public bool IsEnabled => DeviceInfo.IsEnabled; 13 | public bool IsDefault => DeviceInfo.IsDefault; 14 | public bool IsInitialized => DeviceInfo.IsInitialized; 15 | public string Driver => DeviceInfo.Driver; 16 | public string DeviceToString => DeviceInfo.ToString(); 17 | 18 | public AudioDevice(DeviceInfo deviceInfo) 19 | { 20 | DeviceInfo = deviceInfo; 21 | } 22 | 23 | public override string ToString() 24 | { 25 | return DeviceName; 26 | } 27 | } -------------------------------------------------------------------------------- /OsuPlayer.CrashHandler/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | using Avalonia.ReactiveUI; 4 | 5 | namespace OsuPlayer.CrashHandler; 6 | 7 | internal class Program 8 | { 9 | // Initialization code. Don't use any Avalonia, third-party APIs or any 10 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 11 | // yet and stuff might break. 12 | [STAThread] 13 | public static void Main(string[] args) 14 | { 15 | BuildAvaloniaApp() 16 | .StartWithClassicDesktopLifetime(args); 17 | } 18 | 19 | // Avalonia configuration, don't remove; also used by visual designer. 20 | public static AppBuilder BuildAvaloniaApp() 21 | { 22 | return AppBuilder.Configure() 23 | .UsePlatformDetect() 24 | .LogToTrace() 25 | .UseReactiveUI(); 26 | } 27 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/IconNameToIconKindConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Material.Icons; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class IconNameToIconKindConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | if (value is not string s) return MaterialIconKind.Error; 12 | 13 | try 14 | { 15 | return Enum.Parse(s); 16 | } 17 | catch (Exception ex) 18 | { 19 | return MaterialIconKind.Error; 20 | } 21 | } 22 | 23 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | } -------------------------------------------------------------------------------- /OsuPlayer/Modules/Audio/Interfaces/IAudioControls.cs: -------------------------------------------------------------------------------- 1 | namespace OsuPlayer.Modules.Audio.Interfaces; 2 | 3 | /// 4 | /// This interface provides basic audio control functions. 5 | /// 6 | public interface IAudioControls 7 | { 8 | public Bindable IsPlaying { get; } 9 | public Bindable Volume { get; } 10 | 11 | /// 12 | /// Pauses the current song if playing or plays again if paused 13 | /// 14 | public void PlayPause(); 15 | 16 | /// 17 | /// Sets the playing state to Playing 18 | /// 19 | public void Play(); 20 | 21 | /// 22 | /// Sets the playing state to Pause 23 | /// 24 | public void Pause(); 25 | 26 | /// 27 | /// Stops the current song and disposes the audio stream 28 | /// 29 | public void Stop(); 30 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/DataModels/RealmMapEntry.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.DataModels.Interfaces; 2 | 3 | namespace OsuPlayer.Data.DataModels; 4 | 5 | /// 6 | /// a full beatmap entry with optionally used data 7 | /// only created on a call 8 | /// 9 | public class RealmMapEntry : RealmMapEntryBase, IMapEntry 10 | { 11 | public string BackgroundFileLocation { get; init; } = string.Empty; 12 | public string AudioFileName { get; init; } = string.Empty; 13 | public string FolderName { get; init; } = string.Empty; 14 | public string FolderPath { get; init; } = string.Empty; 15 | public string FullPath { get; init; } = string.Empty; 16 | 17 | public Task FindBackground() 18 | { 19 | return Task.FromResult(File.Exists(BackgroundFileLocation) ? BackgroundFileLocation : null); 20 | } 21 | } -------------------------------------------------------------------------------- /OsuPlayer.Tests/FormatTimeTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Nein.Extensions; 3 | using NUnit.Framework; 4 | 5 | // ReSharper disable RedundantExplicitParamsArrayCreation 6 | 7 | namespace OsuPlayer.Tests; 8 | 9 | public class FormatTimeTests 10 | { 11 | [TestCase(new object[] 12 | { 13 | 0, 1, 30, "1:30" 14 | })] 15 | [TestCase(new object[] 16 | { 17 | 0, 10, 30, "10:30" 18 | })] 19 | [TestCase(new object[] 20 | { 21 | 1, 1, 30, "1:01:30" 22 | })] 23 | public void TestTimeFormat(object[] input) 24 | { 25 | var hours = (int) input[0]; 26 | var minutes = (int) input[1]; 27 | var seconds = (int) input[2]; 28 | var expectedString = input[3]; 29 | var actualString = new TimeSpan(hours, minutes, seconds).FormatTime(); 30 | Assert.That(actualString, Is.EqualTo(expectedString)); 31 | } 32 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Extensions/BeatmapInfoExtionsions.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.LazerModels.Beatmaps; 2 | 3 | namespace OsuPlayer.Data.LazerModels.Extensions; 4 | 5 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 6 | // See the LICENCE file in the repository root for full licence text. 7 | public static class BeatmapInfoExtionsions 8 | { 9 | /// 10 | /// A user-presentable display title representing this beatmap. 11 | /// 12 | public static string GetDisplayTitle(this IBeatmapInfo beatmapInfo) 13 | { 14 | return $"{beatmapInfo.Metadata.GetDisplayTitle()} {GetVersionString(beatmapInfo)}".Trim(); 15 | } 16 | 17 | private static string GetVersionString(IBeatmapInfo beatmapInfo) 18 | { 19 | return string.IsNullOrEmpty(beatmapInfo.DifficultyName) ? string.Empty : $"[{beatmapInfo.DifficultyName}]"; 20 | } 21 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Interfaces/IHasOnlineID.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable InconsistentNaming 2 | 3 | namespace OsuPlayer.Data.LazerModels.Interfaces; 4 | 5 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 6 | // See the LICENCE file in the repository root for full licence text. 7 | public interface IHasOnlineID 8 | where T : IEquatable 9 | { 10 | /// 11 | /// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID (except in 12 | /// special cases where autoincrement is not used, like rulesets). 13 | /// 14 | /// 15 | /// Generally we use -1 when specifying "missing" in code, but values of 0 are also considered missing as the online source 16 | /// is generally a MySQL autoincrement value, which can never be 0. 17 | /// 18 | T OnlineID { get; } 19 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/VolumeConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Material.Icons; 4 | 5 | namespace OsuPlayer.Extensions.ValueConverters; 6 | 7 | public class VolumeConverter : IValueConverter 8 | { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | if (value is not double val) return MaterialIconKind.QuestionMark; 12 | 13 | return val switch 14 | { 15 | 0 => MaterialIconKind.VolumeMute, 16 | < 33 => MaterialIconKind.VolumeLow, 17 | < 66 => MaterialIconKind.VolumeMedium, 18 | _ => MaterialIconKind.VolumeHigh 19 | }; 20 | } 21 | 22 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/OsuPlayer.Extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | annotations 7 | en 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /OsuPlayer.Services/ShuffleImpl/RngShuffler.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.OsuPlayer.Enums; 2 | using OsuPlayer.Extensions; 3 | using OsuPlayer.Interfaces.Service; 4 | 5 | namespace OsuPlayer.Services.ShuffleImpl; 6 | 7 | /// 8 | /// This shuffle implementation will randomly select a song each time with no further logic. 9 | /// 10 | [DefaultImplAttr] 11 | public class RngShuffler : OsuPlayerService, IShuffleImpl 12 | { 13 | private int _maxRange = -1; 14 | 15 | public string Name => "Random Shuffle"; 16 | public string Description => "Randomly select a song each time with no further logic."; 17 | 18 | public override string ServiceName => "RNG_SHUFFLE_SERVICE"; 19 | 20 | public void Init(int maxRange) => _maxRange = maxRange; 21 | 22 | public int DoShuffle(int currentIndex, ShuffleDirection direction) => Random.Shared.Next(_maxRange); 23 | 24 | public override string ToString() => Name; 25 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ObjectExtensions/BeatmapModelExtensions.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Api.Data.API.EntityModels; 2 | 3 | namespace OsuPlayer.Extensions.ObjectExtensions; 4 | 5 | public static class BeatmapModelExtensions 6 | { 7 | public static string FullSongName(this BeatmapModel b) => $"{b.Artist} - {b.Title}"; 8 | public static string FullSongNameUnicode(this BeatmapModel b) => $"{b.ArtistUnicode} - {b.TitleUnicode}"; 9 | public static string TimesPlayedString(this BeatmapModel b) => $"{b.TimesPlayed}x played"; 10 | public static string LastPlayedString(this BeatmapModel b) => string.IsNullOrEmpty(b.LastPlayedBy?.Name) 11 | ? "Last played by an unknown user" 12 | : $"Last played by {b.LastPlayedBy.Name}"; 13 | public static string MostPlayedString(this BeatmapModel b) => b.MostPlayedBy == null 14 | ? string.Empty 15 | : $"{b.MostPlayedBy.Item1} played it most with {b.MostPlayedBy.Item2} times"; 16 | } -------------------------------------------------------------------------------- /OsuPlayer.Extensions/ValueConverters/GridFormatter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | 4 | namespace OsuPlayer.Extensions.ValueConverters; 5 | 6 | public class GridFormatter : IValueConverter 7 | { 8 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 9 | { 10 | if (value is not double or int) return 0.0; 11 | 12 | var width = System.Convert.ToDouble(value); 13 | 14 | if (parameter is not string) return 0.0; 15 | 16 | var targetWidth = System.Convert.ToDouble(parameter); 17 | 18 | if (targetWidth <= 0) return 0.0; 19 | 20 | var columns = Math.Ceiling(width / targetWidth); 21 | 22 | return width / columns; 23 | } 24 | 25 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 26 | { 27 | throw new NotImplementedException(); 28 | } 29 | } -------------------------------------------------------------------------------- /OsuPlayer/Views/SearchView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Input; 3 | using Avalonia.Interactivity; 4 | using Nein.Base; 5 | using OsuPlayer.Data.DataModels.Interfaces; 6 | using OsuPlayer.IO.Storage.Blacklist; 7 | 8 | namespace OsuPlayer.Views; 9 | 10 | public partial class SearchView : ReactiveControl 11 | { 12 | public SearchView() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | private async void InputElement_OnDoubleTapped(object? sender, TappedEventArgs e) 18 | { 19 | var list = sender as ListBox; 20 | var song = list!.SelectedItem as IMapEntryBase; 21 | 22 | await ViewModel.Player.TryPlaySongAsync(song); 23 | } 24 | 25 | private void AddToBlacklist_OnClick(object? sender, RoutedEventArgs e) 26 | { 27 | using var blacklist = new Blacklist(); 28 | 29 | blacklist.Container.Songs.Add(ViewModel.SelectedSong?.Hash); 30 | } 31 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/OsuPlayer.Interfaces.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /OsuPlayer/ValueConverters/PlaylistValueConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Avalonia.Data.Converters; 3 | using Nein.Extensions; 4 | using OsuPlayer.IO.Importer; 5 | using Splat; 6 | 7 | namespace OsuPlayer.ValueConverters; 8 | 9 | /// 10 | /// This ValueConverter is in the OsuPlayer Project, because we need access to the Audio class 11 | /// to convert the checksum to a MapEntry 12 | /// 13 | public class PlaylistValueConverter : IValueConverter 14 | { 15 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 16 | { 17 | return value != default ? Locator.Current.GetRequiredService().GetMapEntriesFromHash((ICollection) value, out _) : default; 18 | } 19 | 20 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/OsuPlayer.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | annotations 7 | en 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ..\OsuPlayer.IO\Realm.dll 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Beatmaps/IRulesetInfo.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.LazerModels.Interfaces; 2 | 3 | namespace OsuPlayer.Data.LazerModels.Beatmaps; 4 | 5 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 6 | // See the LICENCE file in the repository root for full licence text. 7 | public interface IRulesetInfo : IHasOnlineID, IEquatable, IComparable 8 | { 9 | /// 10 | /// The user-exposed name of this ruleset. 11 | /// 12 | string Name { get; } 13 | 14 | /// 15 | /// An acronym defined by the ruleset that can be used as a permanent identifier. 16 | /// 17 | string ShortName { get; } 18 | 19 | /// 20 | /// A string representation of this ruleset, to be used with reflection to instantiate the ruleset represented by this 21 | /// metadata. 22 | /// 23 | string InstantiationInfo { get; } 24 | } -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Files/RealmNamedFileUsage.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | using Realms; 3 | 4 | namespace OsuPlayer.Data.LazerModels.Files; 5 | 6 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 7 | // See the LICENCE file in the repository root for full licence text. 8 | public class RealmNamedFileUsage : EmbeddedObject, INamedFile, INamedFileUsage 9 | { 10 | public RealmFile File { get; set; } = null!; 11 | 12 | // [Indexed] cannot be used on `EmbeddedObject`s as it only applies to top-level queries. May need to reconsider this if performance becomes a concern. 13 | public string Filename { get; set; } = null!; 14 | 15 | IFileInfo INamedFileUsage.File => File; 16 | 17 | public RealmNamedFileUsage(RealmFile file, string filename) 18 | { 19 | File = file; 20 | Filename = filename; 21 | } 22 | 23 | [UsedImplicitly] 24 | private RealmNamedFileUsage() 25 | { 26 | } 27 | } -------------------------------------------------------------------------------- /OsuPlayer.Services/OsuPlayer.Services.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | annotations 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /OsuPlayer.Data/LazerModels/Extensions/BeatmapMetadataInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | using OsuPlayer.Data.LazerModels.Beatmaps; 2 | 3 | namespace OsuPlayer.Data.LazerModels.Extensions; 4 | 5 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. 6 | // See the LICENCE file in the repository root for full licence text. 7 | public static class BeatmapMetadataInfoExtensions 8 | { 9 | /// 10 | /// A user-presentable display title representing this metadata. 11 | /// 12 | public static string GetDisplayTitle(this IBeatmapMetadataInfo metadataInfo) 13 | { 14 | var author = string.IsNullOrEmpty(metadataInfo.Author.Username) ? string.Empty : $" ({metadataInfo.Author.Username})"; 15 | 16 | var artist = string.IsNullOrEmpty(metadataInfo.Artist) ? "unknown artist" : metadataInfo.Artist; 17 | var title = string.IsNullOrEmpty(metadataInfo.Title) ? "unknown title" : metadataInfo.Title; 18 | 19 | return $"{artist} - {title}{author}".Trim(); 20 | } 21 | } -------------------------------------------------------------------------------- /OsuPlayer/UI Extensions/MessageBoxWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Media; 3 | using Avalonia.ReactiveUI; 4 | 5 | namespace OsuPlayer.UI_Extensions; 6 | 7 | public partial class MessageBoxWindow : ReactiveWindow 8 | { 9 | public MessageBoxWindow() 10 | { 11 | InitializeComponent(); 12 | 13 | ViewModel = new MessageBoxViewModel(); 14 | 15 | var config = new Config(); 16 | 17 | TransparencyLevelHint = new[] { WindowTransparencyLevel.Mica, WindowTransparencyLevel.AcrylicBlur, WindowTransparencyLevel.None }; 18 | FontFamily = config.Container.Font ?? FontManager.Current.DefaultFontFamily; 19 | } 20 | 21 | public MessageBoxWindow(string text, string? title) 22 | { 23 | InitializeComponent(); 24 | 25 | ViewModel = new MessageBoxViewModel(this, text, title); 26 | 27 | var config = new Config(); 28 | // TransparencyLevelHint = (WindowTransparencyLevel) config.Container.BackgroundMode; 29 | } 30 | } -------------------------------------------------------------------------------- /OsuPlayer.Interfaces/Service/Endpoint/IOsuPlayerApiUserEndpoint.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media.Imaging; 2 | using OsuPlayer.Api.Data.API.EntityModels; 3 | using OsuPlayer.Api.Data.API.RequestModels.User; 4 | 5 | namespace OsuPlayer.Interfaces.Service.Endpoint; 6 | 7 | public interface IOsuPlayerApiUserEndpoint 8 | { 9 | Task UpdateSongsPlayed(int amount, int beatmapSetId = -1); 10 | Task UpdateXp(UpdateXpModel updateXpModel); 11 | Task SetOnlineStatus(UserOnlineStatusModel data); 12 | Task GetProfilePictureAsync(Guid currentUserUniqueId); 13 | Task GetUserFromLoginToken(); 14 | Task EditUser(EditUserModel editUserModel); 15 | Task SaveProfilePicture(byte[] data); 16 | Task GetProfileBannerAsync(string? bannerUrl); 17 | Task DeleteUser(); 18 | Task?> GetAllUsers(); 19 | Task?> GetActivityOfUser(Guid selectedUserUniqueId); 20 | Task Register(AddUserModel addUserModel); 21 | } -------------------------------------------------------------------------------- /.run/OsuPlayer.Tests.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | -------------------------------------------------------------------------------- /OsuPlayer/Views/PartyView.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 12 | 14 |