feat: create base of project

This commit is contained in:
Matyáš Caras 2023-04-26 12:01:35 +02:00
commit e35e98dd41
30 changed files with 1669 additions and 0 deletions

517
.gitignore vendored Normal file
View file

@ -0,0 +1,517 @@
# Created by https://www.toptal.com/developers/gitignore/api/csharp,rider,linux,windows
# Edit at https://www.toptal.com/developers/gitignore?templates=csharp,rider,linux,windows
### Csharp ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
### Linux ###
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Rider ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
# Windows shortcuts
*.lnk
# End of https://www.toptal.com/developers/gitignore/api/csharp,rider,linux,windows

13
.idea/.idea.Ocarina2/.idea/.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/contentModel.xml
/modules.xml
/projectSettingsUpdater.xml
/.idea.Ocarina2.iml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AvaloniaProject">
<option name="projectPerEditor">
<map>
<entry key="Ocarina2/App.axaml" value="Ocarina2/Ocarina2.csproj" />
<entry key="Ocarina2/Views/LibraryView.axaml" value="Ocarina2/Ocarina2.csproj" />
<entry key="Ocarina2/Views/MainWindow.axaml" value="Ocarina2/Ocarina2.csproj" />
</map>
</option>
</component>
</project>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

16
Ocarina2.sln Normal file
View file

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ocarina2", "Ocarina2\Ocarina2.csproj", "{53A95561-EA24-4FA8-B2FD-76FF4D839710}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{53A95561-EA24-4FA8-B2FD-76FF4D839710}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53A95561-EA24-4FA8-B2FD-76FF4D839710}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53A95561-EA24-4FA8-B2FD-76FF4D839710}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53A95561-EA24-4FA8-B2FD-76FF4D839710}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

454
Ocarina2/.gitignore vendored Normal file
View file

@ -0,0 +1,454 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# JetBrains Rider
.idea/
*.sln.iml
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

15
Ocarina2/App.axaml Normal file
View file

@ -0,0 +1,15 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Ocarina2"
x:Class="Ocarina2.App"
>
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme Mode="Dark"/>
<StyleInclude Source="avares://Material.Icons.Avalonia/App.xaml" />
</Application.Styles>
</Application>

40
Ocarina2/App.axaml.cs Normal file
View file

@ -0,0 +1,40 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using DiscordRPC;
using ManagedBass;
using Newtonsoft.Json;
using Ocarina2.Models;
using Ocarina2.ViewModels;
using Ocarina2.Views;
namespace Ocarina2;
public partial class App : Application
{
public static readonly DiscordRpcClient Client = new("690238946378121296");
public override void Initialize()
{
Bass.Init();
Client.Initialize();
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
var l = Language.Load("en_US");
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(l),
};
}
base.OnFrameworkInitializationCompleted();
}
}

View file

@ -0,0 +1,11 @@
{
"Code":"en_US",
"MenuFile":"_File",
"MenuOpen":"_Open...",
"MenuExit":"_Exit",
"Music":"Music",
"NoMusic":"Your music library is empty...",
"RPSong":"Listening to $song",
"RPArtist":"by $artist",
"RPIconText":"Using Ocarina2"
}

