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 can_quit: Cell<bool>, fullscreen: Cell<bool>, can_set_fullscreen: Cell<bool>, can_raise: Cell<bool>, has_track_list: Cell<bool>, identify: String, desktop_entry: String, supported_uri_schemes: RefCell<Vec<String>>, supported_mime_types: RefCell<Vec<String>>, playback_status: Cell<PlaybackStatus>, loop_status: Cell<LoopStatus>, rate: Cell<f64>, shuffle: Cell<bool>, metadata: RefCell<Metadata>, volume: Cell<f64>, position: Cell<i64>, minimum_rate: Cell<f64>, maximum_rate: Cell<f64>, can_go_next: Cell<bool>, can_go_previous: Cell<bool>, can_play: Cell<bool>, can_pause: Cell<bool>, can_seek: Cell<bool>, can_control: Cell<bool>, 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 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 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 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 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 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 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 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}