2023-04-26 12:01:35 +02:00
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
{
2023-04-26 21:13:57 +02:00
/ *
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/>.
* /
2023-04-26 12:01:35 +02:00
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 ) ;
}
}