// Copyright (C) 2016-2017 Sebastian Dröge // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use ffi; use Object; use Element; use miniobject::*; use std::ptr; use std::mem; use std::ffi::CStr; use glib; use glib_ffi; use glib::translate::{from_glib, from_glib_none, from_glib_full, ToGlibPtr}; #[repr(C)] pub struct MessageImpl(ffi::GstMessage); pub type Message = GstRc; unsafe impl MiniObject for MessageImpl { type GstType = ffi::GstMessage; } // TODO builder pattern for message creation impl MessageImpl { pub fn get_src(&self) -> Object { unsafe { from_glib_none((*self.as_ptr()).src) } } pub fn get_seqnum(&self) -> u32 { unsafe { ffi::gst_message_get_seqnum(self.as_mut_ptr()) } } // TODO get_structure() pub fn view(&self) -> MessageView { let type_ = unsafe { (*self.as_ptr()).type_ }; if type_ == ffi::GST_MESSAGE_EOS { MessageView::Eos } else if type_ == ffi::GST_MESSAGE_ERROR { MessageView::Error(Error(self)) } else if type_ == ffi::GST_MESSAGE_WARNING { MessageView::Warning(Warning(self)) } else if type_ == ffi::GST_MESSAGE_INFO { MessageView::Info(Info(self)) } else if type_ == ffi::GST_MESSAGE_TAG { MessageView::Tag(Tag(self)) } else if type_ == ffi::GST_MESSAGE_BUFFERING { MessageView::Buffering(Buffering(self)) } else if type_ == ffi::GST_MESSAGE_STATE_CHANGED { MessageView::StateChanged(StateChanged(self)) } else if type_ == ffi::GST_MESSAGE_STATE_DIRTY { MessageView::StateDirty } else if type_ == ffi::GST_MESSAGE_STEP_DONE { MessageView::StepDone(StepDone(self)) } else if type_ == ffi::GST_MESSAGE_CLOCK_PROVIDE { MessageView::ClockProvide(ClockProvide(self)) } else if type_ == ffi::GST_MESSAGE_CLOCK_LOST { MessageView::ClockLost(ClockLost(self)) } else if type_ == ffi::GST_MESSAGE_NEW_CLOCK { MessageView::NewClock(NewClock(self)) } else if type_ == ffi::GST_MESSAGE_STRUCTURE_CHANGE { MessageView::StructureChange(StructureChange(self)) } else if type_ == ffi::GST_MESSAGE_STREAM_STATUS { MessageView::StreamStatus(StreamStatus(self)) } else if type_ == ffi::GST_MESSAGE_APPLICATION { MessageView::Application } else if type_ == ffi::GST_MESSAGE_ELEMENT { MessageView::Element } else if type_ == ffi::GST_MESSAGE_SEGMENT_START { MessageView::SegmentStart(SegmentStart(self)) } else if type_ == ffi::GST_MESSAGE_SEGMENT_DONE { MessageView::SegmentDone(SegmentDone(self)) } else if type_ == ffi::GST_MESSAGE_DURATION_CHANGED { MessageView::DurationChanged } else if type_ == ffi::GST_MESSAGE_LATENCY { MessageView::Latency } else if type_ == ffi::GST_MESSAGE_ASYNC_START { MessageView::AsyncStart } else if type_ == ffi::GST_MESSAGE_ASYNC_DONE { MessageView::AsyncDone(AsyncDone(self)) } else if type_ == ffi::GST_MESSAGE_REQUEST_STATE { MessageView::RequestState(RequestState(self)) } else if type_ == ffi::GST_MESSAGE_STEP_START { MessageView::StepStart(StepStart(self)) } else if type_ == ffi::GST_MESSAGE_QOS { MessageView::Qos(Qos(self)) } else if type_ == ffi::GST_MESSAGE_PROGRESS { MessageView::Progress(Progress(self)) } else if type_ == ffi::GST_MESSAGE_TOC { MessageView::Toc(Toc(self)) } else if type_ == ffi::GST_MESSAGE_RESET_TIME { MessageView::ResetTime(ResetTime(self)) } else if type_ == ffi::GST_MESSAGE_STREAM_START { MessageView::StreamStart(StreamStart(self)) } else if type_ == ffi::GST_MESSAGE_NEED_CONTEXT { MessageView::NeedContext(NeedContext(self)) } else if type_ == ffi::GST_MESSAGE_HAVE_CONTEXT { MessageView::HaveContext(HaveContext(self)) } else if type_ == ffi::GST_MESSAGE_DEVICE_ADDED { MessageView::DeviceAdded(DeviceAdded(self)) } else if type_ == ffi::GST_MESSAGE_DEVICE_REMOVED { MessageView::DeviceRemoved(DeviceRemoved(self)) } else if type_ == ffi::GST_MESSAGE_PROPERTY_NOTIFY { MessageView::PropertyNotify(PropertyNotify(self)) } else if type_ == ffi::GST_MESSAGE_STREAM_COLLECTION { MessageView::StreamCollection(StreamCollection(self)) } else if type_ == ffi::GST_MESSAGE_STREAMS_SELECTED { MessageView::StreamsSelected(StreamsSelected(self)) } else { MessageView::Other } } } pub enum MessageView<'a> { Eos, Error(Error<'a>), Warning(Warning<'a>), Info(Info<'a>), Tag(Tag<'a>), Buffering(Buffering<'a>), StateChanged(StateChanged<'a>), StateDirty, StepDone(StepDone<'a>), ClockProvide(ClockProvide<'a>), ClockLost(ClockLost<'a>), NewClock(NewClock<'a>), StructureChange(StructureChange<'a>), StreamStatus(StreamStatus<'a>), Application, Element, SegmentStart(SegmentStart<'a>), SegmentDone(SegmentDone<'a>), DurationChanged, Latency, AsyncStart, AsyncDone(AsyncDone<'a>), RequestState(RequestState<'a>), StepStart(StepStart<'a>), Qos(Qos<'a>), Progress(Progress<'a>), Toc(Toc<'a>), ResetTime(ResetTime<'a>), StreamStart(StreamStart<'a>), NeedContext(NeedContext<'a>), HaveContext(HaveContext<'a>), DeviceAdded(DeviceAdded<'a>), DeviceRemoved(DeviceRemoved<'a>), PropertyNotify(PropertyNotify<'a>), StreamCollection(StreamCollection<'a>), StreamsSelected(StreamsSelected<'a>), Redirect(Redirect<'a>), Other, __NonExhaustive, } pub struct Error<'a>(&'a MessageImpl); impl<'a> Error<'a> { pub fn get_error(&self) -> glib::Error { unsafe { let mut error = ptr::null_mut(); ffi::gst_message_parse_error(self.0.as_mut_ptr(), &mut error, ptr::null_mut()); from_glib_full(error) } } pub fn get_debug(&self) -> Option { unsafe { let mut debug = ptr::null_mut(); ffi::gst_message_parse_error(self.0.as_mut_ptr(), ptr::null_mut(), &mut debug); from_glib_full(debug) } } // TODO get_details() } pub struct Warning<'a>(&'a MessageImpl); impl<'a> Warning<'a> { pub fn get_error(&self) -> glib::Error { unsafe { let mut error = ptr::null_mut(); ffi::gst_message_parse_warning(self.0.as_mut_ptr(), &mut error, ptr::null_mut()); from_glib_full(error) } } pub fn get_debug(&self) -> Option { unsafe { let mut debug = ptr::null_mut(); ffi::gst_message_parse_warning(self.0.as_mut_ptr(), ptr::null_mut(), &mut debug); from_glib_full(debug) } } // TODO get_details() } pub struct Info<'a>(&'a MessageImpl); impl<'a> Info<'a> { pub fn get_error(&self) -> glib::Error { unsafe { let mut error = ptr::null_mut(); ffi::gst_message_parse_info(self.0.as_mut_ptr(), &mut error, ptr::null_mut()); from_glib_full(error) } } pub fn get_debug(&self) -> Option { unsafe { let mut debug = ptr::null_mut(); ffi::gst_message_parse_info(self.0.as_mut_ptr(), ptr::null_mut(), &mut debug); from_glib_full(debug) } } // TODO get_details() } pub struct Tag<'a>(&'a MessageImpl); impl<'a> Tag<'a> { // TODO: get_tags() } pub struct Buffering<'a>(&'a MessageImpl); impl<'a> Buffering<'a> { pub fn get_percent(&self) -> i32 { unsafe { let mut p = mem::uninitialized(); ffi::gst_message_parse_buffering(self.0.as_mut_ptr(), &mut p); p } } pub fn get_buffering_stats(&self) -> (::BufferingMode, i32, i32, i64) { unsafe { let mut mode = mem::uninitialized(); let mut avg_in = mem::uninitialized(); let mut avg_out = mem::uninitialized(); let mut buffering_left = mem::uninitialized(); ffi::gst_message_parse_buffering_stats(self.0.as_mut_ptr(), &mut mode, &mut avg_in, &mut avg_out, &mut buffering_left); (from_glib(mode), avg_in, avg_out, buffering_left) } } } pub struct StateChanged<'a>(&'a MessageImpl); impl<'a> StateChanged<'a> { pub fn get_old(&self) -> ::State { unsafe { let mut state = mem::uninitialized(); ffi::gst_message_parse_state_changed(self.0.as_mut_ptr(), &mut state, ptr::null_mut(), ptr::null_mut()); from_glib(state) } } pub fn get_current(&self) -> ::State { unsafe { let mut state = mem::uninitialized(); ffi::gst_message_parse_state_changed(self.0.as_mut_ptr(), ptr::null_mut(), &mut state, ptr::null_mut()); from_glib(state) } } pub fn get_pending(&self) -> ::State { unsafe { let mut state = mem::uninitialized(); ffi::gst_message_parse_state_changed(self.0.as_mut_ptr(), ptr::null_mut(), ptr::null_mut(), &mut state); from_glib(state) } } } pub struct StepDone<'a>(&'a MessageImpl); impl<'a> StepDone<'a> { pub fn get(&self) -> (::Format, u64, f64, bool, bool, u64, bool) { unsafe { let mut format = mem::uninitialized(); let mut amount = mem::uninitialized(); let mut rate = mem::uninitialized(); let mut flush = mem::uninitialized(); let mut intermediate = mem::uninitialized(); let mut duration = mem::uninitialized(); let mut eos = mem::uninitialized(); ffi::gst_message_parse_step_done(self.0.as_mut_ptr(), &mut format, &mut amount, &mut rate, &mut flush, &mut intermediate, &mut duration, &mut eos); (from_glib(format), amount, rate, from_glib(flush), from_glib(intermediate), duration, from_glib(eos)) } } } pub struct ClockProvide<'a>(&'a MessageImpl); impl<'a> ClockProvide<'a> { pub fn get_clock(&self) -> Option<::Clock> { let mut clock = ptr::null_mut(); unsafe { ffi::gst_message_parse_clock_provide(self.0.as_mut_ptr(), &mut clock, ptr::null_mut()); from_glib_none(clock) } } pub fn get_ready(&self) -> bool { unsafe { let mut ready = mem::uninitialized(); ffi::gst_message_parse_clock_provide(self.0.as_mut_ptr(), ptr::null_mut(), &mut ready); from_glib(ready) } } } pub struct ClockLost<'a>(&'a MessageImpl); impl<'a> ClockLost<'a> { pub fn get_clock(&self) -> Option<::Clock> { let mut clock = ptr::null_mut(); unsafe { ffi::gst_message_parse_clock_lost(self.0.as_mut_ptr(), &mut clock); from_glib_none(clock) } } } pub struct NewClock<'a>(&'a MessageImpl); impl<'a> NewClock<'a> { pub fn get_clock(&self) -> Option<::Clock> { let mut clock = ptr::null_mut(); unsafe { ffi::gst_message_parse_new_clock(self.0.as_mut_ptr(), &mut clock); from_glib_none(clock) } } } pub struct StructureChange<'a>(&'a MessageImpl); impl<'a> StructureChange<'a> { pub fn get(&self) -> (::StructureChangeType, Option, bool) { unsafe { let mut type_ = mem::uninitialized(); let mut owner = ptr::null_mut(); let mut busy = mem::uninitialized(); ffi::gst_message_parse_structure_change(self.0.as_mut_ptr(), &mut type_, &mut owner, &mut busy); (from_glib(type_), from_glib_none(owner), from_glib(busy)) } } } pub struct StreamStatus<'a>(&'a MessageImpl); impl<'a> StreamStatus<'a> { pub fn get(&self) -> (::StreamStatusType, Option) { unsafe { let mut type_ = mem::uninitialized(); let mut owner = ptr::null_mut(); ffi::gst_message_parse_stream_status(self.0.as_mut_ptr(), &mut type_, &mut owner); (from_glib(type_), from_glib_none(owner)) } } pub fn get_stream_status_object(&self) -> Option { unsafe { let value = ffi::gst_message_get_stream_status_object(self.0.as_mut_ptr()); from_glib_none(value) } } } pub struct SegmentStart<'a>(&'a MessageImpl); impl<'a> SegmentStart<'a> { pub fn get(&self) -> (::Format, i64) { unsafe { let mut format = mem::uninitialized(); let mut position = mem::uninitialized(); ffi::gst_message_parse_segment_start(self.0.as_mut_ptr(), &mut format, &mut position); (from_glib(format), position) } } } pub struct SegmentDone<'a>(&'a MessageImpl); impl<'a> SegmentDone<'a> { pub fn get(&self) -> (::Format, i64) { unsafe { let mut format = mem::uninitialized(); let mut position = mem::uninitialized(); ffi::gst_message_parse_segment_done(self.0.as_mut_ptr(), &mut format, &mut position); (from_glib(format), position) } } } pub struct AsyncDone<'a>(&'a MessageImpl); impl<'a> AsyncDone<'a> { pub fn get_running_time(&self) -> u64 { unsafe { let mut running_time = mem::uninitialized(); ffi::gst_message_parse_async_done(self.0.as_mut_ptr(), &mut running_time); running_time } } } pub struct RequestState<'a>(&'a MessageImpl); impl<'a> RequestState<'a> { pub fn get_requested_state(&self) -> ::State { unsafe { let mut state = mem::uninitialized(); ffi::gst_message_parse_request_state(self.0.as_mut_ptr(), &mut state); from_glib(state) } } } pub struct StepStart<'a>(&'a MessageImpl); impl<'a> StepStart<'a> { pub fn get(&self) -> (bool, ::Format, u64, f64, bool, bool) { unsafe { let mut active = mem::uninitialized(); let mut format = mem::uninitialized(); let mut amount = mem::uninitialized(); let mut rate = mem::uninitialized(); let mut flush = mem::uninitialized(); let mut intermediate = mem::uninitialized(); ffi::gst_message_parse_step_start(self.0.as_mut_ptr(), &mut active, &mut format, &mut amount, &mut rate, &mut flush, &mut intermediate); (from_glib(active), from_glib(format), amount, rate, from_glib(flush), from_glib(intermediate)) } } } pub struct Qos<'a>(&'a MessageImpl); impl<'a> Qos<'a> { pub fn get(&self) -> (bool, u64, u64, u64, u64) { unsafe { let mut live = mem::uninitialized(); let mut running_time = mem::uninitialized(); let mut stream_time = mem::uninitialized(); let mut timestamp = mem::uninitialized(); let mut duration = mem::uninitialized(); ffi::gst_message_parse_qos(self.0.as_mut_ptr(), &mut live, &mut running_time, &mut stream_time, &mut timestamp, &mut duration); (from_glib(live), running_time, stream_time, timestamp, duration) } } pub fn get_values(&self) -> (i64, f64, i32) { unsafe { let mut jitter = mem::uninitialized(); let mut proportion = mem::uninitialized(); let mut quality = mem::uninitialized(); ffi::gst_message_parse_qos_values(self.0.as_mut_ptr(), &mut jitter, &mut proportion, &mut quality); (jitter, proportion, quality) } } pub fn get_stats(&self) -> (::Format, u64, u64) { unsafe { let mut format = mem::uninitialized(); let mut processed = mem::uninitialized(); let mut dropped = mem::uninitialized(); ffi::gst_message_parse_qos_stats(self.0.as_mut_ptr(), &mut format, &mut processed, &mut dropped); (from_glib(format), processed, dropped) } } } pub struct Progress<'a>(&'a MessageImpl); pub struct Toc<'a>(&'a MessageImpl); impl<'a> Toc<'a> { // TODO get_toc() } pub struct ResetTime<'a>(&'a MessageImpl); impl<'a> ResetTime<'a> { pub fn get_running_time(&self) -> u64 { unsafe { let mut running_time = mem::uninitialized(); ffi::gst_message_parse_reset_time(self.0.as_mut_ptr(), &mut running_time); running_time } } } pub struct StreamStart<'a>(&'a MessageImpl); impl<'a> StreamStart<'a> { pub fn get_group_id(&self) -> Option { unsafe { let mut group_id = mem::uninitialized(); if from_glib(ffi::gst_message_parse_group_id(self.0.as_mut_ptr(), &mut group_id)) { Some(group_id) } else { None } } } } pub struct NeedContext<'a>(&'a MessageImpl); impl<'a> NeedContext<'a> { pub fn get_context_type(&self) -> Option<&str> { unsafe { let mut context_type = ptr::null(); if from_glib(ffi::gst_message_parse_context_type(self.0.as_mut_ptr(), &mut context_type)) && !context_type.is_null() { Some(CStr::from_ptr(context_type).to_str().unwrap()) } else { None } } } } pub struct HaveContext<'a>(&'a MessageImpl); impl<'a> HaveContext<'a> { // TODO: get_context() } pub struct DeviceAdded<'a>(&'a MessageImpl); impl<'a> DeviceAdded<'a> { pub fn get_device(&self) -> ::Device { unsafe { let mut device = ptr::null_mut(); ffi::gst_message_parse_device_added(self.0.as_mut_ptr(), &mut device); from_glib_none(device) } } } pub struct DeviceRemoved<'a>(&'a MessageImpl); impl<'a> DeviceRemoved<'a> { pub fn get_device(&self) -> ::Device { unsafe { let mut device = ptr::null_mut(); ffi::gst_message_parse_device_removed(self.0.as_mut_ptr(), &mut device); from_glib_none(device) } } } pub struct PropertyNotify<'a>(&'a MessageImpl); impl<'a> PropertyNotify<'a> { #[cfg(feature = "v1_10")] pub fn get(&self) -> (Object, &str, ::Value) { unsafe { let mut object = ptr::null_mut(); let mut property_name = ptr::null(); let mut value = ptr::null(); ffi::gst_message_parse_property_notify(self.0.as_mut_ptr(), &mut object, &mut property_name, &mut value); (from_glib_none(object), CStr::from_ptr(property_name).to_str().unwrap(), from_glib_none(value)) } } } pub struct StreamCollection<'a>(&'a MessageImpl); impl<'a> StreamCollection<'a> { #[cfg(feature = "v1_10")] pub fn get_stream_collection(&self) -> ::StreamCollection { unsafe { let mut collection = ptr::null_mut(); ffi::gst_message_parse_stream_selection(self.0.as_mut_ptr(), &mut collection); from_glib_full(collection) } } } pub struct StreamsSelected<'a>(&'a MessageImpl); impl<'a> StreamsSelected<'a> { #[cfg(feature = "v1_10")] pub fn get_stream_collection(&self) -> ::StreamCollection { unsafe { let mut collection = ptr::null_mut(); ffi::gst_message_parse_streams_selected(self.0.as_mut_ptr(), &mut collection); from_glib_full(collection) } } #[cfg(feature = "v1_10")] pub fn get_streams(&self) -> Vec<::Stream> { unsafe { let n = ffi::gst_message_streams_selected_get_size(self.0.as_mut_ptr()); (0..n).map(|i| from_glib_full(ffi::gst_message_streams_selected_get_stream(self.0.as_mut_ptr(), i))).collect() } } } pub struct Redirect<'a>(&'a MessageImpl); impl<'a> StreamsSelected<'a> { // TODO: tags, structure #[cfg(feature = "v1_10")] pub fn get_entries(&self) -> Vec<&str> { unsafe { let n = ffi::gst_message_num_redirect_entries(self.0.as_mut_ptr()); (0..n).map(|i| { let mut location = ptr::null(); ffi::gst_message_parse_redirect_entry(self.0.as_mut_ptr(), &mut location, ptr::null_mut(), ptr::null_mut()); CStr::from_ptr(location).to_str().unwrap() }).collect() } } } pub struct EosBuilder { src: Option, seqnum: Option, } impl EosBuilder { pub fn new() -> EosBuilder { EosBuilder { src: None, seqnum: None, } } pub fn src(self, src: Option) -> EosBuilder { EosBuilder { src: src, .. self } } pub fn seqnum(self, seqnum: u32) -> EosBuilder { EosBuilder { seqnum: Some(seqnum), .. self } } pub fn build(self) -> Message { unsafe { let msg = ffi::gst_message_new_eos(self.src.to_glib_none().0); if let Some(seqnum) = self.seqnum { ffi::gst_message_set_seqnum(msg, seqnum); } from_glib_full(msg) } } } impl glib::types::StaticType for GstRc { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_message_get_type()) } } }