BIN
Ocarina2/Assets/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,28 @@
using System;
using System.Globalization;
using System.IO;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Media.Imaging;
using Material.Icons;
using Material.Icons.Avalonia;
using TagLib;
namespace Ocarina2.Converter;
public class AlbumArtConverter:IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value == null) return new MaterialIconExt(MaterialIconKind.Music);
if(value is not IPicture[] p) return new BindingNotification(new InvalidCastException(), BindingErrorType.Error);
if(p.Length==0)return new MaterialIconExt(MaterialIconKind.Music);
var stream = new MemoryStream(p[0].Data.Data);
return new Bitmap(stream);
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,34 @@
using System;
using System.Globalization;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Ocarina2.Models;
namespace Ocarina2.Converter;
public class SongMetadataConverter:IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if(!int.TryParse(parameter as string,out var p)) return new BindingNotification(new InvalidCastException(), BindingErrorType.Error); // get int param
// for null return placeholders
if (value == null && p == 1) return "Nothing";
if (value == null && p == 2) return "Start playing something...";
if (value is MusicFile m)
{
if (p == 1)
{
return m.Metadata.Tag.Title;
}
return m.Metadata.Tag.FirstPerformer == ""?"Unknown":m.Metadata.Tag.FirstPerformer;
}
return new BindingNotification(new InvalidCastException(), BindingErrorType.Error);
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,42 @@
using System;
using System.IO;
using Avalonia;
using Avalonia.Platform;
using Newtonsoft.Json;
namespace Ocarina2.Models;
public class Language
{
public string Code;
public readonly string MenuFile;
public readonly string MenuOpen;
public readonly string MenuExit;
public readonly string Music;
public readonly string NoMusic;
public readonly string RPSong;
public readonly string RPArtist;
public readonly string RPIconText;
public Language(string code, string menuFile, string menuOpen, string menuExit, string music, string noMusic, string rpSong, string rpArtist, string rpIconText)
{
Code = code;
MenuFile = menuFile;
MenuOpen = menuOpen;
MenuExit = menuExit;
Music = music;
NoMusic = noMusic;
RPSong = rpSong;
RPArtist = rpArtist;
RPIconText = rpIconText;
}
public static Language Load(string code)
{
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
using var stream = assets?.Open(new Uri($"avares://Ocarina2/Assets/Languages/{code}.json"));
if (stream == null) throw new Exception("Could not load language strings");
using var reader = new StreamReader(stream);
return JsonConvert.DeserializeObject<Language>(reader.ReadToEnd())!;
}
}

View file

@ -0,0 +1,15 @@
using TagLib;
namespace Ocarina2.Models;
public class MusicFile
{
public File Metadata { get; }
public string Path { get; }
public MusicFile(File metadata, string path)
{
Metadata = metadata;
Path = path;
}
}

40
Ocarina2/Ocarina2.csproj Normal file
View file

@ -0,0 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
<None Remove=".gitignore" />
</ItemGroup>
<ItemGroup>
<TrimmerRootDescriptor Include="Roots.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.19" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.19" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.19" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.19" />
<PackageReference Include="DiscordRichPresence" Version="1.1.3.18" />
<PackageReference Include="ManagedBass" Version="3.1.1" />
<PackageReference Include="Material.Icons.Avalonia" Version="1.1.10" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="TagLibSharp" Version="2.3.0" />
<PackageReference Include="XamlNameReferenceGenerator" Version="1.5.1" />
</ItemGroup>
<ItemGroup>
<None Remove="Languages\en_US.json" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\Languages\en_US.json" />
</ItemGroup>
</Project>

23
Ocarina2/Program.cs Normal file
View file

@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.ReactiveUI;
using System;
using System.Runtime.InteropServices;
namespace Ocarina2;
class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToTrace()
.UseReactiveUI();
}

5
Ocarina2/Roots.xml Normal file
View file

@ -0,0 +1,5 @@
<linker>
<!-- Can be removed if CompiledBinding and no reflection are used -->
<assembly fullname="Ocarina2" preserve="All" />
<assembly fullname="Avalonia.Themes.Fluent" preserve="All" />
</linker>

27
Ocarina2/ViewLocator.cs Normal file
View file

@ -0,0 +1,27 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Ocarina2.ViewModels;
namespace Ocarina2;
public class ViewLocator : IDataTemplate
{
public IControl Build(object data)
{
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object data)
{
return data is ViewModelBase;
}
}

View file

