blob: d7542c6c5fe1ed30d15adb393cdafc15d75a6f76 [file] [log] [blame]
#![feature(async_await, await_macro)]
#![recursion_limit = "1024"]
use failure::Error;
use fidl::endpoints::create_endpoints;
use fidl_fuchsia_media_sessions::*;
use fuchsia_async as fasync;
use fuchsia_component as component;
use fuchsia_zircon::AsHandleRef;
use futures::prelude::*;
use futures::{
channel::mpsc::{channel, Receiver},
executor, select,
};
use std::io::{self, BufRead};
const HELP_TEXT: &str =
r"This is a small utility that prints out active session changes as they occur in
the Media Session service and can send basic commands to the active session.
Commands:
play
pause
stop
";
#[allow(unused)]
enum Never {}
type Result<T> = std::result::Result<T, Error>;
const CHANNEL_BUFFER_SIZE: usize = 10;
fn stdin_lines() -> Result<Receiver<String>> {
let (mut line_sender, line_receiver) = channel(CHANNEL_BUFFER_SIZE);
std::thread::spawn(move || {
executor::block_on(
async move {
for line in io::stdin().lock().lines() {
let line = String::from(line.expect("Stdin line.").trim());
if let Err(e) = await!(line_sender.send(line)) {
eprintln!("Media Session Service task died: {:?}", e);
}
}
},
)
});
Ok(line_receiver)
}
async fn control_active_session(
registry_proxy: RegistryProxy,
mut control_receiver: Receiver<PlaybackState>,
) -> Result<Never> {
let mut event_stream = registry_proxy.take_event_stream();
let mut active_session = None;
loop {
select! {
event = event_stream.select_next_some() => {
match event? {
RegistryEvent::OnActiveSessionChanged {
active_session: new_active_session
} => {
if let Some(session_id) = new_active_session.session_id {
let (client_end, server_end) = create_endpoints()?;
let koid = session_id.as_handle_ref().get_koid()?;
registry_proxy.connect_to_session_by_id(session_id, server_end)?;
let session_proxy = client_end.into_proxy()?;
let mut session_events = session_proxy.take_event_stream();
fasync::spawn(async move {
while let Ok(Some(event)) = await!(session_events.try_next()) {
println!("Active session event:");
println!("{:#?}", event);
}
});
active_session = Some(session_proxy);
println!("Active session is now {:?}.", koid);
} else {
println!("There is no active session.");
active_session = None;
}
registry_proxy.notify_active_session_change_handled()?;
}
RegistryEvent::OnSessionsChanged { sessions_change } => {
println!("Sessions collection changed: {:?}", sessions_change);
registry_proxy.notify_sessions_change_handled()?;
}
}
}
new_state = control_receiver.select_next_some() => {
if let Some(ref proxy) = &active_session {
match new_state {
PlaybackState::Paused => proxy.pause()?,
PlaybackState::Playing => proxy.play()?,
PlaybackState::Stopped => proxy.pause()?,
_ => (),
}
} else {
println!("There is no active session to control.");
}
}
}
}
}
#[fasync::run_singlethreaded]
async fn main() -> Result<()> {
let registry_proxy = component::client::connect_to_service::<RegistryMarker>()?;
let line_receiver = stdin_lines()?;
let mut line_feed = line_receiver
.take_while(|line| future::ready(line.as_str() != "quit"))
.filter_map(|line| {
future::ready(match line.as_str() {
"pause" => Some(PlaybackState::Paused),
"play" => Some(PlaybackState::Playing),
"stop" => Some(PlaybackState::Stopped),
_ => {
println!("Unrecognized commmand.");
println!("{}", HELP_TEXT);
None
}
})
});
let (mut control_sender, control_receiver) = channel(CHANNEL_BUFFER_SIZE);
fasync::spawn(
control_active_session(registry_proxy, control_receiver)
.map_err(|e| eprintln!("{:?}", e))
.map(|_| ()),
);
println!("{}", HELP_TEXT);
await!(control_sender.send_all(&mut line_feed).map_err(|e| eprintln!("{:?}", e)).map(|_| ()));
Ok(())
}