Split outputs into virtual cam and replay buffer

v5-api
Dominik Nakamura 2 years ago
parent b237b8b471
commit db12a54e72
No known key found for this signature in database
GPG Key ID: E4C6A749B2491910

@ -30,10 +30,10 @@ use tracing::{debug, error, info, trace};
use self::connection::{ReceiverList, ReidentifyReceiverList};
pub use self::{
config::Config, connection::HandshakeError, filters::Filters, general::General,
hotkeys::Hotkeys, inputs::Inputs, media_inputs::MediaInputs, outputs::Outputs,
profiles::Profiles, recording::Recording, scene_collections::SceneCollections,
hotkeys::Hotkeys, inputs::Inputs, media_inputs::MediaInputs, profiles::Profiles,
recording::Recording, replay_buffer::ReplayBuffer, scene_collections::SceneCollections,
scene_items::SceneItems, scenes::Scenes, sources::Sources, streaming::Streaming,
transitions::Transitions, ui::Ui,
transitions::Transitions, ui::Ui, virtual_cam::VirtualCam,
};
#[cfg(feature = "events")]
use crate::events::Event;
@ -50,9 +50,9 @@ mod general;
mod hotkeys;
mod inputs;
mod media_inputs;
mod outputs;
mod profiles;
mod recording;
mod replay_buffer;
mod scene_collections;
mod scene_items;
mod scenes;
@ -60,6 +60,7 @@ mod sources;
mod streaming;
mod transitions;
mod ui;
mod virtual_cam;
#[derive(Debug, thiserror::Error)]
enum InnerError {
@ -481,11 +482,6 @@ impl Client {
MediaInputs { client: self }
}
/// Access API functions related to outputs.
pub fn outputs(&self) -> Outputs<'_> {
Outputs { client: self }
}
/// Access API functions related to profiles.
pub fn profiles(&self) -> Profiles<'_> {
Profiles { client: self }
@ -496,6 +492,11 @@ impl Client {
Recording { client: self }
}
/// Access API functions related to the replay buffer.
pub fn replay_buffer(&self) -> ReplayBuffer<'_> {
ReplayBuffer { client: self }
}
/// Access API functions related to scene collections.
pub fn scene_collections(&self) -> SceneCollections<'_> {
SceneCollections { client: self }
@ -530,6 +531,11 @@ impl Client {
pub fn ui(&self) -> Ui<'_> {
Ui { client: self }
}
/// Access API functions related to the virtual camera.
pub fn virtual_cam(&self) -> VirtualCam<'_> {
VirtualCam { client: self }
}
}
impl Drop for Client {

@ -1,74 +0,0 @@
use super::Client;
use crate::{requests::outputs::Request, responses, Result};
/// API functions related to outputs.
pub struct Outputs<'a> {
pub(super) client: &'a Client,
}
impl<'a> Outputs<'a> {
/// Gets the status of the virtual cam output.
pub async fn virtual_cam_status(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::VirtualCamStatus)
.await
.map(|oa| oa.active)
}
/// Toggles the state of the virtual cam output.
pub async fn toggle_virtual_cam(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::ToggleVirtualCam)
.await
.map(|oa| oa.active)
}
/// Starts the virtual cam output.
pub async fn start_virtual_cam(&self) -> Result<()> {
self.client.send_message(Request::StartVirtualCam).await
}
/// Stops the virtual cam output.
pub async fn stop_virtual_cam(&self) -> Result<()> {
self.client.send_message(Request::StopVirtualCam).await
}
/// Gets the status of the replay buffer output.
pub async fn replay_buffer_status(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::ReplayBufferStatus)
.await
.map(|oa| oa.active)
}
/// Toggles the state of the replay buffer output.
pub async fn toggle_replay_buffer(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::ToggleReplayBuffer)
.await
.map(|oa| oa.active)
}
/// Starts the replay buffer output.
pub async fn start_replay_buffer(&self) -> Result<()> {
self.client.send_message(Request::StartReplayBuffer).await
}
/// Stops the replay buffer output.
pub async fn stop_replay_buffer(&self) -> Result<()> {
self.client.send_message(Request::StopReplayBuffer).await
}
/// Saves the contents of the replay buffer output.
pub async fn save_replay_buffer(&self) -> Result<()> {
self.client.send_message(Request::SaveReplayBuffer).await
}
/// Gets the file name of the last replay buffer save file.
pub async fn last_replay_buffer_replay(&self) -> Result<String> {
self.client
.send_message::<_, responses::SavedReplayPath>(Request::LastReplayBufferReplay)
.await
.map(|srp| srp.saved_replay_path)
}
}

