Merge branch 'master' into 'master'
clean up code and fix bug See merge request mpv-ipc/mpvipc!3
This commit is contained in:
commit
86662ffb6b
262
src/ipc.rs
262
src/ipc.rs
|
@ -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 {
|
||||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue