~andrewsomething/exaile/karmic

« back to all changes in this revision

Viewing changes to plugins/mpris/mpris_player.py

  • Committer: Aren Olson
  • Date: 2009-09-12 00:36:59 UTC
  • Revision ID: reacocard@gmail.com-20090912003659-w373sg0n04uoa8op
remove useless files, add soem of the fixes from lp bug 420019

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009 Abhishek Mukherjee
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 3, or (at your option)
6
 
# any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 
"""/Player object for MPRIS specification interface to Exaile
17
 
 
18
 
http://wiki.xmms2.xmms.se/wiki/MPRIS#.2FPlayer_object_methods
19
 
"""
20
 
 
21
 
 
22
 
from __future__ import division
23
 
 
24
 
from xl import settings
25
 
 
26
 
import dbus
27
 
import dbus.service
28
 
 
29
 
import xl.event
30
 
 
31
 
import mpris_tag_converter
32
 
 
33
 
INTERFACE_NAME = 'org.freedesktop.MediaPlayer'
34
 
 
35
 
class MprisCaps(object):
36
 
    """
37
 
        Specification for the capabilities field in MPRIS
38
 
    """
39
 
    NONE                  = 0
40
 
    CAN_GO_NEXT           = 1 << 0
41
 
    CAN_GO_PREV           = 1 << 1
42
 
    CAN_PAUSE             = 1 << 2
43
 
    CAN_PLAY              = 1 << 3
44
 
    CAN_SEEK              = 1 << 4
45
 
    CAN_PROVIDE_METADATA  = 1 << 5
46
 
    CAN_HAS_TRACKLIST     = 1 << 6
47
 
 
48
 
EXAILE_CAPS = (MprisCaps.CAN_GO_NEXT
49
 
                | MprisCaps.CAN_GO_PREV
50
 
                | MprisCaps.CAN_PAUSE
51
 
                | MprisCaps.CAN_PLAY
52
 
                | MprisCaps.CAN_SEEK
53
 
                | MprisCaps.CAN_PROVIDE_METADATA
54
 
                | MprisCaps.CAN_HAS_TRACKLIST)
55
 
 
56
 
class ExaileMprisPlayer(dbus.service.Object):
57
 
 
58
 
    """
59
 
        /Player (Root) object methods
60
 
    """
61
 
 
62
 
    def __init__(self, exaile, bus):
63
 
        dbus.service.Object.__init__(self, bus, '/Player')
64
 
        self.exaile = exaile
65
 
        self._tag_converter = mpris_tag_converter.ExaileTagConverter(exaile)
66
 
        xl.event.add_callback(self.track_change_cb, 'playback_track_start')
67
 
        # FIXME: Does not watch for shuffle, repeat
68
 
        # TODO: playback_start does not distinguish if play button was pressed
69
 
        #       or we simply moved to a new track
70
 
        for event in ('playback_player_end', 'playback_player_start',
71
 
                'playback_toggle_pause'):
72
 
            xl.event.add_callback(self.status_change_cb, event)
73
 
 
74
 
 
75
 
    @dbus.service.method(INTERFACE_NAME)
76
 
    def Next(self):
77
 
        """
78
 
            Goes to the next element
79
 
        """
80
 
        self.exaile.queue.next()
81
 
 
82
 
    @dbus.service.method(INTERFACE_NAME)
83
 
    def Prev(self):
84
 
        """
85
 
            Goes to the previous element
86
 
        """
87
 
        self.exaile.queue.prev()
88
 
 
89
 
    @dbus.service.method(INTERFACE_NAME)
90
 
    def Pause(self):
91
 
        """
92
 
            If playing, pause. If paused, unpause.
93
 
        """
94
 
        self.exaile.player.toggle_pause()
95
 
 
96
 
    @dbus.service.method(INTERFACE_NAME)
97
 
    def Stop(self):
98
 
        """
99
 
            Stop playing
100
 
        """
101
 
        self.exaile.player.stop()
102
 
 
103
 
    @dbus.service.method(INTERFACE_NAME)
104
 
    def Play(self):
105
 
        """
106
 
            If Playing, rewind to the beginning of the current track, else.
107
 
            start playing
108
 
        """
109
 
        if self.exaile.player.is_playing():
110
 
            self.exaile.player.play(self.exaile.player.current)
111
 
        else:
112
 
            self.exaile.queue.play()
113
 
 
114
 
    @dbus.service.method(INTERFACE_NAME, in_signature="b")
115
 
    def Repeat(self, repeat):
116
 
        """
117
 
            Toggle the current track repeat
118
 
        """
119
 
        pass
120
 
 
121
 
    @dbus.service.method(INTERFACE_NAME, out_signature="(iiii)")
122
 
    def GetStatus(self):
