Ocarina2/Ocarina2/ViewModels/MainWindowViewModel.cs

204 lines
5.9 KiB
C#

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
{
/*
OCARINA2 Open-source music player and library manager
Copyright (C) 2023 Matyáš Caras
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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);
}
}