// Copyright (C) 2018 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 std::ffi::CStr; use std::fmt; use std::mem; use std::ops; use std::ptr; use ffi; use glib::translate::*; use gst; use gst::prelude::*; use sdp_attribute::SDPAttribute; use sdp_bandwidth::SDPBandwidth; use sdp_connection::SDPConnection; use sdp_key::SDPKey; #[cfg(any(feature = "v1_8_1", feature = "dox"))] use MIKEYMessage; glib_wrapper! { #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SDPMedia(Boxed); match fn { copy => |ptr| { let mut copy = ptr::null_mut(); ffi::gst_sdp_media_copy(ptr as *const ffi::GstSDPMedia, &mut copy); copy }, free => |ptr| { ffi::gst_sdp_media_free(ptr); }, } } impl SDPMedia { pub fn new() -> Result { assert_initialized_main_thread!(); unsafe { let mut media = ptr::null_mut(); let result = ffi::gst_sdp_media_new(&mut media); match result { ffi::GST_SDP_OK => Ok(from_glib_full(media)), _ => Err(()), } } } } unsafe impl Send for SDPMedia {} unsafe impl Sync for SDPMedia {} impl ops::Deref for SDPMedia { type Target = SDPMediaRef; fn deref(&self) -> &SDPMediaRef { unsafe { &*(self.to_glib_none().0 as *const SDPMediaRef) } } } impl ops::DerefMut for SDPMedia { fn deref_mut(&mut self) -> &mut SDPMediaRef { unsafe { &mut *(self.to_glib_none_mut().0 as *mut SDPMediaRef) } } } impl fmt::Debug for SDPMedia { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ::fmt(&*self, f) } } impl fmt::Display for SDPMedia { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ::fmt(&*self, f) } } #[repr(C)] pub struct SDPMediaRef(ffi::GstSDPMedia); impl fmt::Debug for SDPMediaRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("SDPMedia") // TODO .finish() } } impl fmt::Display for SDPMediaRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.as_text() { Some(text) => f.write_str(text.as_str()), None => Err(fmt::Error), } } } unsafe impl Send for SDPMediaRef {} unsafe impl Sync for SDPMediaRef {} impl SDPMediaRef { pub fn add_attribute<'a, P: Into>>( &mut self, key: &str, value: P, ) -> Result<(), ()> { let value = value.into(); let value = value.to_glib_none(); let result = unsafe { ffi::gst_sdp_media_add_attribute(&mut self.0, key.to_glib_none().0, value.0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn add_bandwidth(&mut self, bwtype: &str, bandwidth: u32) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_add_bandwidth(&mut self.0, bwtype.to_glib_none().0, bandwidth) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn add_connection( &mut self, nettype: &str, addrtype: &str, address: &str, ttl: u32, addr_number: u32, ) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_add_connection( &mut self.0, nettype.to_glib_none().0, addrtype.to_glib_none().0, address.to_glib_none().0, ttl, addr_number, ) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn add_format(&mut self, format: &str) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_add_format(&mut self.0, format.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn as_text(&self) -> Option { unsafe { from_glib_full(ffi::gst_sdp_media_as_text(&self.0)) } } pub fn attributes_len(&self) -> u32 { unsafe { ffi::gst_sdp_media_attributes_len(&self.0) } } pub fn attributes_to_caps(&self, caps: &gst::Caps) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_attributes_to_caps(&self.0, caps.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn bandwidths_len(&self) -> u32 { unsafe { ffi::gst_sdp_media_bandwidths_len(&self.0) } } pub fn connections_len(&self) -> u32 { unsafe { ffi::gst_sdp_media_connections_len(&self.0) } } pub fn formats_len(&self) -> u32 { unsafe { ffi::gst_sdp_media_formats_len(&self.0) } } pub fn get_attribute(&self, idx: u32) -> Option<&SDPAttribute> { unsafe { let ptr = ffi::gst_sdp_media_get_attribute(&self.0, idx); if ptr.is_null() { None } else { Some(&*(ptr as *mut SDPAttribute)) } } } pub fn get_attribute_val(&self, key: &str) -> Option<&str> { unsafe { let ptr = ffi::gst_sdp_media_get_attribute_val(&self.0, key.to_glib_none().0); if ptr.is_null() { None } else { let result = CStr::from_ptr(ptr).to_str(); match result { Ok(attr) => Some(attr), Err(_) => None, } } } } pub fn get_attribute_val_n(&self, key: &str, nth: u32) -> Option<&str> { unsafe { let ptr = ffi::gst_sdp_media_get_attribute_val_n(&self.0, key.to_glib_none().0, nth); if ptr.is_null() { None } else { let result = CStr::from_ptr(ptr).to_str(); match result { Ok(attr) => Some(attr), Err(_) => None, } } } } pub fn get_bandwidth(&self, idx: u32) -> Option<&SDPBandwidth> { unsafe { let ptr = ffi::gst_sdp_media_get_bandwidth(&self.0, idx); if ptr.is_null() { None } else { Some(&*(ptr as *mut SDPBandwidth)) } } } pub fn get_caps_from_media(&self, pt: i32) -> Option { unsafe { from_glib_full(ffi::gst_sdp_media_get_caps_from_media(&self.0, pt)) } } pub fn get_connection(&self, idx: u32) -> Option<&SDPConnection> { unsafe { let ptr = ffi::gst_sdp_media_get_connection(&self.0, idx); if ptr.is_null() { None } else { Some(&*(ptr as *mut SDPConnection)) } } } pub fn get_format(&self, idx: u32) -> Option<&str> { unsafe { let ptr = ffi::gst_sdp_media_get_format(&self.0, idx); if ptr.is_null() { None } else { let result = CStr::from_ptr(ptr).to_str(); match result { Ok(attr) => Some(attr), Err(_) => None, } } } } pub fn get_information(&self) -> Option<&str> { unsafe { let ptr = ffi::gst_sdp_media_get_information(&self.0); if ptr.is_null() { None } else { let result = CStr::from_ptr(ptr).to_str(); match result { Ok(attr) => Some(attr), Err(_) => None, } } } } pub fn get_key(&self) -> Option<&SDPKey> { unsafe { let ptr = ffi::gst_sdp_media_get_key(&self.0); if ptr.is_null() { None } else { Some(&*(ptr as *mut SDPKey)) } } } pub fn get_media(&self) -> Option<&str> { unsafe { let ptr = ffi::gst_sdp_media_get_media(&self.0); if ptr.is_null() { None } else { let result = CStr::from_ptr(ptr).to_str(); match result { Ok(attr) => Some(attr), Err(_) => None, } } } } pub fn get_num_ports(&self) -> u32 { unsafe { ffi::gst_sdp_media_get_num_ports(&self.0) } } pub fn get_port(&self) -> u32 { unsafe { ffi::gst_sdp_media_get_port(&self.0) } } pub fn get_proto(&self) -> Option<&str> { unsafe { let ptr = ffi::gst_sdp_media_get_proto(&self.0); if ptr.is_null() { None } else { let result = CStr::from_ptr(ptr).to_str(); match result { Ok(attr) => Some(attr), Err(_) => None, } } } } pub fn insert_attribute(&mut self, idx: i32, mut attr: SDPAttribute) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_insert_attribute(&mut self.0, idx, &mut attr.0) }; mem::forget(attr); match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn insert_bandwidth(&mut self, idx: i32, mut bw: SDPBandwidth) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_insert_bandwidth(&mut self.0, idx, &mut bw.0) }; mem::forget(bw); match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn insert_connection(&mut self, idx: i32, mut conn: SDPConnection) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_insert_connection(&mut self.0, idx, &mut conn.0) }; mem::forget(conn); match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn insert_format(&mut self, idx: i32, format: &str) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_insert_format(&mut self.0, idx, format.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } #[cfg(any(feature = "v1_8_1", feature = "dox"))] pub fn parse_keymgmt(&self) -> Result { unsafe { let mut mikey = ptr::null_mut(); let result = ffi::gst_sdp_media_parse_keymgmt(&self.0, &mut mikey); match result { ffi::GST_SDP_OK => Ok(from_glib_full(mikey)), _ => Err(()), } } } pub fn remove_attribute(&mut self, idx: u32) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_remove_attribute(&mut self.0, idx) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn remove_bandwidth(&mut self, idx: u32) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_remove_bandwidth(&mut self.0, idx) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn remove_connection(&mut self, idx: u32) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_remove_connection(&mut self.0, idx) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn remove_format(&mut self, idx: u32) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_remove_format(&mut self.0, idx) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn replace_attribute(&mut self, idx: u32, mut attr: SDPAttribute) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_replace_attribute(&mut self.0, idx, &mut attr.0) }; mem::forget(attr); match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn replace_bandwidth(&mut self, idx: u32, mut bw: SDPBandwidth) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_replace_bandwidth(&mut self.0, idx, &mut bw.0) }; mem::forget(bw); match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn replace_connection(&mut self, idx: u32, mut conn: SDPConnection) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_replace_connection(&mut self.0, idx, &mut conn.0) }; mem::forget(conn); match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn replace_format(&mut self, idx: u32, format: &str) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_replace_format(&mut self.0, idx, format.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn set_information(&mut self, information: &str) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_set_information(&mut self.0, information.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn set_key(&mut self, type_: &str, data: &str) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_set_key(&mut self.0, type_.to_glib_none().0, data.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn set_media(&mut self, med: &str) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_set_media(&mut self.0, med.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn set_port_info(&mut self, port: u32, num_ports: u32) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_set_port_info(&mut self.0, port, num_ports) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn set_proto(&mut self, proto: &str) -> Result<(), ()> { let result = unsafe { ffi::gst_sdp_media_set_proto(&mut self.0, proto.to_glib_none().0) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } pub fn set_media_from_caps(caps: &gst::Caps, media: &mut SDPMedia) -> Result<(), ()> { assert_initialized_main_thread!(); let result = unsafe { ffi::gst_sdp_media_set_media_from_caps( caps.to_glib_none().0, media.to_glib_none_mut().0, ) }; match result { ffi::GST_SDP_OK => Ok(()), _ => Err(()), } } }