[gnome-music/wip/jfelder/tracker3: 22/22] Bundle Tracker 3 in the Flatpak for systems which don't have it




commit 9174a453174c1165423e72baf19737387da2ae0b
Author: Sam Thursfield <sam afuera me uk>
Date:   Tue Jun 30 00:38:57 2020 +0200

    Bundle Tracker 3 in the Flatpak for systems which don't have it
    
    This commit allows the tracker3 version of GNOME Music to run on systems
    which don't have a suitable version of Tracker in the base OS. It does
    this by running tracker-miner-fs-3 inside the Flatpak sandbox. This will
    lead to increased resource consumption as it'll duplicate the work of
    any indexer in the host OS, but it's better than a broken app.

 data/meson.build                                   |   2 +
 data/tracker/meson.build                           |  31 +++++
 ...g.gnome.Music.Tracker3.Miner.Extract.service.in |   7 ++
 ...org.gnome.Music.Tracker3.Miner.Files.service.in |   7 ++
 data/tracker/org.gnome.Music.domain.rule.in        |  20 +++
 gnomemusic/coregrilo.py                            |   2 +
 gnomemusic/grilowrappers/grltrackerplaylists.py    |  40 +++---
 gnomemusic/grilowrappers/grltrackerwrapper.py      |  41 +++---
 gnomemusic/trackerwrapper.py                       | 138 ++++++++++++++++-----
 meson.build                                        |   2 +-
 org.gnome.Music.json                               |  23 ++--
 11 files changed, 239 insertions(+), 74 deletions(-)
---
diff --git a/data/meson.build b/data/meson.build
index 25ff1e10..a093f1e2 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -81,3 +81,5 @@ install_data(
     install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'icons/hicolor/symbolic/apps'),
     rename: '@0 -symbolic svg'.format(APPLICATION_ID)
 )
