Skip to content

Commit

Permalink
start fleshing out concept for audio player
Browse files Browse the repository at this point in the history
  • Loading branch information
krogenth committed Jan 31, 2024
1 parent 049c9e8 commit 406c11d
Show file tree
Hide file tree
Showing 18 changed files with 279 additions and 27 deletions.
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<PackageVersion Include="Pfim" Version="0.11.2" />

<PackageVersion Include="NVorbis" Version="0.10.5" />
<PackageVersion Include="NAudio.Vorbis" Version="1.5.0" />
<packageVersion Include="NAudio" Version="2.2.1" />

<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="NUnit" Version="3.13.3" />
Expand Down
53 changes: 53 additions & 0 deletions src/G2DataGUI.Common/Data/Audio/AudioFiles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;

namespace G2DataGUI.Common.Data.Audio;

public class AudioFiles
{
public static AudioFiles Instance { get; private set; } = new();
public ObservableCollection<AudioNode> DirectoryAudioFiles { get; private set; } = [];
public event EventHandler CollectionRefreshed;

private AudioFiles()
{
_ = ReadAudioFileSystemStructureAsync();
}

public void Reload() { }

private async Task ReadAudioFileSystemStructureAsync() =>
await Task.Run(ReadAudioFileSystemStructure).ConfigureAwait(false);

private void ReadAudioFileSystemStructure()
{
DirectoryAudioFiles.Clear();
foreach (var node in RecursiveDirectoryCrawl(Version.Instance.RootContentDirectory))
{
DirectoryAudioFiles.Add(node);
}

CollectionRefreshed?.Invoke(this, EventArgs.Empty);
}

private ObservableCollection<AudioNode> RecursiveDirectoryCrawl(string directory)
{
ObservableCollection<AudioNode> node = [];

foreach(string dir in Directory.GetDirectories(directory))
{
var child = new AudioNode(new DirectoryInfo(dir).Name, dir, false, RecursiveDirectoryCrawl(dir));
node.Add(child);
}

foreach(string file in Directory.GetFiles(directory, "*.ogg"))
{
AudioNode child = new(new DirectoryInfo(file).Name, file, true);
node.Add(child);
}

return node;
}
}
13 changes: 13 additions & 0 deletions src/G2DataGUI.Common/Data/Audio/AudioNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.ObjectModel;

namespace G2DataGUI.Common.Data.Audio;

public class AudioNode(string title, string path, bool isFile, ObservableCollection<AudioNode> children)
{
public ObservableCollection<AudioNode> Children { get; } = children;
public string Title { get; } = title;
public string Path { get; } = path;
public bool IsFile { get; } = isFile;

public AudioNode(string title, string path, bool isFile) : this(title, path, isFile, []) { }
}
4 changes: 2 additions & 2 deletions src/G2DataGUI.Common/Data/DDS/DDSFiles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace G2DataGUI.Common.Data.DDS;
public class DDSFiles
{
public static DDSFiles Instance { get; private set; } = new();
public ObservableCollection<DDSNode> DirectoryDDSFiles { get; private set; } = new();
public ObservableCollection<DDSNode> DirectoryDDSFiles { get; private set; } = [];
public event EventHandler CollectionRefreshed;

private DDSFiles()
Expand All @@ -19,7 +19,7 @@ private DDSFiles()
public void Reload() => _ = ReadDDSFileSystemStructureAsync();

private async Task ReadDDSFileSystemStructureAsync() =>
await Task.Run(() => ReadDDSFileSystemStructure()).ConfigureAwait(false);
await Task.Run(ReadDDSFileSystemStructure).ConfigureAwait(false);

private void ReadDDSFileSystemStructure()
{
Expand Down
23 changes: 7 additions & 16 deletions src/G2DataGUI.Common/Data/DDS/DDSNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,15 @@

namespace G2DataGUI.Common.Data.DDS;

public class DDSNode
public class DDSNode(string title, string path, uint guid, bool isFile, ObservableCollection<DDSNode> children)
{
public ObservableCollection<DDSNode> Children { get; }
public string Title { get; }
public string Path { get; }
public bool IsFile { get; }
public uint Guid { get; }
public ObservableCollection<DDSNode> Children { get; } = children;
public string Title { get; } = title;
public string Path { get; } = path;
public bool IsFile { get; } = isFile;
public uint Guid { get; } = guid;

public DDSNode(string title, string path, uint guid, bool isFile) : this(title, path, guid, isFile, new ObservableCollection<DDSNode>()) { }

public DDSNode(string title, string path, uint guid, bool isFile, ObservableCollection<DDSNode> children)
{
Title = title;
Path = path;
Guid = guid;
IsFile = isFile;
Children = children;
}
public DDSNode(string title, string path, uint guid, bool isFile) : this(title, path, guid, isFile, []) { }

public void AddChild(DDSNode child) => Children.Add(child);
}
6 changes: 6 additions & 0 deletions src/G2DataGUI.Common/Version.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ private Version()
}
}