@ -0,0 +1,187 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Threading;
using DiscordRPC;
using ManagedBass;
using Ocarina2.Models;
using ReactiveUI;
namespace Ocarina2.ViewModels;
public class MainWindowViewModel : ViewModelBase
{
private readonly Language _l = Language.Load("en_US");
private string _menuOpen;
private string _menuFile;
private string _menuExit;
private string _music;
private string _nomusic;
private MusicFile? _selectedFile;
public MusicFile? SelectedFile
{
get => _selectedFile;
set => this.RaiseAndSetIfChanged(ref _selectedFile, value);
}
public string MenuOpen
{
get => _menuOpen;
set => this.RaiseAndSetIfChanged(ref _menuOpen, value);
}
public string Music
{
get => _music;
set => this.RaiseAndSetIfChanged(ref _music, value);
}
public string MenuExit
{
get => _menuExit;
set => this.RaiseAndSetIfChanged(ref _menuExit, value);
}
public string MenuFile
{
get => _menuFile;
set => this.RaiseAndSetIfChanged(ref _menuFile, value);
}
public string NoMusic
{
get => _nomusic;
set => this.RaiseAndSetIfChanged(ref _nomusic, value);
}
public ObservableCollection<MusicFile> MusicFiles {get;}
/// <summary>
/// Finds music files in the music library folder
/// </summary>
/// <returns>ObservableCollection of found files</returns>
private ObservableCollection<MusicFile> LoadFiles()
{
var musicfiles = new ObservableCollection<MusicFile>();
if (!Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)))
return musicfiles;
var subfolders = Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.MyMusic));
foreach (var folder in subfolders)
{
// get files in subfolders
var f = Directory.GetFiles(folder).Where(f=>f.EndsWith("mp3")).ToList(); //TODO: change to other supported formats
foreach (var file in f)
{
var tfile = TagLib.File.Create(file);
musicfiles.Add(new MusicFile(tfile,file));
}
}
// get directory-level files
var files = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)).Where(f=>f.EndsWith("mp3")).ToList(); //TODO: change to other supported formats
foreach (var file in files)
{
var tfile = TagLib.File.Create(file);
musicfiles.Add(new MusicFile(tfile,file));
}
return musicfiles;
}
/// <summary>
/// Runs when a song is selected in the listbox to start playing it
/// </summary>
public void FileSelected()
{
if (SelectedFile == null) return;
Stop();
try
{
var t = new Thread(async () => // TODO: toto thread asi neni fajn?
{
_player = new MediaPlayer();
await _player.LoadAsync(SelectedFile.Path);
_player.Play();
App.Client.SetPresence(new RichPresence()
{
State = _l.RPArtist.Replace("$artist",SelectedFile.Metadata.Tag.FirstAlbumArtist),
Details = _l.RPSong.Replace("$song",SelectedFile.Metadata.Tag.Title),
Timestamps = new Timestamps
{
Start = DateTime.Now
},
Assets = new Assets
{
LargeImageKey = "rpcon",
LargeImageText = _l.RPIconText
}
});
});
t.Start();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
/// <summary>
/// Player of the ManagedBass library, used for playback
/// </summary>
private MediaPlayer? _player;
public ReactiveCommand<Unit,Unit> StopMusic { get; }
/// <summary>
/// Stops and disposes of the player
/// </summary>
public void Stop()
{
_player?.Stop();
_player?.Dispose();
}
/// <summary>
/// Used to play/pause playback
/// </summary>
public void PlayPause()
{
if (_player == null) return;
if (_player.State == PlaybackState.Playing)
{
_player.Stop();
}
else
{
_player.Play();
}
}
public MainWindowViewModel()
{
_menuOpen = _l.MenuOpen;
_menuExit = _l.MenuExit;
_menuFile = _l.MenuFile;
_music = _l.Music;
MusicFiles = LoadFiles();
_nomusic = _l.NoMusic;
StopMusic = ReactiveCommand.Create(Stop);
}
public MainWindowViewModel(Language l)
{
_l = l;
_menuOpen = _l.MenuOpen;
_menuExit = _l.MenuExit;
_menuFile = _l.MenuFile;
_music = _l.Music;
_nomusic = _l.NoMusic;
MusicFiles = LoadFiles();
StopMusic = ReactiveCommand.Create(Stop);
}
}

View file

@ -0,0 +1,8 @@
using ReactiveUI;
namespace Ocarina2.ViewModels;
public class ViewModelBase : ReactiveObject
{
public string AppName => "Ocarina2";
}

View file

@ -0,0 +1,22 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Ocarina2.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ocarina2.Views.LibraryView">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<viewModels:MainWindowViewModel />
</Design.DataContext> <!-- TODO: Handle empty library -->
<ListBox x:Name="MusicBox" Grid.Row="1" Grid.Column="1" IsEnabled="{Binding MusicFiles.Count}"
Items="{Binding MusicFiles}" SelectedItem="{Binding SelectedFile}" SelectionChanged="MusicBox_OnSelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Metadata.Tag.Title}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>

View file

@ -0,0 +1,23 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Ocarina2.ViewModels;
namespace Ocarina2.Views;
public partial class LibraryView : UserControl
{
public LibraryView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void MusicBox_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
(DataContext as MainWindowViewModel)?.FileSelected();
}
}