+
+subdir('tracker')
diff --git a/data/tracker/meson.build b/data/tracker/meson.build
new file mode 100644
index 00000000..588d5c9a
--- /dev/null
+++ b/data/tracker/meson.build
@@ -0,0 +1,31 @@
+# Files needed for running Tracker inside the Flatpak sandbox, for systems
+# which don't have a suitable version of Tracker in the host OS.
+#
+# We must export the .service files from the sandbox so they work on the
+# session bus. This means the Tracker domain name must correspond with the
+# application ID.
+
+domain_ontologies_dir = get_option('datadir') / 'tracker3' / 'domain-ontologies'
+dbus_services_dir = get_option('datadir') / 'dbus-1' / 'services'
+
+tracker_domain_config = configuration_data()
+tracker_domain_config.set('application_id', APPLICATION_ID)
+tracker_domain_config.set('domain_rule', get_option('prefix') / domain_ontologies_dir / APPLICATION_ID + 
'.domain.rule')
+
+configure_file(
+  input: 'org.gnome.Music.domain.rule.in',
+  output: APPLICATION_ID + '.domain.rule',
+  configuration: tracker_domain_config,
+  install_dir: domain_ontologies_dir)
+
+configure_file(
+  input: 'org.gnome.Music.Tracker3.Miner.Extract.service.in',
+  output: APPLICATION_ID + '.Tracker3.Miner.Extract.service',
+  configuration: tracker_domain_config,
+  install_dir: dbus_services_dir)
+
+configure_file(
+  input: 'org.gnome.Music.Tracker3.Miner.Files.service.in',
+  output: APPLICATION_ID + '.Tracker3.Miner.Files.service',
+  configuration: tracker_domain_config,
+  install_dir: dbus_services_dir)
diff --git a/data/tracker/org.gnome.Music.Tracker3.Miner.Extract.service.in 
b/data/tracker/org.gnome.Music.Tracker3.Miner.Extract.service.in
new file mode 100644
index 00000000..eb7a87aa
--- /dev/null
+++ b/data/tracker/org.gnome.Music.Tracker3.Miner.Extract.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Extract
+Exec=/app/libexec/tracker-extract-3 --domain-ontology @domain_rule@
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Extract
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Music.Tracker3.Miner.Files.service.in 
b/data/tracker/org.gnome.Music.Tracker3.Miner.Files.service.in
new file mode 100644
index 00000000..4fa7371d
--- /dev/null
+++ b/data/tracker/org.gnome.Music.Tracker3.Miner.Files.service.in
@@ -0,0 +1,7 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Files
+Exec=/app/libexec/tracker-miner-fs-3 --domain-ontology @domain_rule@ --initial-sleep 0
+
+# Miner details needed for tracker-control
+Path=/org/freedesktop/Tracker3/Miner/Files
+NameSuffix=Miner.Files
diff --git a/data/tracker/org.gnome.Music.domain.rule.in b/data/tracker/org.gnome.Music.domain.rule.in
new file mode 100644
index 00000000..6119cfc5
--- /dev/null
+++ b/data/tracker/org.gnome.Music.domain.rule.in
@@ -0,0 +1,20 @@
+# This defines a private Tracker domain for GNOME Music.
+#
+# It's used to run the Tracker indexer inside a Flatpak sandbox, when Music is
+# running on a host that doesn't have a suitable version of Tracker installed.
+
+[DomainOntology]
+# Location for the Tracker database
+CacheLocation=$XDG_CACHE_HOME/gnome-music/miner/files
+
+# Name of the ontology to use, must be one located in
+# $(sharedir)/tracker/ontologies
+OntologyName=nepomuk
+
+# DBus name for the owner (not optional). Tracker will use
+# the domain as the prefix of the DBus name for all the
+# services related to this domain ontology.
+Domain=@application_id@
+
+# List of miners we expect to run in this domain.
+Miners=Miner.Files;Miner.Extract
diff --git a/gnomemusic/coregrilo.py b/gnomemusic/coregrilo.py
index e3e9cf3d..d96eb1b5 100644
--- a/gnomemusic/coregrilo.py
+++ b/gnomemusic/coregrilo.py
@@ -87,6 +87,8 @@ class CoreGrilo(GObject.GObject):
         self._registry.add_config(config)
 
         config = Grl.Config.new("grl-tracker3", "grl-tracker3-source")
+        config.set_string(
+            "miner-service", self._tracker_wrapper.props.miner_fs_busname)
         config.set_string(
             "store-path", self._tracker_wrapper.cache_directory())
         self._registry.add_config(config)
diff --git a/gnomemusic/grilowrappers/grltrackerplaylists.py b/gnomemusic/grilowrappers/grltrackerplaylists.py
index d67e39a7..c7854dfc 100644
--- a/gnomemusic/grilowrappers/grltrackerplaylists.py
+++ b/gnomemusic/grilowrappers/grltrackerplaylists.py
@@ -74,7 +74,7 @@ class GrlTrackerPlaylists(GObject.GObject):
         self._user_model_filter = self._coremodel.props.user_playlists_filter
         self._pls_todelete = []
         self._songs_hash = songs_hash
-        self._tracker = tracker_wrapper.props.tracker
+        self._tracker = tracker_wrapper.props.local_db
         self._tracker_wrapper = tracker_wrapper
         self._window = application.props.window
 
@@ -323,7 +323,7 @@ class Playlist(GObject.GObject):
         self._coreselection = application.props.coreselection
         self._log = application.props.log
         self._songs_hash = songs_hash
-        self._tracker = tracker_wrapper.props.tracker
+        self._tracker = tracker_wrapper.props.local_db
         self._tracker_wrapper = tracker_wrapper
         self._window = application.props.window
 