public string RootContentDirectory =>
IsHDVersion ? ".\\content\\data" : ".\\data";

public string RootDataDirectory =>
IsHDVersion ? ".\\content\\data\\afs\\" : ".\\data\\afs\\";

public string RootTextDirectory =>
IsHDVersion ? ".\\content\\data\\text" : ".\\data\\text";

public string RootAudioDirectory =>
IsHDVersion ? ".\\content\\data\\sound" : ".\\data\\sound";
}
11 changes: 11 additions & 0 deletions src/G2DataGUI/Events/AudioEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace G2DataGUI.Events;

public class AudioEventArgs() : EventArgs
{
}
9 changes: 2 additions & 7 deletions src/G2DataGUI/Events/ImageEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@

namespace G2DataGUI.Events;

public class ImageEventArgs : EventArgs
public class ImageEventArgs(IImage image) : EventArgs
{
public ImageEventArgs(IImage image)
{
Image = image;
}

public IImage Image { get; }
public IImage Image { get; } = image;
}
3 changes: 3 additions & 0 deletions src/G2DataGUI/G2DataGUI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
<PackageReference Include="Avalonia.Diagnostics" Condition="'$(Configuration)' == 'Debug'" />
<PackageReference Include="XamlNameReferenceGenerator" />
<PackageReference Include="Pfim" />
<PackageReference Include="NAudio.Vorbis" />
<PackageReference Include="NAudio" />

</ItemGroup>

<ItemGroup>
Expand Down
75 changes: 75 additions & 0 deletions src/G2DataGUI/UI/ViewModels/AudioViewerViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using System.Collections.ObjectModel;
using G2DataGUI.Common.Data.Audio;
using G2DataGUI.UI.Common.ViewModels;
using NAudio.Vorbis;
using NAudio.CoreAudioApi;
using NAudio.Wave;

namespace G2DataGUI.UI.ViewModels;

public class AudioViewerViewModel : BaseViewModel, IDisposable
{
public ObservableCollection<AudioNode> GameDirectoryAudioFiles { get; } = AudioFiles.Instance.DirectoryAudioFiles;
private AudioNode _selectedAudioFile = null;
private VorbisWaveReader _waveReader = null;
private WasapiOut _wasapiOut = null;
public int TreeViewWidth { get; } = 200;

public static AudioViewerViewModel Instance { get; private set; } = new();

private AudioViewerViewModel() { }

private MMDevice GetDefaultAudioDevice()
{
using var enumerator = new MMDeviceEnumerator();
return enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Console);
}

private void AudioFileCollectionRefreshed(object sender, EventArgs args) { }

private void LoadAudioFile()
{
StopPlayback();

if (SelectedAudioFile != null)
{
_waveReader = new VorbisWaveReader(SelectedAudioFile.Path);
_wasapiOut = new(GetDefaultAudioDevice(), AudioClientShareMode.Shared, false, 10);
_wasapiOut.Init(_waveReader);
_wasapiOut.Play();
}
}

private void StopPlayback()
{
if (_wasapiOut != null && _wasapiOut.PlaybackState == PlaybackState.Playing)
{
_wasapiOut.Stop();
_wasapiOut?.Dispose();
_wasapiOut = null;
}

if (_waveReader != null)
{
_waveReader?.Dispose();
_waveReader = null;
}
}

