~davidc3/onehundredscopes/musicfolder

« back to all changes in this revision

Viewing changes to src/musicfolder.py

  • Committer: David Call√©
  • Date: 2011-10-15 11:52:53 UTC
  • Revision ID: davidc@framli.eu-20111015115253-xeq3291hla1w1iou
Branch init

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
#    Copyright (c) 2011 David Calle <davidc@framli.eu>
 
4
 
 
5
#    This program is free software: you can redistribute it and/or modify
 
6
#    it under the terms of the GNU General Public License as published by
 
7
#    the Free Software Foundation, either version 3 of the License, or
 
8
#    (at your option) any later version.
 
9
 
 
10
#    This program is distributed in the hope that it will be useful,
 
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
#    GNU General Public License for more details.
 
14
 
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
import sys, os
 
18
from gi.repository import GLib, GObject, Gio
 
19
from gi.repository import Dee
 
20
_m = dir(Dee.SequenceModel)
 
21
from gi.repository import Unity
 
22
from ID3 import *
 
23
import socket
 
24
 
 
25
socket.setdefaulttimeout(5)
 
26
BUS_NAME = "net.launchpad.scope.music.musicfolder"
 
27
 
 
28
class Daemon:
 
29
        def __init__ (self):
 
30
                self.scope = Unity.Scope.new ("/net/launchpad/scope/music/musicfolder")
 
31
                self.scope.search_in_global = False
 
32
                self.scope.connect ("notify::active-search", self.on_search_changed)
 
33
                self.scope.connect ("filters-changed", self.on_search_changed);
 
34
                self.scope.export()
 
35
 
 
36
        def get_search_string (self):
 
37
                search = self.scope.props.active_search
 
38
                return search.props.search_string if search else None
 
39
 
 
40
        def on_search_changed (self, scope, param_spec=None):
 
41
                        search = self.get_search_string()
 
42
                        print "Search changed to: '%s'" % search
 
43
                        results = self.scope.props.results_model
 
44
                        results.clear()
 
45
                        self.update_results_model (search, results)
 
46
                        results.flush_revision_queue ()
 
47
 
 
48
        def update_results_model(self, search, model):
 
49
                for i in self.musicfolder(search):
 
50
                        title = i[0]
 
51
                        comment = i[1]
 
52
                        uri = "file://"+ i[2]
 
53
                        icon_hint = i[3]
 
54
                        model.append (uri, icon_hint, 0,"text/html", title, comment, uri)
 
55
                        model.append (uri, icon_hint, 1,"text/html", title, comment, uri)
 
56
 
 
57
 
 
58
        def searchid3(self, files, search):
 
59
                result = []
 
60
                title = ""
 
61
                artist = ""
 
62
                album = ""
 
63
                for f in files:
 
64
                        if not os.path.isdir(f):
 
65
                                id3info = ID3(f)
 
66
                                try :
 
67
                                        title = id3info['TITLE']
 
68
                                except KeyError:
 
69
                                        pass
 
70
                                try :
 
71
                                        artist = id3info['ARTIST']
 
72
                                except KeyError:
 
73
                                        pass
 
74
                                try :
 
75
                                        album = id3info['ALBUM']
 
76
                                except KeyError:
 
77
                                        pass
 
78
                                if title.lower().find(search.lower()) > -1 or artist.lower().find(search.lower()) > -1 or album.lower().find(search.lower()) > -1:
 
79
                                        result.append(self.get_info(f, title, artist, album))
 
80
                return result
 
81
 
 
82
        def musicfolder(self, search):
 
83
                import glib
 
84
                result = []
 
85
                folders = []
 
86
                folder = glib.get_user_special_dir (glib.USER_DIRECTORY_MUSIC)
 
87
                files = self.listFiles(folder)
 
88
                return self.searchid3(files, search)
 
89
 
 
90
        def listFiles(self, dir):
 
91
                files = []
 
92
                basedir = dir
 
93
                subdirlist = []
 
94
                for item in os.listdir(dir):
 
95
                        if os.path.isfile(os.path.join(basedir,item)):
 
96
                                files.append(basedir+"/"+item)
 
97
                        else:
 
98
                                subdirlist.append(os.path.join(basedir, item))
 
99
                for subdir in subdirlist:
 
100
                        self.listFiles(subdir)
 
101
                return files
 
102
 
 
103
 
 
104
        def get_info(self, item, title, artist, album):
 
105
                import gio
 
106
                item_list = []
 
107
                f = gio.File(item)
 
108
                path = f.get_path()
 
109
                icon = f.query_info(gio.FILE_ATTRIBUTE_THUMBNAIL_PATH)
 
110
                icon = icon.get_attribute_as_string(gio.FILE_ATTRIBUTE_THUMBNAIL_PATH)
 
111
                if not icon:
 
112
                        icon = "sound"
 
113
                item_list.append(str(title))
 
114
                item_list.append(str(artist))
 
115
                item_list.append(str(item))
 
116
                item_list.append(str(icon))
 
117
                return item_list
 
118
 
 
119
if __name__ == "__main__":
 
120
        session_bus_connection = Gio.bus_get_sync (Gio.BusType.SESSION, None)
 
121
        session_bus = Gio.DBusProxy.new_sync (session_bus_connection, 0, None,
 
122
                                              'org.freedesktop.DBus',
 
123
                                              '/org/freedesktop/DBus',
 
124
                                              'org.freedesktop.DBus', None)
 
125
        result = session_bus.call_sync('RequestName',
 
126
                                       GLib.Variant ("(su)", (BUS_NAME, 0x4)),
 
127
                                       0, -1, None)
 
128
                                       
 
129
        # Unpack variant response with signature "(u)". 1 means we got it.
 
130
        result = result.unpack()[0]
 
131
        
 
132
        if result != 1 :
 
133
                print >> sys.stderr, "Failed to own name %s. Bailing out." % BUS_NAME
 
134
                raise SystemExit (1)
 
135
        
 
136
        daemon = Daemon()
 
137
        GObject.MainLoop().run()