@@ -367,7 +367,7 @@ class Playlist(GObject.GObject):
                         nfo:hasMediaFileListEntry ?entry .
             ?entry a nfo:MediaFileListEntry ;
                      nfo:entryUrl ?url .
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         ?song
@@ -395,7 +395,8 @@ class Playlist(GObject.GObject):
         """.replace('\n', ' ').strip() % {
             "media_type": int(Grl.MediaType.AUDIO),
             "filter_clause": 'tracker:id(?playlist) = ' + self.props.pl_id,
-            "location_filter": self._tracker_wrapper.location_filter()
+            "location_filter": self._tracker_wrapper.location_filter(),
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
         }
 
         def _add_to_playlist_cb(
@@ -607,6 +608,7 @@ class Playlist(GObject.GObject):
                 return
 
             media_id = coresong.props.media.get_id()
+            miner_fs_busname = self._tracker_wrapper.props.miner_fs_busname
             query = """
             SELECT
                 %(media_type)s AS ?type
@@ -625,7 +627,7 @@ class Playlist(GObject.GObject):
                             nfo:hasMediaFileListEntry ?entry .
                 ?entry a nfo:MediaFileListEntry ;
                          nfo:entryUrl ?url .
-                SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+                SERVICE <dbus:%(miner_fs_busname)s> {
                     GRAPH tracker:Audio {
                         SELECT
                             ?song
@@ -651,7 +653,8 @@ class Playlist(GObject.GObject):
             """.replace("\n", " ").strip() % {
                 "media_type": int(Grl.MediaType.AUDIO),
                 "filter_clause": "tracker:id(?song) = " + media_id,
-                "location_filter": self._tracker_wrapper.location_filter()
+                "location_filter": self._tracker_wrapper.location_filter(),
+                "miner_fs_busname": miner_fs_busname,
             }
 
             options = self._fast_options.copy()
@@ -840,7 +843,7 @@ class MostPlayed(SmartPlaylist):
             ?playCount
             ?tag AS ?favorite
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         ?song
@@ -865,7 +868,8 @@ class MostPlayed(SmartPlaylist):
         ORDER BY DESC(?playCount) LIMIT 50
         """.replace('\n', ' ').strip() % {
             "media_type": int(Grl.MediaType.AUDIO),
-            "location_filter": self._tracker_wrapper.location_filter()
+            "location_filter": self._tracker_wrapper.location_filter(),
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
         }
 
 
@@ -892,7 +896,7 @@ class NeverPlayed(SmartPlaylist):
             nie:usageCounter(?song) AS ?playCount
             ?tag AS ?favorite
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         ?song
@@ -916,7 +920,8 @@ class NeverPlayed(SmartPlaylist):
         } ORDER BY nfo:fileLastAccessed(?song) LIMIT 50
         """.replace('\n', ' ').strip() % {
             "media_type": int(Grl.MediaType.AUDIO),
-            "location_filter": self._tracker_wrapper.location_filter()
+            "location_filter": self._tracker_wrapper.location_filter(),
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
         }
 
 
@@ -950,7 +955,7 @@ class RecentlyPlayed(SmartPlaylist):
             nie:usageCounter(?song) AS ?playCount
             ?tag AS ?favorite
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         ?song
@@ -977,7 +982,8 @@ class RecentlyPlayed(SmartPlaylist):
         """.replace('\n', ' ').strip() % {
             "media_type": int(Grl.MediaType.AUDIO),
             'compare_date': compare_date,
-            "location_filter": self._tracker_wrapper.location_filter()
+            "location_filter": self._tracker_wrapper.location_filter(),
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
         }
 
 
@@ -1011,7 +1017,7 @@ class RecentlyAdded(SmartPlaylist):
             nie:usageCounter(?song) AS ?playCount
             ?tag AS ?favorite
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         ?song
@@ -1038,7 +1044,8 @@ class RecentlyAdded(SmartPlaylist):
         """.replace('\n', ' ').strip() % {
             "media_type": int(Grl.MediaType.AUDIO),
             'compare_date': compare_date,
-            "location_filter": self._tracker_wrapper.location_filter()
+            "location_filter": self._tracker_wrapper.location_filter(),
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
         }
 
 
@@ -1065,7 +1072,7 @@ class Favorites(SmartPlaylist):
                 nie:usageCounter(?song) AS ?playCount
                 nao:predefined-tag-favorite AS ?favorite
             WHERE {
-                SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+                SERVICE <dbus:%(miner_fs_busname)s> {
                     GRAPH tracker:Audio {
                         SELECT
                             ?song
@@ -1088,5 +1095,6 @@ class Favorites(SmartPlaylist):
             } ORDER BY DESC(?added)
         """.replace('\n', ' ').strip() % {
             "media_type": int(Grl.MediaType.AUDIO),
-            "location_filter": self._tracker_wrapper.location_filter()
+            "location_filter": self._tracker_wrapper.location_filter(),
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
         }
diff --git a/gnomemusic/grilowrappers/grltrackerwrapper.py b/gnomemusic/grilowrappers/grltrackerwrapper.py
index 52cc2cc1..83fc41a8 100644
--- a/gnomemusic/grilowrappers/grltrackerwrapper.py
+++ b/gnomemusic/grilowrappers/grltrackerwrapper.py
@@ -177,7 +177,7 @@ class GrlTrackerWrapper(GObject.GObject):
             ?type ?id ?title ?composer ?albumArtist
             ?artist ?url ?creationDate
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         %(media_type)s AS ?type
@@ -203,6 +203,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             'location_filter': self._tracker_wrapper.location_filter()
         }
