From e758d1df2bd962b14bc0e4f201444a1758aeb8f0 Mon Sep 17 00:00:00 2001 From: Bucket Of Chicken <122376377+realbucketofchicken@users.noreply.github.com> Date: Sat, 30 Aug 2025 13:31:07 +0200 Subject: [PATCH] loading songs --- Scenes/main.tscn | 53 ++++++++++++++++++++- Scenes/song_display.tscn | 81 ++++++++++++++++++++++++++++++++ Scripts/Context.cs | 37 +++++++++++---- Scripts/Data.cs | 65 +++++++++++++++++--------- Scripts/SearchDisplay.cs | 91 ++++++++++++++++++++++++++++++++++++ Scripts/SearchDisplay.cs.uid | 1 + Scripts/SongDisplay.cs | 25 ++++++++++ Scripts/SongDisplay.cs.uid | 1 + 8 files changed, 323 insertions(+), 31 deletions(-) create mode 100644 Scenes/song_display.tscn create mode 100644 Scripts/SearchDisplay.cs create mode 100644 Scripts/SearchDisplay.cs.uid create mode 100644 Scripts/SongDisplay.cs create mode 100644 Scripts/SongDisplay.cs.uid diff --git a/Scenes/main.tscn b/Scenes/main.tscn index 64508ad..416709b 100644 --- a/Scenes/main.tscn +++ b/Scenes/main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=3 uid="uid://mfcbf2sfino6"] +[gd_scene load_steps=14 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"] @@ -8,7 +8,9 @@ [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"] [ext_resource type="Texture2D" uid="uid://38c8dfym0svn" path="res://Icons/Loop.png" id="4_21xkr"] +[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"] [sub_resource type="GDScript" id="GDScript_bo1nx"] resource_name = "OpenDirGlue" @@ -49,6 +51,7 @@ grow_horizontal = 2 grow_vertical = 2 [node name="Background" type="TextureRect" parent="."] +z_index = -2 layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -133,10 +136,48 @@ layout_mode = 2 icon = ExtResource("2_344ge") expand_icon = true -[node name="Control" type="Control" parent="Padding/VBoxContainer"] +[node name="Center" type="Control" parent="Padding/VBoxContainer"] layout_mode = 2 size_flags_vertical = 3 +[node name="SearchResults" type="Panel" parent="Padding/VBoxContainer/Center"] +custom_minimum_size = Vector2(200, 0) +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.28500003 +anchor_right = 0.71500003 +anchor_bottom = 0.93700004 +offset_left = 0.20996094 +offset_right = -0.21002197 +offset_bottom = 0.12197876 +grow_horizontal = 2 + +[node name="ScrollContainer" type="ScrollContainer" parent="Padding/VBoxContainer/Center/SearchResults"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +follow_focus = true +horizontal_scroll_mode = 0 + +[node name="VBoxContainer" type="VBoxContainer" parent="Padding/VBoxContainer/Center/SearchResults/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/separation = 0 + +[node name="UpperMargin" type="Control" parent="Padding/VBoxContainer/Center/SearchResults/ScrollContainer/VBoxContainer"] +layout_mode = 2 + +[node name="SongContainer" type="VBoxContainer" parent="Padding/VBoxContainer/Center/SearchResults/ScrollContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = 0 + +[node name="LowerMargin" type="Control" parent="Padding/VBoxContainer/Center/SearchResults/ScrollContainer/VBoxContainer"] +layout_mode = 2 + [node name="Bottom" type="Control" parent="Padding/VBoxContainer"] custom_minimum_size = Vector2(0, 42) layout_mode = 2 @@ -214,3 +255,11 @@ offset_top = -23.0 grow_horizontal = 0 grow_vertical = 0 text = "v2.0" + +[node name="SearchDisplay" type="Node" parent="." node_paths=PackedStringArray("UpperMargin", "SongContainer", "LowerMargin", "Scroll")] +script = ExtResource("4_hptm8") +display = ExtResource("5_d1ilt") +UpperMargin = NodePath("../Padding/VBoxContainer/Center/SearchResults/ScrollContainer/VBoxContainer/UpperMargin") +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") diff --git a/Scenes/song_display.tscn b/Scenes/song_display.tscn new file mode 100644 index 0000000..8391ba1 --- /dev/null +++ b/Scenes/song_display.tscn @@ -0,0 +1,81 @@ +[gd_scene load_steps=4 format=3 uid="uid://c21wc1bq2pnm"] + +[ext_resource type="Script" uid="uid://bs55rsv7eh4l5" path="res://Scripts/SongDisplay.cs" id="1_76jf4"] + +[sub_resource type="LabelSettings" id="LabelSettings_swnt4"] +font_size = 20 +shadow_size = 2 +shadow_color = Color(0, 0, 0, 0.5647059) + +[sub_resource type="LabelSettings" id="LabelSettings_8tgr4"] +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")] +custom_minimum_size = Vector2(0, 75) +layout_mode = 3 +anchor_right = 1.0 +grow_horizontal = 2 +script = ExtResource("1_76jf4") +background = NodePath("TextureRect") +NameLabel = NodePath("VBoxContainer/Name") +ArtistLabel = NodePath("VBoxContainer/Artist") + +[node name="Panel" type="Panel" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="TextureRect" type="TextureRect" parent="."] +custom_minimum_size = Vector2(0, 75) +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +expand_mode = 3 +stretch_mode = 6 + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +mouse_filter = 2 + +[node name="Name" type="Label" parent="VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 6 +text = "Name" +label_settings = SubResource("LabelSettings_swnt4") +clip_text = true +text_overrun_behavior = 3 + +[node name="Artist" type="Label" parent="VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 6 +text = "Artist" +label_settings = SubResource("LabelSettings_8tgr4") +clip_text = true +text_overrun_behavior = 3 + +[node name="Playbutton" type="Button" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +flat = true diff --git a/Scripts/Context.cs b/Scripts/Context.cs index 65e4667..c8a1d55 100644 --- a/Scripts/Context.cs +++ b/Scripts/Context.cs @@ -1,22 +1,43 @@ using Godot; +using Instances; using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; public partial class Context : Node { - - Song[] Songs; + public Thread processingThread; + public static Context instance; + public IEnumerable Songs; AudioStreamPlayer[] StreamPlayers; - DirectoryManager manager = new(); + DirectoryLoader manager = new(); + public event EventHandler SongsUpdated; + public delegate void SongsUpdatedEventHandler(object sender, SongsUpdatedEventArgs e); + + public override void _Ready() + { + base._Ready(); + instance = this; + } public void LoadDirectory(String path){ GD.Print(path); Songs = manager.LoadDirectory(path); - GD.Print("got here"); - foreach (Song song in Songs){ - GD.Print("got ", song.Name); - } - + GD.Print("Songs loaded"); + SongsUpdatedEventArgs args = new(); + args.songs = Songs; + OnSongsUpdated(args); } + protected virtual void OnSongsUpdated(SongsUpdatedEventArgs e){ + SongsUpdated.Invoke(this,e); + } + +} + +public class SongsUpdatedEventArgs : EventArgs +{ + public IEnumerable songs; } diff --git a/Scripts/Data.cs b/Scripts/Data.cs index 17e2406..95ed992 100644 --- a/Scripts/Data.cs +++ b/Scripts/Data.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -11,54 +12,76 @@ using TagLib.Riff; public class Song{ public String Name; + public bool LoadedMetadata; public String[] Artists; public String Album; public float Length; public String Comment; 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(); + } + public Image LoadImage(){ + var TLfile = TagLib.File.Create(Directory); + if (TLfile.Tag.Pictures.Count() == 0){ + return null; + } + String type = TLfile.Tag.Pictures[0].MimeType; + byte[] pictureData = TLfile.Tag.Pictures[0].Data.Data; + Image image = new Image(); + Error error = Error.Failed; + switch (type) + { + case "image/jpeg": + error = image.LoadJpgFromBuffer(pictureData); + break; + case "image/png": + error = image.LoadPngFromBuffer(pictureData); + break; + case "image/webp": + error = image.LoadWebpFromBuffer(pictureData); + break; + } + GD.Print(image); + return image; + } } -public class DirectoryManager{ +public class DirectoryLoader{ Task LoadTask; - Song[] LoadedSongs; - public Song[] LoadDirectory(String Path){ + IEnumerable LoadedSongs; + public IEnumerable LoadDirectory(String Path){ - LoadTask = new Task(() => ParseDirectory(Path)); - LoadTask.Start(); - Task.WhenAll([LoadTask]).Wait(); + GD.Print("Finished"); - return LoadedSongs; + return ParseDirectory(Path); //if (file.EndsWith(".mp3")) } - private void ParseDirectory(String Path){ + private IEnumerable ParseDirectory(String Path){ System.Collections.Generic.IEnumerable Files = Directory.EnumerateFiles(Path); - Song[] Songs = []; + IEnumerable Songs = []; foreach (String file in Files){ if (!(file.EndsWith(".mp3") || file.EndsWith(".ogg") || file.EndsWith(".wav"))){ continue; } - var TLfile = TagLib.File.Create(file); - Song song = new() { - Album = TLfile.Tag.Album, - Artists = TLfile.Tag.Performers, - Name = TLfile.Tag.Title, - Length = TLfile.Length, Directory = file, - Comment = TLfile.Tag.Comment }; - if (file.EndsWith(".mp3")){ - song.Comment = TLfile.GetTag(TagLib.TagTypes.Id3v2, true).Comment; - } //TLfile.Tag.CopyTo(Tag) //GD.Print("File Valid, file path ",song.Directory); - Songs.Append(song); + Songs = Songs.Append(song); //if (file.EndsWith(".mp3")) } - LoadedSongs = Songs; + return Songs; } } diff --git a/Scripts/SearchDisplay.cs b/Scripts/SearchDisplay.cs new file mode 100644 index 0000000..d3ee8d1 --- /dev/null +++ b/Scripts/SearchDisplay.cs @@ -0,0 +1,91 @@ +using Godot; +using System; +using System.Collections.Generic; +using System.Linq; + +public partial class SearchDisplay : Node +{ + [Export] PackedScene display; + [Export] Control UpperMargin; + [Export] Control SongContainer; + [Export] Control LowerMargin; + [Export] ScrollContainer Scroll; + + public override void _Ready() + { + base._Ready(); + Context.instance.SongsUpdated += UpdateDisplay; + + } + IEnumerable DisplayedSongs = []; + void UpdateDisplay(object sender,EventArgs eventArgs){ + SongsUpdatedEventArgs args = (SongsUpdatedEventArgs)eventArgs; + DisplayedSongs = args.songs; + GD.Print("Updated, songs ",args.songs.Count()); + + } + + public override void _Process(double delta) + { + base._Process(delta); + int CurrentIndex = (int)(Scroll.ScrollVertical/ 75); + int MaxIndex = (int)((Scroll.Size.Y / 75)+CurrentIndex+1); + + IEnumerable DisplayRemove =[]; + IEnumerable ids = []; + IEnumerable displays = []; + + foreach(Node child in SongContainer.GetChildren()){ + if (child is SongDisplay display1) + { + displays = displays.Append(display1); + } + } + if (displays.Any()) + { + foreach (SongDisplay display in displays){ + if (display.DisplayId < CurrentIndex || display.DisplayId > MaxIndex){ + DisplayRemove = DisplayRemove.Append(display); + } + else{ + ids = ids.Append(display.DisplayId); + } + } + } + for (int i = CurrentIndex; i >= CurrentIndex && i <= MaxIndex;i++) + { + if (!ids.Contains(i)){ + if (i > DisplayedSongs.Count()-1){ + break; + } + Song Songinfo = DisplayedSongs.ElementAt(i); + if (!Songinfo.LoadedMetadata){ + Songinfo.LoadMetadata(); + } + SongDisplay scene = (SongDisplay)display.Instantiate(); + SongContainer.AddChild(scene); + scene.Setup(Songinfo); + scene.DisplayId = i; + SongContainer.MoveChild(scene,i - CurrentIndex); + GD.Print("IDKENX ", i - CurrentIndex ); + GD.Print("CurrentIndex ", CurrentIndex); + displays = displays.Append(scene); + } + } + + foreach (SongDisplay display in DisplayRemove) + { + display.QueueFree(); + } + update_margins(CurrentIndex); + } + void update_margins(int CurrentIndex){ + int ChildSize = SongContainer.GetChildren().Count * 75; + int TotalSize = 75 * DisplayedSongs.Count(); + int TopMarginSize = CurrentIndex*75; + int LowMarginSize = TotalSize-ChildSize-TopMarginSize; + UpperMargin.CustomMinimumSize = new Vector2(0,TopMarginSize); + LowerMargin.CustomMinimumSize = new Vector2(0, LowMarginSize); + } + +} diff --git a/Scripts/SearchDisplay.cs.uid b/Scripts/SearchDisplay.cs.uid new file mode 100644 index 0000000..e7c031d --- /dev/null +++ b/Scripts/SearchDisplay.cs.uid @@ -0,0 +1 @@ +uid://dq3yj21reqk80 diff --git a/Scripts/SongDisplay.cs b/Scripts/SongDisplay.cs new file mode 100644 index 0000000..93ca21e --- /dev/null +++ b/Scripts/SongDisplay.cs @@ -0,0 +1,25 @@ +using Godot; +using System; +using System.Linq; + +public partial class SongDisplay : Control +{ + public int DisplayId; + Song SavedInfo; + [Export] TextureRect background; + [Export] Label NameLabel; + [Export] Label ArtistLabel; + public void Setup(Song info){ + SavedInfo = info; + Image image = info.LoadImage(); + if (image != null){ + ImageTexture tex = ImageTexture.CreateFromImage(image); + background.Texture = tex; + } + NameLabel.Text = SavedInfo.Name; + if (SavedInfo.Artists.Any()){ + ArtistLabel.Text = SavedInfo.Artists[0]; + + } + } +} diff --git a/Scripts/SongDisplay.cs.uid b/Scripts/SongDisplay.cs.uid new file mode 100644 index 0000000..6cdcc5c --- /dev/null +++ b/Scripts/SongDisplay.cs.uid @@ -0,0 +1 @@ +uid://bs55rsv7eh4l5