123
 
        """
124
 
            Return the status of "Media Player" as a struct of 4 ints: 
125
 
              * First integer: 0 = Playing, 1 = Paused, 2 = Stopped. 
126
 
              * Second interger: 0 = Playing linearly , 1 = Playing randomly. 
127
 
              * Third integer: 0 = Go to the next element once the current has
128
 
                finished playing , 1 = Repeat the current element 
129
 
              * Fourth integer: 0 = Stop playing once the last element has been
130
 
                played, 1 = Never give up playing
131
 
        """
132
 
        if self.exaile.player.is_playing():
133
 
            playing = 0
134
 
        elif self.exaile.player.is_paused():
135
 
            playing = 1
136
 
        else:
137
 
            playing = 2
138
 
 
139
 
        if not self.exaile.queue.current_playlist.random_enabled:
140
 
            random = 0
141
 
        else:
142
 
            random = 1
143
 
 
144
 
        go_to_next = 0 # Do not have ability to repeat single track
145
 
        
146
 
        if not self.exaile.queue.current_playlist.repeat_enabled:
147
 
            repeat = 0
148
 
        else:
149
 
            repeat = 1
150
 
 
151
 
        return (playing, random, go_to_next, repeat)
152
 
 
153
 
    @dbus.service.method(INTERFACE_NAME, out_signature="a{sv}")
154
 
    def GetMetadata(self):
155
 
        """
156
 
            Gives all meta data available for the currently played element.
157
 
        """
158
 
        if self.exaile.player.current is None:
159
 
            return []
160
 
        return self._tag_converter.get_metadata(self.exaile.player.current)
161
 
 
162
 
    @dbus.service.method(INTERFACE_NAME, out_signature="i")
163
 
    def GetCaps(self):
164
 
        """
165
 
            Returns the "Media player"'s current capabilities, see MprisCaps
166
 
        """
167
 
        return EXAILE_CAPS
168
 
 
169
 
    @dbus.service.method(INTERFACE_NAME, in_signature="i")
170
 
    def VolumeSet(self, volume):
171
 
        """
172
 
            Sets the volume, arument in the range [0, 100]
173
 
        """
174
 
        if volume < 0 or volume > 100:
175
 
            pass
176
 
 
177
 
        settings.set_option('player/volume', volume / 100)
178
 
 
179
 
    @dbus.service.method(INTERFACE_NAME, out_signature="i")
180
 
    def VolumeGet(self):
181
 
        """
182
 
            Returns the current volume (must be in [0;100])
183
 
        """
184
 
        return settings.get_option('player/volume', 0) * 100
185
 
 
186
 
    @dbus.service.method(INTERFACE_NAME, in_signature="i")
187
 
    def PositionSet(self, millisec):
188
 
        """
189
 
            Sets the playing position (argument must be in [0, <track_length>]
190
 
            in milliseconds)
191
 
        """
192
 
        if millisec > self.exaile.player.current.tags['__length'] * 1000 \
193
 
                or millisec < 0:
194
 
            return
195
 
        self.exaile.player.seek(millisec / 1000)
196
 
 
197
 
    @dbus.service.method(INTERFACE_NAME, out_signature="i")
198
 
    def PositionGet(self):
199
 
        """
200
 
            Returns the playing position (will be [0, track_length] in
201
 
            milliseconds)
202
 
        """
203
 
        return int(self.exaile.player.get_position() / 1000000)
204
 
 
205
 
    def track_change_cb(self, type, object, data):
206
 
        """
207
 
            Callback will emit the dbus signal TrackChange with the current
208
 
            songs metadata
209
 
        """
210
 
        metadata = self.GetMetadata()
211
 
        self.TrackChange(metadata)
212
 
 
213
 
    def status_change_cb(self, type, object, data):
214
 
        """
215
 
            Callback will emit the dbus signal StatusChange with the current
216
 
            status
217
 
        """
218
 
        struct = self.GetStatus()
219
 
        self.StatusChange(struct)
220
 
 
221
 
    def caps_change_cb(self, type, object, data):
222
 
        """
223
 
            Callback will emit the dbus signal CapsChange with the current Caps
224
 
        """
225
 
        caps = self.GetCaps()
226
 
        self.CapsChange(caps)
227
 
 
228
 
    @dbus.service.signal(INTERFACE_NAME, signature="a{sv}")
229
 
    def TrackChange(self, metadata):
230
 
        """
231
 
            Signal is emitted when the "Media Player" plays another "Track".
232
 
            Argument of the signal is the metadata attached to the new "Track"
233
 
        """
234
 
        pass
235
 
 
236
 
    @dbus.service.signal(INTERFACE_NAME, signature="(iiii)")
237
 
    def StatusChange(self, struct):
238
 
        """
239
 
            Signal is emitted when the status of the "Media Player" change. The
240
 
            argument has the same meaning as the value returned by GetStatus.
241
 
        """
242
 
        pass
243
 
 
244
 
    @dbus.service.signal(INTERFACE_NAME)
245
 
    def CapsChange(self):
246
 
        """
247
 
            Signal is emitted when the "Media Player" changes capabilities, see
248
 
            GetCaps method.
249
 
        """
250
 
        pass
251