# -*- coding: utf-8 -*- # Copyright © 2015 Collabora Ltd. # # SPDX-License-Identifier: MPL-2.0 # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. import subprocess import shutil import os from gi.repository import GLib from gi.repository import TrackerControl from gi.repository import Tracker from . import LONG_JPEG_NAME class TrackerIndexerMixin: def __init__(self): print("TrackerIndexerMixin: Stop tracker-store and tracker-miner-fs " "services") subprocess.check_call( 'systemctl --user stop tracker-store tracker-miner-fs', shell=True) print("TrackerIndexerMixin: Reset tracker's DB") subprocess.check_call('yes | tracker reset -r', stdout=subprocess.DEVNULL, shell=True) print("TrackerIndexerMixin: init done") def miner_progress_cb(self, manager, miner, status, progress, remaining_time): # Ignore signal if status didn't change if self.statuses[miner] == status: return print("TrackerIndexer: Miner '%s' status changed to '%s'" % (miner, status)) self.statuses[miner] = status # We are only interested about miners becoming Idle if status != 'Idle': return if miner == 'org.freedesktop.Tracker1.Miner.Files': self.wait_files = False if miner == 'org.freedesktop.Tracker1.Miner.Extract': # If Files miner is not done yet, extractor will have more work to # do even if it's currently Idle waiting for the Files miner to be # done. if not self.wait_files: self.wait_extractor = False if not self.wait_files and not self.wait_extractor: print("TrackerIndexer: quit main loop") self.loop.quit() def start(self): print("TrackerIndexer: start") self.manager = TrackerControl.MinerManager.new_full(True) self.conn = Tracker.SparqlConnection.get(None) self.statuses = {} for miner in self.manager.get_available(): status = self.manager.get_status(miner)[1] print("TrackerIndexer: Miner '%s' initial status is '%s'" % (miner, status)) self.statuses[miner] = status self.manager.connect('miner-progress', self.miner_progress_cb) # Wait for the initial indexing self.wait(True) # wait_extractor is used to tell if we expect the extractor to have work # to do and thus we should wait for it. For example when deleting files # we don't expect extractor to do anything. def wait(self, wait_extractor): self.wait_extractor = wait_extractor self.wait_files = True self.loop.run() def assert_indexed(self, path, extra=None): # Select entries for the given URL. Also check that is has the # tracker:extractor-data-source flag added by tracker-extract when # metadata has been extracted. query = ('select ?urn where { ' ' ?urn nie:url "file://%s" ; ' ' tracker:available true ; ' ' nie:dataSource tracker:extractor-data-source . ') % (path) if extra is not None: query += extra query += ' }' # Must have one and only one result cursor = self.conn.query(query, None) self.assertTrue(cursor.next(None)) self.assertFalse(cursor.next(None)) def assert_not_indexed(self, path): query = ('select ?urn where { ?urn nie:url "file://%s" }') % (path) cursor = self.conn.query(query, None) self.assertFalse(cursor.next(None)) def assert_all_indexed(self, root): playable_query = '?urn bosch:playable true . ' album_query = ('?urn nmm:musicAlbum ?album . ' '?album nmm:albumTitle "GNOME Audio" . ') performer_query = ('?urn nmm:performer ?performer . ' '?performer nmm:artistName "Conrad Parker" . ') title_query = '?urn nie:title "GNOME Generic Sound" . ' audio_query = album_query + performer_query + title_query self.assert_indexed(root + '/Music/generic.mp3', audio_query) self.assert_indexed(root + '/Music/generic.flac', audio_query + playable_query) self.assert_indexed(root + '/Music/generic-no-artwork.mp3', audio_query) self.assert_indexed(root + '/Music/generic.oga', audio_query) self.assert_indexed(root + '/Music/generic.wav', playable_query) self.assert_indexed(root + '/Documents/lorem_presentation.odp') self.assert_indexed(root + '/Documents/lorem_spreadsheet.ods') self.assert_indexed(root + '/Documents/lorem_text.txt') self.assert_indexed(root + '/Documents/more_lorem_ipsum.odt') self.assert_indexed(root + '/Pictures/' + LONG_JPEG_NAME) self.assert_indexed(root + '/Pictures/collabora-logo-big.png') self.assert_indexed(root + '/Music/Generic_Sounds.pls', '?urn nfo:entryCounter 3') self.assert_indexed(root + '/Music/Ghosts.pls', '?urn nfo:entryCounter 38') self.assert_indexed(root + '/Music/Ghosts.m3u', '?urn nfo:entryCounter 38') self.assert_indexed(root + '/Videos/big_buck_bunny_smaller.ogv', playable_query)