1use std::{
4 borrow::{Borrow, BorrowMut, ToOwned},
5 ffi::CStr,
6 fmt, mem, ops, ptr,
7};
8
9use glib::{prelude::*, translate::*};
10
11use crate::{
12 ffi,
13 sdp_attribute::SDPAttribute,
14 sdp_bandwidth::SDPBandwidth,
15 sdp_connection::SDPConnection,
16 sdp_key::SDPKey,
17 sdp_media::{SDPMedia, SDPMediaRef},
18 sdp_origin::SDPOrigin,
19 sdp_time::SDPTime,
20 sdp_zone::SDPZone,
21};
22
23glib::wrapper! {
24 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
25 #[doc(alias = "GstSDPMessage")]
26 pub struct SDPMessage(Boxed<ffi::GstSDPMessage>);
27
28 match fn {
29 copy => |ptr| {
30 let mut copy = std::ptr::null_mut();
31 let res = ffi::gst_sdp_message_copy(ptr, &mut copy);
32 debug_assert_eq!(res, ffi::GST_SDP_OK);
33 copy
34 },
35 free => |ptr| {
36 let res = ffi::gst_sdp_message_free(ptr);
37 debug_assert_eq!(res, ffi::GST_SDP_OK);
38 },
39 type_ => || ffi::gst_sdp_message_get_type(),
40 }
41}
42
43unsafe impl Send for SDPMessage {}
44unsafe impl Sync for SDPMessage {}
45
46impl Default for SDPMessage {
47 fn default() -> Self {
48 Self::new()
49 }
50}
51
52impl ops::Deref for SDPMessage {
53 type Target = SDPMessageRef;
54
55 fn deref(&self) -> &SDPMessageRef {
56 unsafe { &*(self.as_ptr() as *const SDPMessageRef) }
57 }
58}
59
60impl ops::DerefMut for SDPMessage {
61 fn deref_mut(&mut self) -> &mut SDPMessageRef {
62 unsafe { &mut *(self.to_glib_none_mut().0 as *mut SDPMessageRef) }
63 }
64}
65
66impl fmt::Debug for SDPMessage {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 <SDPMessageRef as fmt::Debug>::fmt(self, f)
69 }
70}
71
72impl fmt::Display for SDPMessage {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 <SDPMessageRef as fmt::Display>::fmt(self, f)
75 }
76}
77
78impl SDPMessage {
79 #[doc(alias = "gst_sdp_message_new")]
80 pub fn new() -> SDPMessage {
81 assert_initialized_main_thread!();
82 unsafe {
83 let mut msg = ptr::null_mut();
84 ffi::gst_sdp_message_new(&mut msg);
85 from_glib_full(msg)
86 }
87 }
88
89 #[doc(alias = "gst_sdp_message_parse_buffer")]
90 pub fn parse_buffer(data: &[u8]) -> Result<Self, glib::BoolError> {
91 assert_initialized_main_thread!();
92 unsafe {
93 let size = data.len() as u32;
94 let mut msg = ptr::null_mut();
95 ffi::gst_sdp_message_new(&mut msg);
96 let result = ffi::gst_sdp_message_parse_buffer(data.to_glib_none().0, size, msg);
97 match result {
98 ffi::GST_SDP_OK => Ok(from_glib_full(msg)),
99 _ => {
100 ffi::gst_sdp_message_uninit(msg);
101 Err(glib::bool_error!("Failed to parse buffer"))
102 }
103 }
104 }
105 }
106
107 #[doc(alias = "gst_sdp_message_parse_uri")]
108 pub fn parse_uri(uri: &str) -> Result<Self, glib::BoolError> {
109 assert_initialized_main_thread!();
110 unsafe {
111 let mut msg = ptr::null_mut();
112 ffi::gst_sdp_message_new(&mut msg);
113 let result = ffi::gst_sdp_message_parse_uri(uri.to_glib_none().0, msg);
114 match result {
115 ffi::GST_SDP_OK => Ok(from_glib_full(msg)),
116 _ => {
117 ffi::gst_sdp_message_uninit(msg);
118 Err(glib::bool_error!("Failed to parse URI"))
119 }
120 }
121 }
122 }
123}
124
125#[repr(transparent)]
126#[doc(alias = "GstSDPMessage")]
127pub struct SDPMessageRef(ffi::GstSDPMessage);
128
129impl fmt::Debug for SDPMessageRef {
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 use std::cell::RefCell;
132
133 struct DebugIter<I>(RefCell<I>);
134 impl<I: Iterator> fmt::Debug for DebugIter<I>
135 where
136 I::Item: fmt::Debug,
137 {
138 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
139 f.debug_list().entries(&mut *self.0.borrow_mut()).finish()
140 }
141 }
142
143 f.debug_struct("SDPMessage")
144 .field("connection", &self.connection())
145 .field("information", &self.information())
146 .field("key", &self.key())
147 .field("origin", &self.origin())
148 .field("session-name", &self.session_name())
149 .field("uri", &self.uri())
150 .field("version", &self.version())
151 .field("attributes", &DebugIter(RefCell::new(self.attributes())))
152 .field("bandwidths", &DebugIter(RefCell::new(self.bandwidths())))
153 .field("emails", &DebugIter(RefCell::new(self.emails())))
154 .field("medias", &DebugIter(RefCell::new(self.medias())))
155 .field("phones", &DebugIter(RefCell::new(self.phones())))
156 .field("times", &DebugIter(RefCell::new(self.times())))
157 .field("zones", &DebugIter(RefCell::new(self.zones())))
158 .finish()
159 }
160}
161
162impl fmt::Display for SDPMessageRef {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 match self.as_text() {
165 Ok(text) => f.write_str(text.as_str()),
166 Err(_) => Err(fmt::Error),
167 }
168 }
169}
170
171unsafe impl Send for SDPMessageRef {}
172unsafe impl Sync for SDPMessageRef {}
173
174impl SDPMessageRef {
175 #[doc(alias = "gst_sdp_message_add_attribute")]
176 pub fn add_attribute(&mut self, key: &str, value: Option<&str>) {
177 unsafe {
178 ffi::gst_sdp_message_add_attribute(
179 &mut self.0,
180 key.to_glib_none().0,
181 value.to_glib_none().0,
182 );
183 }
184 }
185
186 #[doc(alias = "gst_sdp_message_add_email")]
187 pub fn add_email(&mut self, email: &str) {
188 unsafe { ffi::gst_sdp_message_add_email(&mut self.0, email.to_glib_none().0) };
189 }
190
191 #[doc(alias = "gst_sdp_message_add_media")]
192 pub fn add_media(&mut self, media: SDPMedia) {
193 unsafe {
194 ffi::gst_sdp_message_add_media(&mut self.0, media.as_ptr());
195 }
196 }
197
198 #[doc(alias = "gst_sdp_message_add_phone")]
199 pub fn add_phone(&mut self, phone: &str) {
200 unsafe { ffi::gst_sdp_message_add_phone(&mut self.0, phone.to_glib_none().0) };
201 }
202
203 #[doc(alias = "gst_sdp_message_add_time")]
204 pub fn add_time(&mut self, start: &str, stop: &str, repeat: &[&str]) {
205 unsafe {
206 ffi::gst_sdp_message_add_time(
207 &mut self.0,
208 start.to_glib_none().0,
209 stop.to_glib_none().0,
210 repeat.to_glib_none().0,
211 )
212 };
213 }
214
215 #[doc(alias = "gst_sdp_message_add_zone")]
216 pub fn add_zone(&mut self, adj_time: &str, typed_time: &str) {
217 unsafe {
218 ffi::gst_sdp_message_add_zone(
219 &mut self.0,
220 adj_time.to_glib_none().0,
221 typed_time.to_glib_none().0,
222 )
223 };
224 }
225
226 #[doc(alias = "gst_sdp_message_as_text")]
227 pub fn as_text(&self) -> Result<String, glib::error::BoolError> {
228 unsafe {
229 match from_glib_full(ffi::gst_sdp_message_as_text(&self.0)) {
230 Some(s) => Ok(s),
231 None => Err(glib::bool_error!(
232 "Failed to convert the contents of message to a text string"
233 )),
234 }
235 }
236 }
237
238 #[doc(alias = "gst_sdp_message_attributes_len")]
239 pub fn attributes_len(&self) -> u32 {
240 unsafe { ffi::gst_sdp_message_attributes_len(&self.0) }
241 }
242
243 #[doc(alias = "gst_sdp_message_attributes_to_caps")]
244 pub fn attributes_to_caps(&self, caps: &mut gst::CapsRef) -> Result<(), glib::BoolError> {
245 let result = unsafe { ffi::gst_sdp_message_attributes_to_caps(&self.0, caps.as_mut_ptr()) };
246 match result {
247 ffi::GST_SDP_OK => Ok(()),
248 _ => Err(glib::bool_error!("Failed to store attributes in caps")),
249 }
250 }
251
252 #[doc(alias = "gst_sdp_message_bandwidths_len")]
253 pub fn bandwidths_len(&self) -> u32 {
254 unsafe { ffi::gst_sdp_message_bandwidths_len(&self.0) }
255 }
256
257 #[doc(alias = "gst_sdp_message_dump")]
258 pub fn dump(&self) {
259 unsafe { ffi::gst_sdp_message_dump(&self.0) };
260 }
261
262 #[doc(alias = "gst_sdp_message_emails_len")]
263 pub fn emails_len(&self) -> u32 {
264 unsafe { ffi::gst_sdp_message_emails_len(&self.0) }
265 }
266
267 #[doc(alias = "get_attribute")]
268 #[doc(alias = "gst_sdp_message_get_attribute")]
269 pub fn attribute(&self, idx: u32) -> Option<&SDPAttribute> {
270 if idx >= self.attributes_len() {
271 return None;
272 }
273
274 unsafe {
275 let ptr = ffi::gst_sdp_message_get_attribute(&self.0, idx);
276 if ptr.is_null() {
277 None
278 } else {
279 Some(&*(ptr as *mut SDPAttribute))
280 }
281 }
282 }
283
284 #[doc(alias = "get_attribute_val")]
285 #[doc(alias = "gst_sdp_message_get_attribute_val")]
286 pub fn attribute_val(&self, key: &str) -> Option<&str> {
287 unsafe {
288 let ptr = ffi::gst_sdp_message_get_attribute_val(&self.0, key.to_glib_none().0);
289 if ptr.is_null() {
290 None
291 } else {
292 CStr::from_ptr(ptr).to_str().ok()
293 }
294 }
295 }
296
297 #[doc(alias = "get_attribute_val_n")]
298 #[doc(alias = "gst_sdp_message_get_attribute_val_n")]
299 pub fn attribute_val_n(&self, key: &str, nth: u32) -> Option<&str> {
300 unsafe {
301 let ptr = ffi::gst_sdp_message_get_attribute_val_n(&self.0, key.to_glib_none().0, nth);
302 if ptr.is_null() {
303 None
304 } else {
305 CStr::from_ptr(ptr).to_str().ok()
306 }
307 }
308 }
309
310 #[doc(alias = "get_bandwidth")]
311 #[doc(alias = "gst_sdp_message_get_bandwidth")]
312 pub fn bandwidth(&self, idx: u32) -> Option<&SDPBandwidth> {
313 if idx >= self.bandwidths_len() {
314 return None;
315 }
316
317 unsafe {
318 let ptr = ffi::gst_sdp_message_get_bandwidth(&self.0, idx);
319 if ptr.is_null() {
320 None
321 } else {
322 Some(&*(ptr as *mut SDPBandwidth))
323 }
324 }
325 }
326
327 #[doc(alias = "get_connection")]
328 #[doc(alias = "gst_sdp_message_get_connection")]
329 pub fn connection(&self) -> Option<&SDPConnection> {
330 unsafe {
331 let ptr = ffi::gst_sdp_message_get_connection(&self.0);
332 if ptr.is_null() {
333 None
334 } else {
335 Some(&*(ptr as *mut SDPConnection))
336 }
337 }
338 }
339
340 #[doc(alias = "get_email")]
341 #[doc(alias = "gst_sdp_message_get_email")]
342 pub fn email(&self, idx: u32) -> Option<&str> {
343 if idx >= self.emails_len() {
344 return None;
345 }
346
347 unsafe {
348 let ptr = ffi::gst_sdp_message_get_email(&self.0, idx);
349 if ptr.is_null() {
350 None
351 } else {
352 CStr::from_ptr(ptr).to_str().ok()
353 }
354 }
355 }
356
357 #[doc(alias = "get_information")]
358 #[doc(alias = "gst_sdp_message_get_information")]
359 pub fn information(&self) -> Option<&str> {
360 unsafe {
361 let ptr = ffi::gst_sdp_message_get_information(&self.0);
362 if ptr.is_null() {
363 None
364 } else {
365 CStr::from_ptr(ptr).to_str().ok()
366 }
367 }
368 }
369
370 #[doc(alias = "get_key")]
371 #[doc(alias = "gst_sdp_message_get_key")]
372 pub fn key(&self) -> Option<&SDPKey> {
373 unsafe {
374 let ptr = ffi::gst_sdp_message_get_key(&self.0);
375 if ptr.is_null() {
376 None
377 } else {
378 Some(&*(ptr as *mut SDPKey))
379 }
380 }
381 }
382
383 #[doc(alias = "get_media")]
384 #[doc(alias = "gst_sdp_message_get_media")]
385 pub fn media(&self, idx: u32) -> Option<&SDPMediaRef> {
386 if idx >= self.medias_len() {
387 return None;
388 }
389
390 unsafe {
391 let ptr = ffi::gst_sdp_message_get_media(&self.0, idx);
392 if ptr.is_null() {
393 None
394 } else {
395 Some(&*(ptr as *const SDPMediaRef))
396 }
397 }
398 }
399
400 #[doc(alias = "get_media_mut")]
401 pub fn media_mut(&mut self, idx: u32) -> Option<&mut SDPMediaRef> {
402 if idx >= self.medias_len() {
403 return None;
404 }
405
406 unsafe {
407 let ptr = ffi::gst_sdp_message_get_media(&self.0, idx);
408 if ptr.is_null() {
409 None
410 } else {
411 Some(&mut *(ptr as *mut SDPMediaRef))
412 }
413 }
414 }
415
416 #[doc(alias = "get_origin")]
417 #[doc(alias = "gst_sdp_message_get_origin")]
418 pub fn origin(&self) -> Option<&SDPOrigin> {
419 unsafe {
420 let ptr = ffi::gst_sdp_message_get_origin(&self.0);
421 if ptr.is_null() {
422 None
423 } else {
424 Some(&*(ptr as *mut SDPOrigin))
425 }
426 }
427 }
428
429 #[doc(alias = "get_phone")]
430 #[doc(alias = "gst_sdp_message_get_phone")]
431 pub fn phone(&self, idx: u32) -> Option<&str> {
432 if idx >= self.phones_len() {
433 return None;
434 }
435
436 unsafe {
437 let ptr = ffi::gst_sdp_message_get_phone(&self.0, idx);
438 if ptr.is_null() {
439 None
440 } else {
441 CStr::from_ptr(ptr).to_str().ok()
442 }
443 }
444 }
445
446 #[doc(alias = "get_session_name")]
447 #[doc(alias = "gst_sdp_message_get_session_name")]
448 pub fn session_name(&self) -> Option<&str> {
449 unsafe {
450 let ptr = ffi::gst_sdp_message_get_session_name(&self.0);
451 if ptr.is_null() {
452 None
453 } else {
454 CStr::from_ptr(ptr).to_str().ok()
455 }
456 }
457 }
458
459 #[doc(alias = "get_time")]
460 #[doc(alias = "gst_sdp_message_get_time")]
461 pub fn time(&self, idx: u32) -> Option<&SDPTime> {
462 if idx >= self.times_len() {
463 return None;
464 }
465
466 unsafe {
467 let ptr = ffi::gst_sdp_message_get_time(&self.0, idx);
468 if ptr.is_null() {
469 None
470 } else {
471 Some(&*(ptr as *mut SDPTime))
472 }
473 }
474 }
475
476 #[doc(alias = "get_uri")]
477 #[doc(alias = "gst_sdp_message_get_uri")]
478 pub fn uri(&self) -> Option<&str> {
479 unsafe {
480 let ptr = ffi::gst_sdp_message_get_uri(&self.0);
481 if ptr.is_null() {
482 None
483 } else {
484 CStr::from_ptr(ptr).to_str().ok()
485 }
486 }
487 }
488
489 #[doc(alias = "get_version")]
490 #[doc(alias = "gst_sdp_message_get_version")]
491 pub fn version(&self) -> Option<&str> {
492 unsafe {
493 let ptr = ffi::gst_sdp_message_get_version(&self.0);
494 if ptr.is_null() {
495 None
496 } else {
497 CStr::from_ptr(ptr).to_str().ok()
498 }
499 }
500 }
501
502 #[doc(alias = "get_zone")]
503 #[doc(alias = "gst_sdp_message_get_zone")]
504 pub fn zone(&self, idx: u32) -> Option<&SDPZone> {
505 if idx >= self.zones_len() {
506 return None;
507 }
508
509 unsafe {
510 let ptr = ffi::gst_sdp_message_get_zone(&self.0, idx);
511 if ptr.is_null() {
512 None
513 } else {
514 Some(&*(ptr as *mut SDPZone))
515 }
516 }
517 }
518
519 #[doc(alias = "gst_sdp_message_insert_attribute")]
520 pub fn insert_attribute(
521 &mut self,
522 idx: Option<u32>,
523 attr: SDPAttribute,
524 ) -> Result<(), glib::BoolError> {
525 if let Some(idx) = idx {
526 if idx >= self.attributes_len() {
527 return Err(glib::bool_error!("Failed to insert attribute"));
528 }
529 }
530
531 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
532 let mut attr = mem::ManuallyDrop::new(attr);
533 let result =
534 unsafe { ffi::gst_sdp_message_insert_attribute(&mut self.0, idx, &mut attr.0) };
535 match result {
536 ffi::GST_SDP_OK => Ok(()),
537 _ => Err(glib::bool_error!("Failed to insert attribute")),
538 }
539 }
540
541 #[doc(alias = "gst_sdp_message_insert_bandwidth")]
542 pub fn insert_bandwidth(
543 &mut self,
544 idx: Option<u32>,
545 bw: SDPBandwidth,
546 ) -> Result<(), glib::BoolError> {
547 if let Some(idx) = idx {
548 if idx >= self.bandwidths_len() {
549 return Err(glib::bool_error!("Failed to insert bandwidth"));
550 }
551 }
552
553 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
554 let mut bw = mem::ManuallyDrop::new(bw);
555 let result = unsafe { ffi::gst_sdp_message_insert_bandwidth(&mut self.0, idx, &mut bw.0) };
556 match result {
557 ffi::GST_SDP_OK => Ok(()),
558 _ => Err(glib::bool_error!("Failed to insert bandwidth")),
559 }
560 }
561
562 #[doc(alias = "gst_sdp_message_insert_email")]
563 pub fn insert_email(&mut self, idx: Option<u32>, email: &str) -> Result<(), glib::BoolError> {
564 if let Some(idx) = idx {
565 if idx >= self.emails_len() {
566 return Err(glib::bool_error!("Failed to insert email"));
567 }
568 }
569
570 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
571 let result =
572 unsafe { ffi::gst_sdp_message_insert_email(&mut self.0, idx, email.to_glib_none().0) };
573 match result {
574 ffi::GST_SDP_OK => Ok(()),
575 _ => Err(glib::bool_error!("Failed to insert email")),
576 }
577 }
578
579 #[doc(alias = "gst_sdp_message_insert_phone")]
580 pub fn insert_phone(&mut self, idx: Option<u32>, phone: &str) -> Result<(), glib::BoolError> {
581 if let Some(idx) = idx {
582 if idx >= self.phones_len() {
583 return Err(glib::bool_error!("Failed to insert phone"));
584 }
585 }
586
587 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
588 let result =
589 unsafe { ffi::gst_sdp_message_insert_phone(&mut self.0, idx, phone.to_glib_none().0) };
590 match result {
591 ffi::GST_SDP_OK => Ok(()),
592 _ => Err(glib::bool_error!("Failed to insert phone")),
593 }
594 }
595
596 #[doc(alias = "gst_sdp_message_insert_time")]
597 pub fn insert_time(&mut self, idx: Option<u32>, time: SDPTime) -> Result<(), glib::BoolError> {
598 if let Some(idx) = idx {
599 if idx >= self.times_len() {
600 return Err(glib::bool_error!("Failed to insert time"));
601 }
602 }
603
604 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
605 let mut time = mem::ManuallyDrop::new(time);
606 let result = unsafe { ffi::gst_sdp_message_insert_time(&mut self.0, idx, &mut time.0) };
607 match result {
608 ffi::GST_SDP_OK => Ok(()),
609 _ => Err(glib::bool_error!("Failed to insert time")),
610 }
611 }
612
613 #[doc(alias = "gst_sdp_message_insert_zone")]
614 pub fn insert_zone(&mut self, idx: Option<u32>, zone: SDPZone) -> Result<(), glib::BoolError> {
615 if let Some(idx) = idx {
616 if idx >= self.zones_len() {
617 return Err(glib::bool_error!("Failed to insert zone"));
618 }
619 }
620
621 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
622 let mut zone = mem::ManuallyDrop::new(zone);
623 let result = unsafe { ffi::gst_sdp_message_insert_zone(&mut self.0, idx, &mut zone.0) };
624 match result {
625 ffi::GST_SDP_OK => Ok(()),
626 _ => Err(glib::bool_error!("Failed to insert zone")),
627 }
628 }
629
630 #[doc(alias = "gst_sdp_message_medias_len")]
631 pub fn medias_len(&self) -> u32 {
632 unsafe { ffi::gst_sdp_message_medias_len(&self.0) }
633 }
634
635 #[doc(alias = "gst_sdp_message_phones_len")]
636 pub fn phones_len(&self) -> u32 {
637 unsafe { ffi::gst_sdp_message_phones_len(&self.0) }
638 }
639
640 #[doc(alias = "gst_sdp_message_remove_attribute")]
641 pub fn remove_attribute(&mut self, idx: u32) -> Result<(), glib::BoolError> {
642 if idx >= self.attributes_len() {
643 return Err(glib::bool_error!("Failed to remove attribute"));
644 }
645
646 let result = unsafe { ffi::gst_sdp_message_remove_attribute(&mut self.0, idx) };
647 match result {
648 ffi::GST_SDP_OK => Ok(()),
649 _ => Err(glib::bool_error!("Failed to remove attribute")),
650 }
651 }
652
653 #[doc(alias = "gst_sdp_message_remove_bandwidth")]
654 pub fn remove_bandwidth(&mut self, idx: u32) -> Result<(), glib::BoolError> {
655 if idx >= self.bandwidths_len() {
656 return Err(glib::bool_error!("Failed to remove bandwidth"));
657 }
658
659 let result = unsafe { ffi::gst_sdp_message_remove_bandwidth(&mut self.0, idx) };
660 match result {
661 ffi::GST_SDP_OK => Ok(()),
662 _ => Err(glib::bool_error!("Failed to remove bandwidth")),
663 }
664 }
665
666 #[doc(alias = "gst_sdp_message_remove_email")]
667 pub fn remove_email(&mut self, idx: u32) -> Result<(), glib::BoolError> {
668 if idx >= self.emails_len() {
669 return Err(glib::bool_error!("Failed to remove email"));
670 }
671
672 let result = unsafe { ffi::gst_sdp_message_remove_email(&mut self.0, idx) };
673 match result {
674 ffi::GST_SDP_OK => Ok(()),
675 _ => Err(glib::bool_error!("Failed to remove email")),
676 }
677 }
678
679 #[doc(alias = "gst_sdp_message_remove_phone")]
680 pub fn remove_phone(&mut self, idx: u32) -> Result<(), glib::BoolError> {
681 if idx >= self.phones_len() {
682 return Err(glib::bool_error!("Failed to remove phone"));
683 }
684
685 let result = unsafe { ffi::gst_sdp_message_remove_phone(&mut self.0, idx) };
686 match result {
687 ffi::GST_SDP_OK => Ok(()),
688 _ => Err(glib::bool_error!("Failed to remove phone")),
689 }
690 }
691
692 #[doc(alias = "gst_sdp_message_remove_time")]
693 pub fn remove_time(&mut self, idx: u32) -> Result<(), glib::BoolError> {
694 if idx >= self.times_len() {
695 return Err(glib::bool_error!("Failed to remove time"));
696 }
697
698 let result = unsafe { ffi::gst_sdp_message_remove_time(&mut self.0, idx) };
699 match result {
700 ffi::GST_SDP_OK => Ok(()),
701 _ => Err(glib::bool_error!("Failed to remove time")),
702 }
703 }
704
705 #[doc(alias = "gst_sdp_message_remove_zone")]
706 pub fn remove_zone(&mut self, idx: u32) -> Result<(), glib::BoolError> {
707 if idx >= self.zones_len() {
708 return Err(glib::bool_error!("Failed to remove zone"));
709 }
710
711 let result = unsafe { ffi::gst_sdp_message_remove_zone(&mut self.0, idx) };
712 match result {
713 ffi::GST_SDP_OK => Ok(()),
714 _ => Err(glib::bool_error!("Failed to remove zone")),
715 }
716 }
717
718 #[doc(alias = "gst_sdp_message_replace_attribute")]
719 pub fn replace_attribute(
720 &mut self,
721 idx: u32,
722 attr: SDPAttribute,
723 ) -> Result<(), glib::BoolError> {
724 if idx >= self.attributes_len() {
725 return Err(glib::bool_error!("Failed to replace attribute"));
726 }
727
728 let mut attr = mem::ManuallyDrop::new(attr);
729 let result =
730 unsafe { ffi::gst_sdp_message_replace_attribute(&mut self.0, idx, &mut attr.0) };
731 match result {
732 ffi::GST_SDP_OK => Ok(()),
733 _ => Err(glib::bool_error!("Failed to replace attribute")),
734 }
735 }
736
737 #[doc(alias = "gst_sdp_message_replace_bandwidth")]
738 pub fn replace_bandwidth(&mut self, idx: u32, bw: SDPBandwidth) -> Result<(), glib::BoolError> {
739 if idx >= self.bandwidths_len() {
740 return Err(glib::bool_error!("Failed to replace bandwidth"));
741 }
742
743 let mut bw = mem::ManuallyDrop::new(bw);
744 let result = unsafe { ffi::gst_sdp_message_replace_bandwidth(&mut self.0, idx, &mut bw.0) };
745 match result {
746 ffi::GST_SDP_OK => Ok(()),
747 _ => Err(glib::bool_error!("Failed to replace bandwidth")),
748 }
749 }
750
751 #[doc(alias = "gst_sdp_message_replace_email")]
752 pub fn replace_email(&mut self, idx: u32, email: &str) -> Result<(), glib::BoolError> {
753 if idx >= self.emails_len() {
754 return Err(glib::bool_error!("Failed to replace email"));
755 }
756
757 let result =
758 unsafe { ffi::gst_sdp_message_replace_email(&mut self.0, idx, email.to_glib_none().0) };
759 match result {
760 ffi::GST_SDP_OK => Ok(()),
761 _ => Err(glib::bool_error!("Failed to replace email")),
762 }
763 }
764
765 #[doc(alias = "gst_sdp_message_replace_phone")]
766 pub fn replace_phone(&mut self, idx: u32, phone: &str) -> Result<(), glib::BoolError> {
767 if idx >= self.phones_len() {
768 return Err(glib::bool_error!("Failed to replace phone"));
769 }
770
771 let result =
772 unsafe { ffi::gst_sdp_message_replace_phone(&mut self.0, idx, phone.to_glib_none().0) };
773 match result {
774 ffi::GST_SDP_OK => Ok(()),
775 _ => Err(glib::bool_error!("Failed to replace phone")),
776 }
777 }
778
779 #[doc(alias = "gst_sdp_message_replace_time")]
780 pub fn replace_time(&mut self, idx: u32, time: SDPTime) -> Result<(), glib::BoolError> {
781 if idx >= self.times_len() {
782 return Err(glib::bool_error!("Failed to replace time"));
783 }
784
785 let mut time = mem::ManuallyDrop::new(time);
786 let result = unsafe { ffi::gst_sdp_message_replace_time(&mut self.0, idx, &mut time.0) };
787 match result {
788 ffi::GST_SDP_OK => Ok(()),
789 _ => Err(glib::bool_error!("Failed to replace time")),
790 }
791 }
792
793 #[doc(alias = "gst_sdp_message_replace_zone")]
794 pub fn replace_zone(&mut self, idx: u32, zone: SDPZone) -> Result<(), glib::BoolError> {
795 if idx >= self.zones_len() {
796 return Err(glib::bool_error!("Failed to replace zone"));
797 }
798
799 let mut zone = mem::ManuallyDrop::new(zone);
800 let result = unsafe { ffi::gst_sdp_message_replace_zone(&mut self.0, idx, &mut zone.0) };
801 match result {
802 ffi::GST_SDP_OK => Ok(()),
803 _ => Err(glib::bool_error!("Failed to replace zone")),
804 }
805 }
806
807 #[doc(alias = "gst_sdp_message_set_connection")]
808 pub fn set_connection(
809 &mut self,
810 nettype: &str,
811 addrtype: &str,
812 address: &str,
813 ttl: u32,
814 addr_number: u32,
815 ) {
816 unsafe {
817 ffi::gst_sdp_message_set_connection(
818 &mut self.0,
819 nettype.to_glib_none().0,
820 addrtype.to_glib_none().0,
821 address.to_glib_none().0,
822 ttl,
823 addr_number,
824 )
825 };
826 }
827
828 #[doc(alias = "gst_sdp_message_set_information")]
829 pub fn set_information(&mut self, information: &str) {
830 unsafe { ffi::gst_sdp_message_set_information(&mut self.0, information.to_glib_none().0) };
831 }
832
833 #[doc(alias = "gst_sdp_message_set_key")]
834 pub fn set_key(&mut self, type_: &str, data: &str) {
835 unsafe {
836 ffi::gst_sdp_message_set_key(&mut self.0, type_.to_glib_none().0, data.to_glib_none().0)
837 };
838 }
839
840 #[doc(alias = "gst_sdp_message_set_origin")]
841 pub fn set_origin(
842 &mut self,
843 username: &str,
844 sess_id: &str,
845 sess_version: &str,
846 nettype: &str,
847 addrtype: &str,
848 addr: &str,
849 ) {
850 unsafe {
851 ffi::gst_sdp_message_set_origin(
852 &mut self.0,
853 username.to_glib_none().0,
854 sess_id.to_glib_none().0,
855 sess_version.to_glib_none().0,
856 nettype.to_glib_none().0,
857 addrtype.to_glib_none().0,
858 addr.to_glib_none().0,
859 )
860 };
861 }
862
863 #[doc(alias = "gst_sdp_message_set_session_name")]
864 pub fn set_session_name(&mut self, session_name: &str) {
865 unsafe {
866 ffi::gst_sdp_message_set_session_name(&mut self.0, session_name.to_glib_none().0)
867 };
868 }
869
870 #[doc(alias = "gst_sdp_message_set_uri")]
871 pub fn set_uri(&mut self, uri: &str) {
872 unsafe { ffi::gst_sdp_message_set_uri(&mut self.0, uri.to_glib_none().0) };
873 }
874
875 #[doc(alias = "gst_sdp_message_set_version")]
876 pub fn set_version(&mut self, version: &str) {
877 unsafe { ffi::gst_sdp_message_set_version(&mut self.0, version.to_glib_none().0) };
878 }
879
880 #[doc(alias = "gst_sdp_message_times_len")]
881 pub fn times_len(&self) -> u32 {
882 unsafe { ffi::gst_sdp_message_times_len(&self.0) }
883 }
884
885 #[doc(alias = "gst_sdp_message_zones_len")]
886 pub fn zones_len(&self) -> u32 {
887 unsafe { ffi::gst_sdp_message_zones_len(&self.0) }
888 }
889
890 #[doc(alias = "gst_sdp_message_as_uri")]
891 pub fn as_uri(&self, scheme: &str) -> Result<String, glib::error::BoolError> {
892 skip_assert_initialized!();
893 unsafe {
894 match from_glib_full(ffi::gst_sdp_message_as_uri(
895 scheme.to_glib_none().0,
896 &self.0,
897 )) {
898 Some(s) => Ok(s),
899 None => Err(glib::bool_error!("Failed to create an URI from message")),
900 }
901 }
902 }
903
904 pub fn attributes(&self) -> AttributesIter {
905 AttributesIter::new(self)
906 }
907
908 pub fn bandwidths(&self) -> BandwidthsIter {
909 BandwidthsIter::new(self)
910 }
911
912 pub fn emails(&self) -> EmailsIter {
913 EmailsIter::new(self)
914 }
915
916 pub fn medias(&self) -> MediasIter {
917 MediasIter::new(self)
918 }
919
920 pub fn medias_mut(&mut self) -> MediasIterMut {
921 MediasIterMut::new(self)
922 }
923
924 pub fn phones(&self) -> PhonesIter {
925 PhonesIter::new(self)
926 }
927
928 pub fn times(&self) -> TimesIter {
929 TimesIter::new(self)
930 }
931
932 pub fn zones(&self) -> ZonesIter {
933 ZonesIter::new(self)
934 }
935}
936
937impl Borrow<SDPMessageRef> for SDPMessage {
938 fn borrow(&self) -> &SDPMessageRef {
939 self
940 }
941}
942
943impl BorrowMut<SDPMessageRef> for SDPMessage {
944 fn borrow_mut(&mut self) -> &mut SDPMessageRef {
945 &mut *self
946 }
947}
948
949impl ToOwned for SDPMessageRef {
950 type Owned = SDPMessage;
951
952 fn to_owned(&self) -> SDPMessage {
953 unsafe {
954 let mut ptr = ptr::null_mut();
955 ffi::gst_sdp_message_copy(&self.0, &mut ptr);
956 from_glib_full(ptr)
957 }
958 }
959}
960
961impl glib::types::StaticType for SDPMessageRef {
962 fn static_type() -> glib::types::Type {
963 unsafe { from_glib(ffi::gst_sdp_message_get_type()) }
964 }
965}
966
967unsafe impl<'a> glib::value::FromValue<'a> for &'a SDPMessageRef {
968 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
969
970 unsafe fn from_value(value: &'a glib::Value) -> Self {
971 skip_assert_initialized!();
972 &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut SDPMessageRef)
973 }
974}
975
976impl glib::value::ToValue for SDPMessageRef {
977 fn to_value(&self) -> glib::Value {
978 let mut value = glib::Value::for_value_type::<SDPMessage>();
979 unsafe {
980 glib::gobject_ffi::g_value_set_boxed(
981 value.to_glib_none_mut().0,
982 &self.0 as *const ffi::GstSDPMessage as *mut _,
983 )
984 }
985 value
986 }
987
988 fn value_type(&self) -> glib::Type {
989 Self::static_type()
990 }
991}
992
993impl glib::value::ToValueOptional for SDPMessageRef {
994 fn to_value_optional(s: Option<&Self>) -> glib::Value {
995 skip_assert_initialized!();
996 let mut value = glib::Value::for_value_type::<SDPMessage>();
997 unsafe {
998 glib::gobject_ffi::g_value_set_boxed(
999 value.to_glib_none_mut().0,
1000 s.map(|s| &s.0 as *const ffi::GstSDPMessage)
1001 .unwrap_or(ptr::null()) as *mut _,
1002 )
1003 }
1004 value
1005 }
1006}
1007
1008macro_rules! define_iter(
1009 ($name:ident, $typ:ty, $get_item:expr, $get_len:expr) => {
1010 #[derive(Debug)]
1011 pub struct $name<'a> {
1012 message: &'a SDPMessageRef,
1013 idx: usize,
1014 len: usize,
1015 }
1016
1017 #[allow(clippy::redundant_closure_call)]
1018 impl<'a> $name<'a> {
1019 fn new(message: &'a SDPMessageRef) -> $name<'a> {
1020 skip_assert_initialized!();
1021 let len = $get_len(message);
1022
1023 $name {
1024 message,
1025 idx: 0,
1026 len: len as usize,
1027 }
1028 }
1029 }
1030
1031 #[allow(clippy::redundant_closure_call)]
1032 impl<'a> Iterator for $name<'a> {
1033 type Item = $typ;
1034
1035 fn next(&mut self) -> Option<Self::Item> {
1036 if self.idx >= self.len {
1037 return None;
1038 }
1039
1040 let item = $get_item(self.message, self.idx as u32).unwrap();
1041 self.idx += 1;
1042 Some(item)
1043 }
1044
1045 fn size_hint(&self) -> (usize, Option<usize>) {
1046 let remaining = self.len - self.idx;
1047
1048 (remaining, Some(remaining))
1049 }
1050
1051 fn count(self) -> usize {
1052 self.len - self.idx
1053 }
1054
1055 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1056 let (end, overflow) = self.idx.overflowing_add(n);
1057 if end >= self.len || overflow {
1058 self.idx = self.len;
1059 None
1060 } else {
1061 self.idx = end + 1;
1062 Some($get_item(self.message, end as u32).unwrap())
1063 }
1064 }
1065
1066 fn last(self) -> Option<Self::Item> {
1067 if self.idx == self.len {
1068 None
1069 } else {
1070 Some($get_item(self.message, self.len as u32 - 1).unwrap())
1071 }
1072 }
1073 }
1074
1075 #[allow(clippy::redundant_closure_call)]
1076 impl<'a> DoubleEndedIterator for $name<'a> {
1077 fn next_back(&mut self) -> Option<Self::Item> {
1078 if self.idx == self.len {
1079 return None;
1080 }
1081
1082 self.len -= 1;
1083
1084 Some($get_item(self.message, self.len as u32).unwrap())
1085 }
1086
1087 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1088 let (end, overflow) = self.len.overflowing_sub(n);
1089 if end <= self.idx || overflow {
1090 self.idx = self.len;
1091 None
1092 } else {
1093 self.len = end - 1;
1094 Some($get_item(self.message, self.len as u32).unwrap())
1095 }
1096 }
1097 }
1098
1099 impl<'a> ExactSizeIterator for $name<'a> {}
1100 impl<'a> std::iter::FusedIterator for $name<'a> {}
1101 }
1102);
1103
1104macro_rules! define_iter_mut(
1105 ($name:ident, $typ:ty, $get_item:expr, $get_len:expr) => {
1106 #[derive(Debug)]
1107 pub struct $name<'a> {
1108 message: &'a mut SDPMessageRef,
1109 idx: usize,
1110 len: usize,
1111 }
1112
1113 #[allow(clippy::redundant_closure_call)]
1114 impl<'a> $name<'a> {
1115 fn new(message: &'a mut SDPMessageRef) -> $name<'a> {
1116 skip_assert_initialized!();
1117 let len = $get_len(message);
1118
1119 $name {
1120 message,
1121 idx: 0,
1122 len: len as usize,
1123 }
1124 }
1125 }
1126
1127 #[allow(clippy::redundant_closure_call)]
1128 impl<'a> Iterator for $name<'a> {
1129 type Item = $typ;
1130
1131 fn next(&mut self) -> Option<Self::Item> {
1132 let message = unsafe {
1142 &mut *(self.message as *mut SDPMessageRef)
1143 };
1144 if self.idx >= self.len {
1145 return None;
1146 }
1147
1148 let item = $get_item(message, self.idx as u32).unwrap();
1149 self.idx += 1;
1150 Some(item)
1151 }
1152
1153 fn size_hint(&self) -> (usize, Option<usize>) {
1154 let remaining = self.len - self.idx;
1155
1156 (remaining, Some(remaining))
1157 }
1158
1159
1160 fn count(self) -> usize {
1161 self.len - self.idx
1162 }
1163
1164 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1165 let message = unsafe {
1166 &mut *(self.message as *mut SDPMessageRef)
1167 };
1168 let (end, overflow) = self.idx.overflowing_add(n);
1169 if end >= self.len || overflow {
1170 self.idx = self.len;
1171 None
1172 } else {
1173 self.idx = end + 1;
1174 Some($get_item(message, end as u32).unwrap())
1175 }
1176 }
1177
1178 fn last(self) -> Option<Self::Item> {
1179 if self.idx == self.len {
1180 None
1181 } else {
1182 Some($get_item(self.message, self.len as u32 - 1).unwrap())
1183 }
1184 }
1185 }
1186
1187 #[allow(clippy::redundant_closure_call)]
1188 impl<'a> DoubleEndedIterator for $name<'a> {
1189 fn next_back(&mut self) -> Option<Self::Item> {
1190 let message = unsafe {
1191 &mut *(self.message as *mut SDPMessageRef)
1192 };
1193 if self.idx == self.len {
1194 return None;
1195 }
1196
1197 self.len -= 1;
1198 Some($get_item(message, self.len as u32).unwrap())
1199 }
1200
1201
1202 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1203 let message = unsafe {
1204 &mut *(self.message as *mut SDPMessageRef)
1205 };
1206 let (end, overflow) = self.len.overflowing_sub(n);
1207 if end <= self.idx || overflow {
1208 self.idx = self.len;
1209 None
1210 } else {
1211 self.len = end - 1;
1212 Some($get_item(message, self.len as u32).unwrap())
1213 }
1214 }
1215 }
1216
1217 impl<'a> ExactSizeIterator for $name<'a> {}
1218 impl<'a> std::iter::FusedIterator for $name<'a> {}
1219 }
1220);
1221
1222define_iter!(
1223 AttributesIter,
1224 &'a SDPAttribute,
1225 |message: &'a SDPMessageRef, idx| message.attribute(idx),
1226 |message: &SDPMessageRef| message.attributes_len()
1227);
1228define_iter!(
1229 BandwidthsIter,
1230 &'a SDPBandwidth,
1231 |message: &'a SDPMessageRef, idx| message.bandwidth(idx),
1232 |message: &SDPMessageRef| message.bandwidths_len()
1233);
1234define_iter!(
1235 EmailsIter,
1236 &'a str,
1237 |message: &'a SDPMessageRef, idx| message.email(idx),
1238 |message: &SDPMessageRef| message.emails_len()
1239);
1240define_iter!(
1241 MediasIter,
1242 &'a SDPMediaRef,
1243 |message: &'a SDPMessageRef, idx| message.media(idx),
1244 |message: &SDPMessageRef| message.medias_len()
1245);
1246define_iter_mut!(
1247 MediasIterMut,
1248 &'a mut SDPMediaRef,
1249 |message: &'a mut SDPMessageRef, idx| message.media_mut(idx),
1250 |message: &SDPMessageRef| message.medias_len()
1251);
1252define_iter!(
1253 PhonesIter,
1254 &'a str,
1255 |message: &'a SDPMessageRef, idx| message.phone(idx),
1256 |message: &SDPMessageRef| message.phones_len()
1257);
1258define_iter!(
1259 TimesIter,
1260 &'a SDPTime,
1261 |message: &'a SDPMessageRef, idx| message.time(idx),
1262 |message: &SDPMessageRef| message.times_len()
1263);
1264define_iter!(
1265 ZonesIter,
1266 &'a SDPZone,
1267 |message: &'a SDPMessageRef, idx| message.zone(idx),
1268 |message: &SDPMessageRef| message.zones_len()
1269);
1270
1271#[cfg(test)]
1272mod tests {
1273 use crate::SDPMessage;
1274
1275 fn init() {
1276 gst::init().unwrap();
1277 }
1278
1279 #[test]
1280 fn media_from_message() {
1281 init();
1282
1283 let sdp = "v=0\r\no=- 1938737043334325940 0 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\na=ice-options:trickle\r\nm=video 9 UDP/TLS/RTP/SAVPF 96\r\nc=IN IP4 0.0.0.0\r\na=setup:actpass\r\na=ice-ufrag:YZxU9JlWHzHcF6O2U09/q3PvBhbTPdZW\r\na=ice-pwd:fyrt730GWo5mFGc9m2z/vbUu3z1lewla\r\na=sendrecv\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:96 VP8/90000\r\na=rtcp-fb:96 nack\r\na=rtcp-fb:96 nack pli\r\na=framerate:30\r\na=mid:video0\r\na=fingerprint:sha-256 DB:48:8F:18:13:F3:AA:13:31:B3:75:3D:1A:D3:BA:88:4A:ED:1B:56:14:C3:09:CD:BC:4D:18:42:B9:6A:5F:98\r\nm=audio 9 UDP/TLS/RTP/SAVPF 97\r\nc=IN IP4 0.0.0.0\r\na=setup:actpass\r\na=ice-ufrag:04KZM9qE2S4r06AN6A9CeXOM6mzO0LZY\r\na=ice-pwd:cJTSfHF6hHDAcsTJXZVJeuYCC6rKqBvW\r\na=sendrecv\r\na=rtcp-mux\r\na=rtcp-rsize\r\na=rtpmap:97 OPUS/48000/2\r\na=rtcp-fb:97 nack\r\na=rtcp-fb:97 nack pli\r\na=mid:audio1\r\na=fingerprint:sha-256 DB:48:8F:18:13:F3:AA:13:31:B3:75:3D:1A:D3:BA:88:4A:ED:1B:56:14:C3:09:CD:BC:4D:18:42:B9:6A:5F:98\r\n";
1284 let sdp = SDPMessage::parse_buffer(sdp.as_bytes()).unwrap();
1285 let media = sdp.media(0).unwrap();
1286 assert_eq!(media.formats_len(), 1);
1287 }
1288
1289 #[test]
1290 fn debug_impl() {
1291 init();
1292
1293 let sdp = SDPMessage::new();
1294 assert!(!format!("{sdp:?}").is_empty());
1295 }
1296}