public void Dispose() => StopPlayback();

public AudioNode SelectedAudioFile
{
get => _selectedAudioFile;
set
{
if (value.IsFile)
{
_selectedAudioFile = value;
LoadAudioFile();
OnPropertyChanged(nameof(SelectedAudioFile));
}
}
}
}
21 changes: 21 additions & 0 deletions src/G2DataGUI/UI/ViewModels/AudioViewerWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using G2DataGUI.Events;
using G2DataGUI.UI.Common.ViewModels;

namespace G2DataGUI.UI.ViewModels;

public class AudioViewerWindowViewModel : BaseViewModel
{
public static AudioViewerWindowViewModel Instance { get; private set; } = new();

private AudioViewerWindowViewModel()
{

}

public void OnAudioChange(object sender, AudioEventArgs e) { }
}
6 changes: 6 additions & 0 deletions src/G2DataGUI/UI/ViewModels/MenuBarViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,10 @@ public void OpenDDSViewer()
DDSViewerWindow ddsViewerWindow = new();
ddsViewerWindow.Show();
}

public void OpenAudioViewer()
{
AudioViewerWindow audioViewerWindow = new();
audioViewerWindow.Show();
}
}
30 changes: 30 additions & 0 deletions src/G2DataGUI/UI/Views/AudioViewerView.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<UserControl x:Class="G2DataGUI.UI.Views.AudioViewerView"
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:vm="using:G2DataGUI.UI.ViewModels"
mc:Ignorable="d"
Focusable="True"
x:CompileBindings="True"
x:DataType="vm:AudioViewerViewModel">
<Grid Name="AudioViewerPage"
Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TreeView Name="AudioFileTree"
Grid.Column="0"
Items="{Binding GameDirectoryAudioFiles}"
SelectedItem="{Binding SelectedAudioFile}"
Width="{Binding TreeViewWidth}"
VerticalAlignment="Stretch"
HorizontalAlignment="Left">
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Title}" />
</TreeDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</UserControl>
13 changes: 13 additions & 0 deletions src/G2DataGUI/UI/Views/AudioViewerView.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Avalonia.Controls;
using G2DataGUI.UI.ViewModels;

namespace G2DataGUI.UI.Views;

public partial class AudioViewerView : UserControl
{
public AudioViewerView()
{
DataContext = AudioViewerViewModel.Instance;
InitializeComponent();
}
}
5 changes: 4 additions & 1 deletion src/G2DataGUI/UI/Views/MenuBar.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@
Header="Windows">
<MenuItem Command="{ReflectionBinding OpenDDSViewer}"
VerticalAlignment="Center"
Header="DDS Viewer"/>
Header="DDS Viewer" />
<MenuItem Command="{ReflectionBinding OpenAudioViewer}"
VerticalAlignment="Center"
Header="Audio Viewer" />
</MenuItem>
</Menu>
<StackPanel HorizontalAlignment="Right"
Expand Down
13 changes: 13 additions & 0 deletions src/G2DataGUI/UI/Windows/AudioViewerWindow.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Window x:Class="G2DataGUI.UI.Windows.AudioViewerWindow"
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:vm="using:G2DataGUI.UI.ViewModels"
xmlns:views="using:G2DataGUI.UI.Views"
Width="500"
Height="1000"
Title="AudioViewerWindow"
mc:Ignorable="d">
<views:AudioViewerView />
</Window>
17 changes: 17 additions & 0 deletions src/G2DataGUI/UI/Windows/AudioViewerWindow.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Avalonia;
using Avalonia.Controls;
using G2DataGUI.UI.ViewModels;

namespace G2DataGUI.UI.Windows;

public partial class AudioViewerWindow : Window
{
public AudioViewerWindow()
{
DataContext = AudioViewerWindowViewModel.Instance;
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}
}
2 changes: 1 addition & 1 deletion src/G2DataGUI/UI/Windows/DDSViewerWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
Title="DDS Viewer"
mc:Ignorable="d">
<views:DDSViewerView />
</Window>
</Window>

0 comments on commit 406c11d

Please sign in to comment.