Merge branch 'master' into 'master'

clean up code and fix bug

See merge request mpv-ipc/mpvipc!3
This commit is contained in:
Jonas Frei 2022-07-20 15:44:23 +00:00
commit 86662ffb6b
2 changed files with 114 additions and 160 deletions

View File

@ -189,30 +189,34 @@ pub fn get_mpv_property<T: TypeHandler>(instance: &Mpv, property: &str) -> Resul
pub fn get_mpv_property_string(instance: &Mpv, property: &str) -> Result<String, Error> { pub fn get_mpv_property_string(instance: &Mpv, property: &str) -> Result<String, Error> {
let ipc_string = format!("{{ \"command\": [\"get_property\",\"{}\"] }}\n", property); let ipc_string = format!("{{ \"command\": [\"get_property\",\"{}\"] }}\n", property);
match serde_json::from_str::<Value>(&send_command_sync(instance, &ipc_string)) { let val = serde_json::from_str::<Value>(&send_command_sync(instance, &ipc_string))
Ok(val) => { .map_err(|why| Error(ErrorCode::JsonParseError(why.to_string())))?;
if let Value::Object(map) = val {
if let Value::String(ref error) = map["error"] { let map = if let Value::Object(map) = val {
if error == "success" && map.contains_key("data") { Ok(map)
match map["data"] { } else {
Value::Bool(b) => Ok(b.to_string()), Err(Error(ErrorCode::UnexpectedValue))
Value::Number(ref n) => Ok(n.to_string()), }?;
Value::String(ref s) => Ok(s.to_string()),
Value::Array(ref array) => Ok(format!("{:?}", array)), let error = if let Value::String(ref error) = map["error"] {
Value::Object(ref map) => Ok(format!("{:?}", map)), Ok(error)
_ => Err(Error(ErrorCode::UnsupportedType)), } else {
} Err(Error(ErrorCode::UnexpectedValue))
} else { }?;
Err(Error(ErrorCode::MpvError(error.to_string())))
} let data = if error == "success" {
} else { Ok(&map["data"])
Err(Error(ErrorCode::UnexpectedValue)) } else {
} Err(Error(ErrorCode::MpvError(error.to_string())))
} else { }?;
Err(Error(ErrorCode::UnexpectedValue))
} match data {
} Value::Bool(b) => Ok(b.to_string()),
Err(why) => Err(Error(ErrorCode::JsonParseError(why.to_string()))), Value::Number(ref n) => Ok(n.to_string()),
Value::String(ref s) => Ok(s.to_string()),
Value::Array(ref array) => Ok(format!("{:?}", array)),
Value::Object(ref map) => Ok(format!("{:?}", map)),
Value::Null => Err(Error(ErrorCode::MissingValue)),
} }
} }
@ -233,14 +237,11 @@ pub fn set_mpv_property<T: TypeHandler>(
} }
pub fn run_mpv_command(instance: &Mpv, command: &str, args: &[&str]) -> Result<(), Error> { pub fn run_mpv_command(instance: &Mpv, command: &str, args: &[&str]) -> Result<(), Error> {
let mut ipc_string = format!("{{ \"command\": [\"{}\"", command); let mut ipc_string = format!(r#"{{ "command": ["{}""#, command);
if args.len() > 0 { for arg in args {
for arg in args { ipc_string.push_str(&format!(r#", "{}""#, arg));
ipc_string.push_str(&format!(", \"{}\"", arg));
}
} }
ipc_string.push_str("] }\n"); ipc_string.push_str("] }\n");
ipc_string = ipc_string;
match serde_json::from_str::<Value>(&send_command_sync(instance, &ipc_string)) { match serde_json::from_str::<Value>(&send_command_sync(instance, &ipc_string)) {
Ok(feedback) => { Ok(feedback) => {
if let Value::String(ref error) = feedback["error"] { if let Value::String(ref error) = feedback["error"] {
@ -334,139 +335,94 @@ fn try_convert_property(name: &str, id: usize, data: MpvDataType) -> Event {
} }
pub fn listen(instance: &mut Mpv) -> Result<Event, Error> { pub fn listen(instance: &mut Mpv) -> Result<Event, Error> {
let mut response = String::new(); let mut e;
instance.reader.read_line(&mut response).unwrap(); // sometimes we get responses unrelated to events, so we read a new line until we receive one
response = response.trim_end().to_string(); // with an event field
debug!("Event: {}", response); let name = loop {
match serde_json::from_str::<Value>(&response) { let mut response = String::new();
Ok(e) => { instance.reader.read_line(&mut response).unwrap();
if let Value::String(ref name) = e["event"] { response = response.trim_end().to_string();
let event: Event; debug!("Event: {}", response);
match name.as_str() {
"shutdown" => {
event = Event::Shutdown;
}
"start-file" => {
event = Event::StartFile;
}
"file-loaded" => {
event = Event::FileLoaded;
}
"seek" => {
event = Event::Seek;
}
"playback-restart" => {
event = Event::PlaybackRestart;
}
"idle" => {
event = Event::Idle;
}
"tick" => {
event = Event::Tick;
}
"video-reconfig" => {
event = Event::VideoReconfig;
}
"audio-reconfig" => {
event = Event::AudioReconfig;
}
"tracks-changed" => {
event = Event::TracksChanged;
}
"track-switched" => {
event = Event::TrackSwitched;
}
"pause" => {
event = Event::Pause;
}
"unpause" => {
event = Event::Unpause;
}
"metadata-update" => {
event = Event::MetadataUpdate;
}
"chapter-change" => {
event = Event::ChapterChange;
}
"end-file" => {
event = Event::EndFile;
}
"property-change" => {
let name: String;
let id: usize;
let data: MpvDataType;
if let Value::String(ref n) = e["name"] { e = serde_json::from_str::<Value>(&response)
name = n.to_string(); .map_err(|why| Error(ErrorCode::JsonParseError(why.to_string())))?;
} else {
return Err(Error(ErrorCode::JsonContainsUnexptectedType));
}
if let Value::Number(ref n) = e["id"] { match e["event"] {
id = n.as_i64().unwrap() as usize; Value::String(ref name) => break name,
} else { _ => {
id = 0; // It was not an event - try again
} debug!("Bad response: {:?}", response)
match e["data"] {
Value::String(ref n) => {
data = MpvDataType::String(n.to_string());
}
Value::Array(ref a) => {
if name == "playlist".to_string() {
data =
MpvDataType::Playlist(Playlist(json_array_to_playlist(a)));
} else {
data = MpvDataType::Array(json_array_to_vec(a));
}
}
Value::Bool(ref b) => {
data = MpvDataType::Bool(*b);
}
Value::Number(ref n) => {
if n.is_u64() {
data = MpvDataType::Usize(n.as_u64().unwrap() as usize);
} else if n.is_f64() {
data = MpvDataType::Double(n.as_f64().unwrap());
} else {
return Err(Error(ErrorCode::JsonContainsUnexptectedType));
}
}
Value::Object(ref m) => {
data = MpvDataType::HashMap(json_map_to_hashmap(m));
}
Value::Null => {
data = MpvDataType::Null;
}
}
event = try_convert_property(name.as_ref(), id, data);
}
_ => {
event = Event::Unimplemented;
}
};
return Ok(event);
} }
} }
Err(why) => return Err(Error(ErrorCode::JsonParseError(why.to_string()))), };
}
unreachable!(); let event = match name.as_str() {
"shutdown" => Event::Shutdown,
"start-file" => Event::StartFile,
"file-loaded" => Event::FileLoaded,
"seek" => Event::Seek,
"playback-restart" => Event::PlaybackRestart,
"idle" => Event::Idle,
"tick" => Event::Tick,
"video-reconfig" => Event::VideoReconfig,
"audio-reconfig" => Event::AudioReconfig,
"tracks-changed" => Event::TracksChanged,
"track-switched" => Event::TrackSwitched,
"pause" => Event::Pause,
"unpause" => Event::Unpause,
"metadata-update" => Event::MetadataUpdate,
"chapter-change" => Event::ChapterChange,
"end-file" => Event::EndFile,
"property-change" => {
let name = match e["name"] {
Value::String(ref n) => Ok(n.to_string()),
_ => Err(Error(ErrorCode::JsonContainsUnexptectedType)),
}?;
let id: usize = match e["id"] {
Value::Number(ref n) => n.as_u64().unwrap() as usize,
_ => 0,
};
let data: MpvDataType = match e["data"] {
Value::String(ref n) => MpvDataType::String(n.to_string()),
Value::Array(ref a) => {
if name == "playlist".to_string() {
MpvDataType::Playlist(Playlist(json_array_to_playlist(a)))
} else {
MpvDataType::Array(json_array_to_vec(a))
}
}
Value::Bool(b) => MpvDataType::Bool(b),
Value::Number(ref n) => {
if n.is_u64() {
MpvDataType::Usize(n.as_u64().unwrap() as usize)
} else if n.is_f64() {
MpvDataType::Double(n.as_f64().unwrap())
} else {
return Err(Error(ErrorCode::JsonContainsUnexptectedType));
}
}
Value::Object(ref m) => MpvDataType::HashMap(json_map_to_hashmap(m)),
Value::Null => MpvDataType::Null,
};
try_convert_property(name.as_ref(), id, data)
}
_ => Event::Unimplemented,
};
Ok(event)
} }
pub fn listen_raw(instance: &mut Mpv) -> String { pub fn listen_raw(instance: &mut Mpv) -> String {
let mut response = String::new(); let mut response = String::new();
instance.reader.read_line(&mut response).unwrap(); instance.reader.read_line(&mut response).unwrap();
response.trim_end().to_string() response.trim_end().to_string()
// let mut stream = &instance.0;
// let mut buffer = [0; 32];
// stream.read(&mut buffer[..]).unwrap();
// String::from_utf8_lossy(&buffer).into_owned()
} }
fn send_command_sync(instance: &Mpv, command: &str) -> String { fn send_command_sync(instance: &Mpv, command: &str) -> String {

View File

@ -54,7 +54,7 @@ pub enum MpvCommand {
}, },
Observe { Observe {
id: isize, id: isize,
property: String property: String,
}, },
PlaylistNext, PlaylistNext,
PlaylistPrev, PlaylistPrev,
@ -118,6 +118,7 @@ pub enum ErrorCode {
JsonContainsUnexptectedType, JsonContainsUnexptectedType,
UnexpectedResult, UnexpectedResult,
UnexpectedValue, UnexpectedValue,
MissingValue,
UnsupportedType, UnsupportedType,
ValueDoesNotContainBool, ValueDoesNotContainBool,
ValueDoesNotContainF64, ValueDoesNotContainF64,
@ -190,6 +191,7 @@ impl Display for ErrorCode {
} }
ErrorCode::UnexpectedResult => f.write_str("Unexpected result received"), ErrorCode::UnexpectedResult => f.write_str("Unexpected result received"),
ErrorCode::UnexpectedValue => f.write_str("Unexpected value received"), ErrorCode::UnexpectedValue => f.write_str("Unexpected value received"),
ErrorCode::MissingValue => f.write_str("Missing value"),
ErrorCode::UnsupportedType => f.write_str("Unsupported type received"), ErrorCode::UnsupportedType => f.write_str("Unsupported type received"),
ErrorCode::ValueDoesNotContainBool => { ErrorCode::ValueDoesNotContainBool => {
f.write_str("The received value is not of type \'std::bool\'") f.write_str("The received value is not of type \'std::bool\'")
@ -486,9 +488,7 @@ impl Mpv {
}, },
], ],
), ),
MpvCommand::Observe { id, property } => { MpvCommand::Observe { id, property } => observe_mpv_property(self, &id, &property),
observe_mpv_property(self, &id, &property)
}
MpvCommand::PlaylistClear => run_mpv_command(self, "playlist-clear", &[]), MpvCommand::PlaylistClear => run_mpv_command(self, "playlist-clear", &[]),
MpvCommand::PlaylistMove { from, to } => { MpvCommand::PlaylistMove { from, to } => {
run_mpv_command(self, "playlist-move", &[&from.to_string(), &to.to_string()]) run_mpv_command(self, "playlist-move", &[&from.to_string(), &to.to_string()])
@ -514,9 +514,7 @@ impl Mpv {
], ],
), ),
MpvCommand::Stop => run_mpv_command(self, "stop", &[]), MpvCommand::Stop => run_mpv_command(self, "stop", &[]),
MpvCommand::Unobserve(id) => { MpvCommand::Unobserve(id) => unobserve_mpv_property(self, &id),
unobserve_mpv_property(self, &id)
}
} }
} }