@@ -249,7 +250,7 @@ class GrlTrackerWrapper(GObject.GObject):
         query = """
         SELECT ?type ?id ?artist
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         %(media_type)s AS ?type
@@ -272,6 +273,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             'location_filter': self._tracker_wrapper.location_filter()
         }
@@ -339,7 +341,7 @@ class GrlTrackerWrapper(GObject.GObject):
             nie:usageCounter(?urn) AS ?playCount
             ?tag AS ?favorite
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -366,6 +368,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.AUDIO),
             'location_filter': self._tracker_wrapper.location_filter(),
             'media_ids': media_ids
@@ -443,7 +446,7 @@ class GrlTrackerWrapper(GObject.GObject):
             nie:usageCounter(?urn) AS ?playCount
             ?tag AS ?favorite
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         %(media_type)s AS ?type
@@ -470,6 +473,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.AUDIO),
             'location_filter': self._tracker_wrapper.location_filter()
         }
@@ -508,7 +512,7 @@ class GrlTrackerWrapper(GObject.GObject):
             ?artist ?url ?creationDate
         WHERE
         {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                         %(media_type)s AS ?type
@@ -537,6 +541,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             'location_filter': self._tracker_wrapper.location_filter()
         }
@@ -573,7 +578,7 @@ class GrlTrackerWrapper(GObject.GObject):
         query = """
         SELECT ?type ?id ?albumArtist
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT
                        %(media_type)s AS ?type
@@ -597,6 +602,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             'location_filter': self._tracker_wrapper.location_filter()
         }
@@ -619,7 +625,7 @@ class GrlTrackerWrapper(GObject.GObject):
         SELECT
             ?type ?id ?title ?creationDate
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -642,6 +648,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             "artist_id": artist_id,
             'location_filter': self._tracker_wrapper.location_filter()
@@ -686,7 +693,7 @@ class GrlTrackerWrapper(GObject.GObject):
         SELECT
             ?type ?id ?albumDiscNumber
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -704,6 +711,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             "album_id": album_id,
             'location_filter': self._tracker_wrapper.location_filter()
@@ -748,7 +756,7 @@ class GrlTrackerWrapper(GObject.GObject):
             nie:usageCounter(?id) AS ?playCount
             ?tag AS ?favorite
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -785,7 +793,8 @@ class GrlTrackerWrapper(GObject.GObject):
             "media_type": int(Grl.MediaType.AUDIO),
             'album_id': album_id,
             'disc_nr': disc_nr,
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
+            'miner_fs_busname': self._tracker_wrapper.props.miner_fs_busname
         }
 
         options = self._fast_options.copy()
