mirror of
https://gitlab.com/futo-org/fcast.git
synced 2025-06-24 21:25:23 +00:00
Rust terminal sender fixes
This commit is contained in:
parent
a955097989
commit
1435d8a2ea
4 changed files with 46 additions and 14 deletions
|
@ -58,5 +58,5 @@ cat dash.mpd | ./fcast -h localhost play --mime_type application/dash+xml
|
||||||
cat image_playlist_example.json | ./fcast -h localhost play --mime_type application/json
|
cat image_playlist_example.json | ./fcast -h localhost play --mime_type application/json
|
||||||
|
|
||||||
# Play from video playlist
|
# Play from video playlist
|
||||||
cat image_playlist_example.json | ./fcast -h localhost play --mime_type application/json
|
cat video_playlist_example.json | ./fcast -h localhost play --mime_type application/json
|
||||||
```
|
```
|
||||||
|
|
|
@ -123,9 +123,9 @@ impl<'a> FCastSession<'a> {
|
||||||
if opcode != Opcode::Initial {
|
if opcode != Opcode::Initial {
|
||||||
return Err(format!("Expected Opcode::Initial, got {opcode:?}").into());
|
return Err(format!("Expected Opcode::Initial, got {opcode:?}").into());
|
||||||
}
|
}
|
||||||
let inital_receiver: v3::InitialReceiverMessage =
|
let initial_receiver: v3::InitialReceiverMessage =
|
||||||
serde_json::from_str(&body.ok_or("InitialReceiverMessage requires body")?)?;
|
serde_json::from_str(&body.ok_or("InitialReceiverMessage requires body")?)?;
|
||||||
println!("Got inital message from sender: {inital_receiver:?}");
|
println!("Got initial message from sender: {initial_receiver:?}");
|
||||||
session.state = SessionState::Connected(ProtoVersion::V3);
|
session.state = SessionState::Connected(ProtoVersion::V3);
|
||||||
} else {
|
} else {
|
||||||
session.state = SessionState::Connected(ProtoVersion::V2);
|
session.state = SessionState::Connected(ProtoVersion::V2);
|
||||||
|
@ -259,6 +259,7 @@ impl<'a> FCastSession<'a> {
|
||||||
time: Option<f64>,
|
time: Option<f64>,
|
||||||
speed: Option<f64>,
|
speed: Option<f64>,
|
||||||
headers: Option<HashMap<String, String>>,
|
headers: Option<HashMap<String, String>>,
|
||||||
|
volume: Option<f64>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
match self.state {
|
match self.state {
|
||||||
SessionState::Connected(ProtoVersion::V2) => {
|
SessionState::Connected(ProtoVersion::V2) => {
|
||||||
|
@ -278,7 +279,7 @@ impl<'a> FCastSession<'a> {
|
||||||
url,
|
url,
|
||||||
content,
|
content,
|
||||||
time,
|
time,
|
||||||
volume: Some(1.0),
|
volume,
|
||||||
speed,
|
speed,
|
||||||
headers,
|
headers,
|
||||||
metadata: None,
|
metadata: None,
|
||||||
|
|
|
@ -135,6 +135,14 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.help("Custom request headers in key:value format")
|
.help("Custom request headers in key:value format")
|
||||||
.required(false)
|
.required(false)
|
||||||
.multiple_occurrences(true),
|
.multiple_occurrences(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("volume")
|
||||||
|
.short('v')
|
||||||
|
.long("volume")
|
||||||
|
.value_name("VOLUME")
|
||||||
|
.help("The desired volume")
|
||||||
|
.takes_value(true)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
|
@ -301,6 +309,11 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.collect::<HashMap<String, String>>()
|
.collect::<HashMap<String, String>>()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let volume = match play_matches.value_of("volume") {
|
||||||
|
Some(v) => v.parse::<f64>().ok(),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
let mut url = None;
|
let mut url = None;
|
||||||
let mut content = None;
|
let mut content = None;
|
||||||
|
@ -313,7 +326,7 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
ctrlc::set_handler(move || {
|
ctrlc::set_handler(move || {
|
||||||
println!(
|
println!(
|
||||||
"Ctrl+C triggered, server will stop when onging request finishes..."
|
"Ctrl+C triggered, server will stop when ongoing request finishes..."
|
||||||
);
|
);
|
||||||
r.store(false, Ordering::SeqCst);
|
r.store(false, Ordering::SeqCst);
|
||||||
})
|
})
|
||||||
|
@ -340,7 +353,7 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
content = Some(buffer);
|
content = Some(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
session.send_play_message(mime_type, url, content, time, speed, headers)?;
|
session.send_play_message(mime_type, url, content, time, speed, headers, volume)?;
|
||||||
} else if let Some(seek_matches) = matches.subcommand_matches("seek") {
|
} else if let Some(seek_matches) = matches.subcommand_matches("seek") {
|
||||||
let seek_message = SeekMessage::new(match seek_matches.value_of("timestamp") {
|
let seek_message = SeekMessage::new(match seek_matches.value_of("timestamp") {
|
||||||
Some(s) => s.parse::<f64>()?,
|
Some(s) => s.parse::<f64>()?,
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub enum MetadataObject {
|
||||||
Generic {
|
Generic {
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
thumbnail_url: Option<String>,
|
thumbnail_url: Option<String>,
|
||||||
custom: Value,
|
custom: Option<Value>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,9 @@ impl Serialize for MetadataObject {
|
||||||
None => Value::Null,
|
None => Value::Null,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
map.insert("custom".to_owned(), custom.clone());
|
if let Some(custom) = custom {
|
||||||
|
map.insert("custom".to_owned(), custom.clone());
|
||||||
|
}
|
||||||
map.serialize(serializer)
|
map.serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,8 +92,7 @@ impl<'de> Deserialize<'de> for MetadataObject {
|
||||||
thumbnail_url,
|
thumbnail_url,
|
||||||
custom: rest
|
custom: rest
|
||||||
.get("custom")
|
.get("custom")
|
||||||
.ok_or(de::Error::missing_field("custom"))?
|
.cloned(),
|
||||||
.clone(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(de::Error::custom(format!("Unknown metadata type {type_}"))),
|
_ => Err(de::Error::custom(format!("Unknown metadata type {type_}"))),
|
||||||
|
@ -476,7 +477,7 @@ mod tests {
|
||||||
&serde_json::to_string(&MetadataObject::Generic {
|
&serde_json::to_string(&MetadataObject::Generic {
|
||||||
title: Some(s!("abc")),
|
title: Some(s!("abc")),
|
||||||
thumbnail_url: Some(s!("def")),
|
thumbnail_url: Some(s!("def")),
|
||||||
custom: serde_json::Value::Null,
|
custom: Some(serde_json::Value::Null),
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
r#"{"custom":null,"thumbnailUrl":"def","title":"abc","type":0}"#
|
r#"{"custom":null,"thumbnailUrl":"def","title":"abc","type":0}"#
|
||||||
|
@ -485,11 +486,20 @@ mod tests {
|
||||||
&serde_json::to_string(&MetadataObject::Generic {
|
&serde_json::to_string(&MetadataObject::Generic {
|
||||||
title: None,
|
title: None,
|
||||||
thumbnail_url: None,
|
thumbnail_url: None,
|
||||||
custom: serde_json::Value::Null,
|
custom: Some(serde_json::Value::Null),
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
r#"{"custom":null,"thumbnailUrl":null,"title":null,"type":0}"#
|
r#"{"custom":null,"thumbnailUrl":null,"title":null,"type":0}"#
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
&serde_json::to_string(&MetadataObject::Generic {
|
||||||
|
title: Some(s!("abc")),
|
||||||
|
thumbnail_url: Some(s!("def")),
|
||||||
|
custom: None,
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
r#"{"thumbnailUrl":"def","title":"abc","type":0}"#
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -502,7 +512,7 @@ mod tests {
|
||||||
MetadataObject::Generic {
|
MetadataObject::Generic {
|
||||||
title: Some(s!("abc")),
|
title: Some(s!("abc")),
|
||||||
thumbnail_url: Some(s!("def")),
|
thumbnail_url: Some(s!("def")),
|
||||||
custom: serde_json::Value::Null,
|
custom: Some(serde_json::Value::Null),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -510,7 +520,15 @@ mod tests {
|
||||||
MetadataObject::Generic {
|
MetadataObject::Generic {
|
||||||
title: None,
|
title: None,
|
||||||
thumbnail_url: None,
|
thumbnail_url: None,
|
||||||
custom: serde_json::Value::Null,
|
custom: Some(serde_json::Value::Null),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::from_str::<MetadataObject>(r#"{"type":0}"#).unwrap(),
|
||||||
|
MetadataObject::Generic {
|
||||||
|
title: None,
|
||||||
|
thumbnail_url: None,
|
||||||
|
custom: None,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert!(serde_json::from_str::<MetadataObject>(r#"{"type":1"#).is_err());
|
assert!(serde_json::from_str::<MetadataObject>(r#"{"type":1"#).is_err());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue