File Coverage

blib/lib/Smil.pm
Criterion Covered Total %
statement 82 193 42.4
branch 13 44 29.5
condition 5 18 27.7
subroutine 23 51 45.1
pod 0 45 0.0
total 123 351 35.0


line stmt bran cond sub pod time code
1             package Smil;
2              
3             $VERSION = "0.898";
4              
5 1     1   3838 use Carp;
  1         1  
  1         629  
6 1     1   1062 use SMIL::XMLBase;
  1         4  
  1         49  
7 1     1   1174 use SMIL::XMLContainer;
  1         3  
  1         29  
8 1     1   639 use SMIL::XMLTag;
  1         3  
  1         124  
9 1     1   804 use SMIL::Head;
  1         3  
  1         35  
10 1     1   761 use SMIL::Body;
  1         66  
  1         5615  
11              
12             my $TRUE = 'true';
13              
14             @ISA = qw( SMIL::XMLContainer );
15              
16             my $head = "head";
17             my $body = "body";
18             my @timelineStack;
19             my $smil;
20             my $file = "file";
21             my $INLINE = 'inline';
22              
23             my $CV_SYSTEM_COMPONENT = "cv:systemComponent";
24             my @RP_SYSTEM_REQUIRED_ATTRIBUTE = ( "system-required" => "cv" );
25              
26             my $RN_EXTENSIONS = 'rn-extensions';
27             my $RN_SHORT = 'rn';
28             my $QT_EXTENSIONS = 'qt-extensions';
29             my $QT_SHORT = 'qt';
30             my $QT_NS_URL = "http://www.apple.com/quicktime/resources/smilextensions";
31             my $QT_NS = "xmlns:qt";
32              
33             my $SMIL_2_NS = 'xmlns';
34             my $SMIL_2_NS_URL = 'http://www.w3.org/2001/SMIL20/Language';
35              
36             my $RN_SMIL_2_NAMESPACE = 'rnSmil2';
37             my $RN_SMIL_2_NS_URL = "http://features.real.com/2001/SMIL20/Extensions";
38             my $RN_SMIL_2_NS = "xmlns:$RN_SMIL_2_NAMESPACE";
39              
40             my $VERSION_COMPATIBLE = 'version';
41             my $PLAYER_COMPATIBLE = 'player';
42             my $RP_COMPATIBLE = 'rp';
43             my $QT_COMPATIBLE = 'qt';
44              
45             my $QT_AUTOPLAY = "qt:autoplay";
46             my $QT_CHAPTER_MODE = "qt:chapter-mode";
47             my $QT_IMMEDIATE_INSTANTIATION = "qt:immediate-instantiation";
48             my $QT_NEXT = "qt:next";
49             my $QT_TIME_SLIDER = "qt:time-slider";
50              
51             my $RN_NS = "xmlns:cv";
52             my $RN_NS_URL = "http://features.real.com/systemComponent";
53              
54             my %earliestAttribute = ( 'inline' => 7 );
55              
56             my @RP_VERSION_MAPPING = ( "", # 0
57             "", # 1, unsupported
58             "", # 2, unsupported
59             "", # 3, unsupported
60             "", # 4, unsupported
61             "", # 5, unsupported
62             "", # 6, no switch allowed
63            
64             # 7, Gold Player 7
65             "http://features.real.com/?component;player=6.0.7.380",
66            
67             # 8, Gold Player 8
68             "http://features.real.com/?component;player=6.0.9.450",
69             );
70              
71             my %VERSION_MAPPING = ( $RP_COMPATIBLE => \@RP_VERSION_MAPPING );
72              
73             my %RP_FEATURE_VERSION_MAPPING = ( 'inline' => 7, 'newwindow' => 7 );
74              
75             my %FEATURE_VERSION_MAPPING = ( $RP_COMPATIBLE => \%RP_FEATURE_VERSION_MAPPING );
76              
77             my @smilAttributes = ( $RN_NS,
78             $QT_AUTOPLAY,
79             $QT_CHAPTER_MODE,
80             $QT_IMMEDIATE_INSTANTIATION,
81             $QT_NEXT,
82             $QT_TIME_SLIDER );
83              
84             my @smil2Extensions = ( 'syncBehavior' );
85             my @rnSmil2Extensions = ( 'backgroundOpacity', 'bgcolor', 'chromaKey',
86             'chromaKeyOpacity', 'chromaKeyTolerance', 'mediaOpacity' );
87              
88              
89             sub init {
90 1     1 0 3 my $self = shift;
91 1         11 $self->SUPER::init( "smil" );
92            
93 1         7 my %hash = @_;
94 1         20 my %smilAttrs = $self->createValidAttributes( { %hash },
95             [ @smilAttributes ] );
96            
97 1 50 33     14 if( $hash{ $QT_SHORT } or
98             $hash{ $QT_EXTENSIONS } ) {
99 0         0 $self->useQtExtensions;
100             }
101            
102 1 50 33     12 if( $hash{ $RN_EXTENSIONS } or
103             $hash{ $RN_SHORT } ) {
104 0         0 $self->useRnExtensions;
105             }
106            
107 1         18 $self->setAttributes( %smilAttrs );
108            
109 1 50       6 $self->setFavorite( $favorite ) if $favorite;
110 1         8 $self->initHead( @_ );
111 1         5 $self->initBody( @_ );
112 1         6 $self->initFile( @_ );
113             }
114              
115             sub setQtAutoplay {
116 0     0 0 0 my $self = shift;
117 0         0 $self->setAttribute( $QT_AUTOPLAY => $TRUE );
118 0         0 $self->useQtExtensions;
119             }
120              
121             sub setQtChapterMode {
122 0     0 0 0 my $self = shift;
123 0         0 my $dur = shift;
124 0         0 $self->setAttribute( $QT_CHAPTER_MODE => $dur );
125 0         0 $self->useQtExtensions;
126             }
127              
128             sub useQtImmediateInstantiation {
129 0     0 0 0 my $self = shift;
130 0         0 $self->setAttribute( $QT_IMMEDIATE_INSTANTIATION => $TRUE );
131 0         0 $self->useQtExtensions;
132             }
133              
134             sub setQtNextPresentation {
135 0     0 0 0 $self = shift;
136 0         0 $next = shift;
137 0         0 $self->setAttribute( $QT_NEXT => $next );
138 0         0 $self->useQtExtensions;
139             }
140              
141             sub useQtTimeSlider {
142 0     0 0 0 $self = shift;
143 0         0 $self->setAttribute( $QT_TIME_SLIDER => $TRUE );
144 0         0 $self->useQtExtensions;
145             }
146              
147             sub useRnExtensions {
148 0     0 0 0 my $self = shift;
149 0         0 my $version = shift;
150            
151 0         0 $self->setAttribute( $RN_NS => $RN_NS_URL );
152 0         0 $self->setFavorite( $RN_NS );
153             }
154              
155             sub useQtExtensions {
156 0     0 0 0 my $self = shift;
157 0         0 $self->setAttribute( $QT_NS => $QT_NS_URL );
158 0         0 $self->setFavorite( $QT_NS );
159             }
160              
161             sub getRootHeight {
162 0     0 0 0 my $self = shift;
163 0         0 my $hd = $self->getContentObjectByName( $head );
164 0 0       0 return $hd ? $hd->getRootHeight() : 0;
165             }
166              
167             sub getRootWidth {
168 0     0 0 0 my $self = shift;
169 0         0 my $hd = $self->getContentObjectByName( $head );
170 0 0       0 return $hd ? $hd->getRootWidth() : 0;
171             }
172              
173             sub getAsString {
174 1     1 0 7 my $self = shift;
175              
176             # croak "Need to make sure to match start with end when defining timeline"
177             # if( $check_errors && @{$self->{$timelineStack}} );
178              
179 1         8 return $self->SUPER::getAsString();
180             }
181              
182             sub initFile {
183 1     1 0 2 my $self = shift;
184 1         4 my %hash = @_;
185 1 50       30 if( $hash{ $file } ) {
186 0         0 $self->{$file} = $hash{ $file };
187             }
188             }
189              
190             sub initHead {
191 1     1 0 3 my $self = shift;
192 1         4 my %hash = @_;
193 1 50 33     39 $self->setTagContents( $head => new SMIL::Head( @_ ) )
      33        
194             if( ( $hash{ 'height' } && $hash{ 'width' } ) ||
195             $hash{ 'meta' } );
196             }
197              
198             sub initBody {
199 1     1 0 3 my $self = shift;
200 1 50       14 $self->setTagContents( $body => new SMIL::Body( @_ ) ) unless $self->{$body};
201             }
202              
203             sub startSequence {
204 1     1 0 6 my $self = shift;
205 1         87 $self->getContentObjectByName( $body )->startSequence( @_ );
206             }
207              
208             sub startParallel {
209 0     0 0 0 my $self = shift;
210 0         0 $self->getContentObjectByName( $body )->startParallel( @_ );
211             }
212              
213             sub endParallel {
214 0     0 0 0 my $self = shift;
215 0         0 $self->getContentObjectByName( $body )->endParallel();
216             }
217              
218             sub endSequence {
219 1     1 0 7 my $self = shift;
220 1         4 $self->getContentObjectByName( $body )->endSequence();
221             }
222              
223             sub hasQtExtensions {
224            
225 3     3 0 3 my $self = shift;
226 3         13 my %hash = @_;
227 3         5 my $returnValue = 0;
228            
229 3         17 foreach my $item ( keys %hash ) {
230 8 50       26 $returnValue = 1 if $item =~ /^qt:/;
231             }
232            
233 3         13 return $returnValue;
234             }
235              
236             sub hasRnSmil2Extensions {
237 3     3 0 8 my $self = shift;
238            
239 3         4 my $returnValue = 0;
240            
241 3         9 my %the_hash = @_;
242            
243 3         10 foreach my $item ( keys %the_hash ) {
244 8         10 foreach my $rnAttribute ( @rnSmil2Extensions ) {
245 48 50       93 $returnValue = 1 if $item eq $rnAttribute;
246             }
247             }
248            
249 3         22 return $returnValue;
250             }
251              
252             sub useRnSmil2Extensions {
253 0     0 0 0 my $self = shift;
254 0         0 $self->setAttribute( $RN_SMIL_2_NS => $RN_SMIL_2_NS_URL );
255             }
256              
257             sub hasSmil2Extensions {
258 3     3 0 4 my $self = shift;
259              
260 3         5 my $returnValue = 0;
261              
262 3         11 my %the_hash = @_;
263            
264 3         7 foreach my $item ( keys %the_hash ) {
265 8         14 foreach my $rnAttribute ( @smil2Extensions ) {
266 8 50       28 $returnValue = 1 if $item eq $rnAttribute;
267             }
268             }
269              
270 3         22 return $returnValue;
271             }
272              
273             sub useSmil2Extensions {
274 0     0 0 0 my $self = shift;
275 0         0 $self->setAttribute( $SMIL_2_NS => $SMIL_2_NS_URL );
276             }
277              
278             sub checkForExtensions {
279            
280 3     3 0 4 my $self = shift;
281            
282             # Check for QT extensions, and add if necessary
283 3 50       10 if( $self->hasQtExtensions( @_ ) ) {
284 0         0 $self->useQtExtensions;
285             }
286            
287             # Check for SMIL 2.0 attributes
288 3 50       12 if( $self->hasSmil2Extensions( @_ ) ) {
289 0         0 $self->useSmil2Extensions;
290             }
291              
292             # Check for RN Smil 2.0 extensions
293 3 50       12 if( $self->hasRnSmil2Extensions( @_ ) ) {
294 0         0 $self->useRnSmil2Extensions;
295             }
296              
297             }
298              
299             sub addInlinedMedia {
300 0     0 0 0 my $self = shift;
301              
302 0         0 $self->addMedia( @_, inline => 1 );
303             }
304              
305             sub addMedia {
306 3     3 0 23 my $self = shift;
307              
308 3         11 $self->checkForExtensions( @_ );
309            
310             # Make sure that if we are adding inline that we
311             # add the RP version checking code in case
312             # we need to add a switch because we are authoring
313             # for all players...
314 3 50 33     12 if( &isInlined( @_ ) and $self->authoringBackwardsCompatible() ) {
315 0         0 $self->useRnExtensions;
316             # Add a switch statement of the possible entries here.
317 0         0 $self->addBackwardsCompatibleSwitch( 'inline', @_ );
318             }
319             else {
320 3         10 $self->getContentObjectByName( $body )->addMedia( @_ );
321             }
322             }
323              
324             sub getEarliestSupportedVersion {
325              
326 0     0 0 0 my $type = shift;
327 0         0 my $feature = shift;
328              
329 0 0       0 print STDERR "Only RealPlayer is supported as backwards compatible type so far.: $type\n"
330             unless $type eq $RP_COMPATIBLE;
331              
332 0         0 return( $FEATURE_VERSION_MAPPING{ $type }->{ $feature } ); # $RP_VERSION_COMPONENT );
333              
334             }
335              
336             sub getSupportedVersionAttribute {
337              
338 0     0 0 0 my $version = shift;
339 0         0 my $player = shift;
340              
341 0 0       0 print STDERR "Only RealPlayer supported as backwards compatible type so far.: $player\n"
342             unless $player eq $RP_COMPATIBLE;
343            
344 0         0 return( $CV_SYSTEM_COMPONENT, $VERSION_MAPPING{ $player }->[ $version ] );
345            
346             }
347              
348             sub getEarliestVersionForAttribute {
349 0     0 0 0 my $attribute = shift;
350 0         0 return $earliestAttribute{ $attribute };
351             }
352              
353             sub addBackwardsCompatibleSwitch {
354            
355 0     0 0 0 my $self = shift;
356            
357             # Check for this 'feature' when adding switch code
358 0         0 my $feature = shift;
359 0         0 my @medias = ();
360            
361 0         0 my $earliestVersion = &getEarliestVersionForAttribute( $feature );
362             # $self->getPrivate( $VERSION_COMPATIBLE ); # Don't really need this right now..
363 0         0 my $playerType = $self->getPrivate( $PLAYER_COMPATIBLE );
364            
365             # Need a attribute list with the attribute we are switching on
366             # and another without.
367 0         0 my %withSwitchingAttribute = @_;
368            
369             # Remove the attribute
370 0         0 my %withoutSwitchingAttribute = @_;
371 0         0 undef( $withoutSwitchingAttribute{ $feature } );
372            
373             # Create a different media object for each of the versions
374             # to support. Make sure to go backwards since switch uses first
375             # match
376 0         0 my $supportedIndex = &getEarliestSupportedVersion( $playerType, $feature );
377            
378 0         0 my @attributes = ( %withSwitchingAttribute,
379             ( @RP_SYSTEM_REQUIRED_ATTRIBUTE,
380             &getSupportedVersionAttribute( $supportedIndex,
381             $self->getPrivate( $PLAYER_COMPATIBLE ) ) ) );
382             # attributes, and push it on the stack
383 0         0 push @medias, SMIL::MediaFactory::getMediaObject( @attributes );
384            
385             # Now, add the one without the attribute
386 0         0 push @medias, SMIL::MediaFactory::getMediaObject( %withoutSwitchingAttribute );
387            
388             # Create the different medias
389 0         0 $self->addSwitchedMedia( 'switch' => 'system-required',
390             medias => [ \@medias ] );
391             }
392              
393             sub authoringBackwardsCompatible {
394 0     0 0 0 my $self = shift;
395 0   0     0 return( $self->getPrivate( $VERSION_COMPATIBLE ) and $self->getPrivate( $PLAYER_COMPATIBLE ) );
396             }
397              
398             sub setBackwardsCompatible {
399            
400 0     0 0 0 my $self = shift;
401            
402             # Get a version number, if they gave it to us.
403 0         0 my %args = @_;
404            
405 0         0 my $version = $args{ $VERSION_COMPATIBLE };
406            
407 0         0 my $player = $args{ $PLAYER_COMPATIBLE };
408            
409             # Only do it for RN players right now...
410 0 0       0 if( $player eq $RP_COMPATIBLE ) {
411 0         0 $self->setPrivate( $PLAYER_COMPATIBLE => $player );
412 0         0 $self->setPrivate( $VERSION_COMPATIBLE => $version );
413             }
414             else {
415 0         0 print STDERR "Backwards compatible only supported for RealPlayer so far.";
416             }
417             }
418              
419             sub isInlined {
420 3     3 0 10 my %args = @_;
421 3         18 return defined( $args{ $INLINE } );
422             }
423              
424             sub addTransition {
425 0     0 0 0 my $self = shift;
426             # Need to add the transition to the head.
427 0         0 $self->useSmil2Extensions;
428 0         0 my $head_ref;
429 0 0       0 if( !( $head_ref = $self->getContentObjectByName( $head ) ) ) {
430 0         0 $head_ref = new SMIL::Head();
431             # Head must go at the top of the items in the
432 0         0 $self->unshiftTagContents( $head => $head_ref );
433             }
434 0         0 $head_ref->addTransition( @_ );
435             }
436              
437             sub addAnimation {
438 0     0 0 0 my $self = shift;
439              
440 0         0 $self->useSmil2Extensions;
441              
442 0         0 die "addAnimation NYI";
443             }
444              
445             sub addCode {
446 1     1 0 7 my $self = shift;
447 1         4 $self->getContentObjectByName( $body )->addCode( @_ );
448             }
449              
450             sub addComment {
451 1     1 0 8 my $self = shift;
452 1         3 my $comment = shift;
453 1         5 $self->getContentObjectByName( $body )->addCode( "" );
454             }
455              
456             sub getRegionAttributeByName
457             {
458 0     0 0 0 my $self = shift;
459 0         0 my $region_name = shift;
460 0         0 my $attr = shift;
461 0         0 my $the_head = $self->getContentObjectByName( $head );
462 0         0 my $return_value;
463 0 0       0 if( $the_head ) {
464 0         0 $return_value = $the_head->getRegionAttribute( $region_name, $attr );
465             }
466 0 0       0 if( 'ZERO_STRING' eq $return_value )
467             {
468 0         0 $return_value = "0";
469             }
470 0         0 return $return_value;
471             }
472              
473             sub addSwitchedMedia {
474 1     1 0 14 my $self = shift;
475 1         4 $self->getContentObjectByName( $body )->addSwitchedMedia( @_ );
476             }
477              
478             # Can only have one layout, so "set" rather than "add"
479             sub setSwitchedLayout {
480 0     0 0 0 my $self = shift;
481 0 0       0 if( $self->{$head} ) {
482 0         0 $self->setTagContents( $head => new SMIL::Head( @_ ) );
483             }
484 0         0 $self->getContentObjectByName( $head )->setSwitchedLayout( @_ );
485             }
486              
487             sub header {
488 0     0 0 0 return "Content-type: " . &getMimeType() . "\n\n";
489             }
490              
491             sub getMimeType {
492 0     0 0 0 return "application/smil";
493             }
494              
495             sub setMeta {
496 0     0 0 0 my $self = shift;
497 0         0 croak "Setting meta for SMIL NYI.";
498             }
499              
500             sub setLayout {
501 0     0 0 0 my $self = shift;
502 0         0 croak "SetLayout for SMIL NYI.";
503             }
504              
505             sub addRegion {
506 2     2 0 16 my $self = shift;
507 2         10 $self->getContentObjectByName( $head )->addRegion( @_ );
508             }
509              
510             1;
511             __END__