diff --git a/build-aux/clapper/clapper.json b/build-aux/clapper/clapper.json index 8a33c8876..58b67ce1b 100644 --- a/build-aux/clapper/clapper.json +++ b/build-aux/clapper/clapper.json @@ -17,6 +17,10 @@ "type": "git", "url": "https://github.com/Rafostar/clapper.git", "branch": "master" - } + }, + { + "type": "shell", + "commands": ["sed -i \"s/version: '0.7.0',/version: '0.8.0',/g\" meson.build"] + } ] -} \ No newline at end of file +} diff --git a/meson.build b/meson.build index 8d367b27d..a6ea9806b 100644 --- a/meson.build +++ b/meson.build @@ -107,6 +107,10 @@ if clapper_support and clapper_dep.found () and clapper_dep.version().version_co if (clapper_dep.get_variable('features').split().contains('mpris')) add_project_arguments(['--define=CLAPPER_MPRIS'], language: 'vala') endif + + if clapper_dep.version().version_compare('>=0.8.0') + add_project_arguments(['--define=CLAPPER_0_8'], language: 'vala') + endif endif if gtk_dep.version().version_compare('>=4.14') diff --git a/src/Views/MediaViewer.vala b/src/Views/MediaViewer.vala index acafc5801..e7baadc21 100644 --- a/src/Views/MediaViewer.vala +++ b/src/Views/MediaViewer.vala @@ -416,8 +416,28 @@ public class Tuba.Views.MediaViewer : Gtk.Widget, Gtk.Buildable, Adw.Swipeable { } } + #if CLAPPER_0_8 + string clapper_cache_dir; + Gee.HashMap clapper_cached_urls; + #endif construct { #if CLAPPER + #if CLAPPER_0_8 + clapper_cached_urls = new Gee.HashMap (); + clapper_cache_dir = GLib.Path.build_path (GLib.Path.DIR_SEPARATOR_S, Tuba.cache_path, "clapper"); + var dir = File.new_for_path (clapper_cache_dir); + if (!dir.query_exists ()) { + try { + dir.make_directory_with_parents (); + } catch (Error e) { + critical (@"Couldn't create Clapper cache dir: $(e.message)"); + } + } + + clapper_cache_cleanup (true); + app.shutdown.connect (() => clapper_cache_cleanup (true)); + #endif + // Clapper can have > 1.0 volumes last_used_volume = settings.media_viewer_last_used_volume; #else @@ -550,6 +570,11 @@ public class Tuba.Views.MediaViewer : Gtk.Widget, Gtk.Buildable, Adw.Swipeable { ~MediaViewer () { debug ("Destroying MediaViewer"); context_menu.unparent (); + #if CLAPPER_0_8 + clapper_cache_cleanup (true); + clapper_cached_urls.clear (); + clapper_cached_locations.clear (); + #endif } private void on_visible_toggle () { @@ -903,6 +928,10 @@ public class Tuba.Views.MediaViewer : Gtk.Widget, Gtk.Buildable, Adw.Swipeable { items.clear (); revealed = false; + + #if CLAPPER_0_8 + clapper_cache_cleanup (); + #endif } private void update_revealer_widget (int pos = -1) { @@ -948,6 +977,13 @@ public class Tuba.Views.MediaViewer : Gtk.Widget, Gtk.Buildable, Adw.Swipeable { var video = new ClapperGtk.Video () { auto_inhibit = true }; + + #if CLAPPER_0_8 + video.player.download_dir = clapper_cache_dir; + video.player.download_enabled = true; + video.player.download_complete.connect (on_clapper_download_complete); + #endif + #else var video = new Gtk.Video () { #if GTK_4_16 @@ -969,7 +1005,7 @@ public class Tuba.Views.MediaViewer : Gtk.Widget, Gtk.Buildable, Adw.Swipeable { #if CLAPPER #if CLAPPER_MPRIS video.player.add_feature (new Clapper.Mpris ( - "org.mpris.MediaPlayer2.Tuba", + @"org.mpris.MediaPlayer2.Tuba.instance$(items.size)", Build.NAME, Build.DOMAIN )); @@ -984,7 +1020,13 @@ public class Tuba.Views.MediaViewer : Gtk.Widget, Gtk.Buildable, Adw.Swipeable { item = new Item (video, final_friendly_url, final_preview, true); #if CLAPPER - var clp_item = new Clapper.MediaItem (url); + Clapper.MediaItem clp_item; + #if CLAPPER_0_8 + clp_item = new Clapper.MediaItem.cached (url, clapper_cached_urls.get (url)); + #else + clp_item = new Clapper.MediaItem (url); + #endif + video.player.queue.add_item (clp_item); video.player.queue.select_item (clp_item); add_todo_item (item); @@ -1037,6 +1079,56 @@ public class Tuba.Views.MediaViewer : Gtk.Widget, Gtk.Buildable, Adw.Swipeable { if (as_is || stream) add_todo_item (item); } + #if CLAPPER_0_8 + // libgee's hashmaps do not preserve insertion order. + // We need the order to know what we should cleanup + // (older items get cleaned up first). + Gee.ArrayList clapper_cached_locations = new Gee.ArrayList (); + private void on_clapper_download_complete (Clapper.MediaItem clp_media_item, string location) { + clapper_cached_urls.set (clp_media_item.uri, location); + clapper_cached_locations.add (location); + } + + private void clapper_cache_cleanup (bool all = false) { + if (!all) { + int to_remove = clapper_cached_locations.size - 10; + if (to_remove > 0) { + var sliced = clapper_cached_locations.slice (0, to_remove); + clapper_cached_locations.remove_all (sliced); + + clapper_cached_urls.foreach (e => { + if (!clapper_cached_locations.contains (e.value)) + clapper_cached_urls.unset (e.key); + + return true; + }); + } + } + + try { + Dir dir = Dir.open (clapper_cache_dir, 0); + string? name = null; + + while ((name = dir.read_name ()) != null) { + string path = Path.build_filename (clapper_cache_dir, name); + if (!all && clapper_cached_locations.contains (path)) continue; + + File file = File.new_for_path (path); + file.delete_async.begin (Priority.LOW, null, (obj, res) => { + try { + file.delete_async.end (res); + } catch (Error e) { + warning (@"Error while deleting Clapper's cache: $(e.message)"); + } + }); + } + } catch (FileError e) { + warning (@"Error while opening Clapper's cache: $(e.message)"); + } + return; + } + #endif + private Gee.ArrayList todo_items = new Gee.ArrayList (); private void add_todo_item (Item todo_item) { if (revealed) {