Philipp Hörist pushed to branch master at gajim / gajim

Commits:

3 changed files:

Changes:

  • gajim/gui_interface.py
    ... ... @@ -56,9 +56,10 @@ from gajim.common import events
    56 56
     
    
    57 57
     from gajim.common import dbus_support
    
    58 58
     if dbus_support.supported:
    
    59
    -    from gajim.music_track_listener import MusicTrackListener
    
    60 59
         import dbus
    
    61 60
     
    
    61
    +from gajim.music_track_listener import MusicTrackListener
    
    62
    +
    
    62 63
     if app.HAVE_GEOCLUE:
    
    63 64
         from gajim.common import location_listener
    
    64 65
     
    
    ... ... @@ -1135,7 +1136,7 @@ class Interface:
    1135 1136
             if connected == invisible_show:
    
    1136 1137
                 return
    
    1137 1138
             # send currently played music
    
    1138
    -        if (obj.conn.pep_supported and dbus_support.supported and
    
    1139
    +        if (obj.conn.pep_supported and sys.platform == 'linux' and
    
    1139 1140
                     app.config.get_per('accounts', account, 'publish_tune')):
    
    1140 1141
                 self.enable_music_listener()
    
    1141 1142
             # enable location listener
    
    ... ... @@ -2192,8 +2193,6 @@ class Interface:
    2192 2193
             if not self.music_track_changed_signal:
    
    2193 2194
                 self.music_track_changed_signal = listener.connect(
    
    2194 2195
                     'music-track-changed', self.music_track_changed)
    
    2195
    -        track = listener.get_playing_track()
    
    2196
    -        self.music_track_changed(listener, track)
    
    2197 2196
     
    
    2198 2197
         def disable_music_listener(self):
    
    2199 2198
             listener = MusicTrackListener.get()
    
    ... ... @@ -2207,9 +2206,7 @@ class Interface:
    2207 2206
             else:
    
    2208 2207
                 accounts = [account]
    
    2209 2208
     
    
    2210
    -        is_paused = hasattr(music_track_info, 'paused') and \
    
    2211
    -            music_track_info.paused == 0
    
    2212
    -        if not music_track_info or is_paused:
    
    2209
    +        if music_track_info is None or music_track_info.paused:
    
    2213 2210
                 artist = title = source = ''
    
    2214 2211
             else:
    
    2215 2212
                 artist = music_track_info.artist
    

  • gajim/music_track_listener.py
    1 1
     # -*- coding: utf-8 -*-
    
    2
    -## src/music_track_listener.py
    
    2
    +## gajim/music_track_listener.py
    
    3 3
     ##
    
    4 4
     ## Copyright (C) 2006 Gustavo Carneiro <gjcarneiro AT gmail.com>
    
    5 5
     ##                    Nikos Kouremenos <kourem AT gmail.com>
    
    ... ... @@ -23,25 +23,40 @@
    23 23
     ## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    24 24
     ##
    
    25 25
     
    
    26
    +import logging
    
    27
    +
    
    26 28
     from gi.repository import GObject
    
    27
    -if __name__ == '__main__':
    
    28
    -    # install _() func before importing dbus_support
    
    29
    -    from gajim.common import i18n
    
    29
    +from gi.repository import Gio, GLib
    
    30
    +
    
    31
    +log = logging.getLogger('gajim.music_track_listener')
    
    32
    +
    
    33
    +
    
    34
    +def _get_music_players():
    
    35
    +    players = [
    
    36
    +        'org.mpris.MediaPlayer2.audacious',
    
    37
    +        'org.mpris.MediaPlayer2.bmp',
    
    38
    +        'org.mpris.MediaPlayer2.GnomeMusic',
    
    39
    +        'org.mpris.MediaPlayer2.quodlibet',
    
    40
    +        'org.mpris.MediaPlayer2.rhythmbox',
    
    41
    +        'org.mpris.MediaPlayer2.vlc',
    
    42
    +        'org.mpris.MediaPlayer2.xmms2'
    
    43
    +    ]
    
    44
    +
    
    45
    +    return players
    
    30 46
     
    
    31
    -from gajim.common import dbus_support
    
    32
    -if dbus_support.supported:
    
    33
    -    import dbus
    
    34 47
     
    
    35 48
     class MusicTrackInfo(object):
    
    36 49
         __slots__ = ['title', 'album', 'artist', 'duration', 'track_number',
    
    37
    -            'paused']
    
    50
    +                 'paused']
    
    51
    +
    
    38 52
     
    
    39 53
     class MusicTrackListener(GObject.GObject):
    
    40 54
         __gsignals__ = {
    
    41
    -            'music-track-changed': (GObject.SignalFlags.RUN_LAST, None, (object,)),
    
    55
    +        'music-track-changed': (GObject.SignalFlags.RUN_LAST, None, (object,)),
    
    42 56
         }
    
    43 57
     
    
    44 58
         _instance = None
    
    59
    +
    
    45 60
         @classmethod
    
    46 61
         def get(cls):
    
    47 62
             if cls._instance is None:
    
    ... ... @@ -51,253 +66,117 @@ class MusicTrackListener(GObject.GObject):
    51 66
         def __init__(self):
    
    52 67
             super(MusicTrackListener, self).__init__()
    
    53 68
             self._last_playing_music = None
    
    69
    +        self.con = {}
    
    70
    +
    
    71
    +        players = _get_music_players()
    
    72
    +        for name in players:
    
    73
    +            Gio.bus_watch_name(
    
    74
    +                Gio.BusType.SESSION,
    
    75
    +                name,
    
    76
    +                Gio.BusNameWatcherFlags.NONE,
    
    77
    +                self._appeared,
    
    78
    +                self._vanished)
    
    79
    +
    
    80
    +    def _appeared(self, connection, name, name_owner, *user_data):
    
    81
    +        '''Set up a listener for music player signals'''
    
    82
    +        log.info('%s appeared', name)
    
    83
    +        self.con[name] = connection.signal_subscribe(
    
    84
    +            name,
    
    85
    +            'org.freedesktop.DBus.Properties',
    
    86
    +            'PropertiesChanged',
    
    87
    +            '/org/mpris/MediaPlayer2',
    
    88
    +            None,
    
    89
    +            Gio.DBusSignalFlags.NONE,
    
    90
    +            self._signal_received,
    
    91
    +            name)
    
    92
    +
    
    93
    +        info = self.get_playing_track(name)
    
    94
    +        if info is not None:
    
    95
    +            self._last_playing_music = info
    
    96
    +            self.emit('music-track-changed', info)
    
    54 97
     
    
    55
    -        bus = dbus.SessionBus()
    
    56
    -
    
    57
    -        ## MPRIS
    
    58
    -        bus.add_signal_receiver(self._mpris_music_track_change_cb, 'TrackChange',
    
    59
    -                'org.freedesktop.MediaPlayer')
    
    60
    -        bus.add_signal_receiver(self._mpris_playing_changed_cb, 'StatusChange',
    
    61
    -                'org.freedesktop.MediaPlayer')
    
    62
    -        bus.add_signal_receiver(self._player_name_owner_changed,
    
    63
    -                'NameOwnerChanged', 'org.freedesktop.DBus',
    
    64
    -                arg0='org.freedesktop.MediaPlayer')
    
    65
    -
    
    66
    -        ## Muine
    
    67
    -        bus.add_signal_receiver(self._muine_music_track_change_cb, 'SongChanged',
    
    68
    -                'org.gnome.Muine.Player')
    
    69
    -        bus.add_signal_receiver(self._player_name_owner_changed,
    
    70
    -                'NameOwnerChanged', 'org.freedesktop.DBus', arg0='org.gnome.Muine')
    
    71
    -        bus.add_signal_receiver(self._player_playing_changed_cb, 'StateChanged',
    
    72
    -                'org.gnome.Muine.Player')
    
    73
    -
    
    74
    -        ## Rhythmbox
    
    75
    -        bus.add_signal_receiver(self._player_name_owner_changed,
    
    76
    -                'NameOwnerChanged', 'org.freedesktop.DBus', arg0='org.gnome.Rhythmbox')
    
    77
    -        bus.add_signal_receiver(self._rhythmbox_playing_changed_cb,
    
    78
    -                'playingChanged', 'org.gnome.Rhythmbox.Player')
    
    79
    -        bus.add_signal_receiver(self._player_playing_song_property_changed_cb,
    
    80
    -                'playingSongPropertyChanged', 'org.gnome.Rhythmbox.Player')
    
    81
    -
    
    82
    -        ## Banshee
    
    83
    -        bus.add_signal_receiver(self._banshee_state_changed_cb,
    
    84
    -                'StateChanged', 'org.bansheeproject.Banshee.PlayerEngine')
    
    85
    -        bus.add_signal_receiver(self._player_name_owner_changed,
    
    86
    -                'NameOwnerChanged', 'org.freedesktop.DBus',
    
    87
    -                arg0='org.bansheeproject.Banshee')
    
    88
    -
    
    89
    -        ## Quod Libet
    
    90
    -        bus.add_signal_receiver(self._quodlibet_state_change_cb,
    
    91
    -                'SongStarted', 'net.sacredchao.QuodLibet')
    
    92
    -        bus.add_signal_receiver(self._quodlibet_state_change_cb,
    
    93
    -                'Paused', 'net.sacredchao.QuodLibet')
    
    94
    -        bus.add_signal_receiver(self._quodlibet_state_change_cb,
    
    95
    -                'Unpaused', 'net.sacredchao.QuodLibet')
    
    96
    -        bus.add_signal_receiver(self._player_name_owner_changed,
    
    97
    -                'NameOwnerChanged', 'org.freedesktop.DBus',
    
    98
    -                arg0='net.sacredchao.QuodLibet')
    
    99
    -
    
    100
    -    def _player_name_owner_changed(self, name, old, new):
    
    101
    -        if not new:
    
    102
    -            self.emit('music-track-changed', None)
    
    98
    +    def _vanished(self, connection, name, *user_data):
    
    99
    +        log.info('%s vanished', name)
    
    100
    +        if name in self.con:
    
    101
    +            connection.signal_unsubscribe(
    
    102
    +                self.con[name])
    
    103
    +            self.con.pop(name)
    
    103 104
     
    
    104
    -    def _player_playing_changed_cb(self, playing):
    
    105
    -        if playing:
    
    106
    -            self.emit('music-track-changed', self._last_playing_music)
    
    107
    -        else:
    
    108 105
                 self.emit('music-track-changed', None)
    
    109 106
     
    
    110
    -    def _player_playing_song_property_changed_cb(self, a, b, c, d):
    
    111
    -        if b == 'rb:stream-song-title':
    
    112
    -            self.emit('music-track-changed', self._last_playing_music)
    
    107
    +    def _signal_received(self, connection, sender_name, object_path,
    
    108
    +                         interface_name, signal_name, parameters, *user_data):
    
    109
    +        '''Signal handler for PropertiesChanged event'''
    
    113 110
     
    
    114
    -    def _mpris_properties_extract(self, song):
    
    115
    -        info = MusicTrackInfo()
    
    116
    -        info.title = song.get('title', '')
    
    117
    -        info.album = song.get('album', '')
    
    118
    -        info.artist = song.get('artist', '')
    
    119
    -        info.duration = int(song.get('length', 0))
    
    120
    -        return info
    
    121
    -
    
    122
    -    def _mpris_playing_changed_cb(self, playing):
    
    123
    -        if type(playing) is dbus.Struct:
    
    124
    -            if playing[0]:
    
    125
    -                self.emit('music-track-changed', None)
    
    126
    -            else:
    
    127
    -                self.emit('music-track-changed', self._last_playing_music)
    
    128
    -        else: # Workaround for e.g. Audacious
    
    129
    -            if playing:
    
    130
    -                self.emit('music-track-changed', None)
    
    131
    -            else:
    
    132
    -                self.emit('music-track-changed', self._last_playing_music)
    
    111
    +        if 'PlaybackStatus' not in parameters[1]:
    
    112
    +            return
    
    133 113
     
    
    134
    -    def _mpris_music_track_change_cb(self, arg):
    
    135
    -        self._last_playing_music = self._mpris_properties_extract(arg)
    
    136
    -        self.emit('music-track-changed', self._last_playing_music)
    
    114
    +        log.info('Signal received: %s - %s', interface_name, parameters)
    
    137 115
     
    
    138
    -    def _muine_properties_extract(self, song_string):
    
    139
    -        d = dict((x.strip() for x in  s1.split(':', 1)) for s1 in \
    
    140
    -                song_string.split('\n'))
    
    141
    -        info = MusicTrackInfo()
    
    142
    -        info.title = d['title']
    
    143
    -        info.album = d['album']
    
    144
    -        info.artist = d['artist']
    
    145
    -        info.duration = int(d['duration'])
    
    146
    -        info.track_number = int(d['track_number'])
    
    147
    -        return info
    
    116
    +        info = self.get_playing_track(user_data[0])
    
    117
    +        self._last_playing_music = info
    
    148 118
     
    
    149
    -    def _muine_music_track_change_cb(self, arg):
    
    150
    -        info = self._muine_properties_extract(arg)
    
    151 119
             self.emit('music-track-changed', info)
    
    152 120
     
    
    153
    -    def _rhythmbox_playing_changed_cb(self, playing):
    
    154
    -        if playing:
    
    155
    -            info = self.get_playing_track()
    
    156
    -            self.emit('music-track-changed', info)
    
    157
    -        else:
    
    158
    -            self.emit('music-track-changed', None)
    
    159
    -
    
    160
    -    def _rhythmbox_properties_extract(self, props):
    
    161
    -        info = MusicTrackInfo()
    
    162
    -        info.title = props.get('title', None)
    
    163
    -        info.album = props.get('album', None)
    
    164
    -        info.artist = props.get('artist', None)
    
    165
    -        info.duration = int(props.get('duration', 0))
    
    166
    -        info.track_number = int(props.get('track-number', 0))
    
    167
    -        return info
    
    168
    -
    
    169
    -    def _banshee_state_changed_cb(self, state):
    
    170
    -        if state == 'playing':
    
    171
    -            bus = dbus.SessionBus()
    
    172
    -            banshee = bus.get_object('org.bansheeproject.Banshee',
    
    173
    -                    '/org/bansheeproject/Banshee/PlayerEngine')
    
    174
    -            currentTrack = banshee.GetCurrentTrack()
    
    175
    -            self._last_playing_music = self._banshee_properties_extract(
    
    176
    -                    currentTrack)
    
    177
    -            self.emit('music-track-changed', self._last_playing_music)
    
    178
    -        elif state == 'paused':
    
    179
    -            self.emit('music-track-changed', None)
    
    121
    +    def _properties_extract(self, properties):
    
    122
    +        meta = properties.get('Metadata')
    
    123
    +        if meta is None or not meta:
    
    124
    +            return None
    
    180 125
     
    
    181
    -    def _banshee_properties_extract(self, props):
    
    182 126
             info = MusicTrackInfo()
    
    183
    -        info.title = props.get('name', None)
    
    184
    -        info.album = props.get('album', None)
    
    185
    -        info.artist = props.get('artist', None)
    
    186
    -        info.duration = int(props.get('length', 0))
    
    187
    -        return info
    
    188
    -
    
    189
    -    def _quodlibet_state_change_cb(self, state=None):
    
    190
    -        info = self.get_playing_track()
    
    191
    -        if info:
    
    192
    -            self.emit('music-track-changed', info)
    
    127
    +        info.title = meta.get('xesam:title')
    
    128
    +        info.album = meta.get('xesam:album')
    
    129
    +        artist = meta.get('xesam:artist')
    
    130
    +        if artist is not None and len(artist):
    
    131
    +            info.artist = artist[0]
    
    193 132
             else:
    
    194
    -            self.emit('music-track-changed', None)
    
    133
    +            info.artist = None
    
    134
    +        info.duration = float(meta.get('mpris:length', 0))
    
    135
    +        info.track_number = meta.get('xesam:trackNumber', 0)
    
    136
    +
    
    137
    +        status = properties.get('PlaybackStatus')
    
    138
    +        info.paused = status is not None and status == 'Paused'
    
    195 139
     
    
    196
    -    def _quodlibet_properties_extract(self, props):
    
    197
    -        info = MusicTrackInfo()
    
    198
    -        info.title = props.get('title', None)
    
    199
    -        info.album = props.get('album', None)
    
    200
    -        info.artist = props.get('artist', None)
    
    201
    -        info.duration = float(props.get('~#length', 0))
    
    202 140
             return info
    
    203 141
     
    
    204
    -    def get_playing_track(self):
    
    142
    +    def get_playing_track(self, name):
    
    205 143
             '''Return a MusicTrackInfo for the currently playing
    
    206 144
             song, or None if no song is playing'''
    
    207
    -
    
    208
    -        bus = dbus.SessionBus()
    
    209
    -
    
    210
    -        ## Check Muine playing track
    
    211
    -        test = False
    
    212
    -        if hasattr(bus, 'name_has_owner'):
    
    213
    -            if bus.name_has_owner('org.gnome.Muine'):
    
    214
    -                test = True
    
    215
    -        elif dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
    
    216
    -        'org.gnome.Muine'):
    
    217
    -            test = True
    
    218
    -        if test:
    
    219
    -            obj = bus.get_object('org.gnome.Muine', '/org/gnome/Muine/Player')
    
    220
    -            player = dbus.Interface(obj, 'org.gnome.Muine.Player')
    
    221
    -            if player.GetPlaying():
    
    222
    -                song_string = player.GetCurrentSong()
    
    223
    -                song = self._muine_properties_extract(song_string)
    
    224
    -                self._last_playing_music = song
    
    225
    -                return song
    
    226
    -
    
    227
    -        ## Check Rhythmbox playing song
    
    228
    -        test = False
    
    229
    -        if hasattr(bus, 'name_has_owner'):
    
    230
    -            if bus.name_has_owner('org.gnome.Rhythmbox'):
    
    231
    -                test = True
    
    232
    -        elif dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
    
    233
    -        'org.gnome.Rhythmbox'):
    
    234
    -            test = True
    
    235
    -        if test:
    
    236
    -            rbshellobj = bus.get_object('org.gnome.Rhythmbox',
    
    237
    -                    '/org/gnome/Rhythmbox/Shell')
    
    238
    -            player = dbus.Interface(
    
    239
    -                    bus.get_object('org.gnome.Rhythmbox',
    
    240
    -                    '/org/gnome/Rhythmbox/Player'), 'org.gnome.Rhythmbox.Player')
    
    241
    -            rbshell = dbus.Interface(rbshellobj, 'org.gnome.Rhythmbox.Shell')
    
    242
    -            try:
    
    243
    -                uri = player.getPlayingUri()
    
    244
    -            except dbus.DBusException:
    
    245
    -                uri = None
    
    246
    -            if not uri:
    
    145
    +        proxy = Gio.DBusProxy.new_for_bus_sync(
    
    146
    +            Gio.BusType.SESSION,
    
    147
    +            Gio.DBusProxyFlags.NONE,
    
    148
    +            None,
    
    149
    +            name,
    
    150
    +            '/org/mpris/MediaPlayer2',
    
    151
    +            'org.freedesktop.DBus.Properties',
    
    152
    +            None)
    
    153
    +
    
    154
    +        try:
    
    155
    +            result = proxy.call_sync(
    
    156
    +                "GetAll",
    
    157
    +                GLib.Variant('(s)', ('org.mpris.MediaPlayer2.Player',)),
    
    158
    +                Gio.DBusCallFlags.NONE,
    
    159
    +                -1,
    
    160
    +                None)
    
    161
    +        except GLib.Error as e:
    
    162
    +            if e.domain == 'g-dbus-error-quark':
    
    163
    +                log.debug("Could not enable music listener: %s", e.message)
    
    247 164
                     return None
    
    248
    -            props = rbshell.getSongProperties(uri)
    
    249
    -            info = self._rhythmbox_properties_extract(props)
    
    165
    +            else:
    
    166
    +                raise
    
    167
    +        else:
    
    168
    +            info = self._properties_extract(result[0])
    
    250 169
                 self._last_playing_music = info
    
    251 170
                 return info
    
    252 171
     
    
    253
    -        ## Check Banshee playing track
    
    254
    -        test = False
    
    255
    -        if hasattr(bus, 'name_has_owner'):
    
    256
    -            if bus.name_has_owner('org.bansheeproject.Banshee'):
    
    257
    -                test = True
    
    258
    -        elif dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
    
    259
    -        'org.bansheeproject.Banshee'):
    
    260
    -            test = True
    
    261
    -        if test:
    
    262
    -            banshee = bus.get_object('org.bansheeproject.Banshee',
    
    263
    -                    '/org/bansheeproject/Banshee/PlayerEngine')
    
    264
    -            currentTrack = banshee.GetCurrentTrack()
    
    265
    -            if currentTrack:
    
    266
    -                song = self._banshee_properties_extract(currentTrack)
    
    267
    -                self._last_playing_music = song
    
    268
    -                return song
    
    269
    -
    
    270
    -        ## Check Quod Libet playing track
    
    271
    -        test = False
    
    272
    -        if hasattr(bus, 'name_has_owner'):
    
    273
    -            if bus.name_has_owner('net.sacredchao.QuodLibet'):
    
    274
    -                test = True
    
    275
    -        elif dbus.dbus_bindings.bus_name_has_owner(bus.get_connection(),
    
    276
    -        'net.sacredchao.QuodLibet'):
    
    277
    -            test = True
    
    278
    -        if test:
    
    279
    -            quodlibet = bus.get_object('net.sacredchao.QuodLibet',
    
    280
    -                    '/net/sacredchao/QuodLibet')
    
    281
    -            if quodlibet.IsPlaying():
    
    282
    -                currentTrack = quodlibet.CurrentSong()
    
    283
    -                song = self._quodlibet_properties_extract(currentTrack)
    
    284
    -                self._last_playing_music = song
    
    285
    -                return song
    
    286
    -
    
    287
    -        return None
    
    288 172
     
    
    289 173
     # here we test :)
    
    290 174
     if __name__ == '__main__':
    
    291 175
         def music_track_change_cb(listener, music_track_info):
    
    292
    -        if music_track_info is None:
    
    176
    +        if music_track_info is None or music_track_info.paused:
    
    293 177
                 print('Stop!')
    
    294 178
             else:
    
    295 179
                 print(music_track_info.title)
    
    296 180
         listener = MusicTrackListener.get()
    
    297 181
         listener.connect('music-track-changed', music_track_change_cb)
    
    298
    -    track = listener.get_playing_track()
    
    299
    -    if track is None:
    
    300
    -        print('Now not playing anything')
    
    301
    -    else:
    
    302
    -        print('Now playing: "%s" by %s' % (track.title, track.artist))
    
    303 182
         GObject.MainLoop().run()

  • gajim/roster_window.py
    ... ... @@ -40,6 +40,7 @@ from gi.repository import GObject
    40 40
     from gi.repository import GLib
    
    41 41
     from gi.repository import Gio
    
    42 42
     import os
    
    43
    +import sys
    
    43 44
     import time
    
    44 45
     import locale
    
    45 46
     import hashlib
    
    ... ... @@ -67,7 +68,6 @@ from gajim.common import i18n
    67 68
     if app.HAVE_GEOCLUE:
    
    68 69
         from gajim.common import location_listener
    
    69 70
     from gajim.common import ged
    
    70
    -from gajim.common import dbus_support
    
    71 71
     from gajim.message_window import MessageWindowMgr
    
    72 72
     from nbxmpp.protocol import NS_FILE, NS_ROSTERX, NS_CONFERENCE
    
    73 73
     
    
    ... ... @@ -4963,7 +4963,7 @@ class RosterWindow:
    4963 4963
     
    
    4964 4964
                     item = Gtk.CheckMenuItem(_('Publish Tune'))
    
    4965 4965
                     pep_submenu.append(item)
    
    4966
    -                if not dbus_support.supported:
    
    4966
    +                if sys.platform != 'linux':
    
    4967 4967
                         item.set_sensitive(False)
    
    4968 4968
                     else:
    
    4969 4969
                         activ = app.config.get_per('accounts', account,