1use std::{
2 cell::{Cell, Ref, RefCell},
3 rc::{Rc, Weak},
4};
5
6use zbus::{fdo, Result};
7
8use crate::{
9 LocalPlayerInterface, LocalRootInterface, LocalServer, LocalServerRunTask, LoopStatus,
10 Metadata, PlaybackRate, PlaybackStatus, Property, Signal, Time, TrackId, Volume,
11};
12
13#[derive(Debug)]
24pub struct Player {
25 server: Rc<LocalServer<State>>,
26}
27
28#[allow(clippy::type_complexity)]
29struct State {
30 server: RefCell<Option<Weak<LocalServer<State>>>>,
31
32 raise_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
33 quit_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
34 set_fullscreen_cbs: RefCell<Vec<Box<dyn Fn(&Player, bool)>>>, can_quit: Cell<bool>,
36 fullscreen: Cell<bool>,
37 can_set_fullscreen: Cell<bool>,
38 can_raise: Cell<bool>,
39 has_track_list: Cell<bool>,
40 identity: RefCell<String>,
41 desktop_entry: RefCell<String>,
42 supported_uri_schemes: RefCell<Vec<String>>,
43 supported_mime_types: RefCell<Vec<String>>,
44
45 next_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
46 previous_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
47 pause_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
48 play_pause_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
49 stop_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
50 play_cbs: RefCell<Vec<Box<dyn Fn(&Player)>>>,
51 seek_cbs: RefCell<Vec<Box<dyn Fn(&Player, Time)>>>,
52 set_position_cbs: RefCell<Vec<Box<dyn Fn(&Player, &TrackId, Time)>>>,
53 open_uri_cbs: RefCell<Vec<Box<dyn Fn(&Player, &str)>>>,
54 set_loop_status_cbs: RefCell<Vec<Box<dyn Fn(&Player, LoopStatus)>>>, set_rate_cbs: RefCell<Vec<Box<dyn Fn(&Player, PlaybackRate)>>>, set_shuffle_cbs: RefCell<Vec<Box<dyn Fn(&Player, bool)>>>, set_volume_cbs: RefCell<Vec<Box<dyn Fn(&Player, Volume)>>>, playback_status: Cell<PlaybackStatus>,
59 loop_status: Cell<LoopStatus>,
60 rate: Cell<PlaybackRate>,
61 shuffle: Cell<bool>,
62 metadata: RefCell<Metadata>,
63 volume: Cell<Volume>,
64 position: Cell<Time>,
65 minimum_rate: Cell<PlaybackRate>,
66 maximum_rate: Cell<PlaybackRate>,
67 can_go_next: Cell<bool>,
68 can_go_previous: Cell<bool>,
69 can_play: Cell<bool>,
70 can_pause: Cell<bool>,
71 can_seek: Cell<bool>,
72 can_control: Cell<bool>,
73}
74
75impl State {
76 fn player(&self) -> Player {
77 Player {
78 server: self
79 .server
80 .borrow()
81 .as_ref()
82 .expect("server must be set up")
83 .upgrade()
84 .expect("server must not be dropped"),
85 }
86 }
87}
88
89impl LocalRootInterface for State {
90 async fn raise(&self) -> fdo::Result<()> {
91 let player = self.player();
92 for cb in self.raise_cbs.borrow().iter() {
93 cb(&player);
94 }
95 Ok(())
96 }
97
98 async fn quit(&self) -> fdo::Result<()> {
99 let player = self.player();
100 for cb in self.quit_cbs.borrow().iter() {
101 cb(&player);
102 }
103 Ok(())
104 }
105
106 async fn can_quit(&self) -> fdo::Result<bool> {
107 Ok(self.can_quit.get())
108 }
109
110 async fn fullscreen(&self) -> fdo::Result<bool> {
111 Ok(self.fullscreen.get())
112 }
113
114 async fn set_fullscreen(&self, fullscreen: bool) -> Result<()> {
115 let player = self.player();
116 for cb in self.set_fullscreen_cbs.borrow().iter() {
117 cb(&player, fullscreen);
118 }
119 Ok(())
120 }
121
122 async fn can_set_fullscreen(&self) -> fdo::Result<bool> {
123 Ok(self.can_set_fullscreen.get())
124 }
125
126 async fn can_raise(&self) -> fdo::Result<bool> {
127 Ok(self.can_raise.get())
128 }
129
130 async fn has_track_list(&self) -> fdo::Result<bool> {
131 Ok(self.has_track_list.get())
132 }
133
134 async fn identity(&self) -> fdo::Result<String> {
135 Ok(self.identity.borrow().clone())
136 }
137
138 async fn desktop_entry(&self) -> fdo::Result<String> {
139 Ok(self.desktop_entry.borrow().clone())
140 }
141
142 async fn supported_uri_schemes(&self) -> fdo::Result<Vec<String>> {
143 Ok(self.supported_uri_schemes.borrow().clone())
144 }
145
146 async fn supported_mime_types(&self) -> fdo::Result<Vec<String>> {
147 Ok(self.supported_mime_types.borrow().clone())
148 }
149}
150
151impl LocalPlayerInterface for State {
152 async fn next(&self) -> fdo::Result<()> {
153 let player = self.player();
154 for cb in self.next_cbs.borrow().iter() {
155 cb(&player);
156 }
157 Ok(())
158 }
159
160 async fn previous(&self) -> fdo::Result<()> {
161 let player = self.player();
162 for cb in self.previous_cbs.borrow().iter() {
163 cb(&player);
164 }
165 Ok(())
166 }
167
168 async fn pause(&self) -> fdo::Result<()> {
169 let player = self.player();
170 for cb in self.pause_cbs.borrow().iter() {
171 cb(&player);
172 }
173 Ok(())
174 }
175
176 async fn play_pause(&self) -> fdo::Result<()> {
177 let player = self.player();
178 for cb in self.play_pause_cbs.borrow().iter() {
179 cb(&player);
180 }
181 Ok(())
182 }
183
184 async fn stop(&self) -> fdo::Result<()> {
185 let player = self.player();
186 for cb in self.stop_cbs.borrow().iter() {
187 cb(&player);
188 }
189 Ok(())
190 }
191
192 async fn play(&self) -> fdo::Result<()> {
193 let player = self.player();
194 for cb in self.play_cbs.borrow().iter() {
195 cb(&player);
196 }
197 Ok(())
198 }
199
200 async fn seek(&self, offset: Time) -> fdo::Result<()> {
201 let player = self.player();
202 for cb in self.seek_cbs.borrow().iter() {
203 cb(&player, offset);
204 }
205 Ok(())
206 }
207
208 async fn set_position(&self, track_id: TrackId, position: Time) -> fdo::Result<()> {
209 let player = self.player();
210 for cb in self.set_position_cbs.borrow().iter() {
211 cb(&player, &track_id, position);
212 }
213 Ok(())
214 }
215
216 async fn open_uri(&self, uri: String) -> fdo::Result<()> {
217 let player = self.player();
218 for cb in self.open_uri_cbs.borrow().iter() {
219 cb(&player, &uri);
220 }
221 Ok(())
222 }
223
224 async fn playback_status(&self) -> fdo::Result<PlaybackStatus> {
225 Ok(self.playback_status.get())
226 }
227
228 async fn loop_status(&self) -> fdo::Result<LoopStatus> {
229 Ok(self.loop_status.get())
230 }
231
232 async fn set_loop_status(&self, loop_status: LoopStatus) -> Result<()> {
233 let player = self.player();
234 for cb in self.set_loop_status_cbs.borrow().iter() {
235 cb(&player, loop_status);
236 }
237 Ok(())
238 }
239
240 async fn rate(&self) -> fdo::Result<PlaybackRate> {
241 Ok(self.rate.get())
242 }
243
244 async fn set_rate(&self, rate: PlaybackRate) -> Result<()> {
245 let player = self.player();
246 for cb in self.set_rate_cbs.borrow().iter() {
247 cb(&player, rate);
248 }
249 Ok(())
250 }
251
252 async fn shuffle(&self) -> fdo::Result<bool> {
253 Ok(self.shuffle.get())
254 }
255
256 async fn set_shuffle(&self, shuffle: bool) -> Result<()> {
257 let player = self.player();
258 for cb in self.set_shuffle_cbs.borrow().iter() {
259 cb(&player, shuffle);
260 }
261 Ok(())
262 }
263
264 async fn metadata(&self) -> fdo::Result<Metadata> {
265 Ok(self.metadata.borrow().clone())
266 }
267
268 async fn volume(&self) -> fdo::Result<Volume> {
269 Ok(self.volume.get())
270 }
271
272 async fn set_volume(&self, volume: Volume) -> Result<()> {
273 let player = self.player();
274 for cb in self.set_volume_cbs.borrow().iter() {
275 cb(&player, volume);
276 }
277 Ok(())
278 }
279
280 async fn position(&self) -> fdo::Result<Time> {
281 Ok(self.position.get())
282 }
283
284 async fn minimum_rate(&self) -> fdo::Result<PlaybackRate> {
285 Ok(self.minimum_rate.get())
286 }
287
288 async fn maximum_rate(&self) -> fdo::Result<PlaybackRate> {
289 Ok(self.maximum_rate.get())
290 }
291
292 async fn can_go_next(&self) -> fdo::Result<bool> {
293 Ok(self.can_go_next.get())
294 }
295
296 async fn can_go_previous(&self) -> fdo::Result<bool> {
297 Ok(self.can_go_previous.get())
298 }
299
300 async fn can_play(&self) -> fdo::Result<bool> {
301 Ok(self.can_play.get())
302 }
303
304 async fn can_pause(&self) -> fdo::Result<bool> {
305 Ok(self.can_pause.get())
306 }
307
308 async fn can_seek(&self) -> fdo::Result<bool> {
309 Ok(self.can_seek.get())
310 }
311
312 async fn can_control(&self) -> fdo::Result<bool> {
313 Ok(self.can_control.get())
314 }
315}
316
317impl Player {
318 pub fn builder(bus_name_suffix: &str) -> PlayerBuilder {
319 PlayerBuilder {
320 bus_name_suffix: bus_name_suffix.to_string(),
321 can_quit: false,
322 fullscreen: false,
323 can_set_fullscreen: false,
324 can_raise: false,
325 has_track_list: false,
326 identity: String::new(),
327 desktop_entry: String::new(),
328 supported_uri_schemes: Vec::new(),
329 supported_mime_types: Vec::new(),
330 playback_status: PlaybackStatus::Stopped,
331 loop_status: LoopStatus::None,
332 rate: 1.0,
333 shuffle: false,
334 metadata: Metadata::new(),
335 volume: 1.0,
336 position: Time::ZERO,
337 minimum_rate: 1.0,
338 maximum_rate: 1.0,
339 can_go_next: false,
340 can_go_previous: false,
341 can_play: false,
342 can_pause: false,
343 can_seek: false,
344 can_control: true,
345 }
346 }
347
348 pub fn run(&self) -> LocalServerRunTask {
355 self.server.run()
356 }
357
358 pub fn connect_raise(&self, cb: impl Fn(&Self) + 'static) {
359 self.server.imp().raise_cbs.borrow_mut().push(Box::new(cb));
360 }
361
362 pub fn connect_quit(&self, cb: impl Fn(&Self) + 'static) {
363 self.server.imp().quit_cbs.borrow_mut().push(Box::new(cb));
364 }
365
366 pub fn connect_set_fullscreen(&self, cb: impl Fn(&Self, bool) + 'static) {
367 self.server
368 .imp()
369 .set_fullscreen_cbs
370 .borrow_mut()
371 .push(Box::new(cb));
372 }
373
374 pub fn can_quit(&self) -> bool {
375 self.server.imp().can_quit.get()
376 }
377
378 pub async fn set_can_quit(&self, can_quit: bool) -> Result<()> {
379 if self.can_quit() == can_quit {
380 return Ok(());
381 }
382
383 self.server.imp().can_quit.set(can_quit);
384 self.server
385 .properties_changed([Property::CanQuit(can_quit)])
386 .await
387 }
388
389 pub fn fullscreen(&self) -> bool {
390 self.server.imp().fullscreen.get()
391 }
392
393 pub async fn set_fullscreen(&self, fullscreen: bool) -> Result<()> {
394 if self.fullscreen() == fullscreen {
395 return Ok(());
396 }
397
398 self.server.imp().fullscreen.set(fullscreen);
399 self.server
400 .properties_changed([Property::Fullscreen(fullscreen)])
401 .await
402 }
403
404 pub fn can_set_fullscreen(&self) -> bool {
405 self.server.imp().can_set_fullscreen.get()
406 }
407
408 pub async fn set_can_set_fullscreen(&self, can_set_fullscreen: bool) -> Result<()> {
409 if self.can_set_fullscreen() == can_set_fullscreen {
410 return Ok(());
411 }
412
413 self.server.imp().can_set_fullscreen.set(can_set_fullscreen);
414 self.server
415 .properties_changed([Property::CanSetFullscreen(can_set_fullscreen)])
416 .await
417 }
418
419 pub fn can_raise(&self) -> bool {
420 self.server.imp().can_raise.get()
421 }
422
423 pub async fn set_can_raise(&self, can_raise: bool) -> Result<()> {
424 if self.can_raise() == can_raise {
425 return Ok(());
426 }
427
428 self.server.imp().can_raise.set(can_raise);
429 self.server
430 .properties_changed([Property::CanRaise(can_raise)])
431 .await
432 }
433
434 pub fn has_track_list(&self) -> bool {
435 self.server.imp().has_track_list.get()
436 }
437
438 pub async fn set_has_track_list(&self, has_track_list: bool) -> Result<()> {
439 if self.has_track_list() == has_track_list {
440 return Ok(());
441 }
442
443 self.server.imp().has_track_list.set(has_track_list);
444 self.server
445 .properties_changed([Property::HasTrackList(has_track_list)])
446 .await
447 }
448
449 pub fn identity(&self) -> Ref<'_, String> {
450 self.server.imp().identity.borrow()
451 }
452
453 pub async fn set_identity(&self, identity: impl Into<String>) -> Result<()> {
454 let identity = identity.into();
455
456 if *self.identity() == identity {
457 return Ok(());
458 }
459
460 self.server.imp().identity.replace(identity.clone());
461 self.server
462 .properties_changed([Property::Identity(identity)])
463 .await
464 }
465
466 pub fn desktop_entry(&self) -> Ref<'_, String> {
467 self.server.imp().desktop_entry.borrow()
468 }
469
470 pub async fn set_desktop_entry(&self, desktop_entry: impl Into<String>) -> Result<()> {
471 let desktop_entry = desktop_entry.into();
472
473 if *self.desktop_entry() == desktop_entry {
474 return Ok(());
475 }
476
477 self.server
478 .imp()
479 .desktop_entry
480 .replace(desktop_entry.clone());
481 self.server
482 .properties_changed([Property::DesktopEntry(desktop_entry)])
483 .await
484 }
485
486 pub fn supported_uri_schemes(&self) -> Ref<'_, Vec<String>> {
487 self.server.imp().supported_uri_schemes.borrow()
488 }
489
490 pub async fn set_supported_uri_schemes(
491 &self,
492 supported_uri_schemes: impl IntoIterator<Item = impl Into<String>>,
493 ) -> Result<()> {
494 let supported_uri_schemes = supported_uri_schemes
495 .into_iter()
496 .map(|i| i.into())
497 .collect::<Vec<_>>();
498
499 if *self.supported_uri_schemes() == supported_uri_schemes {
500 return Ok(());
501 }
502
503 self.server
504 .imp()
505 .supported_uri_schemes
506 .replace(supported_uri_schemes.clone());
507 self.server
508 .properties_changed([Property::SupportedUriSchemes(supported_uri_schemes)])
509 .await
510 }
511
512 pub fn supported_mime_types(&self) -> Ref<'_, Vec<String>> {
513 self.server.imp().supported_mime_types.borrow()
514 }
515
516 pub async fn set_supported_mime_types(
517 &self,
518 supported_mime_types: impl IntoIterator<Item = impl Into<String>>,
519 ) -> Result<()> {
520 let supported_mime_types = supported_mime_types
521 .into_iter()
522 .map(|i| i.into())
523 .collect::<Vec<_>>();
524
525 if *self.supported_mime_types() == supported_mime_types {
526 return Ok(());
527 }
528
529 self.server
530 .imp()
531 .supported_mime_types
532 .replace(supported_mime_types.clone());
533 self.server
534 .properties_changed([Property::SupportedMimeTypes(supported_mime_types)])
535 .await
536 }
537
538 pub fn connect_next(&self, cb: impl Fn(&Self) + 'static) {
539 self.server.imp().next_cbs.borrow_mut().push(Box::new(cb));
540 }
541
542 pub fn connect_previous(&self, cb: impl Fn(&Self) + 'static) {
543 self.server
544 .imp()
545 .previous_cbs
546 .borrow_mut()
547 .push(Box::new(cb));
548 }
549
550 pub fn connect_pause(&self, cb: impl Fn(&Self) + 'static) {
551 self.server.imp().pause_cbs.borrow_mut().push(Box::new(cb));
552 }
553
554 pub fn connect_play_pause(&self, cb: impl Fn(&Self) + 'static) {
555 self.server
556 .imp()
557 .play_pause_cbs
558 .borrow_mut()
559 .push(Box::new(cb));
560 }
561
562 pub fn connect_stop(&self, cb: impl Fn(&Self) + 'static) {
563 self.server.imp().stop_cbs.borrow_mut().push(Box::new(cb));
564 }
565
566 pub fn connect_play(&self, cb: impl Fn(&Self) + 'static) {
567 self.server.imp().play_cbs.borrow_mut().push(Box::new(cb));
568 }
569
570 pub fn connect_seek(&self, cb: impl Fn(&Self, Time) + 'static) {
571 self.server.imp().seek_cbs.borrow_mut().push(Box::new(cb));
572 }
573
574 pub fn connect_set_position(&self, cb: impl Fn(&Self, &TrackId, Time) + 'static) {
575 self.server
576 .imp()
577 .set_position_cbs
578 .borrow_mut()
579 .push(Box::new(cb));
580 }
581
582 pub fn connect_open_uri(&self, cb: impl Fn(&Self, &str) + 'static) {
583 self.server
584 .imp()
585 .open_uri_cbs
586 .borrow_mut()
587 .push(Box::new(cb));
588 }
589
590 pub fn connect_set_loop_status(&self, cb: impl Fn(&Self, LoopStatus) + 'static) {
591 self.server
592 .imp()
593 .set_loop_status_cbs
594 .borrow_mut()
595 .push(Box::new(cb));
596 }
597
598 pub fn connect_set_rate(&self, cb: impl Fn(&Self, PlaybackRate) + 'static) {
599 self.server
600 .imp()
601 .set_rate_cbs
602 .borrow_mut()
603 .push(Box::new(cb));
604 }
605
606 pub fn connect_set_shuffle(&self, cb: impl Fn(&Self, bool) + 'static) {
607 self.server
608 .imp()
609 .set_shuffle_cbs
610 .borrow_mut()
611 .push(Box::new(cb));
612 }
613
614 pub fn connect_set_volume(&self, cb: impl Fn(&Self, Volume) + 'static) {
615 self.server
616 .imp()
617 .set_volume_cbs
618 .borrow_mut()
619 .push(Box::new(cb));
620 }
621
622 pub async fn seeked(&self, position: Time) -> Result<()> {
623 self.server.emit(Signal::Seeked { position }).await
624 }
625
626 pub fn playback_status(&self) -> PlaybackStatus {
627 self.server.imp().playback_status.get()
628 }
629
630 pub async fn set_playback_status(&self, playback_status: PlaybackStatus) -> Result<()> {
631 if self.playback_status() == playback_status {
632 return Ok(());
633 }
634
635 self.server.imp().playback_status.set(playback_status);
636 self.server
637 .properties_changed([Property::PlaybackStatus(playback_status)])
638 .await
639 }
640
641 pub fn loop_status(&self) -> LoopStatus {
642 self.server.imp().loop_status.get()
643 }
644
645 pub async fn set_loop_status(&self, loop_status: LoopStatus) -> Result<()> {
646 if self.loop_status() == loop_status {
647 return Ok(());
648 }
649
650 self.server.imp().loop_status.set(loop_status);
651 self.server
652 .properties_changed([Property::LoopStatus(loop_status)])
653 .await
654 }
655
656 pub fn rate(&self) -> PlaybackRate {
657 self.server.imp().rate.get()
658 }
659
660 pub async fn set_rate(&self, rate: PlaybackRate) -> Result<()> {
661 if self.rate() == rate {
662 return Ok(());
663 }
664
665 self.server.imp().rate.set(rate);
666 self.server.properties_changed([Property::Rate(rate)]).await
667 }
668
669 pub fn shuffle(&self) -> bool {
670 self.server.imp().shuffle.get()
671 }
672
673 pub async fn set_shuffle(&self, shuffle: bool) -> Result<()> {
674 if self.shuffle() == shuffle {
675 return Ok(());
676 }
677
678 self.server.imp().shuffle.set(shuffle);
679 self.server
680 .properties_changed([Property::Shuffle(shuffle)])
681 .await
682 }
683
684 pub fn metadata(&self) -> Ref<'_, Metadata> {
685 self.server.imp().metadata.borrow()
686 }
687
688 pub async fn set_metadata(&self, metadata: Metadata) -> Result<()> {
689 if *self.metadata() == metadata {
690 return Ok(());
691 }
692
693 self.server.imp().metadata.replace(metadata.clone());
694 self.server
695 .properties_changed([Property::Metadata(metadata)])
696 .await
697 }
698
699 pub fn volume(&self) -> Volume {
700 self.server.imp().volume.get()
701 }
702
703 pub async fn set_volume(&self, volume: Volume) -> Result<()> {
704 if self.volume() == volume {
705 return Ok(());
706 }
707
708 self.server.imp().volume.set(volume);
709 self.server
710 .properties_changed([Property::Volume(volume)])
711 .await
712 }
713
714 pub fn position(&self) -> Time {
715 self.server.imp().position.get()
716 }
717
718 pub fn set_position(&self, position: Time) {
720 self.server.imp().position.set(position);
721 }
722
723 pub fn minimum_rate(&self) -> PlaybackRate {
724 self.server.imp().minimum_rate.get()
725 }
726
727 pub async fn set_minimum_rate(&self, minimum_rate: PlaybackRate) -> Result<()> {
728 if self.minimum_rate() == minimum_rate {
729 return Ok(());
730 }
731
732 self.server.imp().minimum_rate.set(minimum_rate);
733 self.server
734 .properties_changed([Property::MinimumRate(minimum_rate)])
735 .await
736 }
737
738 pub fn maximum_rate(&self) -> PlaybackRate {
739 self.server.imp().maximum_rate.get()
740 }
741
742 pub async fn set_maximum_rate(&self, maximum_rate: PlaybackRate) -> Result<()> {
743 if self.maximum_rate() == maximum_rate {
744 return Ok(());
745 }
746
747 self.server.imp().maximum_rate.set(maximum_rate);
748 self.server
749 .properties_changed([Property::MaximumRate(maximum_rate)])
750 .await
751 }
752
753 pub fn can_go_next(&self) -> bool {
754 self.server.imp().can_go_next.get()
755 }
756
757 pub async fn set_can_go_next(&self, can_go_next: bool) -> Result<()> {
758 if self.can_go_next() == can_go_next {
759 return Ok(());
760 }
761
762 self.server.imp().can_go_next.set(can_go_next);
763 self.server
764 .properties_changed([Property::CanGoNext(can_go_next)])
765 .await
766 }
767
768 pub fn can_go_previous(&self) -> bool {
769 self.server.imp().can_go_previous.get()
770 }
771
772 pub async fn set_can_go_previous(&self, can_go_previous: bool) -> Result<()> {
773 if self.can_go_previous() == can_go_previous {
774 return Ok(());
775 }
776
777 self.server.imp().can_go_previous.set(can_go_previous);
778 self.server
779 .properties_changed([Property::CanGoPrevious(can_go_previous)])
780 .await
781 }
782
783 pub fn can_play(&self) -> bool {
784 self.server.imp().can_play.get()
785 }
786
787 pub async fn set_can_play(&self, can_play: bool) -> Result<()> {
788 if self.can_play() == can_play {
789 return Ok(());
790 }
791
792 self.server.imp().can_play.set(can_play);
793 self.server
794 .properties_changed([Property::CanPlay(can_play)])
795 .await
796 }
797
798 pub fn can_pause(&self) -> bool {
799 self.server.imp().can_pause.get()
800 }
801
802 pub async fn set_can_pause(&self, can_pause: bool) -> Result<()> {
803 if self.can_pause() == can_pause {
804 return Ok(());
805 }
806
807 self.server.imp().can_pause.set(can_pause);
808 self.server
809 .properties_changed([Property::CanPause(can_pause)])
810 .await
811 }
812
813 pub fn can_seek(&self) -> bool {
814 self.server.imp().can_seek.get()
815 }
816
817 pub async fn set_can_seek(&self, can_seek: bool) -> Result<()> {
818 if self.can_seek() == can_seek {
819 return Ok(());
820 }
821
822 self.server.imp().can_seek.set(can_seek);
823 self.server
824 .properties_changed([Property::CanSeek(can_seek)])
825 .await
826 }
827
828 pub fn can_control(&self) -> bool {
830 self.server.imp().can_control.get()
831 }
832}
833
834#[derive(Debug)]
836#[must_use = "must call `build()` to finish building the player"]
837pub struct PlayerBuilder {
838 bus_name_suffix: String,
839 can_quit: bool,
840 fullscreen: bool,
841 can_set_fullscreen: bool,
842 can_raise: bool,
843 has_track_list: bool,
844 identity: String,
845 desktop_entry: String,
846 supported_uri_schemes: Vec<String>,
847 supported_mime_types: Vec<String>,
848 playback_status: PlaybackStatus,
849 loop_status: LoopStatus,
850 rate: PlaybackRate,
851 shuffle: bool,
852 metadata: Metadata,
853 volume: Volume,
854 position: Time,
855 minimum_rate: PlaybackRate,
856 maximum_rate: PlaybackRate,
857 can_go_next: bool,
858 can_go_previous: bool,
859 can_play: bool,
860 can_pause: bool,
861 can_seek: bool,
862 can_control: bool,
863}
864
865impl PlayerBuilder {
866 pub fn can_quit(mut self, can_quit: bool) -> Self {
867 self.can_quit = can_quit;
868 self
869 }
870
871 pub fn fullscreen(mut self, fullscreen: bool) -> Self {
872 self.fullscreen = fullscreen;
873 self
874 }
875
876 pub fn can_set_fullscreen(mut self, can_set_fullscreen: bool) -> Self {
877 self.can_set_fullscreen = can_set_fullscreen;
878 self
879 }
880
881 pub fn can_raise(mut self, can_raise: bool) -> Self {
882 self.can_raise = can_raise;
883 self
884 }
885
886 pub fn has_track_list(mut self, has_track_list: bool) -> Self {
887 self.has_track_list = has_track_list;
888 self
889 }
890
891 pub fn identity(mut self, identity: impl Into<String>) -> Self {
892 self.identity = identity.into();
893 self
894 }
895
896 pub fn desktop_entry(mut self, desktop_entry: impl Into<String>) -> Self {
897 self.desktop_entry = desktop_entry.into();
898 self
899 }
900
901 pub fn supported_uri_schemes(
902 mut self,
903 supported_uri_schemes: impl IntoIterator<Item = impl Into<String>>,
904 ) -> Self {
905 self.supported_uri_schemes = supported_uri_schemes
906 .into_iter()
907 .map(|i| i.into())
908 .collect();
909 self
910 }
911
912 pub fn supported_mime_types(
913 mut self,
914 supported_mime_types: impl IntoIterator<Item = impl Into<String>>,
915 ) -> Self {
916 self.supported_mime_types = supported_mime_types.into_iter().map(|i| i.into()).collect();
917 self
918 }
919
920 pub fn playback_status(mut self, playback_status: PlaybackStatus) -> Self {
921 self.playback_status = playback_status;
922 self
923 }
924
925 pub fn loop_status(mut self, loop_status: LoopStatus) -> Self {
926 self.loop_status = loop_status;
927 self
928 }
929
930 pub fn rate(mut self, rate: PlaybackRate) -> Self {
931 self.rate = rate;
932 self
933 }
934
935 pub fn shuffle(mut self, shuffle: bool) -> Self {
936 self.shuffle = shuffle;
937 self
938 }
939
940 pub fn metadata(mut self, metadata: Metadata) -> Self {
941 self.metadata = metadata;
942 self
943 }
944
945 pub fn volume(mut self, volume: Volume) -> Self {
946 self.volume = volume;
947 self
948 }
949
950 pub fn position(mut self, position: Time) -> Self {
951 self.position = position;
952 self
953 }
954
955 pub fn minimum_rate(mut self, minimum_rate: PlaybackRate) -> Self {
956 self.minimum_rate = minimum_rate;
957 self
958 }
959
960 pub fn maximum_rate(mut self, maximum_rate: PlaybackRate) -> Self {
961 self.maximum_rate = maximum_rate;
962 self
963 }
964
965 pub fn can_go_next(mut self, can_go_next: bool) -> Self {
966 self.can_go_next = can_go_next;
967 self
968 }
969
970 pub fn can_go_previous(mut self, can_go_previous: bool) -> Self {
971 self.can_go_previous = can_go_previous;
972 self
973 }
974
975 pub fn can_play(mut self, can_play: bool) -> Self {
976 self.can_play = can_play;
977 self
978 }
979
980 pub fn can_pause(mut self, can_pause: bool) -> Self {
981 self.can_pause = can_pause;
982 self
983 }
984
985 pub fn can_seek(mut self, can_seek: bool) -> Self {
986 self.can_seek = can_seek;
987 self
988 }
989
990 pub fn can_control(mut self, can_control: bool) -> Self {
991 self.can_control = can_control;
992 self
993 }
994
995 #[must_use = "building player is usually expensive and is not expected to have side effects"]
996 pub async fn build(self) -> Result<Player> {
997 let server = Rc::new(
998 LocalServer::new(
999 &self.bus_name_suffix,
1000 State {
1001 server: RefCell::new(None),
1002 raise_cbs: RefCell::new(Vec::new()),
1003 quit_cbs: RefCell::new(Vec::new()),
1004 set_fullscreen_cbs: RefCell::new(Vec::new()),
1005 can_quit: Cell::new(self.can_quit),
1006 fullscreen: Cell::new(self.fullscreen),
1007 can_set_fullscreen: Cell::new(self.can_set_fullscreen),
1008 can_raise: Cell::new(self.can_raise),
1009 has_track_list: Cell::new(self.has_track_list),
1010 identity: RefCell::new(self.identity),
1011 desktop_entry: RefCell::new(self.desktop_entry),
1012 supported_uri_schemes: RefCell::new(self.supported_uri_schemes),
1013 supported_mime_types: RefCell::new(self.supported_mime_types),
1014 next_cbs: RefCell::new(Vec::new()),
1015 previous_cbs: RefCell::new(Vec::new()),
1016 pause_cbs: RefCell::new(Vec::new()),
1017 play_pause_cbs: RefCell::new(Vec::new()),
1018 stop_cbs: RefCell::new(Vec::new()),
1019 play_cbs: RefCell::new(Vec::new()),
1020 seek_cbs: RefCell::new(Vec::new()),
1021 set_position_cbs: RefCell::new(Vec::new()),
1022 open_uri_cbs: RefCell::new(Vec::new()),
1023 set_loop_status_cbs: RefCell::new(Vec::new()),
1024 set_rate_cbs: RefCell::new(Vec::new()),
1025 set_shuffle_cbs: RefCell::new(Vec::new()),
1026 set_volume_cbs: RefCell::new(Vec::new()),
1027 playback_status: Cell::new(self.playback_status),
1028 loop_status: Cell::new(self.loop_status),
1029 rate: Cell::new(self.rate),
1030 shuffle: Cell::new(self.shuffle),
1031 metadata: RefCell::new(self.metadata),
1032 volume: Cell::new(self.volume),
1033 position: Cell::new(self.position),
1034 minimum_rate: Cell::new(self.minimum_rate),
1035 maximum_rate: Cell::new(self.maximum_rate),
1036 can_go_next: Cell::new(self.can_go_next),
1037 can_go_previous: Cell::new(self.can_go_previous),
1038 can_play: Cell::new(self.can_play),
1039 can_pause: Cell::new(self.can_pause),
1040 can_seek: Cell::new(self.can_seek),
1041 can_control: Cell::new(self.can_control),
1042 },
1043 )
1044 .await?,
1045 );
1046
1047 server.imp().server.replace(Some(Rc::downgrade(&server)));
1048
1049 Ok(Player { server })
1050 }
1051}