@ -0,0 +1,48 @@
use super::Client;
use crate::{requests::replay_buffer::Request, responses, Result};
/// API functions related to the replay buffer.
pub struct ReplayBuffer<'a> {
pub(super) client: &'a Client,
}
impl<'a> ReplayBuffer<'a> {
/// Gets the status of the replay buffer output.
pub async fn status(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::Status)
.await
.map(|oa| oa.active)
}
/// Toggles the state of the replay buffer output.
pub async fn toggle(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::Toggle)
.await
.map(|oa| oa.active)
}
/// Starts the replay buffer output.
pub async fn start(&self) -> Result<()> {
self.client.send_message(Request::Start).await
}
/// Stops the replay buffer output.
pub async fn stop(&self) -> Result<()> {
self.client.send_message(Request::Stop).await
}
/// Saves the contents of the replay buffer output.
pub async fn save(&self) -> Result<()> {
self.client.send_message(Request::Save).await
}
/// Gets the file name of the last replay buffer save file.
pub async fn last_replay(&self) -> Result<String> {
self.client
.send_message::<_, responses::SavedReplayPath>(Request::LastReplay)
.await
.map(|srp| srp.saved_replay_path)
}
}

@ -0,0 +1,35 @@
use super::Client;
use crate::{requests::virtual_cam::Request, responses, Result};
/// API functions related to the virtual camera.
pub struct VirtualCam<'a> {
pub(super) client: &'a Client,
}
impl<'a> VirtualCam<'a> {
/// Gets the status of the virtual cam output.
pub async fn status(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::Status)
.await
.map(|oa| oa.active)
}
/// Toggles the state of the virtual cam output.
pub async fn toggle(&self) -> Result<bool> {
self.client
.send_message::<_, responses::OutputActive>(Request::Toggle)
.await
.map(|oa| oa.active)
}
/// Starts the virtual cam output.
pub async fn start(&self) -> Result<()> {
self.client.send_message(Request::Start).await
}
/// Stops the virtual cam output.
pub async fn stop(&self) -> Result<()> {
self.client.send_message(Request::Stop).await
}
}

