From e0c7c050f28fd109bdfd0b87000b7f138fec035e Mon Sep 17 00:00:00 2001 From: Bucket Of Chicken <122376377+realbucketofchicken@users.noreply.github.com> Date: Sun, 31 Aug 2025 20:31:49 +0200 Subject: [PATCH] UI functionality --- Scenes/Metadatatest.cs | 16 +++++++++ Scenes/Metadatatest.cs.uid | 1 + Scenes/main.tscn | 22 ++++++++++-- Scenes/song_display.tscn | 14 +++++++- Scripts/Context.cs | 51 +++++----------------------- Scripts/Data.cs | 33 ++++++++++-------- Scripts/SearchDisplay.cs | 16 ++++----- Scripts/SongDisplay.cs | 13 +++++--- Scripts/SongPlayer.cs | 68 ++++++++++++++++++++++++++++++++++++++ Scripts/SongPlayer.cs.uid | 1 + Scripts/UIManager.cs | 68 ++++++++++++++++++++++++++++++++++++++ Scripts/UIManager.cs.uid | 1 + Simplaudio.csproj | 1 + 13 files changed, 231 insertions(+), 74 deletions(-) create mode 100644 Scenes/Metadatatest.cs create mode 100644 Scenes/Metadatatest.cs.uid create mode 100644 Scripts/SongPlayer.cs create mode 100644 Scripts/SongPlayer.cs.uid create mode 100644 Scripts/UIManager.cs create mode 100644 Scripts/UIManager.cs.uid diff --git a/Scenes/Metadatatest.cs b/Scenes/Metadatatest.cs new file mode 100644 index 0000000..3326ddb --- /dev/null +++ b/Scenes/Metadatatest.cs @@ -0,0 +1,16 @@ +using Godot; +using System; +using System.Reflection.Metadata; +using System.Data.Common; +using System.Reflection.PortableExecutable; +using System.IO; + +public partial class Metadatatest : Control +{ + + public override void _Ready() + { + base._Ready(); + + } +} diff --git a/Scenes/Metadatatest.cs.uid b/Scenes/Metadatatest.cs.uid new file mode 100644 index 0000000..9c4c828 --- /dev/null +++ b/Scenes/Metadatatest.cs.uid @@ -0,0 +1 @@ +uid://csihi5ila47ga diff --git a/Scenes/main.tscn b/Scenes/main.tscn index 1c67da0..bc3ce9b 100644 --- a/Scenes/main.tscn +++ b/Scenes/main.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=15 format=3 uid="uid://mfcbf2sfino6"] +[gd_scene load_steps=18 format=3 uid="uid://mfcbf2sfino6"] [ext_resource type="Texture2D" uid="uid://0jo87vtoeheu" path="res://Images/pole2.jpg" id="1_6bp64"] [ext_resource type="Texture2D" uid="uid://df2e70jxwrmjs" path="res://Icons/BackOne.png" id="1_8gbba"] [ext_resource type="Texture2D" uid="uid://0r1tx6l1lc6x" path="res://Icons/settingscog.png" id="2_344ge"] [ext_resource type="Texture2D" uid="uid://daq8wnhtscpjl" path="res://Icons/Skip.png" id="2_bo1nx"] +[ext_resource type="Script" uid="uid://csihi5ila47ga" path="res://Scenes/Metadatatest.cs" id="2_fdnlq"] [ext_resource type="Texture2D" uid="uid://ctb4s2nks73rx" path="res://Icons/Play.png" id="2_jjvhh"] [ext_resource type="Texture2D" uid="uid://myq6n4bshduj" path="res://Icons/search.png" id="2_ynf5e"] [ext_resource type="Script" uid="uid://bq55jftgugexl" path="res://Scripts/Context.cs" id="3_8gbba"] @@ -11,6 +12,8 @@ [ext_resource type="Script" uid="uid://dq3yj21reqk80" path="res://Scripts/SearchDisplay.cs" id="4_hptm8"] [ext_resource type="Texture2D" uid="uid://cekkhyppj88xi" path="res://Icons/Headphones.png" id="4_kry3j"] [ext_resource type="PackedScene" uid="uid://c21wc1bq2pnm" path="res://Scenes/song_display.tscn" id="5_d1ilt"] +[ext_resource type="Script" uid="uid://ci5h1wwbedkbt" path="res://Scripts/UIManager.cs" id="12_6iyac"] +[ext_resource type="Texture2D" uid="uid://ch8wymyxftkb3" path="res://Icons/Pause.png" id="14_jkdf5"] [sub_resource type="GDScript" id="GDScript_bo1nx"] resource_name = "OpenDirGlue" @@ -81,6 +84,7 @@ offset_right = -29.0 offset_bottom = -31.0 grow_horizontal = 2 grow_vertical = 2 +script = ExtResource("2_fdnlq") [node name="VBoxContainer" type="VBoxContainer" parent="Padding"] layout_mode = 1 @@ -208,6 +212,7 @@ expand_icon = true [node name="PlayButton" type="Button" parent="Padding/VBoxContainer/Bottom/HBoxContainer"] custom_minimum_size = Vector2(42, 0) layout_mode = 2 +toggle_mode = true icon = ExtResource("2_jjvhh") expand_icon = true @@ -221,6 +226,8 @@ expand_icon = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 4 +max_value = 1.0 +step = 0.0010000000038417056 tick_count = 5 ticks_position = 3 @@ -256,7 +263,7 @@ offset_bottom = -42.0 grow_horizontal = 2 grow_vertical = 0 max_value = 1.0 -step = 0.010000000009313226 +step = 0.01000000000931322 value = 1.0 script = SubResource("GDScript_d1ilt") @@ -291,3 +298,14 @@ UpperMargin = NodePath("../Padding/VBoxContainer/Center/SearchResults/ScrollCont SongContainer = NodePath("../Padding/VBoxContainer/Center/SearchResults/ScrollContainer/VBoxContainer/SongContainer") LowerMargin = NodePath("../Padding/VBoxContainer/Center/SearchResults/ScrollContainer/VBoxContainer/LowerMargin") Scroll = NodePath("../Padding/VBoxContainer/Center/SearchResults/ScrollContainer") + +[node name="UiManager" type="Node" parent="." node_paths=PackedStringArray("PlayPauseButton", "ProgressIndicator", "SkipButton", "GoBackButton", "LoopButton", "RandomizeButton")] +script = ExtResource("12_6iyac") +PlayPauseButton = NodePath("../Padding/VBoxContainer/Bottom/HBoxContainer/PlayButton") +PauseImage = ExtResource("14_jkdf5") +PlayImage = ExtResource("2_jjvhh") +ProgressIndicator = NodePath("../Padding/VBoxContainer/Bottom/HBoxContainer/HSlider") +SkipButton = NodePath("../Padding/VBoxContainer/Bottom/HBoxContainer/SkipButton") +GoBackButton = NodePath("../Padding/VBoxContainer/Bottom/HBoxContainer/BackButton") +LoopButton = NodePath("../Padding/VBoxContainer/Bottom/HBoxContainer/Loop") +RandomizeButton = NodePath("../Padding/VBoxContainer/Bottom/HBoxContainer/Shuffle") diff --git a/Scenes/song_display.tscn b/Scenes/song_display.tscn index 568a0ec..f9af488 100644 --- a/Scenes/song_display.tscn +++ b/Scenes/song_display.tscn @@ -12,7 +12,7 @@ font_color = Color(0.7919991, 0.79199916, 0.7919991, 1) shadow_size = 2 shadow_color = Color(0, 0, 0, 0.5647059) -[node name="SongDisplay" type="Control" node_paths=PackedStringArray("background", "NameLabel", "ArtistLabel", "PlayButton")] +[node name="SongDisplay" type="Control" node_paths=PackedStringArray("background", "NameLabel", "ArtistLabel", "PlayButton", "OpenURLButton")] custom_minimum_size = Vector2(0, 75) layout_mode = 3 anchors_preset = 10 @@ -23,6 +23,7 @@ background = NodePath("TextureRect") NameLabel = NodePath("VBoxContainer/Name") ArtistLabel = NodePath("VBoxContainer/Artist") PlayButton = NodePath("Playbutton") +OpenURLButton = NodePath("OpenURl") [node name="Panel" type="Panel" parent="."] layout_mode = 1 @@ -81,3 +82,14 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 flat = true + +[node name="OpenURl" type="Button" parent="."] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -73.0 +grow_horizontal = 0 +grow_vertical = 2 +text = "open url" diff --git a/Scripts/Context.cs b/Scripts/Context.cs index c850826..31719e7 100644 --- a/Scripts/Context.cs +++ b/Scripts/Context.cs @@ -10,61 +10,26 @@ public partial class Context : Node public Thread processingThread; public static Context instance; public IEnumerable Songs; - AudioStreamPlayer[] StreamPlayers; DirectoryLoader manager = new(); - public event EventHandler SongsUpdated; - public delegate void SongsUpdatedEventHandler(object sender, SongsUpdatedEventArgs e); + static public SongPlayer ISongPlayer; + public event Action> SongsUpdated; public override void _Ready() { base._Ready(); instance = this; + ISongPlayer = new SongPlayer(); + AddChild(ISongPlayer); } public void LoadDirectory(String path){ - GD.Print(path); + GD.Print("Loading ",path); Songs = manager.LoadDirectory(path); GD.Print("Songs loaded"); - SongsUpdatedEventArgs args = new(); - args.songs = Songs; - OnSongsUpdated(args); - } - protected virtual void OnSongsUpdated(SongsUpdatedEventArgs e){ - SongsUpdated.Invoke(this,e); - } - - AudioStreamPlayer Player; - public void PlaySong(){ - GD.Print("PlaySongFromDisk"); - Player?.Play(); - } - public void LoadSong(String Path){ - Player?.QueueFree(); - if (Path.ToLower().EndsWith(".mp3")){ - AudioStreamMP3 stream = AudioStreamMP3.LoadFromFile(Path); - Player = new AudioStreamPlayer(); - Player.Stream = stream; - AddChild(Player); - } - else if(Path.ToLower().EndsWith(".wav")){ - AudioStreamWav stream = AudioStreamWav.LoadFromFile(Path); - Player = new AudioStreamPlayer(); - Player.Stream = stream; - AddChild(Player); - } - else if(Path.ToLower().EndsWith(".ogg")){ - AudioStreamOggVorbis stream = AudioStreamOggVorbis.LoadFromFile(Path); - Player = new AudioStreamPlayer(); - Player.Stream = stream; - AddChild(Player); - } - Player.Bus = "Music"; + + // Just event stuff + SongsUpdated(Songs); } } - -public class SongsUpdatedEventArgs : EventArgs -{ - public IEnumerable songs; -} diff --git a/Scripts/Data.cs b/Scripts/Data.cs index 95ed992..0c58bcb 100644 --- a/Scripts/Data.cs +++ b/Scripts/Data.cs @@ -6,26 +6,32 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Godot; -using TagLib; -using TagLib.Riff; + +using ATL.AudioData; +using ATL; public class Song{ public String Name; public bool LoadedMetadata; - public String[] Artists; + public String Artist; public String Album; public float Length; public String Comment; + public String URL; public String Directory; public void LoadMetadata(){ var TLfile = TagLib.File.Create(Directory); - Album ??= TLfile.Tag.Album; - Artists ??= TLfile.Tag.Performers; - Name ??= TLfile.Tag.Title; - Length = TLfile.Length; - Comment ??= TLfile.Tag.Comment; - TLfile.Dispose(); + Track theTrack = new Track(Directory); + if (theTrack.AdditionalFields.ContainsKey("comment")){ + URL = theTrack.AdditionalFields["comment"]; + + } + Album ??= theTrack.Album; + Artist ??= theTrack.Artist; + Name = String.IsNullOrEmpty(TLfile.Tag.Title) ? Name : theTrack.Title; + Length = theTrack.Duration; + Comment = theTrack.Comment; } public Image LoadImage(){ var TLfile = TagLib.File.Create(Directory); @@ -73,13 +79,12 @@ public class DirectoryLoader{ { Directory = file, }; - //TLfile.Tag.CopyTo(Tag) - - - //GD.Print("File Valid, file path ",song.Directory); + String[] parts = file.Split("/"); + String LastPart = parts[^1 ]; + song.Name = LastPart; Songs = Songs.Append(song); - //if (file.EndsWith(".mp3")) + } return Songs; diff --git a/Scripts/SearchDisplay.cs b/Scripts/SearchDisplay.cs index d3ee8d1..05655ac 100644 --- a/Scripts/SearchDisplay.cs +++ b/Scripts/SearchDisplay.cs @@ -18,10 +18,9 @@ public partial class SearchDisplay : Node } IEnumerable DisplayedSongs = []; - void UpdateDisplay(object sender,EventArgs eventArgs){ - SongsUpdatedEventArgs args = (SongsUpdatedEventArgs)eventArgs; - DisplayedSongs = args.songs; - GD.Print("Updated, songs ",args.songs.Count()); + void UpdateDisplay(IEnumerable songs){ + DisplayedSongs = songs; + GD.Print("Updated, songs ",songs.Count()); } @@ -67,7 +66,6 @@ public partial class SearchDisplay : Node scene.Setup(Songinfo); scene.DisplayId = i; SongContainer.MoveChild(scene,i - CurrentIndex); - GD.Print("IDKENX ", i - CurrentIndex ); GD.Print("CurrentIndex ", CurrentIndex); displays = displays.Append(scene); } @@ -79,10 +77,10 @@ public partial class SearchDisplay : Node } update_margins(CurrentIndex); } - void update_margins(int CurrentIndex){ - int ChildSize = SongContainer.GetChildren().Count * 75; - int TotalSize = 75 * DisplayedSongs.Count(); - int TopMarginSize = CurrentIndex*75; + void update_margins(int CurrentIndex,int songsize = 75){ + int ChildSize = SongContainer.GetChildren().Count * songsize; + int TotalSize = songsize * DisplayedSongs.Count(); + int TopMarginSize = CurrentIndex*songsize; int LowMarginSize = TotalSize-ChildSize-TopMarginSize; UpperMargin.CustomMinimumSize = new Vector2(0,TopMarginSize); LowerMargin.CustomMinimumSize = new Vector2(0, LowMarginSize); diff --git a/Scripts/SongDisplay.cs b/Scripts/SongDisplay.cs index 2441a52..38c7ec7 100644 --- a/Scripts/SongDisplay.cs +++ b/Scripts/SongDisplay.cs @@ -10,6 +10,7 @@ public partial class SongDisplay : Control [Export] Label NameLabel; [Export] Label ArtistLabel; [Export] Button PlayButton; + [Export] Button OpenURLButton; public void Setup(Song info){ SavedInfo = info; Image image = info.LoadImage(); @@ -18,14 +19,16 @@ public partial class SongDisplay : Control background.Texture = tex; } NameLabel.Text = SavedInfo.Name; - if (SavedInfo.Artists.Any()){ - ArtistLabel.Text = SavedInfo.Artists[0]; + ArtistLabel.Text = SavedInfo.Artist; - } PlayButton.Pressed += ButtonPressed; + OpenURLButton.Pressed += URLOpen; } void ButtonPressed(){ - Context.instance.LoadSong(SavedInfo.Directory); - Context.instance.PlaySong(); + Context.ISongPlayer.LoadSong(SavedInfo); + Context.ISongPlayer.PlaySong(); + } + void URLOpen(){ + OS.ShellOpen(SavedInfo.URL); } } diff --git a/Scripts/SongPlayer.cs b/Scripts/SongPlayer.cs new file mode 100644 index 0000000..f08d66d --- /dev/null +++ b/Scripts/SongPlayer.cs @@ -0,0 +1,68 @@ +using Godot; +using System; +public partial class SongPlayer : Node{ + AudioStreamPlayer Player; + + public Action SongChanged; + public Action SongStateUpdated; + public void PlaySong(){ + GD.Print("PlaySong"); + Player?.Play(); + SongStateUpdated?.Invoke(false); + } + public void PauseSong(){ + GD.Print("PauseSong"); + if (Player == null){ + return; + } + Player.StreamPaused = true; + SongStateUpdated?.Invoke(true); + } + public void UnpauseSong(){ + GD.Print("UnpauseSong"); + if (Player == null){ + return; + } + Player.StreamPaused = false; + SongStateUpdated?.Invoke(false); + } + public void LoadSong(Song song){ + Player?.QueueFree(); + if (song.Directory.ToLower().EndsWith(".mp3")){ + AudioStreamMP3 stream = AudioStreamMP3.LoadFromFile(song.Directory); + Player = new AudioStreamPlayer(); + Player.Stream = stream; + AddChild(Player); + } + else if(song.Directory.ToLower().EndsWith(".wav")){ + AudioStreamWav stream = AudioStreamWav.LoadFromFile(song.Directory); + Player = new AudioStreamPlayer(); + Player.Stream = stream; + AddChild(Player); + } + else if(song.Directory.ToLower().EndsWith(".ogg")){ + AudioStreamOggVorbis stream = AudioStreamOggVorbis.LoadFromFile(song.Directory); + Player = new AudioStreamPlayer(); + Player.Stream = stream; + AddChild(Player); + } + GD.Print("Playing ", song.Directory); + SongChanged?.Invoke(song); + Player.Bus = "Music"; + } + // 0 - 1 range + public void SetPosition(float Position){ + if (Player == null || Player.Stream == null){ + return; + } + float length = (float)Player.Stream.GetLength(); + Player.Play(length*Position); + } + public float GetPosition(){ + if (Player == null || Player.Stream == null){ + return 0f; + } + float length = (float)Player.Stream.GetLength(); + return (float)Player.GetPlaybackPosition()/length; + } +} diff --git a/Scripts/SongPlayer.cs.uid b/Scripts/SongPlayer.cs.uid new file mode 100644 index 0000000..8f7796d --- /dev/null +++ b/Scripts/SongPlayer.cs.uid @@ -0,0 +1 @@ +uid://d3v27hhdedguv diff --git a/Scripts/UIManager.cs b/Scripts/UIManager.cs new file mode 100644 index 0000000..ce148b7 --- /dev/null +++ b/Scripts/UIManager.cs @@ -0,0 +1,68 @@ +using Godot; +using Instances; +using System; +using System.Collections.Generic; +using System.Linq; + +public partial class UIManager : Node{ + [Export] Button PlayPauseButton; + [Export] Texture2D PauseImage; + [Export] Texture2D PlayImage; + [Export] HSlider ProgressIndicator; + [Export] Button SkipButton; + [Export] Button GoBackButton; + [Export] Button LoopButton; + [Export] Button RandomizeButton; + + bool SliderDragging; + + static UIManager instance; + public override void _Ready() + { + base._Ready(); + instance = this; + ProgressIndicator.DragStarted += sliderDrag; + ProgressIndicator.DragEnded += sliderDragEnded; + PlayPauseButton.Toggled += PausePlay; + Context.ISongPlayer.SongStateUpdated += UpdatePausePlay; + } + + void PausePlay(bool Newstate){ + if (Newstate){ + Context.ISongPlayer.PauseSong(); + PlayPauseButton.Icon = PlayImage; + } + else{ + Context.ISongPlayer.UnpauseSong(); + PlayPauseButton.Icon = PauseImage; + } + } + + void UpdatePausePlay(bool paused){ + if (paused){ + PlayPauseButton.Icon = PlayImage; + PlayPauseButton.ButtonPressed = true; + } + else{ + PlayPauseButton.Icon = PauseImage; + PlayPauseButton.ButtonPressed = false; + } + } + + public override void _Process(double delta) + { + base._Process(delta); + if (!SliderDragging){ + ProgressIndicator.Value = Context.ISongPlayer.GetPosition(); + } + } + + void sliderDrag(){ + SliderDragging = true; + } + void sliderDragEnded(bool changed){ + SliderDragging = false; + + Context.ISongPlayer.SetPosition((float)ProgressIndicator.Value); + } +} \ No newline at end of file diff --git a/Scripts/UIManager.cs.uid b/Scripts/UIManager.cs.uid new file mode 100644 index 0000000..0cf4592 --- /dev/null +++ b/Scripts/UIManager.cs.uid @@ -0,0 +1 @@ +uid://ci5h1wwbedkbt diff --git a/Simplaudio.csproj b/Simplaudio.csproj index 92c58c3..382f7f4 100644 --- a/Simplaudio.csproj +++ b/Simplaudio.csproj @@ -8,5 +8,6 @@ + \ No newline at end of file