def get_songs_with_any_match(name): name = Tracker.sparql_escape_string( GLib.utf8_normalize(GLib.utf8_casefold(name, -1), -1, GLib.NormalizeMode.NFKD)) query = """ { SELECT DISTINCT ?song WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize(nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize(nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) . FILTER ( CONTAINS(tracker:case-fold(tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold(tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold(tracker:unaccent(?match3)), "%(name)s") || CONTAINS(tracker:case-fold(?match3), "%(name)s") ) } } """.replace('\n', ' ').strip() % { 'name': name } return Query.songs(query)
def get_songs_with_any_match(name): name = Tracker.sparql_escape_string(GLib.utf8_normalize(GLib.utf8_casefold(name, -1), -1, GLib.NormalizeMode.NFKD)) query = """ { SELECT DISTINCT ?song WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize(nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize(nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold(tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold(tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold(tracker:unaccent(?match3)), "%(name)s") || CONTAINS(tracker:case-fold(?match3), "%(name)s") || CONTAINS(tracker:case-fold(tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) } } """.replace('\n', ' ').strip() % {'name': name} return Query.songs(query)
def _normalize_and_hash(self, input_str): normalized = " " if input_str and len(input_str) > 0: normalized = self._strip_invalid_entities(input_str) normalized = GLib.utf8_normalize(normalized, -1, GLib.NormalizeMode.NFKD) normalized = normalized.lower() return GLib.compute_checksum_for_string(GLib.ChecksumType.MD5, normalized, -1)
def _normalize_and_hash(self, input_str): normalized = ' ' if input_str and len(input_str) > 0: normalized = self._strip_invalid_entities(input_str) normalized = GLib.utf8_normalize(normalized, -1, GLib.NormalizeMode.NFKD) normalized = normalized.lower() return GLib.compute_checksum_for_string(GLib.ChecksumType.MD5, normalized, -1)
def normalizeAndHash(self, input_str): normalized = " " if input_str is not None and input_str.length() > 0: normalized = self.stripInvalidEntities(input_str) normalized = GLib.utf8_normalize(normalized, -1, GLib.NormalizeMode.NFKD) normalized = normalized.toLowerCase() return GLib.compute_checksum_for_string(GLib.ChecksumType.MD5, normalized, -1)
def string_for_search(s): return GLib.utf8_casefold(GLib.utf8_normalize(s, -1, GLib.NormalizeMode.ALL), -1)
# DO NOT MODIFY IT! # See locale/README.md to know how to import dictionaries """ # Open UnicodeData.txt with open(unicodeDataPath, "r", newline='') as uDataFile: uDataCSV = csv.reader(uDataFile, delimiter=';') fontVariantsDict = SymbolsDictionary("literal") for uCharacter in uDataCSV: # The 6th field starts with <font> code for all font variants # So get the code after <font> and the first field content to have the character and the one to pronounce if uCharacter[5].startswith("<font>"): fontVariant = chr(int("0x" + uCharacter[0], 16)) pronouncedCharacter = chr(int("0x" + uCharacter[5][7:], 16)) if pronouncedCharacter != GLib.utf8_normalize( fontVariant, -1, GLib.NormalizeMode.ALL_COMPOSE): fontVariantsDict[fontVariant] = pronouncedCharacter # Write the dictionary to en/font-variants.dic with documentation at the top with codecs.open("base/font-variants.dic", "w", "utf_8_sig", errors="replace") as dicFile: dicFile.write(docHeader) dicFile.write(str(fontVariantsDict)) # Copy all NVDA symbols dictionaries # Browse the "locale" directory, check if item is a directory and if it contains a symbols.dic file to copy it fter creating this directory in Speech-Dispatcher if not exists NVDALocale = path.join(NVDADir, "source", "locale") for NVDALang in os.listdir(NVDALocale): langPath = path.join(NVDALocale, NVDALang) if not path.isdir(langPath): continue
def search(self, text): # FIXME: Searches are limited to not bog down the UI with # widget creation ({List,Flow}Box limitations). The limit is # arbitrarily set to 50 and set in the Tracker query. It should # be possible to set it through Grilo options instead. This # does not work as expected and needs further investigation. term = Tracker.sparql_escape_string( GLib.utf8_normalize(GLib.utf8_casefold(text, -1), -1, GLib.NormalizeMode.NFKD)) # Artist search query = """ SELECT DISTINCT rdf:type(?artist) tracker:id(?artist) AS ?id WHERE { ?song a nmm:MusicPiece ; nmm:musicAlbum ?album ; nmm:performer ?artist . BIND(tracker:normalize( nmm:artistName(nmm:albumArtist(?album)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } LIMIT 50 """.replace('\n', ' ').strip() % { 'location_filter': self._location_filter(), 'name': term } artist_filter_ids = [] def artist_filter(coreartist): return coreartist.media.get_id() in artist_filter_ids def artist_search_cb(source, op_id, media, data, error): if error: print("ERROR", error) return if not media: self._artist_search_model.set_filter_func(artist_filter) return artist_filter_ids.append(media.get_id()) options = self._fast_options.copy() self._source.query(query, self.METADATA_KEYS, options, artist_search_cb) # Album search query = """ SELECT DISTINCT rdf:type(nmm:musicAlbum(?song)) tracker:id(nmm:musicAlbum(?song)) AS ?id WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize( nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } LIMIT 50 """.replace('\n', ' ').strip() % { 'location_filter': self._location_filter(), 'name': term } album_filter_ids = [] def album_filter(corealbum): return corealbum.media.get_id() in album_filter_ids def albums_search_cb(source, op_id, media, data, error): if error: print("ERROR", error) return if not media: self._album_search_model.set_filter_func(album_filter) return album_filter_ids.append(media.get_id()) options = self._fast_options.copy() self._source.query(query, self.METADATA_KEYS, options, albums_search_cb) # Song search query = """ SELECT DISTINCT rdf:type(?song) tracker:id(?song) AS ?id WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize( nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize( nie:title(?song), 'nfkd') AS ?match3) . BIND( tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match3)), "%(name)s") || CONTAINS(tracker:case-fold(?match3), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } LIMIT 50 """.replace('\n', ' ').strip() % { 'location_filter': self._location_filter(), 'name': term } filter_ids = [] def songs_filter(coresong): return coresong.media.get_id() in filter_ids def songs_search_cb(source, op_id, media, data, error): if error: print("ERROR", error) return if not media: self._song_search_tracker.set_filter_func(songs_filter) return filter_ids.append(media.get_id()) options = self._fast_options.copy() self._source.query(query, self.METADATA_KEYS, options, songs_search_cb)
def search(self, text): term = Tracker.sparql_escape_string( GLib.utf8_normalize(GLib.utf8_casefold(text, -1), -1, GLib.NormalizeMode.NFKD)) query = """ SELECT DISTINCT rdf:type(?song) tracker:id(?song) AS ?id WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize( nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize( nie:title(?song), 'nfkd') AS ?match3) . BIND( tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match3)), "%(name)s") || CONTAINS(tracker:case-fold(?match3), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } """.replace('\n', ' ').strip() % { 'location_filter': self._location_filter(), 'name': term } filter_ids = [] def songs_filter(coresong): return coresong.media.get_id() in filter_ids def songs_search_cb(source, op_id, media, data, error): if error: print("ERROR", error) return if not media: self._song_search_tracker.set_filter_func(songs_filter) return filter_ids.append(media.get_id()) options = self._fast_options.copy() self._source.query(query, self.METADATA_KEYS, options, songs_search_cb) # Album search query = """ SELECT DISTINCT rdf:type(nmm:musicAlbum(?song)) tracker:id(nmm:musicAlbum(?song)) AS ?id WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize( nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match3)), "%(name)s") || CONTAINS(tracker:case-fold(?match3), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } """.replace('\n', ' ').strip() % { 'location_filter': self._location_filter(), 'name': term } album_filter_ids = [] def album_filter(corealbum): return corealbum.media.get_id() in album_filter_ids def albums_search_cb(source, op_id, media, data, error): if error: print("ERROR", error) return if not media: self._album_search_model.set_filter_func(album_filter) return album_filter_ids.append(media.get_id()) options = self._fast_options.copy() self._source.query(query, self.METADATA_KEYS, options, albums_search_cb) # Artist search query = """ SELECT DISTINCT rdf:type(?artist) tracker:id(?artist) AS ?id WHERE { ?song a nmm:MusicPiece ; nmm:musicAlbum ?album ; nmm:performer ?artist . BIND(tracker:normalize( nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:performer(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match3)), "%(name)s") || CONTAINS(tracker:case-fold(?match3), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } """.replace('\n', ' ').strip() % { 'location_filter': self._location_filter(), 'name': term } artist_filter_ids = [] def artist_filter(coreartist): return coreartist.media.get_id() in artist_filter_ids def artist_search_cb(source, op_id, media, data, error): if error: print("ERROR", error) return if not media: self._artist_search_model.set_filter_func(artist_filter) return artist_filter_ids.append(media.get_id()) options = self._fast_options.copy() self._source.query(query, self.METADATA_KEYS, options, artist_search_cb)
def search(self, text): # FIXME: Searches are limited to not bog down the UI with # widget creation ({List,Flow}Box limitations). The limit is # arbitrarily set to 50 and set in the Tracker query. It should # be possible to set it through Grilo options instead. This # does not work as expected and needs further investigation. term = Tracker.sparql_escape_string( GLib.utf8_normalize(GLib.utf8_casefold(text, -1), -1, GLib.NormalizeMode.NFKD)) # Artist search self._notificationmanager.push_loading() query = """ SELECT ?type ?id WHERE { SERVICE <dbus:%(miner_fs_busname)s> { GRAPH tracker:Audio { SELECT DISTINCT %(media_type)s AS ?type COALESCE(?album_artist, ?artist) AS ?id WHERE { ?song a nmm:MusicPiece ; nmm:musicAlbum ?album ; nmm:artist ?artist . OPTIONAL { ?album a nmm:MusicAlbum ; nmm:albumArtist ?album_artist . } BIND(COALESCE(nmm:artistName(?album_artist), nmm:artistName(?artist)) AS ?artist_bind) BIND(tracker:normalize(nmm:artistName( nmm:albumArtist(?artist_bind)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:artist(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } LIMIT 50 } } } """.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 } artist_filter_ids = [] def artist_filter(coreartist): return coreartist.media.get_id() in artist_filter_ids def artist_search_cb(source, op_id, media, remaining, error): if error: self._log.warning("Error: {}".format(error)) self._notificationmanager.pop_loading() return if not media: self._artist_search_model.set_filter_func(artist_filter) self._notificationmanager.pop_loading() return artist_filter_ids.append(media.get_id()) self.props.source.query(query, [Grl.METADATA_KEY_ID], self._fast_options, artist_search_cb) # Album search self._notificationmanager.push_loading() query = """ SELECT ?type ?id WHERE { SERVICE <dbus:%(miner_fs_busname)s> { GRAPH tracker:Audio { SELECT DISTINCT %(media_type)s AS ?type nmm:musicAlbum(?song) AS ?id WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize( nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:artist(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } LIMIT 50 } } } """.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 } album_filter_ids = [] def album_filter(corealbum): return corealbum.media.get_id() in album_filter_ids def albums_search_cb(source, op_id, media, remaining, error): if error: self._log.warning("Error: {}".format(error)) self._notificationmanager.pop_loading() return if not media: self._album_search_model.set_filter_func(album_filter) self._notificationmanager.pop_loading() return album_filter_ids.append(media.get_id()) self.props.source.query(query, [Grl.METADATA_KEY_ID], self._fast_options, albums_search_cb) # Song search self._notificationmanager.push_loading() query = """ SELECT ?type ?id WHERE { SERVICE <dbus:%(miner_fs_busname)s> { GRAPH tracker:Audio { SELECT DISTINCT %(media_type)s AS ?type ?song AS ?id WHERE { ?song a nmm:MusicPiece . BIND(tracker:normalize( nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) . BIND(tracker:normalize( nmm:artistName(nmm:artist(?song)), 'nfkd') AS ?match2) . BIND(tracker:normalize( nie:title(?song), 'nfkd') AS ?match3) . BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) . FILTER ( CONTAINS(tracker:case-fold( tracker:unaccent(?match1)), "%(name)s") || CONTAINS(tracker:case-fold(?match1), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match2)), "%(name)s") || CONTAINS(tracker:case-fold(?match2), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match3)), "%(name)s") || CONTAINS(tracker:case-fold(?match3), "%(name)s") || CONTAINS(tracker:case-fold( tracker:unaccent(?match4)), "%(name)s") || CONTAINS(tracker:case-fold(?match4), "%(name)s") ) %(location_filter)s } LIMIT 50 } } } """.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 } filter_ids = [] def songs_filter(coresong): return coresong.media.get_id() in filter_ids def songs_search_cb(source, op_id, media, remaining, error): if error: self._log.warning("Error: {}".format(error)) self._notificationmanager.pop_loading() return if not media: self._song_search_tracker.set_filter_func(songs_filter) self._notificationmanager.pop_loading() return filter_ids.append(media.get_id()) self.props.source.query(query, [Grl.METADATA_KEY_ID], self._fast_options, songs_search_cb)