blob: 4162c0ad96bf09c9c22101050bb74aa9ca5bdc5b [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::audio::types::AudioMethod;
use crate::server::Facade;
use anyhow::{Context, Error};
use async_trait::async_trait;
use base64;
use fidl_fuchsia_test_audio_recording::{AudioRecordingControlMarker, AudioRecordingControlProxy};
use fuchsia_component::client::connect_to_protocol;
use fuchsia_syslog::macros::fx_log_info;
use serde_json::{to_value, Value};
use std::convert::TryInto;
#[async_trait(?Send)]
impl Facade for AudioFacade {
async fn handle_request(&self, method: String, args: Value) -> Result<Value, Error> {
match method.parse()? {
AudioMethod::PutInputAudio => self.put_input_audio(args).await,
AudioMethod::StartInputInjection => self.start_input_injection(args).await,
AudioMethod::StopInputInjection => self.stop_input_injection().await,
AudioMethod::StartOutputSave => self.start_output_save().await,
AudioMethod::StopOutputSave => self.stop_output_save().await,
AudioMethod::GetOutputAudio => self.get_output_audio().await,
}
}
}
#[derive(Debug)]
pub struct AudioFacade {
audio_proxy: AudioRecordingControlProxy,
}
impl AudioFacade {
pub fn new() -> Result<AudioFacade, Error> {
fx_log_info!("Launching audio_recording component");
let audio_proxy = connect_to_protocol::<AudioRecordingControlMarker>()?;
Ok(AudioFacade { audio_proxy })
}
pub async fn put_input_audio(&self, args: Value) -> Result<Value, Error> {
let data = args.get("data").ok_or(format_err!("PutInputAudio failed, no data"))?;
let data = data.as_str().ok_or(format_err!("PutInputAudio failed, data not string"))?;
let wave_data_vec = base64::decode(data)?;
let max_buffer_bytes = 8192;
let wave_data_iter: Vec<&[u8]> = wave_data_vec.chunks(max_buffer_bytes).collect();
let mut byte_cnt = 0;
let sample_index = args["index"].as_u64().ok_or(format_err!("index not a number"))?;
let sample_index = sample_index.try_into()?;
let _ = self
.audio_proxy
.clear_input_audio(sample_index)
.await
.context("Error calling put_input_audio")?;
for chunk in wave_data_iter {
byte_cnt += self
.audio_proxy
.put_input_audio(sample_index, &chunk)
.await
.context("Error calling put_input_audio")?;
}
Ok(to_value(byte_cnt)?)
}
pub async fn start_input_injection(&self, args: Value) -> Result<Value, Error> {
let sample_index = args["index"].as_u64().ok_or(format_err!("index not a number"))?;
let sample_index = sample_index.try_into()?;
let status = self
.audio_proxy
.start_input_injection(sample_index)
.await
.context("Error calling put_input_audio")?;
match status {
Ok(_) => return Ok(to_value(true)?),
Err(_) => return Ok(to_value(false)?),
}
}
pub async fn stop_input_injection(&self) -> Result<Value, Error> {
let status = self
.audio_proxy
.stop_input_injection()
.await
.context("Error calling stop_input_injection")?;
match status {
Ok(_) => return Ok(to_value(true)?),
Err(_) => return Ok(to_value(false)?),
}
}
pub async fn start_output_save(&self) -> Result<Value, Error> {
let status = self
.audio_proxy
.start_output_save()
.await
.context("Error calling start_output_save")?;
match status {
Ok(_) => return Ok(to_value(true)?),
Err(_) => return Ok(to_value(false)?),
}
}
pub async fn stop_output_save(&self) -> Result<Value, Error> {
let status =
self.audio_proxy.stop_output_save().await.context("Error calling stop_output_save")?;
match status {
Ok(_) => return Ok(to_value(true)?),
Err(_) => return Ok(to_value(false)?),
}
}
pub async fn get_output_audio(&self) -> Result<Value, Error> {
let result =
self.audio_proxy.get_output_audio().await.context("Error calling get_output_audio")?;
let buffer_size = result.get_size()?;
let mut buffer = vec![0; buffer_size.try_into().unwrap()];
result.read(&mut buffer, 0)?;
Ok(to_value(base64::encode(&buffer))?)
}
}