Upgrade to obs-websocket 4.9.1 API

pull/14/head
Dominik Nakamura 3 years ago
parent 7c79c5b20b
commit b6e5835a64
No known key found for this signature in database
GPG Key ID: E4C6A749B2491910

@ -121,4 +121,5 @@ impl<'a> General<'a> {
}
// TODO: Add `ExecuteBatch` request
// TODO: Add `Sleep` request (only useful together with `ExecuteBatch`)
}

@ -15,7 +15,11 @@ impl<'a> MediaControl<'a> {
///
/// - `source_name`: Source name.
/// - `play_pause`: Whether to pause or play the source. `false` for play, `true` for pause.
pub async fn play_pause_media(&self, source_name: &str, play_pause: bool) -> Result<()> {
pub async fn play_pause_media(
&self,
source_name: &str,
play_pause: Option<bool>,
) -> Result<()> {
self.client
.send_message(RequestType::PlayPauseMedia {
source_name,

@ -41,7 +41,7 @@ pub use self::{
general::General, media_control::MediaControl, outputs::Outputs, profiles::Profiles,
recording::Recording, replay_buffer::ReplayBuffer, scene_collections::SceneCollections,
scene_items::SceneItems, scenes::Scenes, sources::Sources, streaming::Streaming,
studio_mode::StudioMode, transitions::Transitions,
studio_mode::StudioMode, transitions::Transitions, virtual_cam::VirtualCam,
};
mod general;
@ -57,6 +57,7 @@ mod sources;
mod streaming;
mod studio_mode;
mod transitions;
mod virtual_cam;
#[derive(Debug, thiserror::Error)]
enum InnerError {
@ -121,8 +122,8 @@ where
const OBS_STUDIO_VERSION: Comparator = Comparator {
op: Op::GreaterEq,
major: 26,
minor: Some(1),
major: 27,
minor: None,
patch: None,
pre: Prerelease::EMPTY,
};
@ -130,7 +131,7 @@ const OBS_WEBSOCKET_VERSION: Comparator = Comparator {
op: Op::Tilde,
major: 4,
minor: Some(9),
patch: None,
patch: Some(1),
pre: Prerelease::EMPTY,
};
@ -468,6 +469,11 @@ impl Client {
pub fn transitions(&self) -> Transitions<'_> {
Transitions { client: self }
}
/// Access API functions related to the virtual cam.
pub fn virtual_cam(&self) -> VirtualCam<'_> {
VirtualCam { client: self }
}
}
fn extract_error(value: &mut serde_json::Value) -> Option<String> {
@ -490,23 +496,3 @@ impl Drop for Client {
drop(self.disconnect());
}
}
#[cfg(test)]
mod tests {
use semver::Version;
use super::*;
#[test]
fn verify_version_req() {
assert!(OBS_STUDIO_VERSION.matches(&Version::new(26, 1, 0)));
assert!(OBS_STUDIO_VERSION.matches(&Version::new(26, 1, 100)));
assert!(OBS_STUDIO_VERSION.matches(&Version::new(26, 100, 100)));
assert!(OBS_STUDIO_VERSION.matches(&Version::new(27, 0, 0)));
assert!(OBS_WEBSOCKET_VERSION.matches(&Version::new(4, 9, 0)));
assert!(OBS_WEBSOCKET_VERSION.matches(&Version::new(4, 9, 100)));
assert!(!OBS_WEBSOCKET_VERSION.matches(&Version::new(4, 100, 100)));
assert!(!OBS_WEBSOCKET_VERSION.matches(&Version::new(5, 0, 0)));
}
}

@ -103,6 +103,16 @@ impl<'a> Sources<'a> {
.await
}
/// Get the source's active status of a specified source (if it is showing in the final mix).
///
/// - `source_name`: Source name.
pub async fn get_source_active(&self, source_name: &str) -> Result<bool> {
self.client
.send_message::<responses::SourceActive>(RequestType::GetSourceActive { source_name })
.await
.map(|sa| sa.source_active)
}
/// Get the audio's active status of a specified source.
///
/// - `source_name`: Source name.

@ -0,0 +1,35 @@
use super::Client;
use crate::requests::RequestType;
use crate::responses;
use crate::Result;
/// API functions related to the virtual cam.
pub struct VirtualCam<'a> {
pub(super) client: &'a Client,
}
impl<'a> VirtualCam<'a> {
/// Get current virtual cam status.
pub async fn get_virtual_cam_status(&self) -> Result<responses::VirtualCamStatus> {
self.client
.send_message(RequestType::GetVirtualCamStatus)
.await
}
/// Toggle virtual cam on or off (depending on the current virtual cam state).
pub async fn start_stop_virtual_cam(&self) -> Result<()> {
self.client
.send_message(RequestType::StartStopVirtualCam)
.await
}
/// Start virtual cam. Will return an `error` if virtual cam is already active.
pub async fn start_virtual_cam(&self) -> Result<()> {
self.client.send_message(RequestType::StartVirtualCam).await
}
/// Stop virtual cam. Will return an error if virtual cam is not active.
pub async fn stop_virtual_cam(&self) -> Result<()> {
self.client.send_message(RequestType::StopVirtualCam).await
}
}

@ -113,6 +113,31 @@ pub struct Scale {
pub x: f64,
/// The y-scale factor of the source.
pub y: f64,
/// The scale filter of the source.
pub filter: ScaleFilter,
}
/// Different scaling filters that can be applied to a scene item as part of [`Scale`].
#[derive(Clone, Copy, Debug, Deserialize)]
pub enum ScaleFilter {
/// Disable any scaling filters.
#[serde(rename = "OBS_SCALE_DISABLE")]
Disable,
/// Nearest neighbor scaling.
#[serde(rename = "OBS_SCALE_POINT")]
Point,
/// Sharpened scaling, 16 samples.
#[serde(rename = "OBS_SCALE_BICUBIC")]
Bicubic,
/// Fast but blurry scaling.
#[serde(rename = "OBS_SCALE_BILINEAR")]
Bilinear,
/// Sharpened scaling, 36 samples.
#[serde(rename = "OBS_SCALE_LANCZOS")]
Lanczos,
/// Weighted sum, 4/6/9 samples.
#[serde(rename = "OBS_SCALE_AREA")]
Area,
}
/// Response value for

@ -233,6 +233,13 @@ pub enum EventType {
/// Current recording resumed.
RecordingResumed,
// --------------------------------
// Virtual Cam
// --------------------------------
/// Virtual cam started successfully.
VirtualCamStarted,
/// Virtual cam stopped successfully.
VirtualCamStopped,
// --------------------------------
// Replay Buffer
// --------------------------------
/// A request to start the replay buffer has been issued.
@ -290,6 +297,8 @@ pub enum EventType {
source_name: String,
/// Source volume.
volume: f32,
/// Source volume in Decibel
volume_db: f32,
},
/// A source has been muted or unmuted.
#[serde(rename_all = "camelCase")]

@ -71,7 +71,7 @@ pub(crate) enum RequestType<'a> {
/// Source name.
source_name: &'a str,
/// Whether to pause or play the source. `false` for play, `true` for pause.
play_pause: bool,
play_pause: Option<bool>,
},
#[serde(rename_all = "camelCase")]
RestartMedia {
@ -154,6 +154,11 @@ pub(crate) enum RequestType<'a> {
source: &'a str,
},
#[serde(rename_all = "camelCase")]
GetSourceActive {
/// Source name.
source_name: &'a str,
},
#[serde(rename_all = "camelCase")]
GetAudioActive {
/// Source name.
source_name: &'a str,
@ -450,6 +455,13 @@ pub(crate) enum RequestType<'a> {
/// manually if you set `release` to false. Defaults to true.
release: Option<bool>,
},
// --------------------------------
// Virtual Cam
// --------------------------------
GetVirtualCamStatus,
StartStopVirtualCam,
StartVirtualCam,
StopVirtualCam,
}
/// Request information for [`open_projector`](crate::client::General::open_projector).

@ -288,6 +288,14 @@ pub struct Mute {
pub muted: bool,
}
/// Response value for [`get_source_active`](crate::client::Sources::get_source_active).
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct SourceActive {
/// Source active status of the source.
pub source_active: bool,
}
/// Response value for [`get_audio_active`](crate::client::Sources::get_audio_active).
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
@ -1018,3 +1026,15 @@ pub struct Transition {
/// Name of the transition.
pub name: String,
}
/// Response value for
/// [`get_virtual_cam_status`](crate::client::VirtualCam::get_virtual_cam_status).
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VirtualCamStatus {
/// Current virtual camera status.
pub is_virtual_cam: bool,
/// Time elapsed since virtual cam started (only present if virtual cam currently active).
#[serde(default, deserialize_with = "crate::de::duration_opt")]
pub virtual_cam_timecode: Option<Duration>,
}

@ -17,13 +17,13 @@ async fn main() -> Result<()> {
pin_mut!(events);
client.play_pause_media(TEST_MEDIA, false).await?;
client.play_pause_media(TEST_MEDIA, Some(false)).await?;
wait_for!(events, EventType::MediaPlaying { .. });
client.next_media(TEST_MEDIA).await?;
wait_for!(events, EventType::MediaNext { .. });
client.previous_media(TEST_MEDIA).await?;
wait_for!(events, EventType::MediaPrevious { .. });
client.play_pause_media(TEST_MEDIA, true).await?;
client.play_pause_media(TEST_MEDIA, Some(true)).await?;
wait_for!(events, EventType::MediaPaused { .. });
let duration = client.get_media_duration(TEST_MEDIA).await?;

@ -31,11 +31,13 @@ async fn main() -> Result<()> {
client.start_recording().await?;
wait_for!(events, EventType::RecordingStarted { .. });
// Pausing doesn't seem to work currently
// client.pause_recording().await?;
// wait_for!(events, EventType::RecordingPaused);
// client.resume_recording().await?;
// wait_for!(events, EventType::RecordingResumed);
time::sleep(Duration::from_secs(1)).await;
client.pause_recording().await?;
wait_for!(events, EventType::RecordingPaused);
time::sleep(Duration::from_secs(1)).await;
client.resume_recording().await?;
wait_for!(events, EventType::RecordingResumed);
time::sleep(Duration::from_secs(1)).await;
client.stop_recording().await?;
wait_for!(events, EventType::RecordingStopped { .. });

@ -24,6 +24,7 @@ async fn main() -> Result<()> {
client.get_sources_list().await?;
client.get_sources_types_list().await?;
client.get_source_active(TEST_MEDIA).await?;
client.get_audio_active(TEST_MEDIA).await?;
client.get_source_default_settings(SOURCE_KIND_VLC).await?;

@ -0,0 +1,38 @@
#![cfg(feature = "test-integration")]
use std::time::Duration;
use anyhow::Result;
use futures_util::{pin_mut, StreamExt};
use obws::events::{Event, EventType};
use tokio::time;
#[macro_use]
mod common;
#[tokio::test]
async fn main() -> Result<()> {
let client = common::new_client().await?;
let events = client.events()?;
let client = client.virtual_cam();
pin_mut!(events);
client.get_virtual_cam_status().await?;
client.start_stop_virtual_cam().await?;
wait_for!(events, EventType::VirtualCamStarted { .. });
client.start_stop_virtual_cam().await?;
wait_for!(events, EventType::VirtualCamStopped { .. });
// Wait a little more as the virtual cam sometimes doesn't start when started/stopped
// frequently.
time::sleep(Duration::from_secs(1)).await;
client.start_virtual_cam().await?;
wait_for!(events, EventType::VirtualCamStarted { .. });
client.stop_virtual_cam().await?;
wait_for!(events, EventType::VirtualCamStopped { .. });
Ok(())
}
Loading…
Cancel
Save