Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement a library #756

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d40c9ac
Split queue into own class and add stack to swtich between library an…
leolost2605 Jul 23, 2023
add684b
Add library prototype
leolost2605 Jul 23, 2023
87fedc0
Playback from library is now working
leolost2605 Jul 23, 2023
0bc75b8
Use a stackswitcher
leolost2605 Jul 23, 2023
a51ea81
Make previous/next work
leolost2605 Jul 23, 2023
e7267ea
Cleanup
leolost2605 Jul 23, 2023
31172ac
Add placeholder
leolost2605 Jul 23, 2023
b11ddac
Implement recursive directory searching and directory monitoring
leolost2605 Jul 23, 2023
ce48707
Cleanup
leolost2605 Jul 23, 2023
a59561c
Cleanup
leolost2605 Jul 23, 2023
172f051
Fix
leolost2605 Jul 23, 2023
ee4fe2d
We've succesfully queried something
leolost2605 Jul 24, 2023
6e874f3
Detect audio files with artist title and duration
leolost2605 Jul 24, 2023
b1749f7
Add notifier (not working yet)
leolost2605 Jul 24, 2023
92adb55
Use audio graph
leolost2605 Jul 24, 2023
9ff8e1f
Cleanup
leolost2605 Jul 24, 2023
687c06e
Notifying somewhat works now
leolost2605 Jul 24, 2023
da2a2c9
Tracker works really good now
leolost2605 Jul 24, 2023
3c0359a
Don't thread manually
leolost2605 Jul 24, 2023
bbf58e6
Workaround tracker bug
leolost2605 Jul 24, 2023
ba600fc
Fix queue crash and deletion is now refelected
leolost2605 Jul 25, 2023
cc1a2af
Sort alphabeticly
leolost2605 Jul 25, 2023
8a3a78e
Add a loading placeholder
leolost2605 Jul 25, 2023
43226a0
Use basename if no title was found + load images in library
leolost2605 Jul 25, 2023
674f3cd
Don't abort when failing to create a thread
leolost2605 Jul 25, 2023
768c94e
Remove need for laoding placeholder
leolost2605 Aug 1, 2023
f570074
Move all metadata discovery to audioobject
leolost2605 Aug 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion io.elementary.music.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ finish-args:
- '--socket=wayland'
- '--socket=pulseaudio'
- '--device=dri'
- '--filesystem=xdg-music:ro'
- '--filesystem=xdg-music'
- '--add-policy=Tracker3.dbus:org.freedesktop.Tracker3.Miner.Files=tracker:Audio'

modules:
- name: music
Expand Down
4 changes: 3 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ gstreamer_dep = dependency('gstreamer-1.0')
gstreamer_pbutils_dep = dependency('gstreamer-pbutils-1.0')
gstreamer_tag_dep = dependency('gstreamer-tag-1.0')
gtk_dep = dependency('gtk4')
tracker_dep = dependency('tracker-sparql-3.0')

dependencies = [
granite_dep,
gstreamer_dep,
gstreamer_pbutils_dep,
gstreamer_tag_dep,
gtk_dep
gtk_dep,
tracker_dep
]

meson.add_install_script('meson/post_install.py')
Expand Down
74 changes: 71 additions & 3 deletions src/AudioObject.vala
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,81 @@
*/