@@ -808,7 +817,7 @@ class GrlTrackerWrapper(GObject.GObject):
         SELECT
             ?type ?id
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -849,6 +858,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.AUDIO),
             'location_filter': self._tracker_wrapper.location_filter(),
             'name': term
@@ -883,7 +893,7 @@ class GrlTrackerWrapper(GObject.GObject):
         SELECT
             ?type ?id
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -916,6 +926,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             'location_filter': self._tracker_wrapper.location_filter(),
             'name': term
@@ -950,7 +961,7 @@ class GrlTrackerWrapper(GObject.GObject):
         SELECT
             ?type ?id
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -988,6 +999,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.AUDIO),
             'location_filter': self._tracker_wrapper.location_filter(),
             'name': term
@@ -1030,7 +1042,7 @@ class GrlTrackerWrapper(GObject.GObject):
         SELECT
             ?type ?id ?mbReleaseGroup ?mbRelease ?artist ?album
         WHERE {
-            SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {
+            SERVICE <dbus:%(miner_fs_busname)s> {
                 GRAPH tracker:Audio {
                     SELECT DISTINCT
                         %(media_type)s AS ?type
@@ -1068,6 +1080,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace("\n", " ").strip() % {
+            "miner_fs_busname": self._tracker_wrapper.props.miner_fs_busname,
             "media_type": int(Grl.MediaType.CONTAINER),
             "filter_clause": filter_clause,
             "location_filter": self._tracker_wrapper.location_filter()
diff --git a/gnomemusic/trackerwrapper.py b/gnomemusic/trackerwrapper.py
index 9bbb40a1..64badd19 100644
--- a/gnomemusic/trackerwrapper.py
+++ b/gnomemusic/trackerwrapper.py
@@ -21,6 +21,8 @@
 # code, but you are not obligated to do so.  If you do not wish to do so,
 # delete this exception statement from your version.
 
+import os
+
 from enum import IntEnum
 
 from gi.repository import Gio, GLib, GObject, Tracker
@@ -44,12 +46,92 @@ class TrackerWrapper(GObject.GObject):
         super().__init__()
 
         self._log = application.props.log
+        self._application_id = application.props.application_id
+
+        self._local_db = None
+        self._local_db_available = TrackerState.UNAVAILABLE
+
+        self._miner_fs = None
+        self._miner_fs_busname = None
+        self._miner_fs_available = TrackerState.UNAVAILABLE
+
+        self._setup_local_db()
+        self._setup_host_miner_fs()
+
+    @staticmethod
+    def _in_flatpak():
+        """Indicates if Music is running as flatpak
+
+        :returns: True if running as flatpak.
+        :rtype: bool
+        """
+        return os.path.exists("/.flatpak-info")
+
+    def _setup_host_miner_fs(self):
+        self._miner_fs_busname = "org.freedesktop.Tracker3.Miner.Files"
 
-        self._tracker = None
-        self._tracker_available = TrackerState.UNAVAILABLE
+        self._log.debug("Connecting to session-wide Tracker indexer at {}"
+                        .format(self._miner_fs_busname))
 
         try:
-            self._tracker = Tracker.SparqlConnection.new(
+            self._miner_fs = Tracker.SparqlConnection.bus_new(
+                self._miner_fs_busname, None, None)
+            self._log.info("Using session-wide tracker-miner-fs-3")
+            self._miner_fs_available = TrackerState.AVAILABLE
+            self.notify("tracker-available")
+        except GLib.Error as error:
+            self._log.warning(
+                "Could not connect to host Tracker miner-fs at {}: {}".format(
+                    self._miner_fs_busname, error))
+            if self._in_flatpak():
+                self._setup_local_miner_fs()
+            else:
+                self._miner_fs_busname = None
+                self.notify("tracker-available")
+
+    def _setup_local_miner_fs(self):
+        self._miner_fs_busname = self._application_id + ".Tracker3.Miner.Files"
+        self._log.debug(
+            "Connecting to bundled Tracker indexer at {}".format(
+                self._miner_fs_busname))
+
+        # Calling self._application.get_dbus_connection() seems to return None
+        # here, so get the bus directly from Gio.
+        Gio.bus_get(Gio.BusType.SESSION, None,
+                    self._setup_local_bus_connection_cb)
+
+    def _setup_local_bus_connection_cb(self, klass, result):
+        # Query callback for _setup_local_miner_fs() to connect to session bus
+        bus = Gio.bus_get_finish(result)
+
+        miner_fs_startup_timeout_msec = 30 * 1000
+        miner_fs_object_path = "/org/freedesktop/Tracker3/Miner/Files"
+
+        bus.call(
+            self._miner_fs_busname, miner_fs_object_path,
+            "org.freedesktop.DBus.Peer", "Ping", None, None,
+            Gio.DBusCallFlags.NONE, miner_fs_startup_timeout_msec, None,
+            self._setup_local_miner_fs_ping_cb)
+
+    def _setup_local_miner_fs_ping_cb(self, klass, result):
+        try:
+            klass.call_finish(result)
+            self._log.info("Using bundled tracker-miner-fs-3")
+            self._miner_fs = Tracker.SparqlConnection.bus_new(
+                self._miner_fs_busname, None, None)
+            self._miner_fs_available = TrackerState.AVAILABLE
+            self.notify("tracker-available")
+        except GLib.Error as error:
+            self._log.warning(
+                "Could not start local Tracker miner-fs at {}: {}".format(
+                    self._miner_fs_busname, error))
+            self._miner_fs_busname = None
+            self.notify("tracker-available")
+
+    def _setup_local_db(self):
+        # Open a local Tracker database.
+        try:
+            self._local_db = Tracker.SparqlConnection.new(
                 Tracker.SparqlConnectionFlags.NONE,
                 Gio.File.new_for_path(self.cache_directory()),
                 Tracker.sparql_get_ontology_nepomuk(),
@@ -60,26 +142,10 @@ class TrackerWrapper(GObject.GObject):
             self.notify("tracker-available")
             return
 
-        query = """
-        SELECT
-            ?e
-        {
-            GRAPH tracker:Audio {
-                ?e a tracker:ExternalReference .
-            }
-        }""".replace("\n", "").strip()
-
-        self._tracker.query_async(query, None, self._query_version_check)
-
-    def _query_version_check(self, klass, result):
-        try:
-            klass.query_finish(result)
-            self._tracker_available = TrackerState.AVAILABLE
-        except GLib.Error as error:
-            self._log.warning(
-                "Error: {}, {}".format(error.domain, error.message))
-            self._tracker_available = TrackerState.OUTDATED
-
+        # Version checks against the local version of Tracker can be done
+        # here, set `self._tracker_available = TrackerState.OUTDATED` if the
+        # checks fail.
+        self._local_db_available = TrackerState.AVAILABLE
         self.notify("tracker-available")
 
     def cache_directory(self):
@@ -92,9 +158,13 @@ class TrackerWrapper(GObject.GObject):
             GLib.DIR_SEPARATOR_S,
             [GLib.get_user_cache_dir(), "gnome-music", "db"])
 
+    @GObject.Property(type=str, flags=GObject.ParamFlags.READABLE)
+    def miner_fs_busname(self):
+        return self._miner_fs_busname
+
     @GObject.Property(type=object, flags=GObject.ParamFlags.READABLE)
-    def tracker(self):
-        return self._tracker
+    def local_db(self):
+        return self._local_db
 
     @GObject.Property(
         type=int, default=TrackerState.UNAVAILABLE,
@@ -102,13 +172,17 @@ class TrackerWrapper(GObject.GObject):
     def tracker_available(self):
         """Get Tracker availability.
 
-        Tracker is available if a SparqlConnection has been opened and
-        if a query can be performed.
-
         :returns: tracker availability
         :rtype: TrackerState
         """
-        return self._tracker_available
+        if (self._local_db_available == TrackerState.AVAILABLE
+                and self._miner_fs_available == TrackerState.AVAILABLE):
+            return TrackerState.AVAILABLE
+        elif (self._local_db_available == TrackerState.OUTDATED
+                or self._miner_fs_available == TrackerState.OUTDATED):
+            return TrackerState.OUTDATED
+        else:
+            return TrackerState.UNAVAILABLE
 
     def location_filter(self):
         try:
@@ -157,7 +231,7 @@ class TrackerWrapper(GObject.GObject):
                 self._log.warning("Unable to update favorite: {}".format(
                     e.message))
 
-        self._tracker.update_async(update, None, _update_favorite_cb)
+        self._local_db.update_async(update, None, _update_favorite_cb)
 
     def _update_play_count(self, media):
         update = """
@@ -180,7 +254,7 @@ class TrackerWrapper(GObject.GObject):
                 self._log.warning("Unable to update play count: {}".format(
                     e.message))
 
-        self._tracker.update_async(update, None, _update_play_count_cb)
+        self._local_db.update_async(update, None, _update_play_count_cb)
 
     def _update_last_played(self, media):
         last_played = media.get_last_played().format_iso8601()
@@ -204,7 +278,7 @@ class TrackerWrapper(GObject.GObject):
                 self._log.warning("Unable to update play count: {}".format(
                     e.message))
 
-        self._tracker.update_async(update, None, _update_last_played_cb)
+        self._local_db.update_async(update, None, _update_last_played_cb)
 
     def update_tag(self, media, tag):
         """Update property of a resource.
diff --git a/meson.build b/meson.build
index 2693e5dc..a01c1c90 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
 project('gnome-music',
     version: '3.37.3',
-    meson_version: '>= 0.46.0'
+    meson_version: '>= 0.49.0'
 )
 
 # Importing modules
diff --git a/org.gnome.Music.json b/org.gnome.Music.json
index f638114e..1d800524 100644
--- a/org.gnome.Music.json
+++ b/org.gnome.Music.json
@@ -23,7 +23,9 @@
         "--talk-name=org.gtk.vfs",
         "--talk-name=org.gtk.vfs.*",
         "--system-talk-name=org.freedesktop.login1",
-        "--add-policy=Tracker3.dbus:org.freedesktop.Tracker3.Miner.Files=tracker:Audio"
+        "--add-policy=Tracker3.dbus:org.freedesktop.Tracker3.Miner.Files=tracker:Audio",
+        "--own-name=org.gnome.Music.Devel.Tracker3.Miner.Files",
+        "--own-name=org.gnome.Music.Devel.Tracker3.Miner.Extract"
     ],
     "cleanup": [
         "/include",
@@ -59,20 +61,19 @@
             ]
         },
         {
-            "name": "tracker",
+            "name": "tracker-miners",
             "buildsystem": "meson",
-            "cleanup": [ "/bin", "/etc", "/libexec" ],
-            "config-opts": [ "-Ddocs=false",
-                             "-Dman=false",
-                             "-Dfunctional_tests=false",
-                             "-Dnetwork_manager=disabled",
-                             "-Dstemmer=disabled",
-                             "-Dunicode_support=icu",
-                             "-Dbash_completion=false" ],
+            "cleanup": [ "/share/dbus-1/services/org.freedesktop.Tracker3.Miner.Extract.service",
+                         "/share/dbus-1/services/org.freedesktop.Tracker3.Miner.Files.service",
+                         "/share/dbus-1/services/org.freedesktop.Tracker3.Writeback.service" ],
+            "config-opts": [ "-Dman=false",
+                             "-Dminer_fs=true",
+                             "-Dminer_rss=false",
+                             "-Dsystemd_user_services=false"],
             "sources": [
                 {
                     "type": "git",
-                    "url": "https://gitlab.gnome.org/GNOME/tracker.git";
+                    "url": "https://gitlab.gnome.org/GNOME/tracker-miners.git";
                 }
             ]
         },


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]