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 #[must_use = "iterators are lazy and do nothing unless consumed"]
1011 #[derive(Debug)]
1012 pub struct $name<'a> {
1013 message: &'a SDPMessageRef,
1014 idx: usize,
1015 len: usize,
1016 }
1017
1018 #[allow(clippy::redundant_closure_call)]
1019 impl<'a> $name<'a> {
1020 fn new(message: &'a SDPMessageRef) -> $name<'a> {
1021 skip_assert_initialized!();
1022 let len = $get_len(message);
1023
1024 $name {
1025 message,
1026 idx: 0,
1027 len: len as usize,
1028 }
1029 }
1030 }
1031
1032 #[allow(clippy::redundant_closure_call)]
1033 impl<'a> Iterator for $name<'a> {
1034 type Item = $typ;
1035
1036 fn next(&mut self) -> Option<Self::Item> {
1037 if self.idx >= self.len {
1038 return None;
1039 }
1040
1041 let item = $get_item(self.message, self.idx as u32).unwrap();
1042 self.idx += 1;
1043 Some(item)
1044 }
1045
1046 fn size_hint(&self) -> (usize, Option<usize>) {
1047 let remaining = self.len - self.idx;
1048
1049 (remaining, Some(remaining))
1050 }
1051
1052 fn count(self) -> usize {
1053 self.len - self.idx
1054 }
1055
1056 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1057 let (end, overflow) = self.idx.overflowing_add(n);
1058 if end >= self.len || overflow {
1059 self.idx = self.len;
1060 None
1061 } else {
1062 self.idx = end + 1;
1063 Some($get_item(self.message, end as u32).unwrap())
1064 }
1065 }
1066
1067 fn last(self) -> Option<Self::Item> {
1068 if self.idx == self.len {
1069 None
1070 } else {
1071 Some($get_item(self.message, self.len as u32 - 1).unwrap())
1072 }
1073 }
1074 }
1075
1076 #[allow(clippy::redundant_closure_call)]
1077 impl<'a> DoubleEndedIterator for $name<'a> {
1078 fn next_back(&mut self) -> Option<Self::Item> {
1079 if self.idx == self.len {
1080 return None;
1081 }
1082
1083 self.len -= 1;
1084
1085 Some($get_item(self.message, self.len as u32).unwrap())
1086 }
1087
1088 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1089 let (end, overflow) = self.len.overflowing_sub(n);
1090 if end <= self.idx || overflow {
1091 self.idx = self.len;
1092 None
1093 } else {
1094 self.len = end - 1;
1095 Some($get_item(self.message, self.len as u32).unwrap())
1096 }
1097 }
1098 }
1099
1100 impl<'a> ExactSizeIterator for $name<'a> {}
1101 impl<'a> std::iter::FusedIterator for $name<'a> {}
1102 }
1103);
1104
1105macro_rules! define_iter_mut(
1106 ($name:ident, $typ:ty, $get_item:expr, $get_len:expr) => {
1107 #[must_use = "iterators are lazy and do nothing unless consumed"]
1108 #[derive(Debug)]
1109 pub struct $name<'a> {
1110 message: &'a mut SDPMessageRef,
1111 idx: usize,
1112 len: usize,
1113 }
1114
1115 #[allow(clippy::redundant_closure_call)]
1116 impl<'a> $name<'a> {
1117 fn new(message: &'a mut SDPMessageRef) -> $name<'a> {
1118 skip_assert_initialized!();
1119 let len = $get_len(message);
1120
1121 $name {
1122 message,
1123 idx: 0,
1124 len: len as usize,
1125 }
1126 }
1127 }
1128
1129 #[allow(clippy::redundant_closure_call)]
1130 impl<'a> Iterator for $name<'a> {
1131 type Item = $typ;
1132
1133 fn next(&mut self) -> Option<Self::Item> {
1134 let message = unsafe {
1144 &mut *(self.message as *mut SDPMessageRef)
1145 };
1146 if self.idx >= self.len {
1147 return None;
1148 }
1149
1150 let item = $get_item(message, self.idx as u32).unwrap();
1151 self.idx += 1;
1152 Some(item)
1153 }
1154
1155 fn size_hint(&self) -> (usize, Option<usize>) {
1156 let remaining = self.len - self.idx;
1157
1158 (remaining, Some(remaining))
1159 }
1160
1161
1162 fn count(self) -> usize {
1163 self.len - self.idx
1164 }
1165
1166 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1167 let message = unsafe {
1168 &mut *(self.message as *mut SDPMessageRef)
1169 };
1170 let (end, overflow) = self.idx.overflowing_add(n);
1171 if end >= self.len || overflow {
1172 self.idx = self.len;
1173 None
1174 } else {
1175 self.idx = end + 1;
1176 Some($get_item(message, end as u32).unwrap())
1177 }
1178 }
1179
1180 fn last(self) -> Option<Self::Item> {
1181 if self.idx == self.len {
1182 None
1183 } else {
1184 Some($get_item(self.message, self.len as u32 - 1).unwrap())
1185 }
1186 }
1187 }
1188
1189 #[allow(clippy::redundant_closure_call)]
1190 impl<'a> DoubleEndedIterator for $name<'a> {
1191 fn next_back(&mut self) -> Option<Self::Item> {
1192 let message = unsafe {
1193 &mut *(self.message as *mut SDPMessageRef)
1194 };
1195 if self.idx == self.len {
1196 return None;
1197 }
1198
1199 self.len -= 1;
1200 Some($get_item(message, self.len as u32).unwrap())
1201 }
1202
1203
1204 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1205 let message = unsafe {
1206 &mut *(self.message as *mut SDPMessageRef)
1207 };
1208 let (end, overflow) = self.len.overflowing_sub(n);
1209 if end <= self.idx || overflow {
1210 self.idx = self.len;
1211 None
1212 } else {
1213 self.len = end - 1;
1214 Some($get_item(message, self.len as u32).unwrap())
1215 }
1216 }
1217 }
1218
1219 impl<'a> ExactSizeIterator for $name<'a> {}
1220 impl<'a> std::iter::FusedIterator for $name<'a> {}
1221 }
1222);
1223
1224define_iter!(
1225 AttributesIter,
1226 &'a SDPAttribute,
1227 |message: &'a SDPMessageRef, idx| message.attribute(idx),
1228 |message: &SDPMessageRef| message.attributes_len()
1229);
1230define_iter!(
1231 BandwidthsIter,
1232 &'a SDPBandwidth,
1233 |message: &'a SDPMessageRef, idx| message.bandwidth(idx),
1234 |message: &SDPMessageRef| message.bandwidths_len()
1235);
1236define_iter!(
1237 EmailsIter,
1238 &'a str,
1239 |message: &'a SDPMessageRef, idx| message.email(idx),
1240 |message: &SDPMessageRef| message.emails_len()
1241);
1242define_iter!(
1243 MediasIter,
1244 &'a SDPMediaRef,
1245 |message: &'a SDPMessageRef, idx| message.media(idx),
1246 |message: &SDPMessageRef| message.medias_len()
1247);
1248define_iter_mut!(
1249 MediasIterMut,
1250 &'a mut SDPMediaRef,
1251 |message: &'a mut SDPMessageRef, idx| message.media_mut(idx),
1252 |message: &SDPMessageRef| message.medias_len()
1253);
1254define_iter!(
1255 PhonesIter,
1256 &'a str,
1257 |message: &'a SDPMessageRef, idx| message.phone(idx),
1258 |message: &SDPMessageRef| message.phones_len()
1259);
1260define_iter!(
1261 TimesIter,
1262 &'a SDPTime,
1263 |message: &'a SDPMessageRef, idx| message.time(idx),
1264 |message: &SDPMessageRef| message.times_len()
1265);
1266define_iter!(
1267 ZonesIter,
1268 &'a SDPZone,
1269 |message: &'a SDPMessageRef, idx| message.zone(idx),
1270 |message: &SDPMessageRef| message.zones_len()
1271);
1272
1273#[cfg(test)]
1274mod tests {
1275 use crate::SDPMessage;
1276
1277 fn init() {
1278 gst::init().unwrap();
1279 }
1280
1281 #[test]
1282 fn media_from_message() {
1283 init();
1284
1285 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";
1286 let sdp = SDPMessage::parse_buffer(sdp.as_bytes()).unwrap();
1287 let media = sdp.media(0).unwrap();
1288 assert_eq!(media.formats_len(), 1);
1289 }
1290
1291 #[test]
1292 fn debug_impl() {
1293 init();
1294
1295 let sdp = SDPMessage::new();
1296 assert!(!format!("{sdp:?}").is_empty());
1297 }
1298}