mpris_player2/
mpris_player.rs

1extern crate glib;
2extern crate dbus;
3use dbus::arg::{Variant, RefArg};
4use dbus::{Connection, BusType, tree, Path, SignalArgs};
5use dbus::tree::{Interface, MTFn, Factory};
6use std::collections::HashMap;
7
8use std::rc::Rc;
9use std::cell::Cell;
10use std::cell::RefCell;
11use std::sync::Arc;
12use std::time::Duration;
13
14use crate::generated::mediaplayer2::org_mpris_media_player2_server;
15use crate::generated::mediaplayer2_player::{org_mpris_media_player2_player_server, OrgFreedesktopDBusPropertiesPropertiesChanged};
16
17use crate::OrgMprisMediaPlayer2Player;
18use crate::OrgMprisMediaPlayer2;
19
20use crate::Metadata;
21use crate::PlaybackStatus;
22use crate::LoopStatus;
23
24pub struct MprisPlayer{
25    connection: Arc<Connection>,
26    factory: Arc<Factory<MTFn<TData>, TData>>,
27
28    // OrgMprisMediaPlayer2         Type
29    can_quit: Cell<bool>,           // R
30    fullscreen: Cell<bool>,         // R/W
31    can_set_fullscreen: Cell<bool>, // R
32    can_raise: Cell<bool>,          // R
33    has_track_list: Cell<bool>,     // R
34    identify: String,               // R
35    desktop_entry: String,          // R
36    supported_uri_schemes: RefCell<Vec<String>>, // R
37    supported_mime_types: RefCell<Vec<String>>,  // R
38
39    // OrgMprisMediaPlayer2Player   Type
40    playback_status: Cell<PlaybackStatus>, // R
41    loop_status: Cell<LoopStatus>,  // R/W
42    rate: Cell<f64>,                // R/W
43    shuffle: Cell<bool>,            // R/W
44    metadata: RefCell<Metadata>,    // R
45    volume: Cell<f64>,              // R/W
46    position: Cell<i64>,            // R
47    minimum_rate: Cell<f64>,        // R
48    maximum_rate: Cell<f64>,        // R
49    can_go_next: Cell<bool>,        // R
50    can_go_previous: Cell<bool>,    // R
51    can_play: Cell<bool>,           // R
52    can_pause: Cell<bool>,          // R
53    can_seek: Cell<bool>,           // R
54    can_control: Cell<bool>,        // R
55
56    // Callbacks
57    raise_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
58    quit_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
59    next_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
60    previous_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
61    pause_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
62    play_pause_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
63    stop_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
64    play_cb: RefCell<Vec<Rc<RefCell<dyn FnMut()>>>>,
65    seek_cb: RefCell<Vec<Rc<RefCell<dyn FnMut(i64)>>>>,
66    open_uri_cb: RefCell<Vec<Rc<RefCell<dyn FnMut(&str)>>>>,
67    fullscreen_cb: RefCell<Vec<Rc<RefCell<dyn FnMut(bool)>>>>,
68    loop_status_cb: RefCell<Vec<Rc<RefCell<dyn FnMut(LoopStatus)>>>>,
69    rate_cb: RefCell<Vec<Rc<RefCell<dyn FnMut(f64)>>>>,
70    shuffle_cb: RefCell<Vec<Rc<RefCell<dyn FnMut(bool)>>>>,
71    volume_cb: RefCell<Vec<Rc<RefCell<dyn FnMut(f64)>>>>,
72}
73
74impl MprisPlayer{
75    pub fn new(mpris_name: String, identify: String, desktop_entry: String) -> Arc<Self>{
76        let connection = Arc::new(Connection::get_private(BusType::Session).unwrap());
77        let factory = Arc::new(Factory::new_fn());
78
79        let mpris_player = Arc::new(MprisPlayer{
80            connection,
81            factory,
82
83            can_quit: Cell::new(false),
84            fullscreen: Cell::new(false),
85            can_set_fullscreen: Cell::new(false),
86            can_raise: Cell::new(false),
87            has_track_list: Cell::new(false),
88            identify,
89            desktop_entry,
90            supported_uri_schemes: RefCell::new(Vec::new()),
91            supported_mime_types: RefCell::new(Vec::new()),
92
93            playback_status: Cell::new(PlaybackStatus::Paused),
94            loop_status: Cell::new(LoopStatus::None),
95            rate: Cell::new(0_f64),
96            shuffle: Cell::new(false),
97            metadata: RefCell::new(Metadata::new()),
98            volume: Cell::new(0_f64),
99            position: Cell::new(0),
100            minimum_rate: Cell::new(0_f64),
101            maximum_rate: Cell::new(0_f64),
102            can_go_next: Cell::new(true),
103            can_go_previous: Cell::new(true),
104            can_play: Cell::new(true),
105            can_pause: Cell::new(true),
106            can_seek: Cell::new(false),
107            can_control: Cell::new(true),
108
109            raise_cb: RefCell::new(Vec::new()),
110            quit_cb: RefCell::new(Vec::new()),
111            next_cb: RefCell::new(Vec::new()),
112            previous_cb: RefCell::new(Vec::new()),
113            pause_cb: RefCell::new(Vec::new()),
114            play_pause_cb: RefCell::new(Vec::new()),
115            stop_cb: RefCell::new(Vec::new()),
116            play_cb: RefCell::new(Vec::new()),
117            seek_cb: RefCell::new(Vec::new()),
118            open_uri_cb: RefCell::new(Vec::new()),
119            fullscreen_cb: RefCell::new(Vec::new()),
120            loop_status_cb: RefCell::new(Vec::new()),
121            rate_cb: RefCell::new(Vec::new()),
122            shuffle_cb: RefCell::new(Vec::new()),
123            volume_cb: RefCell::new(Vec::new()),
124        });
125
126        // Create OrgMprisMediaPlayer2 interface
127        let root_iface: Interface<MTFn<TData>, TData> = org_mpris_media_player2_server(&mpris_player.factory, (), |m| {
128            let a: &Arc<MprisPlayer> = m.path.get_data();
129            let b: &MprisPlayer = &a;
130            b
131        });
132
133        // Create OrgMprisMediaPlayer2Player interface
134        let player_iface: Interface<MTFn<TData>, TData> = org_mpris_media_player2_player_server(&mpris_player.factory, (), |m| {
135            let a: &Arc<MprisPlayer> = m.path.get_data();
136            let b: &MprisPlayer = &a;
137            b
138        });
139
140        // Create dbus tree
141        let mut tree = mpris_player.factory.tree(());
142        tree = tree.add(mpris_player.factory.object_path("/org/mpris/MediaPlayer2", mpris_player.clone())
143            .introspectable()
144            .add(root_iface)
145            .add(player_iface)
146        );
147
148        // Setup dbus connection
149        mpris_player.connection.register_name(&format!("org.mpris.MediaPlayer2.{}", mpris_name), 0).unwrap();
150        tree.set_registered(&mpris_player.connection, true).unwrap();
151        mpris_player.connection.add_handler(tree);
152
153        let connection = mpris_player.connection.clone();
154        glib::source::timeout_add_local(Duration::from_millis(250), move||{
155            connection.incoming(5).next();
156            glib::ControlFlow::Continue
157        });
158
159        mpris_player
160    }
161
162    pub fn property_changed<T: 'static>(&self, name: String, value: T) where T: dbus::arg::RefArg {
163        let mut changed_properties = HashMap::new();
164        let x = Box::new(value) as Box<dyn RefArg>;
165        changed_properties.insert(name, Variant(x));
166
167        let signal = OrgFreedesktopDBusPropertiesPropertiesChanged {
168            changed_properties,
169            interface_name: "org.mpris.MediaPlayer2.Player".to_string(),
170            invalidated_properties: Vec::new(),
171        };
172
173        self.connection.send(signal.to_emit_message(&Path::new("/org/mpris/MediaPlayer2").unwrap())).unwrap();
174    }
175
176    pub fn seeked(&self, value: i64) {
177        self.position.set(value);
178        let signal = dbus::Message::signal(
179            &Path::new("/org/mpris/MediaPlayer2").unwrap(),
180            &dbus::Interface::new("org.mpris.MediaPlayer2.Player").unwrap(),
181            &dbus::Member::new("Seeked").unwrap(),
182        )
183        .append(value);
184        self.connection.send(signal).unwrap();
185    }
186
187    //
188    // OrgMprisMediaPlayer2 setters...
189    //
190
191    pub fn set_supported_mime_types(&self, value: Vec<String>){
192        *self.supported_mime_types.borrow_mut() = value;
193        self.property_changed("SupportedMimeTypes".to_string(), self.get_supported_mime_types().unwrap());
194    }
195
196    pub fn set_supported_uri_schemes(&self, value: Vec<String>){
197        *self.supported_uri_schemes.borrow_mut() = value;
198        self.property_changed("SupportedUriSchemes".to_string(), self.get_supported_uri_schemes().unwrap());
199    }
200
201    pub fn set_can_quit(&self, value: bool){
202        self.can_quit.set(value);
203        self.property_changed("CanQuit".to_string(), self.get_can_quit().unwrap());
204    }
205
206    pub fn set_can_raise(&self, value: bool){
207        self.can_raise.set(value);
208        self.property_changed("CanRaise".to_string(), self.get_can_raise().unwrap());
209    }
210
211    pub fn set_can_set_fullscreen(&self, value: bool){
212        self.can_set_fullscreen.set(value);
213        self.property_changed("CanSetFullscreen".to_string(), self.get_can_set_fullscreen().unwrap());
214    }
215
216    pub fn set_has_track_list(&self, value: bool){
217        self.has_track_list.set(value);
218        self.property_changed("HasTrackList".to_string(), self.get_has_track_list().unwrap());
219    }
220
221
222    //
223    // OrgMprisMediaPlayer2Player setters...
224    //
225
226    pub fn set_playback_status(&self, value: PlaybackStatus){
227        self.playback_status.set(value);
228        self.property_changed("PlaybackStatus".to_string(), self.get_playback_status().unwrap());
229    }
230
231    pub fn set_loop_status(&self, value: LoopStatus){
232        self.loop_status.set(value);
233        self.property_changed("LoopStatus".to_string(), self.get_loop_status().unwrap());
234    }
235
236    pub fn set_metadata(&self, metadata: Metadata){
237        *self.metadata.borrow_mut() = metadata;
238        self.property_changed("Metadata".to_string(), self.get_metadata().unwrap());
239    }
240
241    pub fn set_position(&self, value: i64){
242        self.position.set(value);
243    }
244
245    pub fn set_minimum_rate(&self, value: f64){
246        self.minimum_rate.set(value);
247        self.property_changed("MinimumRate".to_string(), self.get_minimum_rate().unwrap());
248    }
249
250    pub fn set_maximum_rate(&self, value: f64){
251        self.maximum_rate.set(value);
252        self.property_changed("MaximumRate".to_string(), self.get_maximum_rate().unwrap());
253    }
254
255    pub fn set_can_go_next(&self, value: bool){
256        self.can_go_next.set(value);
257        self.property_changed("CanGoNext".to_string(), self.get_can_go_next().unwrap());
258    }
259
260    pub fn set_can_go_previous(&self, value: bool){
261        self.can_go_previous.set(value);
262        self.property_changed("CanPrevious".to_string(), self.get_can_go_previous().unwrap());
263    }
264
265    pub fn set_can_play(&self, value: bool){
266        self.can_play.set(value);
267        self.property_changed("CanPlay".to_string(), self.get_can_play().unwrap());
268    }
269
270    pub fn set_can_pause(&self, value: bool){
271        self.can_pause.set(value);
272        self.property_changed("CanPause".to_string(), self.get_can_pause().unwrap());
273    }
274
275    pub fn set_can_seek(&self, value: bool){
276        self.can_seek.set(value);
277        self.property_changed("CanSeek".to_string(), self.get_can_seek().unwrap());
278    }
279
280    pub fn set_can_control(&self, value: bool){
281        self.can_control.set(value);
282        self.property_changed("CanControl".to_string(), self.get_can_control().unwrap());
283    }
284
285
286    //
287    // Callbacks
288    //
289
290    pub fn connect_raise<F: FnMut()+'static>(&self, callback: F) {
291        let cell = Rc::new(RefCell::new(callback));
292        self.raise_cb.borrow_mut().push(cell);
293    }
294
295    pub fn connect_quit<F: FnMut()+'static>(&self, callback: F) {
296        let cell = Rc::new(RefCell::new(callback));
297        self.quit_cb.borrow_mut().push(cell);
298    }
299
300    pub fn connect_next<F: FnMut()+'static>(&self, callback: F) {
301        let cell = Rc::new(RefCell::new(callback));
302        self.next_cb.borrow_mut().push(cell);
303    }
304
305    pub fn connect_previous<F: FnMut()+'static>(&self, callback: F) {
306        let cell = Rc::new(RefCell::new(callback));
307        self.previous_cb.borrow_mut().push(cell);
308    }
309
310    pub fn connect_pause<F: FnMut()+'static>(&self, callback: F) {
311        let cell = Rc::new(RefCell::new(callback));
312        self.pause_cb.borrow_mut().push(cell);
313    }
314
315    pub fn connect_play_pause<F: FnMut()+'static>(&self, callback: F) {
316        let cell = Rc::new(RefCell::new(callback));
317        self.play_pause_cb.borrow_mut().push(cell);
318    }
319
320    pub fn connect_stop<F: FnMut()+'static>(&self, callback: F) {
321        let cell = Rc::new(RefCell::new(callback));
322        self.stop_cb.borrow_mut().push(cell);
323    }
324
325    pub fn connect_play<F: FnMut()+'static>(&self, callback: F) {
326        let cell = Rc::new(RefCell::new(callback));
327        self.play_cb.borrow_mut().push(cell);
328    }
329
330    pub fn connect_seek<F: FnMut(i64)+'static>(&self, callback: F) {
331        let cell = Rc::new(RefCell::new(callback));
332        self.seek_cb.borrow_mut().push(cell);
333    }
334
335    pub fn connect_open_uri<F: FnMut(&str)+'static>(&self, callback: F) {
336        let cell = Rc::new(RefCell::new(callback));
337        self.open_uri_cb.borrow_mut().push(cell);
338    }
339
340    pub fn connect_fullscreen<F: FnMut(bool)+'static>(&self, callback: F) {
341        let cell = Rc::new(RefCell::new(callback));
342        self.fullscreen_cb.borrow_mut().push(cell);
343    }
344
345    pub fn connect_loop_status<F: FnMut(LoopStatus)+'static>(&self, callback: F) {
346        let cell = Rc::new(RefCell::new(callback));
347        self.loop_status_cb.borrow_mut().push(cell);
348    }
349
350    pub fn connect_rate<F: FnMut(f64)+'static>(&self, callback: F) {
351        let cell = Rc::new(RefCell::new(callback));
352        self.rate_cb.borrow_mut().push(cell);
353    }
354
355    pub fn connect_shuffle<F: FnMut(bool)+'static>(&self, callback: F) {
356        let cell = Rc::new(RefCell::new(callback));
357        self.shuffle_cb.borrow_mut().push(cell);
358    }
359
360    pub fn connect_volume<F: FnMut(f64)+'static>(&self, callback: F) {
361        let cell = Rc::new(RefCell::new(callback));
362        self.volume_cb.borrow_mut().push(cell);
363    }
364}
365
366impl OrgMprisMediaPlayer2 for MprisPlayer {
367    type Err = tree::MethodErr;
368
369    fn raise(&self) -> Result<(), Self::Err> {
370        for callback in self.raise_cb.borrow_mut().iter() {
371            let mut closure = callback.borrow_mut(); (&mut *closure)();
372        }
373        Ok(())
374    }
375
376    fn quit(&self) -> Result<(), Self::Err> {
377        for callback in self.quit_cb.borrow_mut().iter() {
378            let mut closure = callback.borrow_mut(); (&mut *closure)();
379        }
380        Ok(())
381    }
382
383    fn get_can_quit(&self) -> Result<bool, Self::Err> {
384        Ok(self.can_quit.get())
385    }
386
387    fn get_fullscreen(&self) -> Result<bool, Self::Err> {
388        Ok(self.fullscreen.get())
389    }
390
391    fn set_fullscreen(&self, value: bool) -> Result<(), Self::Err> {
392        self.fullscreen.set(value);
393        self.property_changed("Fullscreen".to_string(), self.get_fullscreen().unwrap());
394        for callback in self.fullscreen_cb.borrow_mut().iter() {
395            let mut closure = callback.borrow_mut(); (&mut *closure)(value);
396        }
397        Ok(())
398    }
399
400    fn get_can_set_fullscreen(&self) -> Result<bool, Self::Err> {
401        Ok(self.can_set_fullscreen.get())
402    }
403
404    fn get_can_raise(&self) -> Result<bool, Self::Err> {
405        Ok(self.can_raise.get())
406    }
407
408    fn get_has_track_list(&self) -> Result<bool, Self::Err> {
409        Ok(self.has_track_list.get())
410    }
411
412    fn get_identity(&self) -> Result<String, Self::Err> {
413        Ok(self.identify.clone())
414    }
415
416    fn get_desktop_entry(&self) -> Result<String, Self::Err> {
417        Ok(self.desktop_entry.clone())
418    }
419
420    fn get_supported_uri_schemes(&self) -> Result<Vec<String>, Self::Err> {
421        Ok(self.supported_uri_schemes.borrow().to_vec())
422    }
423
424    fn get_supported_mime_types(&self) -> Result<Vec<String>, Self::Err> {
425        Ok(self.supported_mime_types.borrow().to_vec())
426    }
427}
428
429impl OrgMprisMediaPlayer2Player for MprisPlayer {
430    type Err = tree::MethodErr;
431
432    fn next(&self) -> Result<(), Self::Err> {
433        for callback in self.next_cb.borrow_mut().iter() {
434            let mut closure = callback.borrow_mut(); (&mut *closure)();
435        }
436        Ok(())
437    }
438
439    fn previous(&self) -> Result<(), Self::Err> {
440        for callback in self.previous_cb.borrow_mut().iter() {
441            let mut closure = callback.borrow_mut(); (&mut *closure)();
442        }
443        Ok(())
444    }
445
446    fn pause(&self) -> Result<(), Self::Err> {
447        for callback in self.pause_cb.borrow_mut().iter() {
448            let mut closure = callback.borrow_mut(); (&mut *closure)();
449        }
450        Ok(())
451    }
452
453    fn play_pause(&self) -> Result<(), Self::Err> {
454        for callback in self.play_pause_cb.borrow_mut().iter() {
455            let mut closure = callback.borrow_mut(); (&mut *closure)();
456        }
457        Ok(())
458    }
459
460    fn stop(&self) -> Result<(), Self::Err> {
461        for callback in self.stop_cb.borrow_mut().iter() {
462            let mut closure = callback.borrow_mut(); (&mut *closure)();
463        }
464        Ok(())
465    }
466
467    fn play(&self) -> Result<(), Self::Err> {
468        for callback in self.play_cb.borrow_mut().iter() {
469            let mut closure = callback.borrow_mut(); (&mut *closure)();
470        }
471        Ok(())
472    }
473
474    fn seek(&self, offset: i64) -> Result<(), Self::Err> {
475        for callback in self.seek_cb.borrow_mut().iter() {
476            let mut closure = callback.borrow_mut(); (&mut *closure)(offset);
477        }
478        Ok(())
479    }
480
481    fn set_position(&self, _track_id: dbus::Path, position: i64) -> Result<(), Self::Err> {
482        self.position.set(position);
483        self.property_changed("Position".to_string(), self.get_position().unwrap());
484        Ok(())
485    }
486
487    fn open_uri(&self, uri: &str) -> Result<(), Self::Err> {
488        for callback in self.open_uri_cb.borrow_mut().iter() {
489            let mut closure = callback.borrow_mut(); (&mut *closure)(uri);
490        }
491        Ok(())
492    }
493
494    fn get_playback_status(&self) -> Result<String, Self::Err> {
495        Ok(self.playback_status.get().value())
496    }
497
498    fn get_loop_status(&self) -> Result<String, Self::Err> {
499        Ok(self.loop_status.get().value())
500    }
501
502    fn set_loop_status(&self, value: String) -> Result<(), Self::Err> {
503        let ls = match value.as_ref() {
504            "Track" => LoopStatus::Track,
505            "Playlist" => LoopStatus::Playlist,
506            _ => LoopStatus::None,
507        };
508        self.loop_status.set(ls.clone());
509        self.property_changed("LoopStatus".to_string(), self.get_loop_status().unwrap());
510        for callback in self.loop_status_cb.borrow_mut().iter() {
511            let mut closure = callback.borrow_mut(); (&mut *closure)(ls);
512        }
513        Ok(())
514    }
515
516    fn get_rate(&self) -> Result<f64, Self::Err> {
517        Ok(self.rate.get())
518    }
519
520    fn set_rate(&self, value: f64) -> Result<(), Self::Err> {
521        self.rate.set(value);
522        self.property_changed("Rate".to_string(), self.get_rate().unwrap());
523        for callback in self.rate_cb.borrow_mut().iter() {
524            let mut closure = callback.borrow_mut(); (&mut *closure)(value);
525        }
526        Ok(())
527    }
528
529    fn get_shuffle(&self) -> Result<bool, Self::Err> {
530        Ok(self.shuffle.get())
531    }
532
533    fn set_shuffle(&self, value: bool) -> Result<(), Self::Err> {
534        self.shuffle.set(value);
535        self.property_changed("Shuffle".to_string(), self.get_volume().unwrap());
536        for callback in self.shuffle_cb.borrow_mut().iter() {
537            let mut closure = callback.borrow_mut(); (&mut *closure)(value);
538        }
539        Ok(())
540    }
541
542    fn get_metadata(&self) -> Result<HashMap<String, Variant<Box<dyn RefArg + 'static>>>, Self::Err> {
543        let metadata = self.metadata.borrow().to_hashmap();
544        Ok(metadata)
545    }
546
547    fn get_volume(&self) -> Result<f64, Self::Err> {
548        Ok(self.volume.get())
549    }
550
551    fn set_volume(&self, value: f64) -> Result<(), Self::Err> {
552        self.volume.set(value);
553        self.property_changed("Volume".to_string(), self.get_volume().unwrap());
554        for callback in self.volume_cb.borrow_mut().iter() {
555            let mut closure = callback.borrow_mut(); (&mut *closure)(value);
556        }
557        Ok(())
558    }
559
560    fn get_position(&self) -> Result<i64, Self::Err> {
561        Ok(self.position.get())
562    }
563
564    fn get_minimum_rate(&self) -> Result<f64, Self::Err> {
565        Ok(self.minimum_rate.get())
566    }
567
568    fn get_maximum_rate(&self) -> Result<f64, Self::Err> {
569        Ok(self.maximum_rate.get())
570    }
571
572    fn get_can_go_next(&self) -> Result<bool, Self::Err> {
573        Ok(self.can_go_next.get())
574    }
575
576    fn get_can_go_previous(&self) -> Result<bool, Self::Err> {
577        Ok(self.can_go_previous.get())
578    }
579
580    fn get_can_play(&self) -> Result<bool, Self::Err> {
581        Ok(self.can_play.get())
582    }
583
584    fn get_can_pause(&self) -> Result<bool, Self::Err> {
585        Ok(self.can_pause.get())
586    }
587
588    fn get_can_seek(&self) -> Result<bool, Self::Err> {
589        Ok(self.can_seek.get())
590    }
591
592    fn get_can_control(&self) -> Result<bool, Self::Err> {
593        Ok(self.can_control.get())
594    }
595}
596
597impl ::std::fmt::Debug for MprisPlayer{
598    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result  {
599        write!(f, "mprisplayer")
600    }
601}
602
603#[derive(Copy, Clone, Default, Debug)]
604pub struct TData;
605impl tree::DataType for TData {
606    type Tree = ();
607    type ObjectPath = Arc<MprisPlayer>;
608    type Property = ();
609    type Interface = ();
610    type Method = ();
611    type Signal = ();
612}