View file

@ -0,0 +1,58 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Ocarina2.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:converter="clr-namespace:Ocarina2.Converter"
xmlns:views="clr-namespace:Ocarina2.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
WindowStartupLocation="CenterScreen"
WindowState="Maximized"
x:Class="Ocarina2.Views.MainWindow"
Icon="/Assets/icon.ico"
Title="{Binding AppName}">
<Window.Resources>
<converter:SongMetadataConverter x:Key="SongMeta"/>
<converter:AlbumArtConverter x:Key="AlbumArt"/>
</Window.Resources>
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainWindowViewModel />
</Design.DataContext>
<Grid RowDefinitions="33,*,50" ColumnDefinitions="0.25*,*">
<DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
<Menu DockPanel.Dock="Top">
<MenuItem Header="{Binding MenuOpen}">
<MenuItem Header="{Binding MenuFile}" />
<Separator />
<MenuItem Header="{Binding MenuExit}" />
</MenuItem>
</Menu>
</DockPanel>
<Grid Grid.Row="1" Grid.Column="0" Grid.RowSpan="2" RowDefinitions="*,2*" Margin="0">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="5">
<materialIcons:MaterialIcon Kind="Music" /><TextBlock Text="{Binding Music}" Margin="5,0,0,0" />
</StackPanel>
</StackPanel>
</Grid>
<views:LibraryView Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" x:Name="LibraryView" />
<!-- Song info -->
<StackPanel Grid.Row="1" Grid.Column="0" VerticalAlignment="Bottom">
<Image Source="{Binding SelectedFile.Metadata.Tag.Pictures, FallbackValue={materialIcons:MaterialIconExt Kind=Music} , Converter={StaticResource AlbumArt}}"/>
<TextBlock Text="{Binding SelectedFile, Converter={StaticResource SongMeta}, ConverterParameter=1}" FontWeight="Bold"/>
<TextBlock Text="{Binding SelectedFile, Converter={StaticResource SongMeta}, ConverterParameter=2}" />
</StackPanel>
<!-- Playback Controls -->
<StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="0">
<Button Content="{materialIcons:MaterialIconExt Kind=PlayPause}" Padding="5" Margin="5,0,0,0" Command="{Binding StopMusic}" />
<Button Content="{materialIcons:MaterialIconExt Kind=Stop}" Padding="5" Margin="5,0,0,0" Command="{Binding StopMusic}" />
</StackPanel>
</Grid>
</Window>

View file

@ -0,0 +1,23 @@
using System;
using System.Diagnostics;
using Avalonia.Controls;
using Ocarina2.ViewModels;
using ReactiveUI;
namespace Ocarina2.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Closing += (sender, args) =>
{
// dispose on closea
if (sender == null) return;
if (sender.ToString() != "Ocarina2.Views.MainWindow") return;
App.Client.Dispose();
(DataContext as MainWindowViewModel)?.Stop();
};
}
}

18
Ocarina2/app.manifest Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="AvaloniaTest.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

7
README.md Normal file
View file

@ -0,0 +1,7 @@
# Ocarina2
Revive of one of my oldest projects - a cross-platform music library organizer and player
Very WIP
## Building
Requires BASS library installed