[gnome-music/sam/tracker3-self-contained] WIP: Allow running a local Tracker instance inside the Flatpak sandbox



commit 46060a28e34281eb407766b1ae0c634f129f4214
Author: Sam Thursfield <sam afuera me uk>
Date:   Tue Jun 30 01:14:19 2020 +0200

    WIP: Allow running a local Tracker instance inside the Flatpak sandbox
    
    This will allow Music flatpaks to work on systems that don't have tracker3
    on the host.

 data/tracker/meson.build                           |  31 ++++-
 data/tracker/org.gnome.Music.Miner.Extract.service |   8 --
 data/tracker/org.gnome.Music.Miner.Files.service   |   8 --
 ...g.gnome.Music.Tracker3.Miner.Extract.service.in |   8 ++
 ...org.gnome.Music.Tracker3.Miner.Files.service.in |   8 ++
 ....domain.rule => org.gnome.Music.domain.rule.in} |   2 +-
 gnomemusic/coregrilo.py                            |   4 +-
 gnomemusic/grilowrappers/grltrackerplaylists.py    |  39 ++++---
 gnomemusic/grilowrappers/grltrackerwrapper.py      |  62 ++++++----
 gnomemusic/trackerwrapper.py                       | 128 ++++++++++++++++-----
 meson.build                                        |   2 +-
 org.gnome.Music.json                               |   3 +
 12 files changed, 210 insertions(+), 93 deletions(-)
---
diff --git a/data/tracker/meson.build b/data/tracker/meson.build
index d562b878..e6864568 100644
--- a/data/tracker/meson.build
+++ b/data/tracker/meson.build
@@ -1,8 +1,31 @@
-# Files needed for running Tracker inside the Flatpak sandbox.
+# 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'
 
-install_data('org.gnome.Music.domain.rule', install_dir: domain_ontologies_dir)
-install_data('org.gnome.Music.Miner.Extract.service', install_dir: dbus_services_dir)
-install_data('org.gnome.Music.Miner.Files.service', install_dir: dbus_services_dir)
+tracker_domain_config = configuration_data()
+tracker_domain_config.set('application_id', APPLICATION_ID)
+tracker_domain_config.set('domain_rule', 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..73a8fb11
--- /dev/null
+++ b/data/tracker/org.gnome.Music.Tracker3.Miner.Extract.service.in
@@ -0,0 +1,8 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Extract
+Exec=/app/libexec/tracker-extract-3 --domain-ontology @domain_rule@
+SystemdService=tracker-extract-3.service
+
+# 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..d39dd284
--- /dev/null
+++ b/data/tracker/org.gnome.Music.Tracker3.Miner.Files.service.in
@@ -0,0 +1,8 @@
+[D-BUS Service]
+Name=@application_id@.Tracker3.Miner.Files
+Exec=/app/libexec/tracker-miner-fs-3 --domain-ontology @domain_rule@ --initial-sleep 0
+SystemdService=tracker-miner-fs-3.service
+
+# 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 b/data/tracker/org.gnome.Music.domain.rule.in
similarity index 96%
rename from data/tracker/org.gnome.Music.domain.rule
rename to data/tracker/org.gnome.Music.domain.rule.in
index 31bccfa1..6119cfc5 100644
--- a/data/tracker/org.gnome.Music.domain.rule
+++ b/data/tracker/org.gnome.Music.domain.rule.in
@@ -14,7 +14,7 @@ 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=org.gnome.Music
+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 0dd53a84..7556ffd7 100644
--- a/gnomemusic/coregrilo.py
+++ b/gnomemusic/coregrilo.py
@@ -74,7 +74,7 @@ class CoreGrilo(GObject.GObject):
         self._wrappers = {}
         self._mb_wrappers = {}
 
-        self._tracker_wrapper = TrackerWrapper()
+        self._tracker_wrapper = TrackerWrapper(application.get_application_id())
         self._tracker_wrapper.bind_property(
             "tracker-available", self, "tracker-available",
             GObject.BindingFlags.SYNC_CREATE)
@@ -96,6 +96,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.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 422f0516..d4951f3b 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
@@ -394,7 +394,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.miner_fs_busname(),
         }
 
         def _add_to_playlist_cb(
@@ -624,7 +625,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
@@ -650,7 +651,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": self._tracker_wrapper.miner_fs_busname(),
             }
 
             options = self._fast_options.copy()
@@ -839,7 +841,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
@@ -864,7 +866,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.miner_fs_busname(),
         }
 
 
@@ -891,7 +894,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
@@ -915,7 +918,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.miner_fs_busname(),
         }
 
 
@@ -949,7 +953,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
@@ -976,7 +980,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.miner_fs_busname(),
         }
 
 
@@ -1010,7 +1015,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
@@ -1037,7 +1042,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.miner_fs_busname(),
         }
 
 
@@ -1064,7 +1070,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
@@ -1087,5 +1093,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.miner_fs_busname(),
         }
diff --git a/gnomemusic/grilowrappers/grltrackerwrapper.py b/gnomemusic/grilowrappers/grltrackerwrapper.py
index e00a164a..10cd5b8c 100644
--- a/gnomemusic/grilowrappers/grltrackerwrapper.py
+++ b/gnomemusic/grilowrappers/grltrackerwrapper.py
@@ -178,7 +178,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
@@ -204,8 +204,9 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
         }
 
         def check_album_cb(source, op_id, media, remaining, error):
@@ -250,7 +251,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
@@ -273,8 +274,9 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
         }
 
         def check_artist_cb(source, op_id, media, remaining, error):
@@ -340,7 +342,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
@@ -411,9 +413,10 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.AUDIO),
             'location_filter': self._tracker_wrapper.location_filter(),
