File Coverage

blib/lib/Net/SDP.pm
Criterion Covered Total %
statement 247 372 66.4
branch 90 176 51.1
condition 8 14 57.1
subroutine 38 53 71.7
pod 37 37 100.0
total 420 652 64.4


line stmt bran cond sub pod time code
1             package Net::SDP;
2              
3             ################
4             #
5             # Net::SDP - Session Description Protocol (rfc2327)
6             #
7             # Nicholas J Humfrey
8             # njh@cpan.org
9             #
10             # See the bottom of this file for the POD documentation.
11             #
12             # All parsing and generating of SDP data
13             # is delt with in this file
14              
15              
16 5     5   52268 use strict;
  5         12  
  5         246  
17 5     5   29 use vars qw/$VERSION/;
  5         9  
  5         215  
18              
19 5     5   4320 use Net::SDP::Media;
  5         12  
  5         151  
20 5     5   3768 use Net::SDP::Time;
  5         13  
  5         167  
21 5     5   5179 use Sys::Hostname;
  5         7541  
  5         279  
22 5     5   5133 use Net::hostent;
  5         28729  
  5         66  
23 5     5   305 use Carp;
  5         7  
  5         40522  
24              
25             $VERSION="0.07";
26              
27              
28              
29             sub new {
30 4     4 1 2328 my $class = shift;
31 4         15 my ($data) = @_;
32            
33 4         79 my $self = {'v'=>'0',
34             'session'=> {
35             'o_uname' => '',
36             'o_sess_id' => 0,
37             'o_sess_vers' => 0,
38             'o_net_type' => '',
39             'o_addr_type' => '',
40             'o_address' => '',
41             'p' => [],
42             'e' => [],
43             'a' => {}
44             },
45             'media'=>[],
46             'time'=>[]
47             };
48 4         14 bless $self, $class;
49            
50            
51             # Parse data if we are passed some
52 4 50       20 if (defined $data) {
53 0 0       0 unless ($self->parse( $data )) {
54             # Failed to parse
55 0         0 return undef;
56             }
57             } else {
58             # Use sane defaults
59 4   50     59 $self->{'session'}->{'o_uname'} = $ENV{'USER'} || '-';
60 4         26 $self->{'session'}->{'o_sess_id'} = Net::SDP::Time::_ntptime();
61 4         21 $self->{'session'}->{'o_sess_vers'} = Net::SDP::Time::_ntptime();
62 4         135 $self->{'session'}->{'o_net_type'} = 'IN';
63 4         14 $self->{'session'}->{'o_addr_type'} = 'IP4';
64            
65 4         23 my $hostname = hostname();
66 4 50       83 if (defined $hostname) {
67 4 50       25 if (my $h = gethost($hostname)) {
68 4         4148 $self->{'session'}->{'o_address'} = $h->name();
69             }
70             }
71             }
72              
73 4         76 return $self;
74             }
75              
76             # Try and work out what the source is
77             sub parse {
78 1     1 1 6 my $self = shift;
79 1         2 my ($source) = @_;
80              
81 1 50       4 if (@_ == 1) {
    0          
82              
83 1 50       8 if (ref $source eq 'Net::SAP::Packet') {
    50          
    0          
    0          
    0          
84             # It is a SAP packet
85 0 0       0 if ($source->payload_type() ne 'application/sdp') {
86 0         0 carp "Payload type of Net::SAP::Packet is not application/sdp.";
87 0         0 return 0;
88             }
89 0         0 return $self->parse_data( $source->payload() );
90              
91             } elsif ($source =~ /^v=0/) {
92             # Looks like start of SDP file
93 1         5 return $self->parse_data( $source );
94            
95             } elsif ($source =~ /^\w+:/) {
96             # Looks like a URL
97 0         0 return $self->parse_url( $source );
98            
99             } elsif ($source eq '-') {
100             # Parse STDIN
101 0         0 return $self->parse_stdin();
102            
103             } elsif ($source ne '') {
104             # Assume it is a filename
105 0         0 return $self->parse_file( $source );
106              
107             } else {
108 0         0 carp "Failed to parse empty string.";
109 0         0 return 0;
110             }
111            
112             } elsif (@_ == 0) {
113 0         0 return $self->parse_stdin();
114            
115             } else {
116 0         0 croak "Too many parameters for parse()";
117             }
118            
119             }
120              
121             sub parse_file {
122 0     0 1 0 my $self = shift;
123 0         0 my ($filename) = @_;
124              
125 0 0       0 open(SDP, $filename) or croak "can't open SDP file ($filename): $!";
126 0         0 local $/ = undef; # slurp full file
127 0         0 my $data = ;
128 0         0 close (SDP);
129            
130 0         0 return $self->parse_data( $data );
131             }
132              
133             sub parse_url {
134 0     0 1 0 my $self = shift;
135 0         0 my ($url) = @_;
136              
137 0         0 eval "use LWP::Simple";
138 0 0       0 croak "Couldn't fetch URL because LWP::Simple is unavailable." if ($@);
139              
140 0 0       0 my $data = LWP::Simple::get($url) or
141             croak "Failed to fetch the URL '$url' with LWP: $!\n";
142              
143 0         0 return $self->parse_data( $data );
144             }
145              
146             sub parse_stdin {
147 0     0 1 0 my $self = shift;
148              
149 0         0 local $/ = undef; # slurp STDIN
150 0         0 my $data = <>;
151              
152 0         0 return $self->parse_data( $data );
153             }
154              
155              
156              
157              
158              
159             sub parse_data {
160 1     1 1 2 my $self = shift;
161 1         2 my ($data) = @_;
162 1 50       10 croak "Missing SDP data parameter.\n" unless (defined $data);
163            
164             # Undefine defaults
165 1         2 undef $self->{'v'};
166 1         4 undef $self->{'session'}->{'s'};
167 1         2 undef $self->{'session'}->{'o_sess_id'};
168 1         2 undef $self->{'session'}->{'o_sess_vers'};
169            
170            
171             # Sections of sdp file: 'session', 'media'
172 1         185 my $section = "session";
173              
174            
175             # Split the file up into an array of its lines
176 1         18 my @lines = split(/[\r\n]+/, $data);
177            
178              
179 1         5 while (my $line = shift(@lines)) {
180 12         109 my ($field, $value) = ($line =~ /^(\w)=(.*?)\s*$/);
181 12 50       56 if ($field eq '') {
182 0         0 carp "Failed to parse line of SDP data: $line\n";
183 0         0 next;
184             }
185            
186             # Ignore empty values
187 12 50       21 next if ($value eq '');
188            
189            
190             ## Session description
191 12 100       22 if ($section eq 'session') {
192            
193 10 100 100     80 if ($field eq 'v') {
    100 66        
    100          
    50          
    100          
    100          
    100          
194              
195 1 50       4 $self->_parse_v( $value ) || return 0;
196              
197             } elsif ($field eq 'm') {
198            
199             # Move on to the media section
200 1         1 $section = 'media';
201            
202             } elsif ($field eq 't') {
203            
204 1         11 my $time = new Net::SDP::Time( $value );
205            
206 1         3 push( @{$self->{'time'}}, $time );
  1         9  
207              
208             } elsif ($field eq 'r') {
209            
210             # Add to last time descriptor
211 0 0       0 unless ( $self->{'time'}->[-1] ) {
212 0         0 carp "No previous 't' parameter to associate 'r' with: $line\n";
213 0         0 next;
214             }
215              
216 0         0 $self->{'time'}->[-1]->_parse_r($value);
217              
218             } elsif ($field eq 'o') {
219              
220 1         4 $self->_parse_o( $value );
221              
222             } elsif ($field eq 'p' || $field eq 'e') {
223            
224             # Phone and email can have more than one value
225 2         3 push( @{$self->{'session'}->{$field}}, $value );
  2         5  
226              
227             } elsif ($field eq 'a' || $field eq 'b') {
228            
229             # More than one value is allowed
230 1         6 _add_attribute( $self->{'session'}, $field, $value );
231            
232             } else {
233            
234             # Single value
235 3         9 $self->{'session'}->{$field} = $value;
236             }
237             }
238              
239              
240             ## Media description
241 12 100       42 if ($section eq 'media') {
242            
243 3 100       203 if ($field eq 'm') {
    50          
    100          
244 1         9 my $media = new Net::SDP::Media( $value );
245            
246             # Copy accross connection information for easier access
247 1 50       4 if (defined $self->{'session'}->{'c'}) {
248 0         0 $media->_parse_c( $self->{'session'}->{'c'} );
249             }
250 1         2 push( @{$self->{'media'}}, $media );
  1         4  
251            
252             } elsif ($field =~ /a|b/) {
253              
254             # XXXXXX Check array exists? XXXXXX
255 0         0 _add_attribute( $self->{'media'}->[-1], $field, $value );
256            
257             } elsif ($field =~ /c/) {
258              
259 1         2 my $media = $self->{'media'}->[-1];
260 1         65 $media->_parse_c( $value );
261            
262             } else {
263 1         9 $self->{'media'}->[-1]->{$field} = $value;
264             }
265            
266             }
267            
268             }
269              
270              
271             # Ensure we have the required elements
272 1         11 $self->_validate_self();
273              
274              
275             # Success
276 1         4 return 1;
277             }
278              
279              
280             # Ensure we have the right session elements
281             sub _validate_self {
282 1     1   3 my $self = shift;
283 1         1 my $session = $self->{'session'};
284              
285             # The following elements are required
286 1 50       4 if (!defined $self->{'v'}) {
287 0         0 carp "Invalid SDP file: Missing version field";
288 0         0 return 1;
289             }
290 1 50       4 if (!defined $session->{'o_sess_id'}) {
291 0         0 carp "Invalid SDP file: Missing origin session ID field";
292 0         0 return 1;
293             }
294 1 50       3 if (!defined $session->{'o_sess_vers'}) {
295 0         0 carp "Invalid SDP file: Missing origin version field";
296 0         0 return 1;
297             }
298 1 50       3 if (!defined $session->{'s'}) {
299 0         0 carp "Invalid SDP file: Missing session name field";
300 0         0 return 1;
301             }
302            
303            
304             # We should have a Time Description...
305 1 50       3 if (!exists $self->{'time'}->[0]) {
306 0         0 carp "Invalid SDP file: Session is missing required time discription";
307            
308             # Make it valid :-/
309 0         0 $self->{'time'}->[0] = new Net::SDP::Time();
310             }
311            
312             # Everything is ok :)
313 1         2 return 0;
314             }
315              
316             sub generate {
317 1     1 1 6 my $self=shift;
318 1         2 my $session = $self->{'session'};
319 1         3 my $sdp = '';
320              
321             # The order of the fields must be as stated in the RFC
322 1         4 $sdp .= $self->_generate_v();
323 1         4 $sdp .= $self->_generate_o();
324 1         4 $sdp .= _generate_lines($session, 's', 0 );
325 1         4 $sdp .= _generate_lines($session, 'i', 1 );
326 1         3 $sdp .= _generate_lines($session, 'u', 1 );
327 1         3 $sdp .= _generate_lines($session, 'e', 1 );
328 1         3 $sdp .= _generate_lines($session, 'p', 1 );
329             #c= - I don't like having c lines here !
330             # The module will put c= lines in the media description
331 1         3 $sdp .= _generate_lines($session, 'b', 1 );
332              
333              
334             # Time Descriptions
335 1 50       2 if (scalar(@{$self->{'time'}})==0) {
  1         5  
336             # At least one is required
337 0         0 warn "Missing Time description";
338 0         0 return undef;
339             }
340 1         3 foreach my $time ( @{$self->{'time'}} ) {
  1         2  
341 1         6 $sdp .= $time->_generate_t();
342             #$sdp .= _generate_lines($time, 'z', 1 );
343 1         5 $sdp .= $time->_generate_r();
344             }
345              
346 1         3 $sdp .= _generate_lines($session, 'k', 1 );
347 1         3 $sdp .= _generate_lines($session, 'a', 1 );
348              
349              
350             # Media Descriptions
351 1         3 foreach my $media ( @{$self->{'media'}} ) {
  1         3  
352 1         6 $sdp .= $media->_generate_m();
353 1         3 $sdp .= _generate_lines($media, 'i', 1 );
354             # 'c' is non-optional because we dont have one
355             # in the session description
356 1         5 $sdp .= $media->_generate_c();
357 1         4 $sdp .= _generate_lines($media, 'b', 1 );
358 1         3 $sdp .= _generate_lines($media, 'k', 1 );
359 1         15 $sdp .= _generate_lines($media, 'a', 1 );
360             }
361              
362             # Return the SDP description we just generated
363 1         11 return $sdp;
364             }
365              
366             sub _generate_lines {
367 12     12   19 my ($hashref, $field, $optional) = @_;
368 12         16 my $lines = '';
369              
370 12 100 66     57 if (exists $hashref->{$field} and
371             defined $hashref->{$field}) {
372 8 100       32 if (ref $hashref->{$field} eq 'ARRAY') {
    100          
373 2         3 foreach( @{$hashref->{$field}} ) {
  2         6  
374 4         12 $lines .= "$field=$_\n";
375             }
376             } elsif (ref $hashref->{$field} eq 'HASH') {
377 2         3 foreach my $att_field ( sort keys %{$hashref->{$field}} ) {
  2         14  
378 2         5 my $attrib = $hashref->{$field}->{$att_field};
379 2 50       6 if (ref $attrib eq 'ARRAY') {
380 2         3 foreach my $att_value (@{$attrib}) {
  2         4  
381 2         11 $lines .= "$field=$att_field:$att_value\n";
382             }
383             } else {
384 0         0 $lines .= "$field=$att_field\n";
385             }
386             }
387             } else {
388 4         10 $lines = $field.'='.$hashref->{$field}."\n";
389             }
390             } else {
391 4 50       8 if (!$optional) {
392 0         0 warn "Non-optional field '$field' missing";
393             }
394             }
395            
396 12         27 return $lines;
397             }
398              
399              
400             sub _parse_o {
401 1     1   2 my $self = shift;
402 1         2 my $session = $self->{'session'};
403 1         9 my ($o) = @_;
404              
405 1         12 ($session->{'o_uname'},
406             $session->{'o_sess_id'},
407             $session->{'o_sess_vers'},
408             $session->{'o_net_type'},
409             $session->{'o_addr_type'},
410             $session->{'o_address'}) = split(/\s/, $o);
411            
412             # Success
413 1         3 return 1;
414             }
415              
416              
417             sub _generate_o {
418 1     1   2 my $self = shift;
419 1         5 return "o=".$self->session_origin()."\n";
420             }
421              
422              
423             sub _parse_v {
424 1     1   2 my $self = shift;
425 1         3 $self->{'v'} = shift;
426            
427             # Check the version number
428 1 50       5 if ($self->{'v'} ne '0') {
429 0         0 carp "Unsupported SDP format version number: ".$self->{'v'};
430 0         0 return 0;
431             }
432            
433             # Success
434 1         4 return 1;
435             }
436              
437              
438             sub _generate_v {
439 1     1   2 my $self = shift;
440 1         2 return "v=0\n";
441             }
442              
443             # hashref - the hash to add the attribute to
444             # field - the name of the field - ie 'a'
445             # value - the actual attribute
446             sub _add_attribute {
447 1     1   2 my ($hashref, $field, $value) = @_;
448            
449 1 50       4 if (!defined $hashref->{$field}) {
450 0         0 $hashref->{$field} = {};
451             }
452            
453 1 50       14 if ( my($att_field, $att_value) = ($value =~ /^([\w\-\_]+):(.*)$/) ) {
454 1         2 my $fieldref = $hashref->{$field};
455            
456 1 50       4 if (!defined $fieldref->{$att_field}) {
457 1         3 $fieldref->{$att_field} = [];
458             }
459            
460 1         2 push( @{$fieldref->{$att_field}}, $att_value );
  1         4  
461            
462             } else {
463 0         0 $hashref->{$field}->{$value} = '';
464             }
465             }
466              
467             sub session_origin {
468 1     1 1 2 my $self=shift;
469 1         2 my $session = $self->{'session'};
470 1         2 my ($o) = @_;
471            
472 1 50       4 $self->_parse_o( $o ) if (defined $o);
473              
474 1         10 return $session->{'o_uname'} .' '.
475             $session->{'o_sess_id'} .' '.
476             $session->{'o_sess_vers'} .' '.
477             $session->{'o_net_type'} .' '.
478             $session->{'o_addr_type'} .' '.
479             $session->{'o_address'};
480             }
481              
482             sub session_origin_username {
483 2     2 1 561 my $self=shift;
484 2         4 my ($uname) = @_;
485 2 100       10 $self->{'session'}->{'o_uname'} = $uname if (defined $uname);
486 2         9 return $self->{'session'}->{'o_uname'};
487             }
488              
489             sub session_origin_id {
490 2     2 1 8 my $self=shift;
491 2         4 my ($id) = @_;
492 2 100       9 $self->{'session'}->{'o_sess_id'} = $id if (defined $id);
493 2         8 return $self->{'session'}->{'o_sess_id'};
494             }
495              
496             sub session_origin_version {
497 2     2 1 7 my $self=shift;
498 2         3 my ($vers) = @_;
499 2 100       15 $self->{'session'}->{'o_sess_vers'} = $vers if defined $vers;
500 2         13 return $self->{'session'}->{'o_sess_vers'};
501             }
502              
503             sub session_origin_net_type {
504 2     2 1 8 my $self=shift;
505 2         4 my ($net_type) = @_;
506 2 100       9 $self->{'session'}->{'o_net_type'} = $net_type if defined $net_type;
507 2         8 return $self->{'session'}->{'o_net_type'};
508             }
509              
510             sub session_origin_addr_type {
511 2     2 1 5 my $self=shift;
512 2         38 my ($addr_type) = @_;
513 2 100       8 $self->{'session'}->{'o_addr_type'} = $addr_type if defined $addr_type;
514 2         7 return $self->{'session'}->{'o_addr_type'};
515             }
516              
517             sub session_origin_address {
518 2     2 1 7 my $self=shift;
519 2         11 my ($addr) = @_;
520 2 100       7 $self->{'session'}->{'o_address'} = $addr if defined $addr;
521 2         8 return $self->{'session'}->{'o_address'};
522             }
523              
524              
525              
526             # Returns a unique identifier for this session
527             #
528             sub session_identifier {
529 0     0 1 0 my $self=shift;
530 0         0 my $session = $self->{'session'};
531              
532 0         0 return $session->{'o_uname'} .
533             sprintf("%x",$session->{'o_sess_id'}) .
534             $session->{'o_net_type'} .
535             $session->{'o_addr_type'} .
536             $session->{'o_address'};
537             }
538              
539              
540             sub session_name {
541 2     2 1 6 my $self=shift;
542 2         4 my ($s) = @_;
543 2 100       10 $self->{'session'}->{'s'} = $s if defined $s;
544 2         8 return $self->{'session'}->{'s'};
545             }
546              
547             sub session_info {
548 2     2 1 8 my $self=shift;
549 2         4 my ($i) = @_;
550 2 100       9 $self->{'session'}->{'i'} = $i if defined $i;
551 2         8 return $self->{'session'}->{'i'};
552             }
553              
554             sub session_uri {
555 2     2 1 7 my $self=shift;
556 2         4 my ($u) = @_;
557 2 100       16 $self->{'session'}->{'u'} = $u if defined $u;
558 2         8 return $self->{'session'}->{'u'};
559             }
560              
561             sub session_email {
562 2     2 1 8 my $self=shift;
563 2         5 my ($e) = @_;
564 2         4 my $session = $self->{'session'};
565            
566             # An ARRAYREF may be passed to set more than one email address
567 2 100       19 if (defined $e) {
568 1 50       5 if (ref $e eq 'ARRAY') {
569 1         3 $session->{'e'} = $e;
570             } else {
571 0         0 $session->{'e'} = [ $e ];
572             }
573             }
574              
575             # Multiple emails are allowed, but we just return the first
576 2 50       9 if (exists $session->{'e'}->[0]) {
577 2         8 return $session->{'e'}->[0];
578             }
579 0         0 return undef;
580             }
581              
582             sub session_email_arrayref {
583 0     0 1 0 my $self=shift;
584 0         0 my $session = $self->{'session'};
585            
586 0 0       0 if (defined $session->{'e'}) {
587 0         0 return $session->{'e'};
588             }
589 0         0 return undef;
590             }
591              
592             sub session_phone {
593 2     2 1 8 my $self=shift;
594 2         3 my ($p) = @_;
595 2         4 my $session = $self->{'session'};
596            
597             # An ARRAYREF may be passed to set more than one phone number
598 2 100       7 if (defined $p) {
599 1 50       4 if (ref $p eq 'ARRAY') {
600 1         3 $session->{'p'} = $p;
601             } else {
602 0         0 $session->{'p'} = [ $p ];
603             }
604             }
605              
606             # Multiple phone numbers are allowed, but we just return the first
607 2 50       8 if (exists $session->{'p'}->[0]) {
608 2         13 return $session->{'p'}->[0];
609             }
610 0         0 return undef;
611             }
612              
613             sub session_phone_arrayref {
614 0     0 1 0 my $self=shift;
615 0         0 my $session = $self->{'session'};
616            
617 0 0       0 if (defined $session->{'p'}) {
618 0         0 return $session->{'p'};
619             }
620 0         0 return undef;
621             }
622              
623             sub session_key {
624 0     0 1 0 my $self=shift;
625 0         0 my ($method, $key) = @_;
626            
627 0 0       0 $self->{'session'}->{'k'} = $method if defined $method;
628 0 0       0 $self->{'session'}->{'k'} .= ":$key" if defined $key;
629            
630 0         0 return ($self->{'session'}->{'k'} =~ /^([\w-]+):?(.*)$/);
631             }
632              
633              
634              
635             sub _attribute {
636 2     2   5 my ($hashref, $attr_name, $attr_value) = @_;
637 2 50       7 carp "Missing attribute name" unless (defined $attr_name);
638            
639             # Set attribute to value, if value supplied
640             # Warning - all other values are lost
641 2 100       8 if (defined $attr_value) {
642 1 50       3 if (ref $attr_value eq 'ARRAY') {
643 0         0 $hashref->{'a'}->{$attr_name} = $attr_value;
644             } else {
645 1         5 $hashref->{'a'}->{$attr_name} = [ $attr_value ];
646             }
647             }
648            
649             # Return undef if attribute doesn't exist
650 2 50       23 if (!exists $hashref->{'a'}->{$attr_name}) {
651 0         0 return undef;
652             }
653            
654             # Return 1 if attribute exists but has no value
655             # Return value if attribute has single value
656             # Return arrayref if attribute has more than one value
657 2         6 my $attrib = $hashref->{'a'}->{$attr_name};
658 2 50       7 if (ref $attrib eq 'ARRAY') {
659 2 50       4 if (scalar(@{ $attrib }) == 1) {
  2         7  
660 2         9 return $attrib->[0];
661             } else {
662 0         0 return $attrib;
663             }
664             } else {
665 0         0 return '';
666             }
667             }
668              
669             sub session_attribute {
670 2     2 1 7 my $self=shift;
671              
672 2         9 return Net::SDP::_attribute( $self->{'session'}, @_);
673             }
674              
675             sub session_attributes {
676 0     0 1 0 my $self=shift;
677              
678 0         0 return $self->{'session'}->{'a'};
679             }
680              
681             # Add a session atrribute
682             sub session_add_attribute {
683 0     0 1 0 my $self = shift;
684 0         0 my ($name, $value) = @_;
685 0 0       0 carp "Missing attribute name" unless (defined $name);
686            
687 0         0 my $attrib = $name;
688 0 0       0 $attrib .= ":$value" if (defined $value);
689 0         0 Net::SDP::_add_attribute( $self->{'session'}, 'a', $attrib );
690             }
691              
692             # Delete a session atrribute
693             sub session_del_attribute {
694 0     0 1 0 my $self = shift;
695 0         0 my ($name) = @_;
696 0 0       0 carp "Missing attribute name" unless (defined $name);
697              
698 0 0       0 if ( exists $self->{'session'}->{'a'}->{$name} ) {
699 0         0 delete $self->{'session'}->{'a'}->{$name};
700             }
701             }
702              
703              
704              
705              
706              
707             # Returns first media description of specified type
708             sub media_desc_of_type {
709 1     1 1 177 my $self = shift;
710 1         2 my ($type) = @_;
711 1 50       5 carp "Missing media type parameter" unless (defined $type);
712            
713 1         1 foreach my $media ( @{$self->{'media'}} ) {
  1         3  
714 1 50       13 return $media if ($media->media_type() eq $type);
715             }
716            
717 0         0 return undef;
718             }
719              
720              
721             # Return all media descriptions
722             sub media_desc_arrayref {
723 1     1 1 3 my ($self) = @_;
724            
725 1         3 return $self->{'media'};
726             }
727              
728             # delete all Net::SDP::Media elements
729             sub media_desc_delete_all {
730 0     0 1 0 my ($self) = @_;
731              
732 0         0 $self->{'media'} = [ ];
733            
734 0         0 return 0;
735             }
736              
737             # delete a specific ARRAYREF Net::SDP::Media element
738             sub media_desc_delete {
739 0     0 1 0 my $self = shift;
740 0         0 my ($num) = @_;
741            
742 0 0 0     0 return 1 if ( !defined($num) || !defined($self->{'media'}->[$num]) );
743              
744 0         0 my $results = [ ];
745 0         0 for my $loop ( 0...(scalar(@{$self->{'media'}}) - 1) ) {
  0         0  
746 0 0       0 next if ( $loop == $num );
747            
748 0         0 push @$results, $self->{'media'}->[$loop];
749             }
750 0         0 $self->{'media'} = $results;
751              
752 0         0 return 0;
753             }
754              
755             # Return $num time description, for backwards compatibility the
756             # first time description by default if nothing is passed to it
757             sub time_desc {
758 1     1 1 2 my $self = shift;
759 1         2 my ($num) = @_;
760            
761 1 50       4 $num = 0 unless ( defined $num );
762 1 50       22 return undef unless ( defined($self->{'time'}->[$num]) );
763              
764             ## Ensure that one exists ?
765 1         11 return $self->{'time'}->[$num];
766             }
767              
768             # Return all time descriptions
769             sub time_desc_arrayref {
770 0     0 1 0 my ($self) = @_;
771              
772 0         0 return $self->{'time'};
773             }
774              
775             # delete all Net::SDP::Time elements
776             sub time_desc_delete_all {
777 0     0 1 0 my ($self) = @_;
778              
779 0         0 $self->{'time'} = [ ];
780            
781 0         0 return 0;
782             }
783              
784             # delete a specific ARRAYREF Net::SDP::Time element
785             sub time_desc_delete {
786 0     0 1 0 my $self = shift;
787 0         0 my ($num) = @_;
788            
789 0 0       0 return 1 unless ( defined $num );
790 0 0       0 return 1 unless ( defined $self->{'time'}->[$num] );
791              
792 0         0 my $results = [ ];
793 0         0 for my $loop ( 0...(scalar(@{$self->{'time'}}) - 1) ) {
  0         0  
794 0 0       0 next if ( $loop == $num );
795            
796 0         0 push @$results, $self->{'time'}->[$loop];
797             }
798 0         0 $self->{'time'} = $results;
799              
800 0         0 return 0;
801             }
802              
803              
804             # Net::SDP::Time factory method
805             sub new_time_desc {
806 2     2 1 249 my $self = shift;
807            
808 2         17 my $time = new Net::SDP::Time();
809 2         12 push( @{$self->{'time'}}, $time );
  2         7  
810              
811 2         7 return $time;
812             }
813              
814              
815             # Net::SDP::Media factory method
816             sub new_media_desc {
817 1     1 1 6 my $self = shift;
818 1         2 my ($media_type) = @_;
819            
820 1         8 my $media = new Net::SDP::Media();
821 1 50       8 $media->media_type( $media_type ) if (defined $media_type);
822 1         1 push( @{$self->{'media'}}, $media );
  1         3  
823              
824 1         3 return $media;
825             }
826              
827              
828              
829             sub DESTROY {
830 4     4   4072 my $self=shift;
831            
832             }
833              
834              
835             1;
836              
837             __END__