File Coverage

blib/lib/MIDI/XML/SmpteOffset.pm
Criterion Covered Total %
statement 11 82 13.4
branch 0 38 0.0
condition 0 3 0.0
subroutine 4 13 30.7
pod 9 9 100.0
total 24 145 16.5


line stmt bran cond sub pod time code
1             package MIDI::XML::SmpteOffset;
2              
3 1     1   12 use 5.006;
  1         1  
4 1     1   3 use strict;
  1         1  
  1         17  
5 1     1   3 use warnings;
  1         1  
  1         18  
6              
7 1     1   48 use MIDI::XML::Message;
  1         1  
  1         745  
8              
9             our @ISA = qw(MIDI::XML::Message);
10              
11             =head1 NAME
12              
13             MIDI::XML::SmpteOffset - MIDI SMPTE Offset messages.
14              
15             =head1 SYNOPSIS
16              
17             use MIDI::XML::SmpteOffset;
18             $Offset = MIDI::XML::SmpteOffset->new();
19             $Offset->delta(0);
20             $Offset->time_code_type(3);
21             $Offset->hour(1);
22             $Offset->minute(15);
23             $Offset->second(6);
24             $Offset->frame(2);
25             $Offset->fractional_frame(9);
26             @event = $Offset->as_event();
27             $midi_track = MIDI::Track->new();
28             push( @{$midi_track->events_r},\@event;
29             @xml = $Offset->as_MidiXML();
30             print join("\n",@xml);
31              
32             =head1 DESCRIPTION
33              
34              
35             MIDI::XML::SmpteOffset is a class encapsulating MIDI SMPTE Offset
36             meta messages. A SMPTE Offset message includes either a delta time
37             or absolute time as implemented by MIDI::XML::Message and the MIDI
38             SMPTE Offset event encoded in 8 bytes as follows:
39              
40             0xFF 0x54 0x05 0xhh 0xmm 0xss 0xrr 0xpp
41              
42             hh = frame rate + hours (0rrhhhhh)
43              
44             mm = minutes
45              
46             ss = seconds
47              
48             rr = frames
49              
50             pp =
51              
52             =head2 EXPORT
53              
54             None by default.
55              
56             =cut
57              
58             our $VERSION = '0.01';
59              
60             #==========================================================================
61              
62             =head1 METHODS AND ATTRIBUTES
63              
64             =over 4
65              
66             =item $Offset = MIDI::XML::SmpteOffset->new()
67              
68             This creates a new MIDI::XML::SmpteOffset object.
69              
70             =item $Offset = MIDI::XML::SmpteOffset->new($event);
71              
72             Creates a new SmpteOffset object initialized with the values of a
73             MIDI::Event set_sequence_number array.
74              
75             =cut
76              
77             sub new {
78 0     0 1   my $class = shift;
79 0   0       $class = ref($class) || $class;
80              
81 0           my $self = {
82             '_Delta'=> undef,
83             '_Absolute'=> undef,
84             '_TimeCodeType'=> undef,
85             '_Hour'=> undef,
86             '_Minute'=> undef,
87             '_Second'=> undef,
88             '_Frame'=> undef,
89             '_FractionalFrame'=> undef,
90             };
91 0 0         if (@_) {
92 0 0         if (ref($_[0]) eq 'ARRAY') {
    0          
    0          
93 0 0         if ($_[0][0] eq 'smpte_offset') {
94 0           $self->{'_Delta'} = $_[0][1];
95 0           $self->{'_TimeCodeType'} = ($_[0][2] & 0x60) >> 5;
96 0           $self->{'_Hour'} = $_[0][2] & 0x1F;
97 0           $self->{'_Minute'} = $_[0][3];
98 0           $self->{'_Second'} = $_[0][4];
99 0           $self->{'_Frame'} = $_[0][5];
100 0           $self->{'_FractionalFrame'} = $_[0][6];
101             }
102             } elsif (ref($_[0]) eq 'HASH') {
103 0           foreach my $attr (keys %{$_[0]}) {
  0            
104 0 0         $self->{"_$attr"} = $_[0]->{$attr} unless ($attr =~ /^_/);
105             }
106             } elsif (ref($_[0]) eq '') {
107 0 0         if ($_[0] eq 'smpte_offset') {
108 0           $self->{'_Delta'} = $_[1];
109 0           $self->{'_TimeCodeType'} = ($_[2] & 0x60) >> 5;
110 0           $self->{'_Hour'} = $_[2] & 0x1F;
111 0           $self->{'_Minute'} = $_[3];
112 0           $self->{'_Second'} = $_[4];
113 0           $self->{'_Frame'} = $_[5];
114 0           $self->{'_FractionalFrame'} = $_[6];
115             }
116             }
117             }
118              
119 0           bless($self,$class);
120 0           return $self;
121             }
122              
123             =item $delta_time = $Offset->delta() or $Offset->delta($delta_time);
124              
125             Returns the message time as a delta time or undef if it is an absolute
126             time. Optionally sets the message time to the specified delta time. To
127             avoid contradictory times, the absolute time is set to undef when a delta time
128             is set.
129              
130             This functionality is provided by the MIDI::XML::Message base class.
131              
132             =item $absolute_time = $Offset->absolute() or $Offset->absolute($absolute_time);
133              
134             Returns the message time as an absolute time or undef if it is a delta
135             time. Optionally sets the message time to the specified absolute time. To
136             avoid contradictory times, the delta time is set to undef when an absolute time
137             is set. The absolute time should be zero according to the specification.
138              
139             This functionality is provided by the MIDI::XML::Message base class.
140              
141             =item $time = $Offset->time();
142              
143             Returns the message time, absolute or delta, whichever was last set.
144              
145             This functionality is provided by the MIDI::XML::Message base class.
146              
147             =cut
148              
149             #==========================================================================
150              
151             =item $time_code_type = $Offset->time_code_type() or $Offset->time_code_type($time_code_type);
152              
153             =cut
154              
155             sub time_code_type {
156 0     0 1   my $self = shift;
157 0 0         if (@_) {
158 0           my $r = shift;
159 0           $self->{'_TimeCodeType'} = ($r & 0x03);
160             }
161 0           return $self->{'_Rate'};
162             }
163              
164             #==========================================================================
165              
166             =item $hour = $Offset->hour() or $Offset->hour($hour);
167              
168             =cut
169              
170             sub hour {
171 0     0 1   my $self = shift;
172 0 0         if (@_) {
173 0           $self->{'_Hour'} = shift;
174             }
175 0           return $self->{'_Hour'};
176             }
177              
178             #==========================================================================
179              
180             =item $minute = $Offset->minute() or $Offset->minute($minute);
181              
182             =cut
183              
184             sub minute {
185 0     0 1   my $self = shift;
186 0 0         if (@_) {
187 0           $self->{'_Minute'} = shift;
188             }
189 0           return $self->{'_Minute'};
190             }
191              
192             #==========================================================================
193              
194             =item $second = $Offset->second() or $Offset->second($second);
195              
196             =cut
197              
198             sub second {
199 0     0 1   my $self = shift;
200 0 0         if (@_) {
201 0           $self->{'_Second'} = shift;
202             }
203 0           return $self->{'_Second'};
204             }
205              
206             #==========================================================================
207              
208             =item $frame = $Offset->frame() or $Offset->frame($frame);
209              
210             =cut
211              
212             sub frame {
213 0     0 1   my $self = shift;
214 0 0         if (@_) {
215 0           $self->{'_Frame'} = shift;
216             }
217 0           return $self->{'_Frame'};
218             }
219              
220             #==========================================================================
221              
222             =item $fraction = $Offset->fractional_frame() or $Offset->fractional_frame($fraction);
223              
224             =cut
225              
226             sub fractional_frame {
227 0     0 1   my $self = shift;
228 0 0         if (@_) {
229 0           $self->{'_FractionalFrame'} = shift;
230             }
231 0           return $self->{'_FractionalFrame'};
232             }
233              
234             #==========================================================================
235              
236             =item $ordinal = $Offset->ordinal();
237              
238             Returns a value to be used to order events that occur at the same time.
239              
240             sub ordinal {
241             my $self = shift;
242             return 0x0054 ;
243             }
244              
245             #==========================================================================
246              
247             =item @event = $Offset->as_event();
248              
249             Returns a MIDI::Event smpte_offset array initialized with the values
250             of the SmpteOffset object. MIDI::Event does not expect absolute times
251             and will interpret them as delta times. Calling this method when the time
252             is absolute will not generate a warning or error but it is unlikely that
253             the results will be satisfactory.
254              
255             =cut
256              
257             sub as_event {
258 0     0 1   my $self = shift;
259              
260             my @event = (
261             'smpte_offset',
262             MIDI::XML::Message::time($self),
263             $self->{'_Hour'} | ($self->{'_TimeCodeType'} << 5),
264             $self->{'_Minute'},
265             $self->{'_Second'},
266             $self->{'_Frame'},
267 0           $self->{'_FractionalFrame'}
268             );
269 0           return @event;
270             }
271              
272             #==========================================================================
273              
274             =item @xml = $Offset->as_MidiXML();
275              
276             Returns an array of elements formatted according to the MidiXML DTD. These
277             elements may be assembled by track into entire documents with the following
278             suggested DOCTYPE declaration:
279              
280            
281             "-//Recordare//DTD MusicXML 0.7 MIDI//EN"
282             "http://www.musicxml.org/dtds/midixml.dtd">
283              
284             =back
285              
286             =cut
287              
288             sub as_MidiXML {
289 0     0 1   my $self = shift;
290 0           my @xml;
291             my @attr;
292              
293 0 0         if ( defined($self->{'_TimeCodeType'})) {
294 0           push @attr, "TimeCodeType=\"$self->{'_TimeCodeType'}\"";
295             }
296 0 0         if ( defined($self->{'_Hour'})) {
297 0           push @attr, "Hour=\"$self->{'_Hour'}\"";
298             }
299 0 0         if ( defined($self->{'_Minute'})) {
300 0           push @attr, "Minute=\"$self->{'_Minute'}\"";
301             }
302 0 0         if ( defined($self->{'_Second'})) {
303 0           push @attr, "Second=\"$self->{'_Second'}\"";
304             }
305 0 0         if ( defined($self->{'_Frame'})) {
306 0           push @attr, "Frame=\"$self->{'_Frame'}\"";
307             }
308 0 0         if ( defined($self->{'_FractionalFrame'})) {
309 0           push @attr, "FractionalFrame=\"$self->{'_FractionalFrame'}\"";
310             }
311 0           push @xml, MIDI::XML::Message::as_MidiXML($self);
312 0           $xml[2] = "";
313 0           return @xml;
314             }
315              
316             #==========================================================================
317              
318              
319             return 1;
320             __END__