fix: further layer A (per-app) glitches
This commit is contained in:
parent
2978318019
commit
7797f60128
16 changed files with 1589 additions and 155 deletions
|
|
@ -13,9 +13,9 @@ mod proto;
|
|||
pub use codec::{Codec, DEFAULT_MAX_FRAME_BYTES, MIN_MAX_FRAME_BYTES};
|
||||
pub use error::{Error, ErrorCode, ProtoError};
|
||||
pub use proto::{
|
||||
DaemonEvent, Event, HelloData, LayerALevel, MeterTick, Op, ProfileEvent, ProfileInfo, Request,
|
||||
Response, ResponsePayload, Route, RouteList, RouteRule, RouteRuleMatch, RoutingEvent,
|
||||
ServerFrame, SinkInfo, Sinks, Status, StreamRoute, Topic,
|
||||
DaemonEvent, Event, HelloData, LayerALevel, LayerASnapshot, MeterTick, Op, ProfileEvent,
|
||||
ProfileInfo, Request, Response, ResponsePayload, Route, RouteList, RouteRule, RouteRuleMatch,
|
||||
RoutingEvent, ServerFrame, SinkInfo, Sinks, Status, StreamRoute, Topic,
|
||||
};
|
||||
|
||||
/// Wire-protocol version. Bumped only on incompatible changes.
|
||||
|
|
|
|||
|
|
@ -184,6 +184,36 @@ pub enum Op {
|
|||
enabled: bool,
|
||||
},
|
||||
|
||||
/// List per-app (Layer A) controller state for managed streams.
|
||||
#[serde(rename = "per-app.list")]
|
||||
LayerAList,
|
||||
|
||||
/// Enable or disable Layer A for a specific app (persistent
|
||||
/// overlay override).
|
||||
#[serde(rename = "per-app.set")]
|
||||
PerAppSet {
|
||||
/// Application identifier (process_binary or application_name).
|
||||
app: String,
|
||||
/// `true` to manage the app, `false` to leave it alone.
|
||||
enabled: bool,
|
||||
},
|
||||
|
||||
/// Enable or disable the Layer A master switch (persistent overlay
|
||||
/// override).
|
||||
#[serde(rename = "per-app.master")]
|
||||
PerAppMaster {
|
||||
/// `true` to enable Layer A globally.
|
||||
enabled: bool,
|
||||
},
|
||||
|
||||
/// Clear a managed stream's deference state (user-ceiling /
|
||||
/// strict-mode lock) so the controller resumes normal control.
|
||||
#[serde(rename = "per-app.reset")]
|
||||
LayerAReset {
|
||||
/// PipeWire node id of the managed stream.
|
||||
node_id: u32,
|
||||
},
|
||||
|
||||
/// Subscribe to one or more event topics on this connection.
|
||||
#[serde(rename = "subscribe")]
|
||||
Subscribe {
|
||||
|
|
@ -217,6 +247,10 @@ impl Op {
|
|||
Op::SettingSet { .. } => "setting.set",
|
||||
Op::SettingList => "setting.list",
|
||||
Op::BypassSet { .. } => "bypass.set",
|
||||
Op::LayerAList => "per-app.list",
|
||||
Op::PerAppSet { .. } => "per-app.set",
|
||||
Op::PerAppMaster { .. } => "per-app.master",
|
||||
Op::LayerAReset { .. } => "per-app.reset",
|
||||
Op::Subscribe { .. } => "subscribe",
|
||||
Op::Unsubscribe { .. } => "unsubscribe",
|
||||
}
|
||||
|
|
@ -356,10 +390,20 @@ pub struct Status {
|
|||
pub profile: String,
|
||||
/// Global bypass flag.
|
||||
pub bypass: bool,
|
||||
/// Layer A master switch (per-app level control enabled globally).
|
||||
/// Older clients that don't understand the field treat it as
|
||||
/// absent (serde `default`).
|
||||
#[serde(default)]
|
||||
pub per_app: bool,
|
||||
/// Sink status snapshot.
|
||||
pub sinks: Sinks,
|
||||
/// Currently-tracked playback streams.
|
||||
pub streams: Vec<StreamRoute>,
|
||||
/// Per-app (Layer A) controller state for managed streams.
|
||||
/// Empty when Layer A isn't managing anything. Older clients that
|
||||
/// don't understand the field treat it as absent (serde `default`).
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub layer_a: Vec<LayerASnapshot>,
|
||||
/// Non-fatal warnings the daemon wants operators to see —
|
||||
/// typically from profile loading (TOML parse errors on a single
|
||||
/// file, the active profile name pointing at something not on
|
||||
|
|
@ -411,6 +455,29 @@ pub struct StreamRoute {
|
|||
pub route: Route,
|
||||
}
|
||||
|
||||
/// Per-app (Layer A) controller state for one managed stream.
|
||||
/// Surfaced on `status` and `per-app.list`.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct LayerASnapshot {
|
||||
/// Source PipeWire node id.
|
||||
pub node_id: u32,
|
||||
/// Application identifier.
|
||||
pub app: String,
|
||||
/// True while a tap + controller is actively managing the stream.
|
||||
pub managed: bool,
|
||||
/// Last linear volume the controller wrote (1.0 = unity).
|
||||
pub volume_lin: f32,
|
||||
/// Smoothed gain reduction the controller currently asserts, in dB
|
||||
/// (`>= 0`; `0` means no cut).
|
||||
pub reduction_db: f32,
|
||||
/// User-set ceiling (linear) when ceiling-mode deference is active.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub user_ceiling_lin: Option<f32>,
|
||||
/// True when strict-mode deference has locked the controller until
|
||||
/// an explicit `per-app.reset`.
|
||||
pub deferred: bool,
|
||||
}
|
||||
|
||||
/// Summary entry returned by `profile.list`.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ProfileInfo {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue