root/branches/gajim_0.11/src/music_track_listener.py

Revision 7940, 7.1 kB (checked in by asterix, 22 months ago)

merge diff from trunk

Line 
1# -*- coding: utf-8 -*-
2##      musictracklistener.py
3##
4## Copyright (C) 2006 Gustavo Carneiro <gjcarneiro@gmail.com>
5## Copyright (C) 2006 Nikos Kouremenos <kourem@gmail.com>
6##
7## This program is free software; you can redistribute it and/or modify
8## it under the terms of the GNU General Public License as published
9## by the Free Software Foundation; version 2 only.
10##
11## This program is distributed in the hope that it will be useful,
12## but WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14## GNU General Public License for more details.
15##
16import gobject
17if __name__ == '__main__':
18        # install _() func before importing dbus_support
19        from common import i18n
20
21from common import dbus_support
22if dbus_support.supported:
23        import dbus
24        import dbus.glib
25
26class MusicTrackInfo(object):
27        __slots__ = ['title', 'album', 'artist', 'duration', 'track_number']
28
29
30class MusicTrackListener(gobject.GObject):
31        __gsignals__ = {
32                'music-track-changed': (gobject.SIGNAL_RUN_LAST, None, (object,)),
33        }
34
35        _instance = None
36        @classmethod
37        def get(cls):
38                if cls._instance is None:
39                        cls._instance = cls()
40                return cls._instance
41       
42        def __init__(self):
43                super(MusicTrackListener, self).__init__()
44                self._last_playing_music = None
45               
46                bus = dbus.SessionBus()
47
48                ## Muine
49                bus.add_signal_receiver(self._muine_music_track_change_cb, 'SongChanged',
50                        'org.gnome.Muine.Player')
51                bus.add_signal_receiver(self._player_name_owner_changed,
52                        'NameOwnerChanged', 'org.freedesktop.DBus', arg0='org.gnome.Muine')
53                bus.add_signal_receiver(self._player_playing_changed_cb, 'StateChanged',
54                        'org.gnome.Muine.Player')
55
56                ## Rhythmbox
57                bus.add_signal_receiver(self._rhythmbox_music_track_change_cb,
58                        'playingUriChanged', 'org.gnome.Rhythmbox.Player')
59                bus.add_signal_receiver(self._player_name_owner_changed,
60                        'NameOwnerChanged', 'org.freedesktop.DBus', arg0='org.gnome.Rhythmbox')
61                bus.add_signal_receiver(self._player_playing_changed_cb,
62                        'playingChanged', 'org.gnome.Rhythmbox.Player')
63                       
64                ## Banshee
65                banshee_bus = dbus.SessionBus()
66                dubus = banshee_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/dbus')
67                self.dubus_methods = dbus.Interface(dubus, 'org.freedesktop.DBus')
68                if self.dubus_methods.NameHasOwner('org.gnome.Banshee'):
69                        self._get_banshee_bus()
70                # Otherwise, it opens Banshee!
71                self.banshee_props ={}
72                self.current_banshee_title = ''
73                gobject.timeout_add(1000, self._banshee_check_track_status)
74
75        def _get_banshee_bus(self):
76                bus = dbus.SessionBus()
77                banshee = bus.get_object('org.gnome.Banshee', '/org/gnome/Banshee/Player')
78                self.banshee_methods = dbus.Interface(banshee, 'org.gnome.Banshee.Core')
79
80        def do_music_track_changed(self, info):
81                if info is not None:
82                        self._last_playing_music = info
83
84        def _player_name_owner_changed(self, name, old, new):
85                if not new:
86                        self.emit('music-track-changed', None)
87
88        def _player_playing_changed_cb(self, playing):
89                if playing:
90                        self.emit('music-track-changed', self._last_playing_music)
91                else:
92                        self.emit('music-track-changed', None)
93
94        def _muine_properties_extract(self, song_string):
95                d = dict((x.strip() for x in  s1.split(':', 1)) for s1 in \
96                        song_string.split('\n'))
97                info = MusicTrackInfo()
98                info.title = d['title']
99                info.album = d['album']
100                info.artist = d['artist']
101                info.duration = int(d['duration'])
102                info.track_number = int(d['track_number'])
103                return info
104
105        def _muine_music_track_change_cb(self, arg):
106                info = self._muine_properties_extract(arg)
107                self.emit('music-track-changed', info)
108
109        def _rhythmbox_properties_extract(self, props):
110                info = MusicTrackInfo()
111                info.title = props['title']
112                info.album = props['album']
113                info.artist = props['artist']
114                info.duration = int(props['duration'])
115                info.track_number = int(props['track-number'])
116                return info
117       
118        def _rhythmbox_music_track_change_cb(self, uri):
119                bus = dbus.SessionBus()
120                rbshellobj = bus.get_object('org.gnome.Rhythmbox',
121                        '/org/gnome/Rhythmbox/Shell')
122                rbshell = dbus.Interface(rbshellobj, 'org.gnome.Rhythmbox.Shell')
123                props = rbshell.getSongProperties(uri)
124                info = self._rhythmbox_properties_extract(props)
125                self.emit('music-track-changed', info)
126
127        def _banshee_check_track_status(self):
128                if self.dubus_methods.NameHasOwner('org.gnome.Banshee') and \
129                not hasattr(self, 'banshee_methods'):
130                        self._get_banshee_bus()
131
132                if self.dubus_methods.NameHasOwner('org.gnome.Banshee'):
133                        self.banshee_props['title'] = self.banshee_methods.GetPlayingTitle()
134                        self.banshee_props['album'] = self.banshee_methods.GetPlayingAlbum()
135                        self.banshee_props['artist'] = self.banshee_methods.GetPlayingArtist()
136                        self.banshee_props['duration'] = \
137                                self.banshee_methods.GetPlayingDuration()
138                        info = self._banshee_properties_extract(self.banshee_props)
139                        if self.current_banshee_title != self.banshee_props['title']:
140                                self.emit('music-track-changed', info)
141                        self.current_banshee_title = self.banshee_props['title']
142                return 1
143
144        def _banshee_music_track_change_cb(self, arg):
145                info = self._banshee_properties_extract(arg)
146                self.emit('music-track-changed', info)
147
148        def _banshee_properties_extract(self, props):
149                info = MusicTrackInfo()
150                info.title = props['title']
151                info.album = props['album']
152                info.artist = props['artist']
153                info.duration = int(props['duration'])
154                return info
155
156        def get_playing_track(self):
157                '''Return a MusicTrackInfo for the currently playing
158                song, or None if no song is playing'''
159
160                bus = dbus.SessionBus()
161
162                ## Check Muine playing track
163                test = False
164                if hasattr(bus, 'name_has_owner'):
165                        if bus.name_has_owner('org.gnome.Muine'):
166                                test = True
167                elif dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
168                'org.gnome.Muine'):
169                        test = True
170                if test:
171                        obj = bus.get_object('org.gnome.Muine', '/org/gnome/Muine/Player')
172                        player = dbus.Interface(obj, 'org.gnome.Muine.Player')
173                        if player.GetPlaying():
174                                song_string = player.GetCurrentSong()
175                                song = self._muine_properties_extract(song_string)
176                                self._last_playing_music = song
177                                return song
178
179                ## Check Rhythmbox playing song
180                test = False
181                if hasattr(bus, 'name_has_owner'):
182                        if bus.name_has_owner('org.gnome.Rhythmbox'):
183                                test = True
184                elif dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
185                'org.gnome.Rhythmbox'):
186                        test = True
187                if test:
188                        rbshellobj = bus.get_object('org.gnome.Rhythmbox',
189                                '/org/gnome/Rhythmbox/Shell')
190                        player = dbus.Interface(
191                                bus.get_object('org.gnome.Rhythmbox',
192                                '/org/gnome/Rhythmbox/Player'), 'org.gnome.Rhythmbox.Player')
193                        rbshell = dbus.Interface(rbshellobj, 'org.gnome.Rhythmbox.Shell')
194                        uri = player.getPlayingUri()
195                        props = rbshell.getSongProperties(uri)
196                        info = self._rhythmbox_properties_extract(props)
197                        self._last_playing_music = info
198                        return info
199
200                return None
201
202# here we test :)
203if __name__ == '__main__':
204        def music_track_change_cb(listener, music_track_info):
205                if music_track_info is None:
206                        print "Stop!"
207                else:
208                        print music_track_info.title
209        listener = MusicTrackListener.get()
210        listener.connect('music-track-changed', music_track_change_cb)
211        track = listener.get_playing_track()
212        if track is None:
213                print 'Now not playing anything'
214        else:
215                print 'Now playing: "%s" by %s' % (track.title, track.artist)
216        gobject.MainLoop().run()
Note: See TracBrowser for help on using the browser.