mpris_server/
player.rs

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/// Ready-to-use mutable *service*-side object that internally implements
14/// [`LocalRootInterface`] and [`LocalPlayerInterface`].
15///
16/// This has its own internal state, automatically emits properties changed
17/// signals, and allows you to connect to method and property setter calls.
18///
19/// If you need more control to the implementation, you can use [`LocalServer`]
20/// or [`Server`] directly instead.
21///
22/// [`Server`]: crate::Server
23#[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)>>>, // Property
35    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)>>>, // Property
55    set_rate_cbs: RefCell<Vec<Box<dyn Fn(&Player, PlaybackRate)>>>,      // Property
56    set_shuffle_cbs: RefCell<Vec<Box<dyn Fn(&Player, bool)>>>,           // Property
57    set_volume_cbs: RefCell<Vec<Box<dyn Fn(&Player, Volume)>>>,          // Property
58    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    /// Returns a task that runs the player's server until the player and the
349    /// task is dropped.
350    ///
351    /// The task must be awaited as soon as possible after creating the player.
352    ///
353    /// The returned task is no-op if the player's server has been ran before.
354    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    /// This does not emit `PropertiesChanged` signal.
719    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    /// This can only be set on construct.
829    pub fn can_control(&self) -> bool {
830        self.server.imp().can_control.get()
831    }
832}
833
834/// A builder used to create [`Player`].
835#[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}