aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--libs/hbb_common/build.rs2
-rw-r--r--libs/hbb_common/protos/message.proto14
-rw-r--r--libs/hbb_common/src/config.rs187
-rw-r--r--libs/hbb_common/src/protos/mod.rs1
4 files changed, 183 insertions, 21 deletions
diff --git a/libs/hbb_common/build.rs b/libs/hbb_common/build.rs
index 35ced59..fe0d310 100644
--- a/libs/hbb_common/build.rs
+++ b/libs/hbb_common/build.rs
@@ -2,7 +2,7 @@ fn main() {
let out_dir = format!("{}/protos", std::env::var("OUT_DIR").unwrap());
std::fs::create_dir_all(&out_dir).unwrap();
-
+
protobuf_codegen::Codegen::new()
.pure()
.out_dir(out_dir)
diff --git a/libs/hbb_common/protos/message.proto b/libs/hbb_common/protos/message.proto
index b7965f2..ed27063 100644
--- a/libs/hbb_common/protos/message.proto
+++ b/libs/hbb_common/protos/message.proto
@@ -598,6 +598,18 @@ message Misc {
}
}
+message VoiceCallRequest {
+ int64 req_timestamp = 1;
+ // Indicates whether the request is a connect action or a disconnect action.
+ bool is_connect = 2;
+}
+
+message VoiceCallResponse {
+ bool accepted = 1;
+ int64 req_timestamp = 2; // Should copy from [VoiceCallRequest::req_timestamp].
+ int64 ack_timestamp = 3;
+}
+
message Message {
oneof union {
SignedId signed_id = 3;
@@ -620,5 +632,7 @@ message Message {
Cliprdr cliprdr = 20;
MessageBox message_box = 21;
SwitchSidesResponse switch_sides_response = 22;
+ VoiceCallRequest voice_call_request = 23;
+ VoiceCallResponse voice_call_response = 24;
}
}
diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs
index 8bea991..71dd9a5 100644
--- a/libs/hbb_common/src/config.rs
+++ b/libs/hbb_common/src/config.rs
@@ -115,6 +115,26 @@ macro_rules! serde_field_string {
};
}
+macro_rules! serde_field_bool {
+ ($struct_name: ident, $field_name: literal, $func: ident) => {
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+ pub struct $struct_name {
+ #[serde(rename = $field_name)]
+ pub v: bool,
+ }
+ impl Default for $struct_name {
+ fn default() -> Self {
+ Self { v: Self::$func() }
+ }
+ }
+ impl $struct_name {
+ pub fn $func() -> bool {
+ UserDefaultConfig::load().get($field_name) == "Y"
+ }
+ }
+ };
+}
+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum NetworkType {
Direct,
@@ -192,26 +212,29 @@ pub struct PeerConfig {
deserialize_with = "PeerConfig::deserialize_image_quality"
)]
pub image_quality: String,
- #[serde(default)]
+ #[serde(
+ default = "PeerConfig::default_custom_image_quality",
+ deserialize_with = "PeerConfig::deserialize_custom_image_quality"
+ )]
pub custom_image_quality: Vec<i32>,
- #[serde(default)]
- pub show_remote_cursor: bool,
- #[serde(default)]
- pub lock_after_session_end: bool,
- #[serde(default)]
- pub privacy_mode: bool,
+ #[serde(flatten)]
+ pub show_remote_cursor: ShowRemoteCursor,
+ #[serde(flatten)]
+ pub lock_after_session_end: LockAfterSessionEnd,
+ #[serde(flatten)]
+ pub privacy_mode: PrivacyMode,
#[serde(default)]
pub port_forwards: Vec<(i32, String, i32)>,
#[serde(default)]
pub direct_failures: i32,
- #[serde(default)]
- pub disable_audio: bool,
- #[serde(default)]
- pub disable_clipboard: bool,
- #[serde(default)]
- pub enable_file_transfer: bool,
- #[serde(default)]
- pub show_quality_monitor: bool,
+ #[serde(flatten)]
+ pub disable_audio: DisableAudio,
+ #[serde(flatten)]
+ pub disable_clipboard: DisableClipboard,
+ #[serde(flatten)]
+ pub enable_file_transfer: EnableFileTransfer,
+ #[serde(flatten)]
+ pub show_quality_monitor: ShowQualityMonitor,
#[serde(default)]
pub keyboard_mode: String,
@@ -961,31 +984,88 @@ impl PeerConfig {
serde_field_string!(
default_view_style,
deserialize_view_style,
- "original".to_owned()
+ UserDefaultConfig::load().get("view_style")
);
serde_field_string!(
default_scroll_style,
deserialize_scroll_style,
- "scrollauto".to_owned()
+ UserDefaultConfig::load().get("scroll_style")
);
serde_field_string!(
default_image_quality,
deserialize_image_quality,
- "balanced".to_owned()
+ UserDefaultConfig::load().get("image_quality")
);
+ fn default_custom_image_quality() -> Vec<i32> {
+ let f: f64 = UserDefaultConfig::load()
+ .get("custom_image_quality")
+ .parse()
+ .unwrap_or(50.0);
+ vec![f as _]
+ }
+
+ fn deserialize_custom_image_quality<'de, D>(deserializer: D) -> Result<Vec<i32>, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ let v: Vec<i32> = de::Deserialize::deserialize(deserializer)?;
+ if v.len() == 1 && v[0] >= 10 && v[0] <= 100 {
+ Ok(v)
+ } else {
+ Ok(Self::default_custom_image_quality())
+ }
+ }
+
fn deserialize_options<'de, D>(deserializer: D) -> Result<HashMap<String, String>, D::Error>
where
D: de::Deserializer<'de>,
{
let mut mp: HashMap<String, String> = de::Deserialize::deserialize(deserializer)?;
- if !mp.contains_key("codec-preference") {
- mp.insert("codec-preference".to_owned(), "auto".to_owned());
+ let mut key = "codec-preference";
+ if !mp.contains_key(key) {
+ mp.insert(key.to_owned(), UserDefaultConfig::load().get(key));
+ }
+ key = "custom-fps";
+ if !mp.contains_key(key) {
+ mp.insert(key.to_owned(), UserDefaultConfig::load().get(key));
+ }
+ key = "zoom-cursor";
+ if !mp.contains_key(key) {
+ mp.insert(key.to_owned(), UserDefaultConfig::load().get(key));
}
Ok(mp)
}
}
+serde_field_bool!(
+ ShowRemoteCursor,
+ "show_remote_cursor",
+ default_show_remote_cursor
+);
+serde_field_bool!(
+ ShowQualityMonitor,
+ "show_quality_monitor",
+ default_show_quality_monitor
+);
+serde_field_bool!(DisableAudio, "disable_audio", default_disable_audio);
+serde_field_bool!(
+ EnableFileTransfer,
+ "enable_file_transfer",
+ default_enable_file_transfer
+);
+serde_field_bool!(
+ DisableClipboard,
+ "disable_clipboard",
+ default_disable_clipboard
+);
+serde_field_bool!(
+ LockAfterSessionEnd,
+ "lock_after_session_end",
+ default_lock_after_session_end
+);
+serde_field_bool!(PrivacyMode, "privacy_mode", default_privacy_mode);
+
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct LocalConfig {
#[serde(default)]
@@ -1192,6 +1272,73 @@ impl HwCodecConfig {
}
}
+#[derive(Debug, Default, Serialize, Deserialize, Clone)]
+pub struct UserDefaultConfig {
+ #[serde(default)]
+ options: HashMap<String, String>,
+}
+
+impl UserDefaultConfig {
+ pub fn load() -> UserDefaultConfig {
+ Config::load_::<UserDefaultConfig>("_default")
+ }
+
+ #[inline]
+ fn store(&self) {
+ Config::store_(self, "_default");
+ }
+
+ pub fn get(&self, key: &str) -> String {
+ match key {
+ "view_style" => self.get_string(key, "original", vec!["adaptive"]),
+ "scroll_style" => self.get_string(key, "scrollauto", vec!["scrollbar"]),
+ "image_quality" => self.get_string(key, "balanced", vec!["best", "low", "custom"]),
+ "codec-preference" => self.get_string(key, "auto", vec!["vp9", "h264", "h265"]),
+ "custom_image_quality" => self.get_double_string(key, 50.0, 10.0, 100.0),
+ "custom-fps" => self.get_double_string(key, 30.0, 10.0, 120.0),
+ _ => self
+ .options
+ .get(key)
+ .map(|v| v.to_string())
+ .unwrap_or_default(),
+ }
+ }
+
+ pub fn set(&mut self, key: String, value: String) {
+ self.options.insert(key, value);
+ self.store();
+ }
+
+ #[inline]
+ fn get_string(&self, key: &str, default: &str, others: Vec<&str>) -> String {
+ match self.options.get(key) {
+ Some(option) => {
+ if others.contains(&option.as_str()) {
+ option.to_owned()
+ } else {
+ default.to_owned()
+ }
+ }
+ None => default.to_owned(),
+ }
+ }
+
+ #[inline]
+ fn get_double_string(&self, key: &str, default: f64, min: f64, max: f64) -> String {
+ match self.options.get(key) {
+ Some(option) => {
+ let v: f64 = option.parse().unwrap_or(default);
+ if v >= min && v <= max {
+ v.to_string()
+ } else {
+ default.to_string()
+ }
+ }
+ None => default.to_string(),
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/libs/hbb_common/src/protos/mod.rs b/libs/hbb_common/src/protos/mod.rs
new file mode 100644
index 0000000..c001c58
--- /dev/null
+++ b/libs/hbb_common/src/protos/mod.rs
@@ -0,0 +1 @@
+include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); \ No newline at end of file