1use std::{
2 cell::RefCell,
3 fmt,
4 future::Future,
5 marker::PhantomData,
6 pin::Pin,
7 rc::Rc,
8 task::{Context, Poll},
9};
10
11use async_channel::{Receiver, Sender};
12use futures_channel::oneshot;
13use zbus::{fdo, Result};
14
15use crate::{
16 LocalPlayerInterface, LocalPlaylistsInterface, LocalTrackListInterface, LoopStatus, Metadata,
17 PlaybackRate, PlaybackStatus, PlayerInterface, Playlist, PlaylistId, PlaylistOrdering,
18 PlaylistsInterface, PlaylistsProperty, PlaylistsSignal, Property, RootInterface, Server,
19 Signal, Time, TrackId, TrackListInterface, TrackListProperty, TrackListSignal, Uri, Volume,
20};
21
22enum RootAction {
23 Raise(oneshot::Sender<fdo::Result<()>>),
25 Quit(oneshot::Sender<fdo::Result<()>>),
26
27 CanQuit(oneshot::Sender<fdo::Result<bool>>),
29 Fullscreen(oneshot::Sender<fdo::Result<bool>>),
30 SetFullscreen(bool, oneshot::Sender<Result<()>>),
31 CanSetFullScreen(oneshot::Sender<fdo::Result<bool>>),
32 CanRaise(oneshot::Sender<fdo::Result<bool>>),
33 HasTrackList(oneshot::Sender<fdo::Result<bool>>),
34 Identity(oneshot::Sender<fdo::Result<String>>),
35 DesktopEntry(oneshot::Sender<fdo::Result<String>>),
36 SupportedUriSchemes(oneshot::Sender<fdo::Result<Vec<String>>>),
37 SupportedMimeTypes(oneshot::Sender<fdo::Result<Vec<String>>>),
38}
39
40enum PlayerAction {
41 Next(oneshot::Sender<fdo::Result<()>>),
43 Previous(oneshot::Sender<fdo::Result<()>>),
44 Pause(oneshot::Sender<fdo::Result<()>>),
45 PlayPause(oneshot::Sender<fdo::Result<()>>),
46 Stop(oneshot::Sender<fdo::Result<()>>),
47 Play(oneshot::Sender<fdo::Result<()>>),
48 Seek(Time, oneshot::Sender<fdo::Result<()>>),
49 SetPosition(TrackId, Time, oneshot::Sender<fdo::Result<()>>),
50 OpenUri(String, oneshot::Sender<fdo::Result<()>>),
51
52 PlaybackStatus(oneshot::Sender<fdo::Result<PlaybackStatus>>),
54 LoopStatus(oneshot::Sender<fdo::Result<LoopStatus>>),
55 SetLoopStatus(LoopStatus, oneshot::Sender<Result<()>>),
56 Rate(oneshot::Sender<fdo::Result<PlaybackRate>>),
57 SetRate(PlaybackRate, oneshot::Sender<Result<()>>),
58 Shuffle(oneshot::Sender<fdo::Result<bool>>),
59 SetShuffle(bool, oneshot::Sender<Result<()>>),
60 Metadata(oneshot::Sender<fdo::Result<Metadata>>),
61 Volume(oneshot::Sender<fdo::Result<Volume>>),
62 SetVolume(Volume, oneshot::Sender<Result<()>>),
63 Position(oneshot::Sender<fdo::Result<Time>>),
64 MinimumRate(oneshot::Sender<fdo::Result<PlaybackRate>>),
65 MaximumRate(oneshot::Sender<fdo::Result<PlaybackRate>>),
66 CanGoNext(oneshot::Sender<fdo::Result<bool>>),
67 CanGoPrevious(oneshot::Sender<fdo::Result<bool>>),
68 CanPlay(oneshot::Sender<fdo::Result<bool>>),
69 CanPause(oneshot::Sender<fdo::Result<bool>>),
70 CanSeek(oneshot::Sender<fdo::Result<bool>>),
71 CanControl(oneshot::Sender<fdo::Result<bool>>),
72}
73
74enum TrackListAction {
75 GetTracksMetadata(Vec<TrackId>, oneshot::Sender<fdo::Result<Vec<Metadata>>>),
77 AddTrack(Uri, TrackId, bool, oneshot::Sender<fdo::Result<()>>),
78 RemoveTrack(TrackId, oneshot::Sender<fdo::Result<()>>),
79 GoTo(TrackId, oneshot::Sender<fdo::Result<()>>),
80
81 Tracks(oneshot::Sender<fdo::Result<Vec<TrackId>>>),
83 CanEditTracks(oneshot::Sender<fdo::Result<bool>>),
84}
85
86enum PlaylistsAction {
87 ActivatePlaylist(PlaylistId, oneshot::Sender<fdo::Result<()>>),
89 GetPlaylists(
90 u32,
91 u32,
92 PlaylistOrdering,
93 bool,
94 oneshot::Sender<fdo::Result<Vec<Playlist>>>,
95 ),
96
97 PlaylistCount(oneshot::Sender<fdo::Result<u32>>),
99 Orderings(oneshot::Sender<fdo::Result<Vec<PlaylistOrdering>>>),
100 ActivePlaylist(oneshot::Sender<fdo::Result<Option<Playlist>>>),
101}
102
103enum Action {
104 Root(RootAction),
105 Player(PlayerAction),
106 TrackList(TrackListAction),
107 Playlists(PlaylistsAction),
108}
109
110struct InnerImp<T> {
111 tx: Sender<Action>,
112
113 imp_ty: PhantomData<fn() -> T>,
119}
120
121impl<T> InnerImp<T> {
122 async fn send_root(&self, action: RootAction) {
123 self.tx.send(Action::Root(action)).await.unwrap();
124 }
125
126 async fn send_player(&self, action: PlayerAction) {
127 self.tx.send(Action::Player(action)).await.unwrap();
128 }
129
130 async fn send_track_list(&self, action: TrackListAction) {
131 self.tx.send(Action::TrackList(action)).await.unwrap();
132 }
133
134 async fn send_playlists(&self, action: PlaylistsAction) {
135 self.tx.send(Action::Playlists(action)).await.unwrap();
136 }
137}
138
139impl<T> RootInterface for InnerImp<T> {
140 async fn raise(&self) -> fdo::Result<()> {
141 let (tx, rx) = oneshot::channel();
142 self.send_root(RootAction::Raise(tx)).await;
143 rx.await.unwrap()
144 }
145
146 async fn quit(&self) -> fdo::Result<()> {
147 let (tx, rx) = oneshot::channel();
148 self.send_root(RootAction::Quit(tx)).await;
149 rx.await.unwrap()
150 }
151
152 async fn can_quit(&self) -> fdo::Result<bool> {
153 let (tx, rx) = oneshot::channel();
154 self.send_root(RootAction::CanQuit(tx)).await;
155 rx.await.unwrap()
156 }
157
158 async fn fullscreen(&self) -> fdo::Result<bool> {
159 let (tx, rx) = oneshot::channel();
160 self.send_root(RootAction::Fullscreen(tx)).await;
161 rx.await.unwrap()
162 }
163
164 async fn set_fullscreen(&self, fullscreen: bool) -> Result<()> {
165 let (tx, rx) = oneshot::channel();
166 self.send_root(RootAction::SetFullscreen(fullscreen, tx))
167 .await;
168 rx.await.unwrap()
169 }
170
171 async fn can_set_fullscreen(&self) -> fdo::Result<bool> {
172 let (tx, rx) = oneshot::channel();
173 self.send_root(RootAction::CanSetFullScreen(tx)).await;
174 rx.await.unwrap()
175 }
176
177 async fn can_raise(&self) -> fdo::Result<bool> {
178 let (tx, rx) = oneshot::channel();
179 self.send_root(RootAction::CanRaise(tx)).await;
180 rx.await.unwrap()
181 }
182
183 async fn has_track_list(&self) -> fdo::Result<bool> {
184 let (tx, rx) = oneshot::channel();
185 self.send_root(RootAction::HasTrackList(tx)).await;
186 rx.await.unwrap()
187 }
188
189 async fn identity(&self) -> fdo::Result<String> {
190 let (tx, rx) = oneshot::channel();
191 self.send_root(RootAction::Identity(tx)).await;
192 rx.await.unwrap()
193 }
194
195 async fn desktop_entry(&self) -> fdo::Result<String> {
196 let (tx, rx) = oneshot::channel();
197 self.send_root(RootAction::DesktopEntry(tx)).await;
198 rx.await.unwrap()
199 }
200
201 async fn supported_uri_schemes(&self) -> fdo::Result<Vec<String>> {
202 let (tx, rx) = oneshot::channel();
203 self.send_root(RootAction::SupportedUriSchemes(tx)).await;
204 rx.await.unwrap()
205 }
206
207 async fn supported_mime_types(&self) -> fdo::Result<Vec<String>> {
208 let (tx, rx) = oneshot::channel();
209 self.send_root(RootAction::SupportedMimeTypes(tx)).await;
210 rx.await.unwrap()
211 }
212}
213
214impl<T> PlayerInterface for InnerImp<T> {
215 async fn next(&self) -> fdo::Result<()> {
216 let (tx, rx) = oneshot::channel();
217 self.send_player(PlayerAction::Next(tx)).await;
218 rx.await.unwrap()
219 }
220
221 async fn previous(&self) -> fdo::Result<()> {
222 let (tx, rx) = oneshot::channel();
223 self.send_player(PlayerAction::Previous(tx)).await;
224 rx.await.unwrap()
225 }
226
227 async fn pause(&self) -> fdo::Result<()> {
228 let (tx, rx) = oneshot::channel();
229 self.send_player(PlayerAction::Pause(tx)).await;
230 rx.await.unwrap()
231 }
232
233 async fn play_pause(&self) -> fdo::Result<()> {
234 let (tx, rx) = oneshot::channel();
235 self.send_player(PlayerAction::PlayPause(tx)).await;
236 rx.await.unwrap()
237 }
238
239 async fn stop(&self) -> fdo::Result<()> {
240 let (tx, rx) = oneshot::channel();
241 self.send_player(PlayerAction::Stop(tx)).await;
242 rx.await.unwrap()
243 }
244
245 async fn play(&self) -> fdo::Result<()> {
246 let (tx, rx) = oneshot::channel();
247 self.send_player(PlayerAction::Play(tx)).await;
248 rx.await.unwrap()
249 }
250
251 async fn seek(&self, offset: Time) -> fdo::Result<()> {
252 let (tx, rx) = oneshot::channel();
253 self.send_player(PlayerAction::Seek(offset, tx)).await;
254 rx.await.unwrap()
255 }
256
257 async fn set_position(&self, track_id: TrackId, position: Time) -> fdo::Result<()> {
258 let (tx, rx) = oneshot::channel();
259 self.send_player(PlayerAction::SetPosition(track_id, position, tx))
260 .await;
261 rx.await.unwrap()
262 }
263
264 async fn open_uri(&self, uri: String) -> fdo::Result<()> {
265 let (tx, rx) = oneshot::channel();
266 self.send_player(PlayerAction::OpenUri(uri, tx)).await;
267 rx.await.unwrap()
268 }
269
270 async fn playback_status(&self) -> fdo::Result<PlaybackStatus> {
271 let (tx, rx) = oneshot::channel();
272 self.send_player(PlayerAction::PlaybackStatus(tx)).await;
273 rx.await.unwrap()
274 }
275
276 async fn loop_status(&self) -> fdo::Result<LoopStatus> {
277 let (tx, rx) = oneshot::channel();
278 self.send_player(PlayerAction::LoopStatus(tx)).await;
279 rx.await.unwrap()
280 }
281
282 async fn set_loop_status(&self, loop_status: LoopStatus) -> Result<()> {
283 let (tx, rx) = oneshot::channel();
284 self.send_player(PlayerAction::SetLoopStatus(loop_status, tx))
285 .await;
286 rx.await.unwrap()
287 }
288
289 async fn rate(&self) -> fdo::Result<PlaybackRate> {
290 let (tx, rx) = oneshot::channel();
291 self.send_player(PlayerAction::Rate(tx)).await;
292 rx.await.unwrap()
293 }
294
295 async fn set_rate(&self, rate: PlaybackRate) -> Result<()> {
296 let (tx, rx) = oneshot::channel();
297 self.send_player(PlayerAction::SetRate(rate, tx)).await;
298 rx.await.unwrap()
299 }
300
301 async fn shuffle(&self) -> fdo::Result<bool> {
302 let (tx, rx) = oneshot::channel();
303 self.send_player(PlayerAction::Shuffle(tx)).await;
304 rx.await.unwrap()
305 }
306
307 async fn set_shuffle(&self, shuffle: bool) -> Result<()> {
308 let (tx, rx) = oneshot::channel();
309 self.send_player(PlayerAction::SetShuffle(shuffle, tx))
310 .await;
311 rx.await.unwrap()
312 }
313
314 async fn metadata(&self) -> fdo::Result<Metadata> {
315 let (tx, rx) = oneshot::channel();
316 self.send_player(PlayerAction::Metadata(tx)).await;
317 rx.await.unwrap()
318 }
319
320 async fn volume(&self) -> fdo::Result<Volume> {
321 let (tx, rx) = oneshot::channel();
322 self.send_player(PlayerAction::Volume(tx)).await;
323 rx.await.unwrap()
324 }
325
326 async fn set_volume(&self, volume: Volume) -> Result<()> {
327 let (tx, rx) = oneshot::channel();
328 self.send_player(PlayerAction::SetVolume(volume, tx)).await;
329 rx.await.unwrap()
330 }
331
332 async fn position(&self) -> fdo::Result<Time> {
333 let (tx, rx) = oneshot::channel();
334 self.send_player(PlayerAction::Position(tx)).await;
335 rx.await.unwrap()
336 }
337
338 async fn minimum_rate(&self) -> fdo::Result<PlaybackRate> {
339 let (tx, rx) = oneshot::channel();
340 self.send_player(PlayerAction::MinimumRate(tx)).await;
341 rx.await.unwrap()
342 }
343
344 async fn maximum_rate(&self) -> fdo::Result<PlaybackRate> {
345 let (tx, rx) = oneshot::channel();
346 self.send_player(PlayerAction::MaximumRate(tx)).await;
347 rx.await.unwrap()
348 }
349
350 async fn can_go_next(&self) -> fdo::Result<bool> {
351 let (tx, rx) = oneshot::channel();
352 self.send_player(PlayerAction::CanGoNext(tx)).await;
353 rx.await.unwrap()
354 }
355
356 async fn can_go_previous(&self) -> fdo::Result<bool> {
357 let (tx, rx) = oneshot::channel();
358 self.send_player(PlayerAction::CanGoPrevious(tx)).await;
359 rx.await.unwrap()
360 }
361
362 async fn can_play(&self) -> fdo::Result<bool> {
363 let (tx, rx) = oneshot::channel();
364 self.send_player(PlayerAction::CanPlay(tx)).await;
365 rx.await.unwrap()
366 }
367
368 async fn can_pause(&self) -> fdo::Result<bool> {
369 let (tx, rx) = oneshot::channel();
370 self.send_player(PlayerAction::CanPause(tx)).await;
371 rx.await.unwrap()
372 }
373
374 async fn can_seek(&self) -> fdo::Result<bool> {
375 let (tx, rx) = oneshot::channel();
376 self.send_player(PlayerAction::CanSeek(tx)).await;
377 rx.await.unwrap()
378 }
379
380 async fn can_control(&self) -> fdo::Result<bool> {
381 let (tx, rx) = oneshot::channel();
382 self.send_player(PlayerAction::CanControl(tx)).await;
383 rx.await.unwrap()
384 }
385}
386
387impl<T> TrackListInterface for InnerImp<T>
388where
389 T: LocalTrackListInterface,
390{
391 async fn get_tracks_metadata(&self, track_ids: Vec<TrackId>) -> fdo::Result<Vec<Metadata>> {
392 let (tx, rx) = oneshot::channel();
393 self.send_track_list(TrackListAction::GetTracksMetadata(track_ids, tx))
394 .await;
395 rx.await.unwrap()
396 }
397
398 async fn add_track(
399 &self,
400 uri: Uri,
401 after_track: TrackId,
402 set_as_current: bool,
403 ) -> fdo::Result<()> {
404 let (tx, rx) = oneshot::channel();
405 self.send_track_list(TrackListAction::AddTrack(
406 uri,
407 after_track,
408 set_as_current,
409 tx,
410 ))
411 .await;
412 rx.await.unwrap()
413 }
414
415 async fn remove_track(&self, track_id: TrackId) -> fdo::Result<()> {
416 let (tx, rx) = oneshot::channel();
417 self.send_track_list(TrackListAction::RemoveTrack(track_id, tx))
418 .await;
419 rx.await.unwrap()
420 }
421
422 async fn go_to(&self, track_id: TrackId) -> fdo::Result<()> {
423 let (tx, rx) = oneshot::channel();
424 self.send_track_list(TrackListAction::GoTo(track_id, tx))
425 .await;
426 rx.await.unwrap()
427 }
428
429 async fn tracks(&self) -> fdo::Result<Vec<TrackId>> {
430 let (tx, rx) = oneshot::channel();
431 self.send_track_list(TrackListAction::Tracks(tx)).await;
432 rx.await.unwrap()
433 }
434
435 async fn can_edit_tracks(&self) -> fdo::Result<bool> {
436 let (tx, rx) = oneshot::channel();
437 self.send_track_list(TrackListAction::CanEditTracks(tx))
438 .await;
439 rx.await.unwrap()
440 }
441}
442
443impl<T> PlaylistsInterface for InnerImp<T>
444where
445 T: LocalPlaylistsInterface,
446{
447 async fn activate_playlist(&self, playlist_id: PlaylistId) -> fdo::Result<()> {
448 let (tx, rx) = oneshot::channel();
449 self.send_playlists(PlaylistsAction::ActivatePlaylist(playlist_id, tx))
450 .await;
451 rx.await.unwrap()
452 }
453
454 async fn get_playlists(
455 &self,
456 index: u32,
457 max_count: u32,
458 order: PlaylistOrdering,
459 reverse_order: bool,
460 ) -> fdo::Result<Vec<Playlist>> {
461 let (tx, rx) = oneshot::channel();
462 self.send_playlists(PlaylistsAction::GetPlaylists(
463 index,
464 max_count,
465 order,
466 reverse_order,
467 tx,
468 ))
469 .await;
470 rx.await.unwrap()
471 }
472
473 async fn playlist_count(&self) -> fdo::Result<u32> {
474 let (tx, rx) = oneshot::channel();
475 self.send_playlists(PlaylistsAction::PlaylistCount(tx))
476 .await;
477 rx.await.unwrap()
478 }
479
480 async fn orderings(&self) -> fdo::Result<Vec<PlaylistOrdering>> {
481 let (tx, rx) = oneshot::channel();
482 self.send_playlists(PlaylistsAction::Orderings(tx)).await;
483 rx.await.unwrap()
484 }
485
486 async fn active_playlist(&self) -> fdo::Result<Option<Playlist>> {
487 let (tx, rx) = oneshot::channel();
488 self.send_playlists(PlaylistsAction::ActivePlaylist(tx))
489 .await;
490 rx.await.unwrap()
491 }
492}
493
494type TaskInner = Pin<Box<dyn Future<Output = ()>>>;
495
496#[must_use = "futures do nothing unless you `.await` or poll them"]
503pub struct LocalServerRunTask {
504 inner: Option<TaskInner>,
505}
506
507impl fmt::Debug for LocalServerRunTask {
508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 f.debug_struct("LocalServerRunTask")
510 .field("has_inner", &self.inner.is_some())
511 .finish()
512 }
513}
514
515impl Future for LocalServerRunTask {
516 type Output = ();
517
518 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
519 match self.inner.as_mut() {
520 Some(inner) => Pin::new(inner).poll(cx),
521 None => Poll::Ready(()),
522 }
523 }
524}
525
526pub struct LocalServer<T> {
534 inner: Server<InnerImp<T>>,
535 imp: Rc<T>,
536 runner: RefCell<Option<TaskInner>>,
537}
538
539impl<T> fmt::Debug for LocalServer<T> {
540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541 f.debug_struct("LocalServer").finish()
542 }
543}
544
545impl<T> LocalServer<T>
546where
547 T: LocalPlayerInterface + 'static,
548{
549 pub async fn new(bus_name_suffix: &str, imp: T) -> Result<Self> {
570 Self::new_inner(bus_name_suffix, imp, Server::new, |rx, imp| async move {
571 while let Ok(action) = rx.recv().await {
572 match action {
573 Action::Root(action) => Self::handle_root_action(&imp, action).await,
574 Action::Player(action) => Self::handle_player_action(&imp, action).await,
575 Action::TrackList(_) | Action::Playlists(_) => unreachable!(),
576 }
577 }
578 })
579 .await
580 }
581
582 pub fn run(&self) -> LocalServerRunTask {
589 LocalServerRunTask {
590 inner: self.runner.take(),
591 }
592 }
593
594 #[inline]
596 pub fn imp(&self) -> &T {
597 &self.imp
598 }
599
600 #[cfg(feature = "unstable")]
604 #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
605 #[inline]
606 pub fn connection(&self) -> &zbus::Connection {
607 self.inner.connection()
608 }
609
610 #[inline]
612 pub async fn emit(&self, signal: Signal) -> Result<()> {
613 self.inner.emit(signal).await
614 }
615
616 #[inline]
626 pub async fn properties_changed(
627 &self,
628 properties: impl IntoIterator<Item = Property>,
629 ) -> Result<()> {
630 self.inner.properties_changed(properties).await
631 }
632
633 async fn handle_root_action(imp: &T, action: RootAction) {
634 match action {
635 RootAction::Raise(sender) => {
637 let ret = imp.raise().await;
638 sender.send(ret).unwrap();
639 }
640 RootAction::Quit(sender) => {
641 let ret = imp.quit().await;
642 sender.send(ret).unwrap();
643 }
644 RootAction::CanQuit(sender) => {
646 let ret = imp.can_quit().await;
647 sender.send(ret).unwrap();
648 }
649 RootAction::Fullscreen(sender) => {
650 let ret = imp.fullscreen().await;
651 sender.send(ret).unwrap();
652 }
653 RootAction::SetFullscreen(fullscreen, sender) => {
654 let ret = imp.set_fullscreen(fullscreen).await;
655 sender.send(ret).unwrap();
656 }
657 RootAction::CanSetFullScreen(sender) => {
658 let ret = imp.can_set_fullscreen().await;
659 sender.send(ret).unwrap();
660 }
661 RootAction::CanRaise(sender) => {
662 let ret = imp.can_raise().await;
663 sender.send(ret).unwrap();
664 }
665 RootAction::HasTrackList(sender) => {
666 let ret = imp.has_track_list().await;
667 sender.send(ret).unwrap();
668 }
669 RootAction::Identity(sender) => {
670 let ret = imp.identity().await;
671 sender.send(ret).unwrap();
672 }
673 RootAction::DesktopEntry(sender) => {
674 let ret = imp.desktop_entry().await;
675 sender.send(ret).unwrap();
676 }
677 RootAction::SupportedUriSchemes(sender) => {
678 let ret = imp.supported_uri_schemes().await;
679 sender.send(ret).unwrap();
680 }
681 RootAction::SupportedMimeTypes(sender) => {
682 let ret = imp.supported_mime_types().await;
683 sender.send(ret).unwrap();
684 }
685 }
686 }
687
688 async fn handle_player_action(imp: &T, action: PlayerAction) {
689 match action {
690 PlayerAction::Next(sender) => {
692 let ret = imp.next().await;
693 sender.send(ret).unwrap();
694 }
695 PlayerAction::Previous(sender) => {
696 let ret = imp.previous().await;
697 sender.send(ret).unwrap();
698 }
699 PlayerAction::Pause(sender) => {
700 let ret = imp.pause().await;
701 sender.send(ret).unwrap();
702 }
703 PlayerAction::PlayPause(sender) => {
704 let ret = imp.play_pause().await;
705 sender.send(ret).unwrap();
706 }
707 PlayerAction::Stop(sender) => {
708 let ret = imp.stop().await;
709 sender.send(ret).unwrap();
710 }
711 PlayerAction::Play(sender) => {
712 let ret = imp.play().await;
713 sender.send(ret).unwrap();
714 }
715 PlayerAction::Seek(offset, sender) => {
716 let ret = imp.seek(offset).await;
717 sender.send(ret).unwrap();
718 }
719 PlayerAction::SetPosition(track_id, position, sender) => {
720 let ret = imp.set_position(track_id, position).await;
721 sender.send(ret).unwrap();
722 }
723 PlayerAction::OpenUri(uri, sender) => {
724 let ret = imp.open_uri(uri).await;
725 sender.send(ret).unwrap();
726 }
727 PlayerAction::PlaybackStatus(sender) => {
729 let ret = imp.playback_status().await;
730 sender.send(ret).unwrap();
731 }
732 PlayerAction::LoopStatus(sender) => {
733 let ret = imp.loop_status().await;
734 sender.send(ret).unwrap();
735 }
736 PlayerAction::SetLoopStatus(loop_status, sender) => {
737 let ret = imp.set_loop_status(loop_status).await;
738 sender.send(ret).unwrap();
739 }
740 PlayerAction::Rate(sender) => {
741 let ret = imp.rate().await;
742 sender.send(ret).unwrap();
743 }
744 PlayerAction::SetRate(rate, sender) => {
745 let ret = imp.set_rate(rate).await;
746 sender.send(ret).unwrap();
747 }
748 PlayerAction::Shuffle(sender) => {
749 let ret = imp.shuffle().await;
750 sender.send(ret).unwrap();
751 }
752 PlayerAction::SetShuffle(shuffle, sender) => {
753 let ret = imp.set_shuffle(shuffle).await;
754 sender.send(ret).unwrap();
755 }
756 PlayerAction::Metadata(sender) => {
757 let ret = imp.metadata().await;
758 sender.send(ret).unwrap();
759 }
760 PlayerAction::Volume(sender) => {
761 let ret = imp.volume().await;
762 sender.send(ret).unwrap();
763 }
764 PlayerAction::SetVolume(volume, sender) => {
765 let ret = imp.set_volume(volume).await;
766 sender.send(ret).unwrap();
767 }
768 PlayerAction::Position(sender) => {
769 let ret = imp.position().await;
770 sender.send(ret).unwrap();
771 }
772 PlayerAction::MinimumRate(sender) => {
773 let ret = imp.minimum_rate().await;
774 sender.send(ret).unwrap();
775 }
776 PlayerAction::MaximumRate(sender) => {
777 let ret = imp.maximum_rate().await;
778 sender.send(ret).unwrap();
779 }
780 PlayerAction::CanGoNext(sender) => {
781 let ret = imp.can_go_next().await;
782 sender.send(ret).unwrap();
783 }
784 PlayerAction::CanGoPrevious(sender) => {
785 let ret = imp.can_go_previous().await;
786 sender.send(ret).unwrap();
787 }
788 PlayerAction::CanPlay(sender) => {
789 let ret = imp.can_play().await;
790 sender.send(ret).unwrap();
791 }
792 PlayerAction::CanPause(sender) => {
793 let ret = imp.can_pause().await;
794 sender.send(ret).unwrap();
795 }
796 PlayerAction::CanSeek(sender) => {
797 let ret = imp.can_seek().await;
798 sender.send(ret).unwrap();
799 }
800 PlayerAction::CanControl(sender) => {
801 let ret = imp.can_control().await;
802 sender.send(ret).unwrap();
803 }
804 }
805 }
806
807 async fn new_inner<'a, SR, RR>(
808 bus_name_suffix: &'a str,
809 imp: T,
810 server_func: impl FnOnce(&'a str, InnerImp<T>) -> SR + 'static,
811 runner_func: impl FnOnce(Receiver<Action>, Rc<T>) -> RR + 'static,
812 ) -> Result<Self>
813 where
814 SR: Future<Output = Result<Server<InnerImp<T>>>>,
815 RR: Future<Output = ()> + 'static,
816 {
817 let (tx, rx) = async_channel::bounded(1);
818
819 let inner = server_func(
820 bus_name_suffix,
821 InnerImp {
822 tx,
823 imp_ty: PhantomData,
824 },
825 )
826 .await?;
827
828 let imp = Rc::new(imp);
829 let runner = Box::pin(runner_func(rx, Rc::clone(&imp)));
830
831 Ok(Self {
832 inner,
833 imp,
834 runner: RefCell::new(Some(runner)),
835 })
836 }
837}
838
839impl<T> LocalServer<T>
840where
841 T: LocalTrackListInterface + 'static,
842{
843 pub async fn new_with_track_list(bus_name_suffix: &str, imp: T) -> Result<Self> {
851 Self::new_inner(
852 bus_name_suffix,
853 imp,
854 Server::new_with_track_list,
855 |rx, imp| async move {
856 while let Ok(action) = rx.recv().await {
857 match action {
858 Action::Root(action) => Self::handle_root_action(&imp, action).await,
859 Action::Player(action) => Self::handle_player_action(&imp, action).await,
860 Action::TrackList(action) => {
861 Self::handle_track_list_action(&imp, action).await
862 }
863 Action::Playlists(_) => unreachable!(),
864 }
865 }
866 },
867 )
868 .await
869 }
870
871 #[inline]
873 pub async fn track_list_emit(&self, signal: TrackListSignal) -> Result<()> {
874 self.inner.track_list_emit(signal).await
875 }
876
877 #[inline]
882 pub async fn track_list_properties_changed(
883 &self,
884 properties: impl IntoIterator<Item = TrackListProperty>,
885 ) -> Result<()> {
886 self.inner.track_list_properties_changed(properties).await
887 }
888
889 async fn handle_track_list_action(imp: &T, action: TrackListAction) {
890 match action {
891 TrackListAction::GetTracksMetadata(track_ids, sender) => {
893 let ret = imp.get_tracks_metadata(track_ids).await;
894 sender.send(ret).unwrap();
895 }
896 TrackListAction::AddTrack(uri, after_track, set_as_current, sender) => {
897 let ret = imp.add_track(uri, after_track, set_as_current).await;
898 sender.send(ret).unwrap();
899 }
900 TrackListAction::RemoveTrack(track_id, sender) => {
901 let ret = imp.remove_track(track_id).await;
902 sender.send(ret).unwrap();
903 }
904 TrackListAction::GoTo(track_id, sender) => {
905 let ret = imp.go_to(track_id).await;
906 sender.send(ret).unwrap();
907 }
908 TrackListAction::Tracks(sender) => {
910 let ret = imp.tracks().await;
911 sender.send(ret).unwrap();
912 }
913 TrackListAction::CanEditTracks(sender) => {
914 let ret = imp.can_edit_tracks().await;
915 sender.send(ret).unwrap();
916 }
917 }
918 }
919}
920
921impl<T> LocalServer<T>
922where
923 T: LocalPlaylistsInterface + 'static,
924{
925 pub async fn new_with_playlists(bus_name_suffix: &str, imp: T) -> Result<Self> {
933 Self::new_inner(
934 bus_name_suffix,
935 imp,
936 Server::new_with_playlists,
937 |rx, imp| async move {
938 while let Ok(action) = rx.recv().await {
939 match action {
940 Action::Root(action) => Self::handle_root_action(&imp, action).await,
941 Action::Player(action) => Self::handle_player_action(&imp, action).await,
942 Action::Playlists(action) => {
943 Self::handle_playlists_action(&imp, action).await
944 }
945 Action::TrackList(_) => unreachable!(),
946 }
947 }
948 },
949 )
950 .await
951 }
952
953 #[inline]
955 pub async fn playlists_emit(&self, signal: PlaylistsSignal) -> Result<()> {
956 self.inner.playlists_emit(signal).await
957 }
958
959 #[inline]
964 pub async fn playlists_properties_changed(
965 &self,
966 properties: impl IntoIterator<Item = PlaylistsProperty>,
967 ) -> Result<()> {
968 self.inner.playlists_properties_changed(properties).await
969 }
970
971 async fn handle_playlists_action(imp: &T, action: PlaylistsAction) {
972 match action {
973 PlaylistsAction::ActivatePlaylist(playlist_id, sender) => {
974 let ret = imp.activate_playlist(playlist_id).await;
975 sender.send(ret).unwrap();
976 }
977 PlaylistsAction::GetPlaylists(index, max_count, order, reverse_order, sender) => {
978 let ret = imp
979 .get_playlists(index, max_count, order, reverse_order)
980 .await;
981 sender.send(ret).unwrap();
982 }
983 PlaylistsAction::PlaylistCount(sender) => {
984 let ret = imp.playlist_count().await;
985 sender.send(ret).unwrap();
986 }
987 PlaylistsAction::Orderings(sender) => {
988 let ret = imp.orderings().await;
989 sender.send(ret).unwrap();
990 }
991 PlaylistsAction::ActivePlaylist(sender) => {
992 let ret = imp.active_playlist().await;
993 sender.send(ret).unwrap();
994 }
995 }
996 }
997}
998
999impl<T> LocalServer<T>
1000where
1001 T: LocalTrackListInterface + LocalPlaylistsInterface + 'static,
1002{
1003 pub async fn new_with_all(bus_name_suffix: &str, imp: T) -> Result<Self> {
1012 Self::new_inner(
1013 bus_name_suffix,
1014 imp,
1015 Server::new_with_all,
1016 |rx, imp| async move {
1017 while let Ok(action) = rx.recv().await {
1018 match action {
1019 Action::Root(action) => Self::handle_root_action(&imp, action).await,
1020 Action::Player(action) => Self::handle_player_action(&imp, action).await,
1021 Action::Playlists(action) => {
1022 Self::handle_playlists_action(&imp, action).await
1023 }
1024 Action::TrackList(action) => {
1025 Self::handle_track_list_action(&imp, action).await
1026 }
1027 }
1028 }
1029 },
1030 )
1031 .await
1032 }
1033}
1034
1035#[cfg(test)]
1036mod tests {
1037 use static_assertions::{assert_impl_all, assert_not_impl_any};
1038
1039 use super::LocalServer;
1040
1041 #[allow(dead_code)]
1042 pub struct TestPlayer;
1043
1044 assert_not_impl_any!(LocalServer<TestPlayer>: Send, Sync);
1045 assert_impl_all!(LocalServer<TestPlayer>: Unpin);
1046}