-            'media_ids': media_ids
+            'media_ids': media_ids,
         }
 
         return query
@@ -488,7 +491,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
@@ -559,8 +562,9 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.AUDIO),
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
         }
 
         options = self._fast_options.copy()
@@ -597,7 +601,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
@@ -626,8 +630,9 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
         }
 
         options = self._fast_options.copy()
@@ -662,7 +667,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
@@ -686,8 +691,9 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
         }
 
         options = self._fast_options.copy()
@@ -708,7 +714,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
@@ -731,9 +737,10 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
             'artist_id': artist_id,
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
         }
 
         albums = []
@@ -775,7 +782,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
@@ -793,9 +800,10 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
             'album_id': album_id,
-            'location_filter': self._tracker_wrapper.location_filter()
+            'location_filter': self._tracker_wrapper.location_filter(),
         }
 
         def _disc_nr_cb(source, op_id, media, remaining, error):
@@ -837,7 +845,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
@@ -911,7 +919,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.miner_fs_busname(),
         }
 
         options = self._fast_options.copy()
@@ -934,7 +943,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
@@ -975,9 +984,10 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.AUDIO),
             'location_filter': self._tracker_wrapper.location_filter(),
-            'name': term
+            'name': term,
         }
 
         artist_filter_ids = []
@@ -1009,7 +1019,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
@@ -1042,6 +1052,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
             'location_filter': self._tracker_wrapper.location_filter(),
             'name': term
@@ -1076,7 +1087,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
@@ -1114,6 +1125,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace('\n', ' ').strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.AUDIO),
             'location_filter': self._tracker_wrapper.location_filter(),
             'name': term
@@ -1169,7 +1181,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
@@ -1207,6 +1219,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace("\n", " ").strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
             'album_id': album_id,
             'location_filter': self._tracker_wrapper.location_filter()
@@ -1220,7 +1233,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
@@ -1261,6 +1274,7 @@ class GrlTrackerWrapper(GObject.GObject):
             }
         }
         """.replace("\n", " ").strip() % {
+            'miner_fs_busname': self._tracker_wrapper.miner_fs_busname(),
             'media_type': int(Grl.MediaType.CONTAINER),
             'location_filter': self._tracker_wrapper.location_filter(),
             'song_id': song_id
diff --git a/gnomemusic/trackerwrapper.py b/gnomemusic/trackerwrapper.py
index a99e4c86..364f8f32 100644
--- a/gnomemusic/trackerwrapper.py
+++ b/gnomemusic/trackerwrapper.py
@@ -53,57 +53,121 @@ class MbReference(Enum):
         self.method = method
 
 
+def in_flatpak():
+    if os.path.exists('/.flatpak-info'):
+        return True
+    return False
+
+
 class TrackerWrapper(GObject.GObject):
     """Create a connection to an instance of Tracker"""
 
-    def __init__(self):
+    def __init__(self, application_id):
         super().__init__()
 
         self._log = MusicLogger()
+        self._application_id = 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()
 
-        self._tracker = None
-        self._tracker_available = TrackerState.UNAVAILABLE
+    def _setup_host_miner_fs(self):
+        self._miner_fs_busname = 'org.freedesktop.Tracker3.Miner.Files'
 
+        self._log.debug("Connecting to session-wide Tracker indexer at {}"
+                        .format(self._miner_fs_busname))
+
+        self._miner_fs = Tracker.SparqlConnection.bus_new(
+            self._miner_fs_busname, None, None)
+        self._miner_fs.query_async('ASK { ?r a rdfs:Resource }', None,
+                                   self._query_host_miner_fs)
+
+    def _query_host_miner_fs(self, klass, result):
+        # Query callback for _setup_host_miner_fs()
         try:
-            self._tracker = Tracker.SparqlConnection.new(
-                Tracker.SparqlConnectionFlags.NONE,
-                Gio.File.new_for_path(self.cache_directory()),
-                Tracker.sparql_get_ontology_nepomuk(),
-                None)
+            klass.query_finish(result)
+            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(
-                "Error: {}, {}".format(error.domain, error.message))
-            self.notify("tracker-available")
-            return
+                "Could not connect to host Tracker miner-fs at {}: {}"
+                .format(self._miner_fs_busname, error))
+            if in_flatpak():
+                self._setup_local_miner_fs()
+            else:
+                self._miner_fs_busname = None
+                self.notify('tracker-available')
 
-        query = """
-        SELECT
-            ?e
-        {
-            GRAPH tracker:Audio {
-                ?e a tracker:ExternalReference .
-            }
-        }""".replace("\n", "").strip()
+    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))
+
+        Gio.bus_get(Gio.BusType.SESSION, None, self._setup_local_bus_connection_cb)
 
-        self._tracker.query_async(query, None, self._query_version_check)
+    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)
 
-    def _query_version_check(self, klass, 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.query_finish(result)
-            self._tracker_available = TrackerState.AVAILABLE
+            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(),
+                None)
         except GLib.Error as error:
             self._log.warning(
                 "Error: {}, {}".format(error.domain, error.message))
-            self._tracker_available = TrackerState.OUTDATED
+            self.notify("tracker-available")
+            return
 
+        # 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):
         return os.path.join(GLib.get_user_cache_dir(), 'gnome-music', 'db')
 
+    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,
@@ -111,13 +175,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:
diff --git a/meson.build b/meson.build
index a3208f59..a3e2feec 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
 project('gnome-music',
     version: '3.37.2',
-    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 0acddce3..466c2a52 100644
--- a/org.gnome.Music.json
+++ b/org.gnome.Music.json
@@ -62,6 +62,9 @@
         {
             "name": "tracker-miners",
             "buildsystem": "meson",
+            "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",


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