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, names::WellKnownName, 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 fn bus_name(&self) -> &WellKnownName<'_> {
613 self.inner.bus_name()
614 }
615
616 #[inline]
626 pub async fn release_bus_name(&self) -> Result<bool> {
627 self.inner.release_bus_name().await
628 }
629
630 #[inline]
632 pub async fn emit(&self, signal: Signal) -> Result<()> {
633 self.inner.emit(signal).await
634 }
635
636 #[inline]
646 pub async fn properties_changed(
647 &self,
648 properties: impl IntoIterator<Item = Property>,
649 ) -> Result<()> {
650 self.inner.properties_changed(properties).await
651 }
652
653 async fn handle_root_action(imp: &T, action: RootAction) {
654 match action {
655 RootAction::Raise(sender) => {
657 let ret = imp.raise().await;
658 sender.send(ret).unwrap();
659 }
660 RootAction::Quit(sender) => {
661 let ret = imp.quit().await;
662 sender.send(ret).unwrap();
663 }
664 RootAction::CanQuit(sender) => {
666 let ret = imp.can_quit().await;
667 sender.send(ret).unwrap();
668 }
669 RootAction::Fullscreen(sender) => {
670 let ret = imp.fullscreen().await;
671 sender.send(ret).unwrap();
672 }
673 RootAction::SetFullscreen(fullscreen, sender) => {
674 let ret = imp.set_fullscreen(fullscreen).await;
675 sender.send(ret).unwrap();
676 }
677 RootAction::CanSetFullScreen(sender) => {
678 let ret = imp.can_set_fullscreen().await;
679 sender.send(ret).unwrap();
680 }
681 RootAction::CanRaise(sender) => {
682 let ret = imp.can_raise().await;
683 sender.send(ret).unwrap();
684 }
685 RootAction::HasTrackList(sender) => {
686 let ret = imp.has_track_list().await;
687 sender.send(ret).unwrap();
688 }
689 RootAction::Identity(sender) => {
690 let ret = imp.identity().await;
691 sender.send(ret).unwrap();
692 }
693 RootAction::DesktopEntry(sender) => {
694 let ret = imp.desktop_entry().await;
695 sender.send(ret).unwrap();
696 }
697 RootAction::SupportedUriSchemes(sender) => {
698 let ret = imp.supported_uri_schemes().await;
699 sender.send(ret).unwrap();
700 }
701 RootAction::SupportedMimeTypes(sender) => {
702 let ret = imp.supported_mime_types().await;
703 sender.send(ret).unwrap();
704 }
705 }
706 }
707
708 async fn handle_player_action(imp: &T, action: PlayerAction) {
709 match action {
710 PlayerAction::Next(sender) => {
712 let ret = imp.next().await;
713 sender.send(ret).unwrap();
714 }
715 PlayerAction::Previous(sender) => {
716 let ret = imp.previous().await;
717 sender.send(ret).unwrap();
718 }
719 PlayerAction::Pause(sender) => {
720 let ret = imp.pause().await;
721 sender.send(ret).unwrap();
722 }
723 PlayerAction::PlayPause(sender) => {
724 let ret = imp.play_pause().await;
725 sender.send(ret).unwrap();
726 }
727 PlayerAction::Stop(sender) => {
728 let ret = imp.stop().await;
729 sender.send(ret).unwrap();
730 }
731 PlayerAction::Play(sender) => {
732 let ret = imp.play().await;
733 sender.send(ret).unwrap();
734 }
735 PlayerAction::Seek(offset, sender) => {
736 let ret = imp.seek(offset).await;
737 sender.send(ret).unwrap();
738 }
739 PlayerAction::SetPosition(track_id, position, sender) => {
740 let ret = imp.set_position(track_id, position).await;
741 sender.send(ret).unwrap();
742 }
743 PlayerAction::OpenUri(uri, sender) => {
744 let ret = imp.open_uri(uri).await;
745 sender.send(ret).unwrap();
746 }
747 PlayerAction::PlaybackStatus(sender) => {
749 let ret = imp.playback_status().await;
750 sender.send(ret).unwrap();
751 }
752 PlayerAction::LoopStatus(sender) => {
753 let ret = imp.loop_status().await;
754 sender.send(ret).unwrap();
755 }
756 PlayerAction::SetLoopStatus(loop_status, sender) => {
757 let ret = imp.set_loop_status(loop_status).await;
758 sender.send(ret).unwrap();
759 }
760 PlayerAction::Rate(sender) => {
761 let ret = imp.rate().await;
762 sender.send(ret).unwrap();
763 }
764 PlayerAction::SetRate(rate, sender) => {
765 let ret = imp.set_rate(rate).await;
766 sender.send(ret).unwrap();
767 }
768 PlayerAction::Shuffle(sender) => {
769 let ret = imp.shuffle().await;
770 sender.send(ret).unwrap();
771 }
772 PlayerAction::SetShuffle(shuffle, sender) => {
773 let ret = imp.set_shuffle(shuffle).await;
774 sender.send(ret).unwrap();
775 }
776 PlayerAction::Metadata(sender) => {
777 let ret = imp.metadata().await;
778 sender.send(ret).unwrap();
779 }
780 PlayerAction::Volume(sender) => {
781 let ret = imp.volume().await;
782 sender.send(ret).unwrap();
783 }
784 PlayerAction::SetVolume(volume, sender) => {
785 let ret = imp.set_volume(volume).await;
786 sender.send(ret).unwrap();
787 }
788 PlayerAction::Position(sender) => {
789 let ret = imp.position().await;
790 sender.send(ret).unwrap();
791 }
792 PlayerAction::MinimumRate(sender) => {
793 let ret = imp.minimum_rate().await;
794 sender.send(ret).unwrap();
795 }
796 PlayerAction::MaximumRate(sender) => {
797 let ret = imp.maximum_rate().await;
798 sender.send(ret).unwrap();
799 }
800 PlayerAction::CanGoNext(sender) => {
801 let ret = imp.can_go_next().await;
802 sender.send(ret).unwrap();
803 }
804 PlayerAction::CanGoPrevious(sender) => {
805 let ret = imp.can_go_previous().await;
806 sender.send(ret).unwrap();
807 }
808 PlayerAction::CanPlay(sender) => {
809 let ret = imp.can_play().await;
810 sender.send(ret).unwrap();
811 }
812 PlayerAction::CanPause(sender) => {
813 let ret = imp.can_pause().await;
814 sender.send(ret).unwrap();
815 }
816 PlayerAction::CanSeek(sender) => {
817 let ret = imp.can_seek().await;
818 sender.send(ret).unwrap();
819 }
820 PlayerAction::CanControl(sender) => {
821 let ret = imp.can_control().await;
822 sender.send(ret).unwrap();
823 }
824 }
825 }
826
827 async fn new_inner<'a, SR, RR>(
828 bus_name_suffix: &'a str,
829 imp: T,
830 server_func: impl FnOnce(&'a str, InnerImp<T>) -> SR + 'static,
831 runner_func: impl FnOnce(Receiver<Action>, Rc<T>) -> RR + 'static,
832 ) -> Result<Self>
833 where
834 SR: Future<Output = Result<Server<InnerImp<T>>>>,
835 RR: Future<Output = ()> + 'static,
836 {
837 let (tx, rx) = async_channel::bounded(1);
838
839 let inner = server_func(
840 bus_name_suffix,
841 InnerImp {
842 tx,
843 imp_ty: PhantomData,
844 },
845 )
846 .await?;
847
848 let imp = Rc::new(imp);
849 let runner = Box::pin(runner_func(rx, Rc::clone(&imp)));
850
851 Ok(Self {
852 inner,
853 imp,
854 runner: RefCell::new(Some(runner)),
855 })
856 }
857}
858
859impl<T> LocalServer<T>
860where
861 T: LocalTrackListInterface + 'static,
862{
863 pub async fn new_with_track_list(bus_name_suffix: &str, imp: T) -> Result<Self> {
871 Self::new_inner(
872 bus_name_suffix,
873 imp,
874 Server::new_with_track_list,
875 |rx, imp| async move {
876 while let Ok(action) = rx.recv().await {
877 match action {
878 Action::Root(action) => Self::handle_root_action(&imp, action).await,
879 Action::Player(action) => Self::handle_player_action(&imp, action).await,
880 Action::TrackList(action) => {
881 Self::handle_track_list_action(&imp, action).await
882 }
883 Action::Playlists(_) => unreachable!(),
884 }
885 }
886 },
887 )
888 .await
889 }
890
891 #[inline]
893 pub async fn track_list_emit(&self, signal: TrackListSignal) -> Result<()> {
894 self.inner.track_list_emit(signal).await
895 }
896
897 #[inline]
902 pub async fn track_list_properties_changed(
903 &self,
904 properties: impl IntoIterator<Item = TrackListProperty>,
905 ) -> Result<()> {
906 self.inner.track_list_properties_changed(properties).await
907 }
908
909 async fn handle_track_list_action(imp: &T, action: TrackListAction) {
910 match action {
911 TrackListAction::GetTracksMetadata(track_ids, sender) => {
913 let ret = imp.get_tracks_metadata(track_ids).await;
914 sender.send(ret).unwrap();
915 }
916 TrackListAction::AddTrack(uri, after_track, set_as_current, sender) => {
917 let ret = imp.add_track(uri, after_track, set_as_current).await;
918 sender.send(ret).unwrap();
919 }
920 TrackListAction::RemoveTrack(track_id, sender) => {
921 let ret = imp.remove_track(track_id).await;
922 sender.send(ret).unwrap();
923 }
924 TrackListAction::GoTo(track_id, sender) => {
925 let ret = imp.go_to(track_id).await;
926 sender.send(ret).unwrap();
927 }
928 TrackListAction::Tracks(sender) => {
930 let ret = imp.tracks().await;
931 sender.send(ret).unwrap();
932 }
933 TrackListAction::CanEditTracks(sender) => {
934 let ret = imp.can_edit_tracks().await;
935 sender.send(ret).unwrap();
936 }
937 }
938 }
939}
940
941impl<T> LocalServer<T>
942where
943 T: LocalPlaylistsInterface + 'static,
944{
945 pub async fn new_with_playlists(bus_name_suffix: &str, imp: T) -> Result<Self> {
953 Self::new_inner(
954 bus_name_suffix,
955 imp,
956 Server::new_with_playlists,
957 |rx, imp| async move {
958 while let Ok(action) = rx.recv().await {
959 match action {
960 Action::Root(action) => Self::handle_root_action(&imp, action).await,
961 Action::Player(action) => Self::handle_player_action(&imp, action).await,
962 Action::Playlists(action) => {
963 Self::handle_playlists_action(&imp, action).await
964 }
965 Action::TrackList(_) => unreachable!(),
966 }
967 }
968 },
969 )
970 .await
971 }
972
973 #[inline]
975 pub async fn playlists_emit(&self, signal: PlaylistsSignal) -> Result<()> {
976 self.inner.playlists_emit(signal).await
977 }
978
979 #[inline]
984 pub async fn playlists_properties_changed(
985 &self,
986 properties: impl IntoIterator<Item = PlaylistsProperty>,
987 ) -> Result<()> {
988 self.inner.playlists_properties_changed(properties).await
989 }
990
991 async fn handle_playlists_action(imp: &T, action: PlaylistsAction) {
992 match action {
993 PlaylistsAction::ActivatePlaylist(playlist_id, sender) => {
994 let ret = imp.activate_playlist(playlist_id).await;
995 sender.send(ret).unwrap();
996 }
997 PlaylistsAction::GetPlaylists(index, max_count, order, reverse_order, sender) => {
998 let ret = imp
999 .get_playlists(index, max_count, order, reverse_order)
1000 .await;
1001 sender.send(ret).unwrap();
1002 }
1003 PlaylistsAction::PlaylistCount(sender) => {
1004 let ret = imp.playlist_count().await;
1005 sender.send(ret).unwrap();
1006 }
1007 PlaylistsAction::Orderings(sender) => {
1008 let ret = imp.orderings().await;
1009 sender.send(ret).unwrap();
1010 }
1011 PlaylistsAction::ActivePlaylist(sender) => {
1012 let ret = imp.active_playlist().await;
1013 sender.send(ret).unwrap();
1014 }
1015 }
1016 }
1017}
1018
1019impl<T> LocalServer<T>
1020where
1021 T: LocalTrackListInterface + LocalPlaylistsInterface + 'static,
1022{
1023 pub async fn new_with_all(bus_name_suffix: &str, imp: T) -> Result<Self> {
1032 Self::new_inner(
1033 bus_name_suffix,
1034 imp,
1035 Server::new_with_all,
1036 |rx, imp| async move {
1037 while let Ok(action) = rx.recv().await {
1038 match action {
1039 Action::Root(action) => Self::handle_root_action(&imp, action).await,
1040 Action::Player(action) => Self::handle_player_action(&imp, action).await,
1041 Action::Playlists(action) => {
1042 Self::handle_playlists_action(&imp, action).await
1043 }
1044 Action::TrackList(action) => {
1045 Self::handle_track_list_action(&imp, action).await
1046 }
1047 }
1048 }
1049 },
1050 )
1051 .await
1052 }
1053}
1054
1055#[cfg(test)]
1056mod tests {
1057 use static_assertions::{assert_impl_all, assert_not_impl_any};
1058
1059 use super::LocalServer;
1060
1061 #[allow(dead_code)]
1062 pub struct TestPlayer;
1063
1064 assert_not_impl_any!(LocalServer<TestPlayer>: Send, Sync);
1065 assert_impl_all!(LocalServer<TestPlayer>: Unpin);
1066}