@ -12,9 +12,9 @@ pub mod general;
pub mod hotkeys;
pub mod inputs;
pub(crate) mod media_inputs;
pub(crate) mod outputs;
pub mod profiles;
pub(crate) mod recording;
pub(crate) mod replay_buffer;
pub(crate) mod scene_collections;
pub mod scene_items;
pub mod scenes;
@ -23,6 +23,7 @@ pub mod sources;
pub(crate) mod streaming;
pub(crate) mod transitions;
pub(crate) mod ui;
pub(crate) mod virtual_cam;
pub(crate) enum ClientRequest<'a> {
/// Response to [`crate::responses::ServerMessage::Hello`] message, should contain
@ -215,9 +216,9 @@ pub(crate) enum RequestType<'a> {
Hotkeys(self::hotkeys::Request<'a>),
Inputs(self::inputs::Request<'a>),
MediaInputs(self::media_inputs::Request<'a>),
Outputs(self::outputs::Request),
Profiles(self::profiles::Request<'a>),
Recording(self::recording::Request),
ReplayBuffer(self::replay_buffer::Request),
SceneCollections(self::scene_collections::Request<'a>),
SceneItems(self::scene_items::Request<'a>),
Scenes(self::scenes::Request<'a>),
@ -225,6 +226,7 @@ pub(crate) enum RequestType<'a> {
Streaming(self::streaming::Request<'a>),
Transitions(self::transitions::Request<'a>),
Ui(self::ui::Request<'a>),
VirtualCam(self::virtual_cam::Request),
}
impl<'a> Serialize for RequestType<'a> {
@ -239,9 +241,9 @@ impl<'a> Serialize for RequestType<'a> {
Self::Hotkeys(req) => req.serialize(serializer),
Self::Inputs(req) => req.serialize(serializer),
Self::MediaInputs(req) => req.serialize(serializer),
Self::Outputs(req) => req.serialize(serializer),
Self::Profiles(req) => req.serialize(serializer),
Self::Recording(req) => req.serialize(serializer),
Self::ReplayBuffer(req) => req.serialize(serializer),
Self::SceneCollections(req) => req.serialize(serializer),
Self::SceneItems(req) => req.serialize(serializer),
Self::Scenes(req) => req.serialize(serializer),
@ -249,6 +251,7 @@ impl<'a> Serialize for RequestType<'a> {
Self::Streaming(req) => req.serialize(serializer),
Self::Transitions(req) => req.serialize(serializer),
Self::Ui(req) => req.serialize(serializer),
Self::VirtualCam(req) => req.serialize(serializer),
}
}
}

@ -5,30 +5,22 @@ use serde::Serialize;
#[derive(Serialize)]
#[serde(tag = "requestType", content = "requestData")]
pub(crate) enum Request {
#[serde(rename = "GetVirtualCamStatus")]
VirtualCamStatus,
#[serde(rename = "ToggleVirtualCam")]
ToggleVirtualCam,
#[serde(rename = "StartVirtualCam")]
StartVirtualCam,
#[serde(rename = "StopVirtualCam")]
StopVirtualCam,
#[serde(rename = "GetReplayBufferStatus")]
ReplayBufferStatus,
Status,
#[serde(rename = "ToggleReplayBuffer")]
ToggleReplayBuffer,
Toggle,
#[serde(rename = "StartReplayBuffer")]
StartReplayBuffer,
Start,
#[serde(rename = "StopReplayBuffer")]
StopReplayBuffer,
Stop,
#[serde(rename = "SaveReplayBuffer")]
SaveReplayBuffer,
Save,
#[serde(rename = "GetLastReplayBufferReplay")]
LastReplayBufferReplay,
LastReplay,
}
impl<'a> From<Request> for super::RequestType<'a> {
fn from(value: Request) -> Self {
super::RequestType::Outputs(value)
super::RequestType::ReplayBuffer(value)
}
}

@ -0,0 +1,22 @@
//! Requests related to the virtual camera.
use serde::Serialize;
#[derive(Serialize)]
#[serde(tag = "requestType", content = "requestData")]
pub(crate) enum Request {
#[serde(rename = "GetVirtualCamStatus")]
Status,
#[serde(rename = "ToggleVirtualCam")]
Toggle,
#[serde(rename = "StartVirtualCam")]
Start,
#[serde(rename = "StopVirtualCam")]
Stop,
}
impl<'a> From<Request> for super::RequestType<'a> {
fn from(value: Request) -> Self {
super::RequestType::VirtualCam(value)
}
}

@ -138,13 +138,13 @@ async fn ensure_obs_setup(client: &Client) -> Result<()> {
"recording active, required to be stopped for recording tests"
);
let virtual_cam_active = client.outputs().virtual_cam_status().await?;
let virtual_cam_active = client.virtual_cam().status().await?;
ensure!(
!virtual_cam_active,
"virtual cam active, required to be stopped for outputs tests"
);
let replay_buffer_active = client.outputs().replay_buffer_status().await?;
let replay_buffer_active = client.replay_buffer().status().await?;
ensure!(
!replay_buffer_active,
"replay buffer active, required to be stopped for outputs tests"

@ -4,7 +4,7 @@ use obws::requests::hotkeys::KeyModifiers;
use crate::common;
#[tokio::test]
async fn general() -> Result<()> {
async fn hotkeys() -> Result<()> {
let client = common::new_client().await?;
let client = client.hotkeys();

@ -7,9 +7,9 @@ mod general;
mod hotkeys;
mod inputs;
mod media_inputs;
mod outputs;
mod profiles;
mod recording;
mod replay_buffer;
mod scene_collections;
mod scene_items;
mod scenes;
@ -17,3 +17,4 @@ mod sources;
mod streaming;
mod transitions;
mod ui;
mod virtual_cam;

@ -1,100 +0,0 @@
#![cfg(feature = "test-integration")]
use std::time::Duration;
use anyhow::Result;
use obws::events::{Event, OutputState};
use tokio::time;
use crate::{common, wait_for};
#[tokio::test]
async fn outputs() -> Result<()> {
let client = common::new_client().await?;
let events = client.events()?;
let client = client.outputs();
tokio::pin!(events);
client.virtual_cam_status().await?;
client.toggle_virtual_cam().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.toggle_virtual_cam().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.start_virtual_cam().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.stop_virtual_cam().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.replay_buffer_status().await?;
client.toggle_replay_buffer().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.toggle_replay_buffer().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.start_replay_buffer().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.save_replay_buffer().await?;
client.last_replay_buffer_replay().await?;
client.stop_replay_buffer().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
Ok(())
}

@ -0,0 +1,61 @@
#![cfg(feature = "test-integration")]
use std::time::Duration;
use anyhow::Result;
use obws::events::{Event, OutputState};
use tokio::time;
use crate::{common, wait_for};
#[tokio::test]
async fn replay_buffer() -> Result<()> {
let client = common::new_client().await?;
let events = client.events()?;
let client = client.replay_buffer();
tokio::pin!(events);
client.status().await?;
client.toggle().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.toggle().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.start().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.save().await?;
client.last_replay().await?;
client.stop().await?;
wait_for!(
events,
Event::ReplayBufferStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
Ok(())
}

@ -0,0 +1,59 @@
#![cfg(feature = "test-integration")]
use std::time::Duration;
use anyhow::Result;
use obws::events::{Event, OutputState};
use tokio::time;
use crate::{common, wait_for};
#[tokio::test]
async fn virtual_cam() -> Result<()> {
let client = common::new_client().await?;
let events = client.events()?;
let client = client.virtual_cam();
tokio::pin!(events);
client.status().await?;
client.toggle().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.toggle().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.start().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Started,
..
}
);
time::sleep(Duration::from_secs(1)).await;
client.stop().await?;
wait_for!(
events,
Event::VirtualcamStateChanged {
state: OutputState::Stopped,
..
}
);
time::sleep(Duration::from_secs(1)).await;
Ok(())
}
Loading…
Cancel
Save