Implement common traits for responses and events

pull/28/head
Dominik Nakamura 2 years ago
parent 32df0d4e76
commit 35cf3d6c80
No known key found for this signature in database
GPG Key ID: E4C6A749B2491910

@ -19,6 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
named different to be more concise.
- Thank you to [@715209](https://github.com/715209) and [@Elinvynia](https://github.com/Elinvynia)
for testing out these changes pre-release ❤️. Your ideas and bug reports helped a lot!
- All response and event data structures now implement the recommended common traits, where
possible. In addition, `serde::Serialize` and `serde::Deserialize` is implemented for all of
them. That means, they can now be constructred easier, and used in more places, for example, as a
`HashMap` key.
## [0.9.1] - 2022-02-25

@ -6,9 +6,12 @@ use serde::{Deserialize, Serialize};
use crate::Error;
/// Monitoring type for audio outputs.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[derive(
Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
)]
pub enum MonitorType {
/// No monitoring.
#[default]
#[serde(rename = "OBS_MONITORING_TYPE_NONE")]
None,
/// Only monitor but don't output any sounds.
@ -54,7 +57,7 @@ bitflags! {
/// For example, only using `LEFT` would arrange the target to the left horizontally and
/// centered vertically. To align to the top right, the alignments can be combined to
/// `LEFT | TOP`. Combining both values for a single axis is invalid, like `LEFT | RIGHT`.
#[derive(Serialize, Deserialize)]
#[derive(Default, Deserialize, Serialize)]
#[serde(transparent)]
pub struct Alignment: u8 {
/// Align to the center.
@ -85,9 +88,12 @@ impl From<Alignment> for u8 {
}
/// Different kinds of bounds that can be applied to different items on the scene.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[derive(
Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
)]
pub enum BoundsType {
/// No bounds.
#[default]
#[serde(rename = "OBS_BOUNDS_NONE")]
None,
/// Stretch to bounds.
@ -111,9 +117,12 @@ pub enum BoundsType {
}
/// Different kinds of media actions that can be performed (or happen in events).
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[derive(
Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
)]
pub enum MediaAction {
/// No media action.
#[default]
#[serde(rename = "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NONE")]
None,
/// Start media playback.
@ -137,9 +146,12 @@ pub enum MediaAction {
}
/// Different kinds of scene item blend modes.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[derive(
Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
)]
pub enum BlendMode {
/// No blending, overlaying without mixing colors, except for transparency.
#[default]
#[serde(rename = "OBS_BLEND_NORMAL")]
Normal,
/// Add the pixel values to the ones beneath.

@ -2,7 +2,7 @@
use std::{collections::BTreeMap, path::PathBuf};
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
use crate::{
@ -11,7 +11,7 @@ use crate::{
};
/// All possible event types that can occur while the user interacts with OBS.
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(tag = "eventType", content = "eventData")]
pub enum Event {
// --------------------------------
@ -545,7 +545,7 @@ pub enum Event {
}
/// Volume meter information for a single input, describing the current volume level.
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct InputVolumeMeter {
/// Name of this input.
#[serde(rename = "inputName")]
@ -556,7 +556,7 @@ pub struct InputVolumeMeter {
}
/// The output state describes the current status of any output (like recording, virtual-cam, ...).
#[derive(Clone, Copy, Debug, Deserialize)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum OutputState {
/// A request to start the output has been issued.
#[serde(rename = "OBS_WEBSOCKET_OUTPUT_STARTING")]
@ -582,7 +582,7 @@ pub enum OutputState {
}
/// A basic scene item, only describing identifier and position.
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct BasicSceneItem {
/// Identifier of this scene item.
#[serde(rename = "sceneItemId")]
@ -593,7 +593,7 @@ pub struct BasicSceneItem {
}
/// The scene describes basic details about a single scene setup in OBS.
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Scene {
/// Name of this scene.
#[serde(rename = "sceneName")]

@ -150,7 +150,10 @@ pub(crate) enum Request<'a> {
#[serde(rename = "inputName")]
name: &'a str,
/// Track settings to apply.
#[serde(rename = "inputAudioTracks", with = "crate::serde::audio_tracks")]
#[serde(
rename = "inputAudioTracks",
with = "crate::serde::audio_tracks::option"
)]
tracks: [Option<bool>; 6],
},
#[serde(rename = "GetInputPropertiesListPropertyItems")]

@ -1,9 +1,9 @@
//! Responses related to the OBS configuration.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
/// Response value for [`crate::client::Config::video_settings`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct VideoSettings {
/// Numerator of the fractional FPS value.
#[serde(rename = "fpsNumerator")]
@ -26,7 +26,7 @@ pub struct VideoSettings {
}
/// Response value for [`crate::client::Config::stream_service_settings`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct StreamServiceSettings<T> {
/// Stream service type, like `rtmp_custom` or `rtmp_common`.
#[serde(rename = "streamServiceType")]

@ -1,6 +1,6 @@
//! Responses related to filters.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
/// Response value for [`crate::client::Filters::get_source_filter_list`].
#[derive(Debug, Deserialize)]
@ -11,7 +11,7 @@ pub(crate) struct Filters {
}
/// Response value for [`crate::client::Filters::list`] and [`crate::client::Filters::get`].
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct SourceFilter {
/// Whether the filter is enabled.
#[serde(rename = "filterEnabled")]

@ -1,9 +1,9 @@
//! General responses, not fitting into any category.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
/// Response value for [`crate::client::General::version`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Version {
/// Current OBS Studio version.
#[serde(rename = "obsVersion")]
@ -30,7 +30,7 @@ pub struct Version {
}
/// Response value for [`crate::client::General::stats`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct Stats {
/// Current CPU usage in percent.
#[serde(rename = "cpuUsage")]
@ -68,7 +68,7 @@ pub struct Stats {
}
/// Response value for [`crate::client::General::call_vendor_request`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct VendorResponse<T> {
/// Name of the vendor.
#[serde(rename = "vendorName")]

@ -1,6 +1,6 @@
//! Responses related to inputs.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
use crate::common::MonitorType;
@ -14,7 +14,7 @@ pub(crate) struct Inputs {
}
/// Response value for [`crate::client::Inputs::list`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Input {
/// Name of the input source.
#[serde(rename = "inputName")]
@ -36,7 +36,7 @@ pub(crate) struct InputKinds {
}
/// Response value for [`crate::client::Inputs::specials`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct SpecialInputs {
/// Name of the Desktop Audio input.
#[serde(rename = "desktop1")]
@ -68,7 +68,7 @@ pub(crate) struct DefaultInputSettings<T> {
}
/// Response value for [`crate::client::Inputs::settings`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct InputSettings<T> {
/// Object of settings for the input.
#[serde(rename = "inputSettings")]
@ -88,7 +88,7 @@ pub(crate) struct InputMuted {
}
/// Response value for [`crate::client::Inputs::volume`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct InputVolume {
/// Volume setting in mul.
#[serde(rename = "inputVolumeMul")]
@ -141,7 +141,7 @@ pub(crate) struct ListPropertyItems {
}
/// Response value for [`crate::client::Inputs::properties_list_property_items`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct ListPropertyItem {
/// Name of the item.
#[serde(rename = "itemName")]

@ -1,10 +1,10 @@
//! Responses related to media inputs.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
/// Response value for [`crate::client::MediaInputs::status`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct MediaStatus {
/// State of the media input.
#[serde(rename = "mediaState")]
@ -21,9 +21,12 @@ pub struct MediaStatus {
}
/// Response value for [`crate::client::MediaInputs::status`] as part of [`MediaStatus`].
#[derive(Copy, Clone, Debug, Deserialize)]
#[derive(
Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize,
)]
pub enum MediaState {
/// No state.
#[default]
#[serde(rename = "OBS_MEDIA_STATE_NONE")]
None,
/// Media is playing.

@ -20,7 +20,7 @@ pub mod ui;
pub(crate) mod virtual_cam;
use serde::{de, Deserialize, Deserializer};
use serde_repr::Deserialize_repr;
use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Debug)]
pub(crate) enum ServerMessage {
@ -168,7 +168,9 @@ pub(crate) struct Status {
/// The status code gives information about the result of a request. It gives further insight into
/// what went wrong, if a request failed.
#[derive(Debug, Deserialize_repr)]
#[derive(
Clone, Copy, Debug, Deserialize_repr, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize_repr,
)]
#[repr(u16)]
pub enum StatusCode {
/// Unknown status, should never be used.
@ -263,7 +265,9 @@ pub enum StatusCode {
/// Additional close codes, defined by `obs-websocket`. These can be used to further pin down the
/// details of why the web-socket connection was closed.
#[derive(Debug)]
#[derive(
Clone, Copy, Debug, Deserialize_repr, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize_repr,
)]
#[repr(u16)]
pub enum WebSocketCloseCode {
/// Unknown reason, should never be used.

@ -1,6 +1,6 @@
//! Responses related to outputs.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
#[derive(Debug, Deserialize)]
@ -9,7 +9,7 @@ pub(crate) struct OutputList {
}
/// Response value for [`crate::client::Outputs::list`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Output {
/// Name of this output.
#[serde(rename = "outputName")]
@ -32,7 +32,7 @@ pub struct Output {
}
/// Response value for [`crate::client::Outputs::list`] as part of [`Output`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct OutputFlags {
/// Output supports audio.
#[serde(rename = "OBS_OUTPUT_AUDIO")]
@ -52,7 +52,7 @@ pub struct OutputFlags {
}
/// Response value for [`crate::client::Outputs::status`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct OutputStatus {
/// Whether the output is active.
#[serde(rename = "outputActive")]

@ -1,9 +1,9 @@
//! Responses related to profiles.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
/// Response value for [`crate::client::Profiles::list`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Profiles {
/// The name of the current profile.
#[serde(rename = "currentProfileName")]
@ -13,7 +13,7 @@ pub struct Profiles {
}
/// Response value for [`crate::client::Profiles::parameter`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct ProfileParameter {
/// Value associated with the parameter.
#[serde(rename = "parameterValue")]

@ -1,10 +1,10 @@
//! Responses related to recording.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
/// Response value for [`crate::client::Recording::status`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct RecordStatus {
/// Whether the output is active.
#[serde(rename = "outputActive")]

@ -1,9 +1,9 @@
//! Responses related to scene collections.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
/// Response value for [`crate::client::SceneCollections::list`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct SceneCollections {
/// The name of the current scene collection.
#[serde(rename = "currentSceneCollectionName")]

@ -1,6 +1,6 @@
//! Responses related to scene items.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use crate::common::{Alignment, BlendMode, BoundsType};
@ -22,7 +22,7 @@ pub(crate) struct SceneItemList {
/// Response value for [`crate::client::SceneItems::list`] and
/// [`crate::client::SceneItems::list_group`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct SceneItem {
/// Identifier of the scene item.
#[serde(rename = "sceneItemId")]
@ -45,7 +45,7 @@ pub struct SceneItem {
}
/// Kind of source that is represented by a [`SceneItem`].
#[derive(Copy, Clone, Debug, Deserialize)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum SourceType {
/// Input source from outside of OBS.
#[serde(rename = "OBS_SOURCE_TYPE_INPUT")]
@ -70,7 +70,7 @@ pub(crate) struct GetSceneItemTransform {
}
/// Response value for [`crate::client::SceneItems::transform`].
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct SceneItemTransform {
/// Base width (without scaling) of the source.
#[serde(rename = "sourceWidth")]

@ -1,10 +1,10 @@
//! Responses related to scenes.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
/// Response value for [`crate::client::Scenes::list`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Scenes {
/// Current program scene.
#[serde(rename = "currentProgramSceneName")]
@ -18,7 +18,7 @@ pub struct Scenes {
}
/// Response value for [`crate::client::Scenes::list`] as part of [`Scenes`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Scene {
/// Name of the scene.
#[serde(rename = "sceneName")]
@ -55,7 +55,7 @@ pub(crate) struct CurrentPreviewScene {
}
/// Response value for [`crate::client::Scenes::transition_override`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct SceneTransitionOverride {
/// Name of the overridden scene transition.
#[serde(rename = "transitionName")]

@ -1,9 +1,9 @@
//! Responses related to sources.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
/// Response value for [`crate::client::Sources::active`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct SourceActive {
/// Whether the source is showing in program.
#[serde(rename = "videoActive")]

@ -1,10 +1,10 @@
//! Responses related to streaming.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
/// Response value for [`crate::client::Streaming::status`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct StreamStatus {
/// Whether the output is active.
#[serde(rename = "outputActive")]

@ -1,6 +1,6 @@
//! Responses related to transitions.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use time::Duration;
/// Response value for
@ -13,7 +13,7 @@ pub(crate) struct TransitionKinds {
}
/// Response value for [`crate::client::Transitions::list`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct SceneTransitionList {
/// Name of the current scene transition.
#[serde(rename = "currentSceneTransitionName")]
@ -27,7 +27,7 @@ pub struct SceneTransitionList {
}
/// Response value for [`crate::client::Transitions::list`] as part of [`SceneTransitionList`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Transition {
/// Name of the transition.
#[serde(rename = "transitionName")]
@ -44,7 +44,7 @@ pub struct Transition {
}
/// Response value for [`crate::client::Transitions::current`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct CurrentSceneTransition {
/// Name of the transition.
#[serde(rename = "transitionName")]

@ -1,6 +1,6 @@
//! Responses related to the user interface.
use serde::Deserialize;
use serde::{Deserialize, Serialize};
/// Response value for [`crate::client::Ui::get_studio_mode_enabled`].
#[derive(Debug, Deserialize)]
@ -18,7 +18,7 @@ pub(crate) struct MonitorList {
}
/// Response value for [`crate::client::Ui::list_monitors`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Monitor {
/// Name of this monitor.
#[serde(rename = "monitorName")]
@ -35,7 +35,7 @@ pub struct Monitor {
}
/// Response value for [`crate::client::Ui::list_monitors`] as part of [`Monitor`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct MonitorSize {
/// Pixel width.
#[serde(rename = "monitorWidth")]
@ -46,7 +46,7 @@ pub struct MonitorSize {
}
/// Response value for [`crate::client::Ui::list_monitors`] as part of [`Monitor`].
#[derive(Debug, Deserialize)]
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct MonitorPosition {
/// Horizontal position on the screen.
#[serde(rename = "monitorPositionX")]

@ -11,21 +11,6 @@ enum Error<'a> {
OutOfRange(&'a str),
}
pub fn serialize<S>(value: &[Option<bool>; 6], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(value.iter().copied().flatten().count()))?;
for (k, v) in ["1", "2", "3", "4", "5", "6"]
.into_iter()
.zip(value)
.filter_map(|(k, v)| v.map(|v| (k, v)))
{
map.serialize_entry(k, &v)?;
}
map.end()
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<[bool; 6], D::Error>
where
D: Deserializer<'de>,
@ -61,6 +46,25 @@ impl<'de> Visitor<'de> for AudioTracksVisitor {
}
}
pub mod option {
use super::*;
pub fn serialize<S>(value: &[Option<bool>; 6], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(value.iter().copied().flatten().count()))?;
for (k, v) in ["1", "2", "3", "4", "5", "6"]
.into_iter()
.zip(value)
.filter_map(|(k, v)| v.map(|v| (k, v)))
{
map.serialize_entry(k, &v)?;
}
map.end()
}
}
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
@ -68,7 +72,7 @@ mod tests {
#[derive(Debug, PartialEq, Serialize)]
struct SimpleTracksSer {
#[serde(with = "super")]
#[serde(with = "super::option")]
value: [Option<bool>; 6],
}

Loading…
Cancel
Save