unity-scope-clementine-0.1+13.10.20130723/0000755000015700001700000000000012173420253020302 5ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/po/0000755000015700001700000000000012173420253020720 5ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/po/unity-scope-clementine.pot0000644000015700001700000000231712173417355026060 0ustar pbuserpbgroup00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #: ../src/unity_clementine_daemon.py:41 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-02-21 01:59+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../src/unity_clementine_daemon.py:39 msgid "Search Clementime" msgstr "" #: ../src/unity_clementine_daemon.py:40 msgid "Sorry, there are no Clementine results that match your search." msgstr "" #: ../src/unity_clementine_daemon.py:51 msgid "Songs" msgstr "" #: ../src/unity_clementine_daemon.py:55 msgid "Albums" msgstr "" #: ../data/clementine.scope.in.h:1 msgid "clementine;" msgstr "" #: ../data/clementine.scope.in.h:2 msgid "Clementine" msgstr "" #: ../data/clementine.scope.in.h:3 msgid "Find Clementine items" msgstr "" #: ../data/clementine.scope.in.h:4 msgid "Search Clementine" msgstr "" unity-scope-clementine-0.1+13.10.20130723/po/POTFILES.in0000644000015700001700000000013512173417355022505 0ustar pbuserpbgroup00000000000000[encoding: UTF-8] src/unity_clementine_daemon.py [type: gettext/ini]data/clementine.scope.in unity-scope-clementine-0.1+13.10.20130723/MANIFEST.in0000644000015700001700000000007612173417355022054 0ustar pbuserpbgroup00000000000000include MANIFEST.in include src/* include data/* include po/* unity-scope-clementine-0.1+13.10.20130723/tests/0000755000015700001700000000000012173420253021444 5ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/tests/test_clementine.py0000644000015700001700000000454212173417355025216 0ustar pbuserpbgroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- from gi.repository import Unity from unittest import TestCase import imp class ResultSet(Unity.ResultSet): def __init__(self): Unity.ResultSet.__init__(self) self.results = [] def do_add_result(self, result): self.results.append({'uri': result.uri, 'title': result.title, 'comment': result.comment, 'icon': result.icon_hint}) class ScopeTestCase(TestCase): def init_scope(self, scope_path): self.scope_module = imp.load_source('scope', scope_path) self.scope = self.scope_module.load_scope() def perform_query(self, query, filter_set=Unity.FilterSet.new()): result_set = ResultSet() ctx = Unity.SearchContext.create(query, 0, filter_set, None, result_set, None) s = self.scope.create_search_for_query(ctx) s.run() return result_set class TestClementine(ScopeTestCase): def setUp(self): self.init_scope('src/unity_clementine_daemon.py') def tearDown(self): self.scope = None self.scope_module = None def test_search(self): self.scope_module.CLEMENTINE_DBFILE = 'tests/data/mock_clementine_pass.db' self.scope_module.CLEMENTINE_BACKUP_FILE = 'tests/data/mock_clementine_backup.db' expected_results = ["file:///home/mark/Music/Bell X1/Flock/01. Reacharound.mp3", "Reacharound", "album://Bell X1/Flock", "Flock"] results = [] for s in ['flock']: result_set = self.perform_query(s) results.append(result_set.results[0]['uri']) results.append(result_set.results[0]['title']) results.append(result_set.results[1]['uri']) results.append(result_set.results[1]['title']) self.assertEqual(results, expected_results) def test_failing_search(self): self.scope_module.CLEMENTINE_DBFILE = 'tests/data/mock_clementine_fail' self.scope_module.CLEMENTINE_BACKUP_FILE = 'tests/data/mock_clementine_backup.db' for s in ['upnriitnyt']: result_set = self.perform_query(s) self.assertEqual(len(result_set.results), 0) if __name__ == '__main__': unittest.main() unity-scope-clementine-0.1+13.10.20130723/tests/__init__.py0000644000015700001700000000000012173417355023554 0ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/tests/data/0000755000015700001700000000000012173420253022355 5ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/tests/data/mock_clementine_pass.db0000644000015700001700000003200012173417355027052 0ustar pbuserpbgroup00000000000000SQLite format 3@  v-'    ; 85artist TEXT, albumartist TEXT, composer TEXT, track INTEGER, disc INTEGER, bpm REAL, year INTEGER, genre TEXT, comment TEXT, compilation INTEGER, length INTEGER, bitrate INTEGER, samplerate INTEGER, /* Information about the file on disk */ directory INTEGER NOT NULL, filename TEXT NOT NULL, mtime INTEGER NOT NULL, ctime INTEGER NOT NULL, filesize INTEGER NOT NULL , sampler INTEGER NOT NULL DEFAULT 0, art_automatic TEXT, art_manual TEXT, filetype INTEGER NOT NULL DEFAULT 0, playcount INTEGER NOT NULL DEFAULT 0, lastplayed INTEGER, rating INTEGER, forced_compilation_on INTEGER NOT NULL DEFAULT 0, forced_compilation_off INTEGER NOT NULL DEFAULT 0, effective_compilation NOT NULL DEFAULT 0, skipcount INTEGER NOT NULL DEFAULT 0, score INTEGER NOT NULL DEFAULT 0, beginning INTEGER NOT NULL DEFAULT 0, cue_path TEXT, unavailable INTEGER DEFAULT 0, effective_albumartist TEXT) [yj[Bell X1Bell X1Bell X1Bell X1Bell X1Bell X1Bell X1Bell X1Bell X1Bell X1Bell X1  Flock Flock Flock Flock Flock Flock Flock Flock Flock Flock Flock 0viX@0!Trampoline1Rocky Took a Lover#Reacharound Natalie=My First Born for a Song Lamposts/Just Like Mr Benn-He Said She Said Flame)Bigger Than Me%Bad Skin Day .W a@file:///home/mark/Music/Bell%20X1/Flock/11.%20Lamposts.mp3Bfile:///home/mark/Music/Bell%20X1/Flock/10.%20Trampoline.mp3Z4file:///home/mark/Music/Bell%20X1/Flock/09.%20My%20First%20Born%20for%20a%20Song.mp3Ofile:///home/mark/Music/Bell%20X1/Flock/08.%20Just%20Like%20Mr%20Benn.mp3Jfile:///home/mark/Music/Bell%20X1/Flock/07.%20Bigger%20Than%20Me.mp3>~file:///home/mark/Music/Bell%20X1/Flock/06.%20Natalie.mp3Hfile:///home/mark/Music/Bell%20X1/Flock/05.%20Bad%20Skin%20Day.mp3Nfile:///home/mark/Music/Bell%20X1/Flock/04.%20He%20Said%20She%20Said.mp3P file:///home/mark/Music/Bell%20X1/Flock/03.%20Rocky%20Took%20a%20Lover.mp3<zfile:///home/mark/Music/Bell%20X1/Flock/02.%20Flame.mp3Cfile:///home/mark/Music/Bell%20X1/Flock/01.%20Reacharound.mp3 +i+:5'# ]9ReacharoundFlockBell X1Bell X1Crosby;Rock,<Dfile:///home/mark/Music/Bell%20X1/Flock/01.%20Reacharound.mp3N:N:./home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1^4'= 4]9My First Born for a SongFlockBell X1Bell X1Crosby @RockKoDfile:///home/mark/Music/Bell%20X1/Flock/09.%20My%20First%20Born%20for%20a%20Song.mp3LŋMO=/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X113& ~]9NatalieFlockBell X1Bell X1CrosbySRock6{|Dfile:///home/mark/Music/Bell%20X1/Flock/06.%20Natalie.mp3NrNr9&k/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1 .v.D8') ]9Bigger Than MeFlockBell X1Bell X1CrosbyfRock6GDfile:///home/mark/Music/Bell%20X1/Flock/07.%20Bigger%20Than%20Me.mp3NFNF8/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1J7'- ]9He Said She SaidFlockBell X1Bell X1CrosbyMRock=wPDfile:///home/mark/Music/Bell%20X1/Flock/04.%20He%20Said%20She%20Said.mp3LŌM@E/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X186'! ]9TrampolineFlockBell X1Bell X1Crosby .RockC#@Dfile:///home/mark/Music/Bell%20X1/Flock/10.%20Trampoline.mp3LŋMFj/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1 88N;'1  ]9Rocky Took a LoverFlockBell X1Bell X1Crosby.Rock:5)DDfile:///home/mark/Music/Bell%20X1/Flock/03.%20Rocky%20Took%20a%20Lover.mp3NN="/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1A:'% ]9Bad Skin DayFlockBell X1Bell X1CrosbyRockRDfile:///home/mark/Music/Bell%20X1/Flock/05.%20Bad%20Skin%20Day.mp3L$MVa/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1-9& z]9FlameFlockBell X1Bell X1Crosby5Rock6?Dfile:///home/mark/Music/Bell%20X1/Flock/02.%20Flame.mp3NqvNqv8/home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1 ww5=' ]9LampostsFlockBell X1Bell X1Crosby Rockjވ.Dfile:///home/mark/Music/Bell%20X1/Flock/11.%20Lamposts.mp3M/uMp./home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1L<'/ ]9Just Like Mr BennFlockBell X1Bell X1Crosby/Rock>*pDfile:///home/mark/Music/Bell%20X1/Flock/08.%20Just%20Like%20Mr%20Benn.mp3LŌMA</home/mark/Music/Bell X1/Flock/cover.jpg/home/mark/.config/Clementine/albumcovers/38c2512ddee89bada236a312cb6a3423bdc0381d.jpgBell X1 zL{UtablesongssongsCREATE TABLE songs ( /* Metadata from taglib */ title TEXT, album TEXT, f+indexidx_comp_artistsongsCREATE INDEX idx_comp_artist ON songs (effective_compilation, artist)A[indexidx_albumsongsCREATE INDEX idx_album ON songs (album)A[indexidx_titlesongsCREATE INDEX idx_title ON songs (title)J%gindexidx_filenamesongsCREATE INDEX idx_filename ON songs (filename)13tablesongs_ftssongs_ftsCREATE VIRTUAL TABLE songs_fts USING fts3( ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsgenre, ftscomment, tokenize=unicode ) LLO33Gtablemagnatune_songs_ftsmagnatune_songs_ftsCREATE VIRTUAL TABLE magnatune_songs_fts USING fts3( ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsgenre, ftscomment, tokenize=unicode )_==Stablespotify_search_songs_ftsspotify_search_songs_ftsCREATE VIRTUAL TABLE spotify_search_songs_fts USING fts3 ( ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsgenre, ftscomment, tokenize=unicode )unity-scope-clementine-0.1+13.10.20130723/tests/data/mock_clementine_fail0000644000015700001700000000000612173417355026434 0ustar pbuserpbgroup00000000000000 unity-scope-clementine-0.1+13.10.20130723/src/0000755000015700001700000000000012173420253021071 5ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/src/unity_clementine_daemon.py0000644000015700001700000003161612173417355026361 0ustar pbuserpbgroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- # Copyright(C) 2013 Mark Tully # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . from gi.repository import GLib, Gio from gi.repository import Unity import gettext import urllib.parse import hashlib import unicodedata import os import shutil import sqlite3 APP_NAME = 'unity-scope-clementine' LOCAL_PATH = '/usr/share/locale/' gettext.bindtextdomain(APP_NAME, LOCAL_PATH) gettext.textdomain(APP_NAME) _ = gettext.gettext GROUP_NAME = 'com.canonical.Unity.Scope.Music.Clementine' UNIQUE_PATH = '/com/canonical/unity/scope/music/clementine' SEARCH_HINT = _('Search Clementime') NO_RESULTS_HINT = _('Sorry, there are no Clementine results that match your search.') PROVIDER_CREDITS = _('') SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/' PROVIDER_ICON = SVG_DIR + 'service-clementine.svg' DEFAULT_RESULT_ICON = SVG_DIR + 'result-clementine.svg' DEFAULT_RESULT_MIMETYPE = 'taglib/mp3' DEFAULT_RESULT_TYPE = Unity.ResultType.PERSONAL CLEMENTINE_DBFILE = os.getenv("HOME") + "/.config/Clementine/clementine.db" CLEMENTINE_BACKUP_FILE = os.getenv("HOME") + "/.config/Clementine/clementine-scope-backup.db" c1 = {'id': 'songs', 'name': _('Songs'), 'icon': SVG_DIR + 'group-installed.svg', 'renderer': Unity.CategoryRenderer.VERTICAL_TILE} c2 = {'id': 'albums', 'name': _('Albums'), 'icon': SVG_DIR + 'group-installed.svg', 'renderer': Unity.CategoryRenderer.VERTICAL_TILE} CATEGORIES = [c1, c2] FILTERS = [] m1 = {'id': 'album', 'type': 's', 'field': Unity.SchemaFieldType.OPTIONAL} m2 = {'id': 'artist', 'type': 's', 'field': Unity.SchemaFieldType.OPTIONAL} m3 = {'id': 'genre', 'type': 's', 'field': Unity.SchemaFieldType.OPTIONAL} m4 = {'id': 'year', 'type': 'i', 'field': Unity.SchemaFieldType.OPTIONAL} m5 = {'id': 'track_length', 'type': 'i', 'field': Unity.SchemaFieldType.OPTIONAL} m6 = {'id': 'track_number', 'type': 'i', 'field': Unity.SchemaFieldType.OPTIONAL} EXTRA_METADATA = [m1, m2, m3, m4, m5, m6] SEARCH_SQL = '''SELECT title, filename, artist, album, albumartist, art_automatic, year, genre, art_manual, track, length FROM songs WHERE album LIKE '%%%s%%' OR artist LIKE '%%%s%%' OR title LIKE '%%%s%%' ORDER BY track''' ALBUM_SQL = '''SELECT title, filename, artist, album, albumartist, art_automatic, year, genre, art_manual, track, length FROM songs WHERE album LIKE '%%%s%%' AND artist LIKE '%%%s%%' ORDER BY track''' def get_music_from_clementine(query): ''' Parses Clementine's database into a form we can use using the supplied SQL query ''' tracks = [] if not os.path.exists(CLEMENTINE_BACKUP_FILE): return tracks conn = sqlite3.connect(CLEMENTINE_BACKUP_FILE) cursor = conn.cursor() cursor.execute(query) tracks = cursor.fetchall() cursor.close() return tracks def get_album_art(track): # First try manually set album art if not track[8] is None: if not track[8] == "(embedded)": return track[8] # Next try automatically set album art if not track[5] is None: if not track[5] == "(embedded)": return track[5] # Try thumbnailing any embedded album art and use that hashname = '%s\t%s' % (unicodedata.normalize("NFKD", track[4]), unicodedata.normalize("NFKD", track[3])) file_hash = hashlib.md5(hashname.encode('utf-8')).hexdigest() tb_filename = os.path.join(os.path.expanduser("~/.cache/media-art"), ("album-" + file_hash)) + ".jpg" if os.path.exists(tb_filename): return tb_filename else: try: from mutagen import File trackfile = track[1][7:] trackfile.replace("%20", " ") trackfile = urllib.parse.unquote(trackfile) audio = File(trackfile) if "APIC" in audio: artwork = audio.tags["APIC:"].data if not os.path.exists(os.path.expanduser("~/.cache/media-art")): os.makedirs(os.path.expanduser("~/.cache/media-art")) with open(tb_filename, "wb") as img: img.write(artwork) return tb_filename else: return "audio-x-generic" except: # Otherwise, return a generic audio icon return "audio-x-generic" def search(search, filters): ''' Search for help documents matching the search string ''' results = [] shutil.copy2(CLEMENTINE_DBFILE, CLEMENTINE_BACKUP_FILE) tracks = get_music_from_clementine(SEARCH_SQL % (search, search, search)) albumresults = [] for track in tracks: title = "" if track[0] is None else track[0] uri = "" if track[1] is None else track[1].decode('utf-8') artist = "" if track[2] is None else track[2] album = "" if track[3] is None else track[3] albumartist = "" if track[4] is None else track[4] year = 0 if track[6] is None else track[6] genre = "" if track[7] is None else track[7] track_length = 0 if track[10] is None else track[10] / 1000000000 track_number = 0 if track[9] is None else track[9] albumart = get_album_art(track) albumuri = "album://" + albumartist + "/" + album results.append({'uri': urllib.parse.unquote(uri), 'icon': albumart, 'category': 0, 'title': title, 'album': GLib.Variant('s', album), 'artist': GLib.Variant('s', artist), 'genre': GLib.Variant('s', genre), 'year': GLib.Variant('i', year), 'track_length': GLib.Variant('i', track_length), 'track_number': GLib.Variant('i', track_number)}) if album not in albumresults: results.append({'uri': albumuri, 'icon': albumart, 'category': 1, 'title': album, 'album': GLib.Variant('s', album), 'artist': GLib.Variant('s', artist), 'genre': GLib.Variant('s', genre), 'year': GLib.Variant('i', year)}) albumresults.append(album) return results class Preview(Unity.ResultPreviewer): def do_run(self): album = self.result.metadata['album'].get_string() artist = self.result.metadata['artist'].get_string() preview = Unity.MusicPreview.new(self.result.title, '', None) preview.props.image_source_uri = 'file://%s' % self.result.icon_hint preview.props.subtitle = self.result.metadata['artist'].get_string() if self.result.uri.startswith("album://"): tracks = get_music_from_clementine(ALBUM_SQL % (album, artist)) for track in tracks: track = Unity.TrackMetadata.full(track[1].decode('utf-8'), track[9], track[0], track[2], track[3], track[10] / 1000000000) preview.add_track(track) else: track = Unity.TrackMetadata.full(self.result.uri, self.result.metadata['track_number'].get_int32(), self.result.title, self.result.metadata['artist'].get_string(), self.result.metadata['album'].get_string(), self.result.metadata['track_length'].get_int32()) preview.add_track(track) icon = Gio.FileIcon.new(Gio.file_new_for_path(PROVIDER_ICON)) view_action = Unity.PreviewAction.new("play", _("Play"), None) preview.add_action(view_action) show_action = Unity.PreviewAction.new("show", _("Show in Folder"), None) preview.add_action(show_action) return preview # Classes below this point establish communication # with Unity, you probably shouldn't modify them. class MySearch(Unity.ScopeSearchBase): def __init__(self, search_context): super(MySearch, self).__init__() self.set_search_context(search_context) def do_run(self): ''' Adds results to the model ''' try: result_set = self.search_context.result_set for i in search(self.search_context.search_query, self.search_context.filter_state): if not 'uri' in i or not i['uri'] or i['uri'] == '': continue if not 'icon' in i or not i['icon'] or i['icon'] == '': i['icon'] = DEFAULT_RESULT_ICON if not 'mimetype' in i or not i['mimetype'] or i['mimetype'] == '': i['mimetype'] = DEFAULT_RESULT_MIMETYPE if not 'result_type' in i or not i['result_type'] or i['result_type'] == '': i['result_type'] = DEFAULT_RESULT_TYPE if not 'category' in i or not i['category'] or i['category'] == '': i['category'] = 0 if not 'title' in i or not i['title']: i['title'] = '' if not 'comment' in i or not i['comment']: i['comment'] = '' if not 'dnd_uri' in i or not i['dnd_uri'] or i['dnd_uri'] == '': i['dnd_uri'] = i['uri'] i['provider_credits'] = GLib.Variant('s', PROVIDER_CREDITS) result_set.add_result(**i) except Exception as error: print(error) class Scope(Unity.AbstractScope): def __init__(self): Unity.AbstractScope.__init__(self) def do_get_search_hint(self): return SEARCH_HINT def do_get_schema(self): ''' Adds specific metadata fields ''' schema = Unity.Schema.new() if EXTRA_METADATA: for m in EXTRA_METADATA: schema.add_field(m['id'], m['type'], m['field']) #FIXME should be REQUIRED for credits schema.add_field('provider_credits', 's', Unity.SchemaFieldType.OPTIONAL) return schema def do_get_categories(self): ''' Adds categories ''' cs = Unity.CategorySet.new() if CATEGORIES: for c in CATEGORIES: cat = Unity.Category.new(c['id'], c['name'], Gio.ThemedIcon.new(c['icon']), c['renderer']) cs.add(cat) return cs def do_get_filters(self): ''' Adds filters ''' fs = Unity.FilterSet.new() #if FILTERS: # return fs def do_get_group_name(self): return GROUP_NAME def do_get_unique_name(self): return UNIQUE_PATH def do_create_search_for_query(self, search_context): se = MySearch(search_context) return se def do_activate(self, result, metadata, id): album = result.metadata['album'].get_string() artist = result.metadata['artist'].get_string() if id == 'show': if result.uri.startswith("album://"): tracks = get_music_from_clementine(ALBUM_SQL % (album, artist)) filename = tracks[0][1].decode('utf-8') else: filename = result.uri dirname = os.path.dirname(filename) os.system("xdg-open '%s'" % str(dirname)) else: albumtracks = '' if result.uri.startswith('album://'): tracks = get_music_from_clementine(ALBUM_SQL % (album, artist)) for track in tracks: albumtracks = '%s \'%s\'' % (albumtracks, track[1].decode('utf-8')) else: albumtracks = result.uri os.system('clementine -a %s' % albumtracks) return Unity.ActivationResponse(handled=Unity.HandledType.HIDE_DASH, goto_uri=None) def do_create_previewer(self, result, metadata): rp = Preview() rp.set_scope_result(result) rp.set_search_metadata(metadata) return rp def load_scope(): return Scope() unity-scope-clementine-0.1+13.10.20130723/src/__init__.py0000644000015700001700000000000012173417355023201 0ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/setup.py0000644000015700001700000000161512173417355022030 0ustar pbuserpbgroup00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' Setup file for clementine dash plugin ''' from distutils.core import setup from DistUtilsExtra.command import build_extra from DistUtilsExtra.command import build_i18n setup(name='unity-scope-clementine', version='0.1', author='Mark Tully', author_email='markjtully@gmail.com', url='http://launchpad.net/ubuntu-scopes', license='GNU General Public License (GPL)', data_files=[('share/dbus-1/services', ['data/unity-scope-clementine.service']), #('share/icons/unity-icon-theme/places/svg', ['data/icons/service-clementine.svg']), ('share/unity-scopes/clementine', ['src/unity_clementine_daemon.py']), ('share/unity-scopes/clementine', ['src/__init__.py']), ], cmdclass={'build': build_extra.build_extra, 'build_i18n': build_i18n.build_i18n, }) unity-scope-clementine-0.1+13.10.20130723/setup.cfg0000644000015700001700000000021212173417355022127 0ustar pbuserpbgroup00000000000000[build] i18n=True [build_i18n] domain=unity-scope-clementine desktop_files=[('share/unity/scopes/music', ('data/clementine.scope.in',))] unity-scope-clementine-0.1+13.10.20130723/data/0000755000015700001700000000000012173420253021213 5ustar pbuserpbgroup00000000000000unity-scope-clementine-0.1+13.10.20130723/data/clementine.scope.in0000644000015700001700000000146612173417355025016 0ustar pbuserpbgroup00000000000000[Scope] DBusName=com.canonical.Unity.Scope.Music.Clementine DBusPath=/com/canonical/unity/scope/music/clementine Icon=/usr/share/unity/icons/lens-nav-music.svg QueryBinary=clementine _Keywords=clementine; RequiredMetadata= OptionalMetadata=album[s];artist[s];genre[s];year[i];track_length[i];track_number[i] Loader=/usr/share/unity-scopes/clementine/unity_clementine_daemon.py Module=clementine.unity_clementine_daemon ModuleType=python3 RemoteContent=false Type=music _Name=Clementine _Description=This is an Ubuntu search plugin that enables information from Clementine to be searched and displayed in the Dash underneath the Music header. If you do not wish to search this content source, you can disable this search plugin. _SearchHint=Search Clementine [Desktop Entry] X-Ubuntu-Gettext-Domain=unity-scope-clementine unity-scope-clementine-0.1+13.10.20130723/data/unity-scope-clementine.service0000644000015700001700000000023512173417355027206 0ustar pbuserpbgroup00000000000000[D-BUS Service] Name=com.canonical.Unity.Scope.Music.Clementine Exec=/usr/bin/python3 /usr/share/unity-scopes/scope-runner-dbus.py -s music/clementine.scope unity-scope-clementine-0.1+13.10.20130723/data/icons/0000755000015700001700000000000012173420253022326 5ustar pbuserpbgroup00000000000000