lavalink_rs/model/
player.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
use crate::model::*;

#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Information about the player of a guild.
pub struct Player {
    #[serde(deserialize_with = "deserialize_number_from_string")]
    pub guild_id: GuildId,
    /// The currently playing track.
    pub track: Option<track::TrackData>,
    /// The current volume of the player.
    pub volume: u16,
    /// Whether the player is paused or not.
    pub paused: bool,
    /// The state of the player.
    pub state: State,
    /// The filters currently in use by the player
    pub filters: Option<Filters>,
    /// The voice connection information of the player.
    pub voice: ConnectionInfo,
}

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
pub struct State {
    /// Unix timestamp in milliseconds.
    pub time: u64,
    /// The current position of the track in milliseconds.
    pub position: u64,
    /// Whether Lavalink is connected to the discord voice gateway.
    pub connected: bool,
    #[serde(deserialize_with = "deserialize_option_number")]
    /// The latency of the node to the Discord voice gateway in milliseconds.
    ///
    /// None if not connected.
    pub ping: Option<u32>,
}

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Discord voice websocket connection information.
pub struct ConnectionInfo {
    /// The Discord voice endpoint to connect to.
    ///
    /// Provided by `Voice Server Update`.
    pub endpoint: String,
    /// The Discord voice token to authenticate with.
    ///
    /// Provided by `Voice Server Update`.
    pub token: String,
    /// The Discord voice session id to authenticate with.
    ///
    /// Not to be confused by the Lavalink `session_id`.
    ///
    /// Provided by `Voice State Update`.
    pub session_id: String,
}

impl ConnectionInfo {
    pub fn fix(&mut self) {
        self.endpoint = self.endpoint.replace("wss://", "");
    }
}

#[cfg(feature = "songbird")]
use songbird_dep::ConnectionInfo as SongbirdConnectionInfo;

#[cfg(feature = "songbird")]
impl From<SongbirdConnectionInfo> for ConnectionInfo {
    fn from(connection_info: SongbirdConnectionInfo) -> ConnectionInfo {
        ConnectionInfo {
            endpoint: connection_info.endpoint,
            token: connection_info.token,
            session_id: connection_info.session_id,
        }
    }
}

#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass)]
pub struct Filters {
    /// Adjusts the player volume from 0.0 to 5.0, where 1.0 is 100%.
    ///
    /// NOTE: Values >1.0 may cause clipping
    #[serde(skip_serializing_if = "Option::is_none")]
    pub volume: Option<f64>,
    /// Adjusts 15 different bands.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub equalizer: Option<Vec<Equalizer>>,
    /// Eliminates part of a band, usually targeting vocals.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub karaoke: Option<Karaoke>,
    /// Changes the speed, pitch, and rate.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub timescale: Option<Timescale>,
    /// Creates a shuddering effect, where the volume quickly oscillates.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tremolo: Option<TremoloVibrato>,
    /// Creates a shuddering effect, where the pitch quickly oscillates.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub vibrato: Option<TremoloVibrato>,
    /// Rotates the audio around the stereo channels/user headphones (aka Audio Panning).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rotation: Option<Rotation>,
    /// Distorts the audio.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub distortion: Option<Distortion>,
    /// Mixes both stereo channels (left and right).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub channel_mix: Option<ChannelMix>,
    /// Filters out higher frequencies.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub low_pass: Option<LowPass>,
    /// Filter plugin configurations.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub plugin_filters: Option<serde_json::Value>,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Mixes both channels (left and right), with a configurable factor on how much each channel affects the other.
///
/// With the defaults, both channels are kept independent of each other.
/// Setting all factors to 0.5 means both channels get the same audio.
/// All values are (0.0 <= x <= 1.0)
pub struct ChannelMix {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub left_to_left: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub left_to_right: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub right_to_left: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub right_to_right: Option<f64>,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Distortion effect.
///
/// It can generate some pretty unique audio effects.
pub struct Distortion {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sin_offset: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sin_scale: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cos_offset: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cos_scale: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tan_offset: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tan_scale: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub offset: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub scale: Option<f64>,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// A fixed band equalizer.
pub struct Equalizer {
    /// The band (0 to 14)
    pub band: u8,
    /// The gain (-0.25 to 1.0)
    ///
    /// -0.25 means the given band is completely muted, and 0.25 means it is doubled.
    /// Modifying the gain could also change the volume of the output.
    pub gain: f64,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Uses equalization to eliminate part of a band, usually targeting vocals.
pub struct Karaoke {
    /// The level (0 to 1.0 where 0.0 is no effect and 1.0 is full effect)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level: Option<f64>,
    /// The mono level (0 to 1.0 where 0.0 is no effect and 1.0 is full effect)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mono_level: Option<f64>,
    /// The filter band (in Hz)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filter_band: Option<f64>,
    /// The filter width.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filter_width: Option<f64>,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Higher frequencies get suppressed, while lower frequencies pass through this filter.
pub struct LowPass {
    /// The smoothing factor (1.0 < x)
    ///
    /// Any smoothing values equal to or less than 1.0 will disable the filter.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub smoothing: Option<f64>,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Rotates the sound around the stereo channels/user headphones (aka Audio Panning).
///
/// It can produce an effect similar to [this](https://youtu.be/QB9EB8mTKcc) without the reverb.
pub struct Rotation {
    /// The frequency of the audio rotating around the listener in Hz.
    ///
    /// 0.2 is similar to the example video above
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rotation_hz: Option<f64>,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Changes the speed, pitch, and rate.
///
/// All default to 1.0.
pub struct Timescale {
    /// The playback speed (0.0 <= x)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub speed: Option<f64>,
    /// The pitch (0.0 <= x)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub pitch: Option<f64>,
    /// The rate (0.0 <= x)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rate: Option<f64>,
}

#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "python", pyo3::pyclass(get_all, set_all))]
/// Tremolo uses amplification to create a shuddering effect, where the volume quickly oscillates.
///
/// [Demo](https://en.wikipedia.org/wiki/File:Fuse_Electronics_Tremolo_MK-III_Quick_Demo.ogv)
///
/// Vibrato is similar to tremolo, but rather than oscillating the volume, it oscillates the pitch.
pub struct TremoloVibrato {
    /// For tremolo (0.0 < x)
    /// For vibrato (0.0 < x <= 14.0)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub frequency: Option<f64>,
    /// For both tremolo and vibrato (0.0 < x <= 1.0)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub depth: Option<f64>,
}