Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 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
9e9f7f6
Merge branch 'main' into library
leolost2605 Mar 9, 2025
845d0ec
Fix the merge
leolost2605 Mar 9, 2025
5b08ea4
Revert some next/previous stuff
leolost2605 Mar 9, 2025
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 @@ -25,14 +25,16 @@ 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 = [
adw_dep,
granite_dep,
gstreamer_dep,
gstreamer_pbutils_dep,
gstreamer_tag_dep,
gtk_dep
gtk_dep,
tracker_dep
]

gnome.post_install(glib_compile_schemas: true)
Expand Down
58 changes: 57 additions & 1 deletion src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class Music.Application : Gtk.Application {
public const string ACTION_PREVIOUS = "action-previous";
public const string ACTION_SHUFFLE = "action-shuffle";
public const string ACTION_FIND = "action-find";
public const string ACTION_OPEN = "action-open";
public const string ACTION_QUIT = "action-quit";

private const ActionEntry[] ACTION_ENTRIES = {
Expand All @@ -18,6 +19,7 @@ public class Music.Application : Gtk.Application {
{ ACTION_PREVIOUS, action_previous },
{ ACTION_SHUFFLE, action_shuffle },
{ ACTION_FIND, action_find },
{ ACTION_OPEN, action_open },
{ ACTION_QUIT, quit }
};

Expand Down Expand Up @@ -187,7 +189,61 @@ public class Music.Application : Gtk.Application {
}

private void action_find () {
((MainWindow)active_window).start_search ();
// ((MainWindow)active_window).start_search ();
}

private void action_open () {
var all_files_filter = new Gtk.FileFilter () {
name = _("All files"),
};
all_files_filter.add_pattern ("*");

var music_files_filter = new Gtk.FileFilter () {
name = _("Music files"),
};
music_files_filter.add_mime_type ("audio/*");

var filter_model = new ListStore (typeof (Gtk.FileFilter));
filter_model.append (all_files_filter);
filter_model.append (music_files_filter);

var file_dialog = new Gtk.FileDialog () {
accept_label = _("Open"),
default_filter = music_files_filter,
filters = filter_model,
modal = true,
title = _("Open audio files")
};

file_dialog.open_multiple.begin (active_window, null, (obj, res) => {
try {
var files = file_dialog.open_multiple.end (res);

File[] file_array = {};
for (int i = 0; i < files.get_n_items (); i++) {
file_array += (File)(files.get_item (i));
}

var files_to_play = Application.loop_through_files (file_array);
PlaybackManager.get_default ().queue_files (files_to_play);
} catch (Error e) {
if (e.matches (Gtk.DialogError.quark (), Gtk.DialogError.DISMISSED)) {
return;
}

var dialog = new Granite.MessageDialog (
"Couldn't add audio files",
e.message,
new ThemedIcon ("document-open")
) {
badge_icon = new ThemedIcon ("dialog-error"),
modal = true,
transient_for = active_window
};
dialog.present ();
dialog.response.connect (dialog.destroy);
}
});
}

private void on_bus_acquired (DBusConnection connection, string name) {
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);
}
}
}
Loading