public class Music.AudioObject : Object {
public string uri { get; construct; }
public string uri { get; set; }
public Gdk.Texture texture { get; set; }
public string artist { get; set; }
public string title { get; set; }
public int64 duration { get; set; default = 0; }

public AudioObject (string uri) {
Object (uri: uri);
public AudioObject.from_file (File file) {
uri = file.get_uri ();

string? basename = file.get_basename ();

if (basename != null) {
title = basename;
} else {
title = uri;
}
}

public void update_metadata () {
try {
new Thread<void*>.try (null, () => {
try {
var discoverer = new Gst.PbUtils.Discoverer ((Gst.ClockTime) (5 * Gst.SECOND));

var info = discoverer.discover_uri (uri);

if (info == null) {
warning ("Discovery failed.");
return null;
}

unowned Gst.TagList? tag_list = info.get_tags ();

duration = (int64) info.get_duration ();

string _title;
tag_list.get_string (Gst.Tags.TITLE, out _title);
if (_title != null) {
title = _title;
}

string _artist;
tag_list.get_string (Gst.Tags.ARTIST, out _artist);
if (_artist != null) {
artist = _artist;
} else if (_title != null) { // Don't set artist for files without tags
artist = _("Unknown");
}

var sample = PlaybackManager.get_cover_sample (tag_list);
if (sample != null) {
var buffer = sample.get_buffer ();

Gst.MapInfo? map_info = null;
if (buffer != null && buffer.map (out map_info, Gst.MapFlags.READ) && map_info != null) {
var bytes = new Bytes (map_info.data);
try {
texture = Gdk.Texture.from_bytes (bytes);
} catch (Error e) {
warning ("Error processing image data: %s", e.message);
}

buffer.unmap (map_info);
} else {
warning ("Could not map memory buffer");
}
}
} catch (Error e) {
warning ("Failed to create texture: %s", e.message);
}

return null;
});
} catch (Error e) {
warning ("Failed to create thread: %s", e.message);
}
}
}
126 changes: 23 additions & 103 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
private Settings settings;

construct {
var playback_manager = PlaybackManager.get_default ();

var start_window_controls = new Gtk.WindowControls (Gtk.PackType.START);

var stack_switcher = new Gtk.StackSwitcher () {
hexpand = false
};
((Gtk.BoxLayout)stack_switcher.get_layout_manager ()).homogeneous = true;

shuffle_button = new Gtk.Button.from_icon_name ("media-playlist-shuffle-symbolic") {
action_name = Application.ACTION_PREFIX + Application.ACTION_SHUFFLE,
tooltip_text = _("Shuffle")
Expand All @@ -24,46 +27,30 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
show_title_buttons = false,
title_widget = new Gtk.Label ("")
};
queue_header.add_css_class (Granite.STYLE_CLASS_FLAT);
queue_header.add_css_class (Granite.STYLE_CLASS_DEFAULT_DECORATION);
queue_header.pack_start (start_window_controls);
queue_header.pack_end (shuffle_button);
queue_header.pack_end (repeat_button);

var queue_placeholder = new Granite.Placeholder (_("Queue is Empty")) {
description = _("Audio files opened from Files will appear here"),
icon = new ThemedIcon ("playlist-queue")
};

var queue_listbox = new Gtk.ListBox () {
hexpand = true,
vexpand = true
};
queue_listbox.bind_model (playback_manager.queue_liststore, create_queue_row);
queue_listbox.set_placeholder (queue_placeholder);

var scrolled = new Gtk.ScrolledWindow () {
child = queue_listbox
var start_header = new Gtk.HeaderBar () {
show_title_buttons = false,
title_widget = stack_switcher
};
start_header.add_css_class (Granite.STYLE_CLASS_FLAT);
start_header.pack_start (start_window_controls);
start_header.pack_end (shuffle_button);
start_header.pack_end (repeat_button);

var drop_target = new Gtk.DropTarget (typeof (Gdk.FileList), Gdk.DragAction.COPY);
var queue_view = new QueueView ();

var queue = new Gtk.Grid ();
queue.add_css_class (Granite.STYLE_CLASS_VIEW);
queue.attach (queue_header, 0, 0);
queue.attach (scrolled, 0, 1);
queue.add_controller (drop_target);
var library_view = new LibraryView ();

var error_toast = new Granite.Toast ("");
var stack = new Gtk.Stack ();
stack.add_titled (library_view, null, _("Library"));
stack.add_titled (queue_view, null, _("Play Queue"));

var queue_overlay = new Gtk.Overlay () {
child = queue
};
queue_overlay.add_overlay (error_toast);
stack_switcher.stack = stack;

var queue_handle = new Gtk.WindowHandle () {
child = queue_overlay
};
var start_box = new Gtk.Box (VERTICAL, 0);
start_box.add_css_class (Granite.STYLE_CLASS_VIEW);
start_box.append (start_header);
start_box.append (stack);

var end_window_controls = new Gtk.WindowControls (Gtk.PackType.END);

Expand All @@ -72,7 +59,6 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
title_widget = new Gtk.Label ("")
};
end_header.add_css_class (Granite.STYLE_CLASS_FLAT);
end_header.add_css_class (Granite.STYLE_CLASS_DEFAULT_DECORATION);
end_header.pack_end (end_window_controls);

var now_playing_view = new NowPlayingView () {
Expand All @@ -92,7 +78,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
};

var paned = new Gtk.Paned (Gtk.Orientation.HORIZONTAL) {
start_child = queue_handle,
start_child = start_box,
end_child = now_playing_handle,
resize_end_child = false,
shrink_end_child = false,
Expand All @@ -113,40 +99,6 @@ public class Music.MainWindow : Gtk.ApplicationWindow {

update_repeat_button ();

drop_target.drop.connect ((target, value, x, y) => {
if (value.type () == typeof (Gdk.FileList)) {
File[] files;
SList<File> file_list = null;
foreach (unowned var file in (SList<File>) value.get_boxed ()) {
var file_type = file.query_file_type (FileQueryInfoFlags.NONE);
if (file_type == FileType.DIRECTORY) {
prepend_directory_files (file, ref file_list);
} else {
file_list.prepend (file);
}
}

file_list.reverse ();
foreach (unowned var file in file_list) {
files += file;
}

playback_manager.queue_files (files);

return true;
}

return false;
});

playback_manager.invalids_found.connect ((count) => {
error_toast.title = ngettext (
"%d invalid file was not added to the queue",
"%d invalid files were not added to the queue",
count).printf (count);
error_toast.send_notification ();
});

repeat_button.clicked.connect (() => {
var enum_step = settings.get_enum ("repeat-mode");
if (enum_step < 2) {
Expand All @@ -155,33 +107,6 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
settings.set_enum ("repeat-mode", 0);
}
});

queue_listbox.row_activated.connect ((row) => {
playback_manager.current_audio = ((TrackRow) row).audio_object;
});
}

//Array concatenation not permitted for parameters so use a list instead
private void prepend_directory_files (GLib.File dir, ref SList<File> file_list) {
try {
var enumerator = dir.enumerate_children (
"standard::*",
FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
null
);

FileInfo info = null;
while ((info = enumerator.next_file (null)) != null) {
var child = dir.resolve_relative_path (info.get_name ());
if (info.get_file_type () == FileType.DIRECTORY) {
prepend_directory_files (child, ref file_list);
} else {
file_list.prepend (child);
}
}
} catch (Error e) {
warning ("Error while enumerating children of %s: %s", dir.get_uri (), e.message);
}
}

private void update_repeat_button () {
Expand All @@ -200,9 +125,4 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
break;
}
}

private Gtk.Widget create_queue_row (GLib.Object object) {
unowned var audio_object = (AudioObject) object;
return new TrackRow (audio_object);
}
}
Loading