2 Copyright (C) 2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Lesser General Public License as published
6 by the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 675 Mass Ave, Cambridge, MA 02139, USA.
19 #define Timecode_IS_AROUND_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours)
20 #define Timecode_IS_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours && !(sm.subframes))
22 #include "control_protocol/timecode.h"
23 #include "ardour/rc_configuration.h"
27 float Time::default_rate = 30.0;
30 /** Increment @a timecode by exactly one frame (keep subframes value).
32 * @return true if seconds wrap.
35 increment( Time& timecode, uint32_t subframes_per_frame )
39 if (timecode.negative) {
40 if (Timecode_IS_AROUND_ZERO(timecode) && timecode.subframes) {
41 // We have a zero transition involving only subframes
42 timecode.subframes = subframes_per_frame - timecode.subframes;
43 timecode.negative = false;
47 timecode.negative = false;
48 wrap = decrement( timecode, subframes_per_frame );
49 if (!Timecode_IS_ZERO( timecode )) {
50 timecode.negative = true;
55 switch ((int)ceil(timecode.rate)) {
57 if (timecode.frames == 23) {
63 if (timecode.frames == 24) {
70 if (timecode.frames == 29) {
71 if ( ((timecode.minutes + 1) % 10) && (timecode.seconds == 59) ) {
81 if (timecode.frames == 29) {
88 if (timecode.frames == 59) {
95 if (wrap == SECONDS) {
96 if (timecode.seconds == 59) {
99 if (timecode.minutes == 59) {
100 timecode.minutes = 0;
117 /** Decrement @a timecode by exactly one frame (keep subframes value)
119 * @return true if seconds wrap. */
121 decrement( Time& timecode, uint32_t subframes_per_frame )
126 if (timecode.negative || Timecode_IS_ZERO(timecode)) {
127 timecode.negative = false;
128 wrap = increment( timecode, subframes_per_frame );
129 timecode.negative = true;
131 } else if (Timecode_IS_AROUND_ZERO(timecode) && timecode.subframes) {
132 // We have a zero transition involving only subframes
133 timecode.subframes = subframes_per_frame - timecode.subframes;
134 timecode.negative = true;
138 switch ((int)ceil(timecode.rate)) {
140 if (timecode.frames == 0) {
141 timecode.frames = 23;
146 if (timecode.frames == 0) {
147 timecode.frames = 24;
153 if ((timecode.minutes % 10) && (timecode.seconds == 0)) {
154 if (timecode.frames <= 2) {
155 timecode.frames = 29;
158 } else if (timecode.frames == 0) {
159 timecode.frames = 29;
164 if (timecode.frames == 0) {
165 timecode.frames = 29;
171 if (timecode.frames == 0) {
172 timecode.frames = 59;
178 if (wrap == SECONDS) {
179 if (timecode.seconds == 0) {
180 timecode.seconds = 59;
182 if (timecode.minutes == 0) {
183 timecode.minutes = 59;
197 if (Timecode_IS_ZERO( timecode )) {
198 timecode.negative = false;
205 /** Go to lowest absolute subframe value in this frame (set to 0 :-) ) */
207 frames_floor( Time& timecode )
209 timecode.subframes = 0;
210 if (Timecode_IS_ZERO(timecode)) {
211 timecode.negative = false;
216 /** Increment @a timecode by one subframe */
218 increment_subframes( Time& timecode, uint32_t subframes_per_frame )
222 if (timecode.negative) {
223 timecode.negative = false;
224 wrap = decrement_subframes( timecode, subframes_per_frame );
225 if (!Timecode_IS_ZERO(timecode)) {
226 timecode.negative = true;
231 timecode.subframes++;
232 if (timecode.subframes >= subframes_per_frame) {
233 timecode.subframes = 0;
234 increment( timecode, subframes_per_frame );
241 /** Decrement @a timecode by one subframe */
243 decrement_subframes( Time& timecode, uint32_t subframes_per_frame )
247 if (timecode.negative) {
248 timecode.negative = false;
249 wrap = increment_subframes( timecode, subframes_per_frame );
250 timecode.negative = true;
254 if (timecode.subframes <= 0) {
255 timecode.subframes = 0;
256 if (Timecode_IS_ZERO(timecode)) {
257 timecode.negative = true;
258 timecode.subframes = 1;
261 decrement( timecode, subframes_per_frame );
262 timecode.subframes = 79;
266 timecode.subframes--;
267 if (Timecode_IS_ZERO(timecode)) {
268 timecode.negative = false;
275 /** Go to next whole second (frames == 0 or frames == 2) */
277 increment_seconds( Time& timecode, uint32_t subframes_per_frame )
282 frames_floor( timecode );
284 if (timecode.negative) {
285 // Wrap second if on second boundary
286 wrap = increment(timecode, subframes_per_frame);
287 // Go to lowest absolute frame value
288 seconds_floor( timecode );
289 if (Timecode_IS_ZERO(timecode)) {
290 timecode.negative = false;
293 // Go to highest possible frame in this second
294 switch ((int)ceil(timecode.rate)) {
296 timecode.frames = 23;
299 timecode.frames = 24;
302 timecode.frames = 29;
305 timecode.frames = 59;
309 // Increment by one frame
310 wrap = increment( timecode, subframes_per_frame );
317 /** Go to lowest (absolute) frame value in this second
318 * Doesn't care about positive/negative */
320 seconds_floor( Time& timecode )
323 frames_floor( timecode );
325 // Go to lowest possible frame in this second
326 switch ((int)ceil(timecode.rate)) {
331 if (!(timecode.drop)) {
335 if ((timecode.minutes % 10) && (timecode.seconds == 0)) {
344 if (Timecode_IS_ZERO(timecode)) {
345 timecode.negative = false;
350 /** Go to next whole minute (seconds == 0, frames == 0 or frames == 2) */
352 increment_minutes( Time& timecode, uint32_t subframes_per_frame )
357 frames_floor( timecode );
359 if (timecode.negative) {
360 // Wrap if on minute boundary
361 wrap = increment_seconds( timecode, subframes_per_frame );
362 // Go to lowest possible value in this minute
363 minutes_floor( timecode );
365 // Go to highest possible second
366 timecode.seconds = 59;
367 // Wrap minute by incrementing second
368 wrap = increment_seconds( timecode, subframes_per_frame );
375 /** Go to lowest absolute value in this minute */
377 minutes_floor( Time& timecode )
379 // Go to lowest possible second
380 timecode.seconds = 0;
381 // Go to lowest possible frame
382 seconds_floor( timecode );
384 if (Timecode_IS_ZERO(timecode)) {
385 timecode.negative = false;
390 /** Go to next whole hour (minute = 0, second = 0, frame = 0) */
392 increment_hours( Time& timecode, uint32_t subframes_per_frame )
397 frames_floor(timecode);
399 if (timecode.negative) {
400 // Wrap if on hour boundary
401 wrap = increment_minutes( timecode, subframes_per_frame );
402 // Go to lowest possible value in this hour
403 hours_floor( timecode );
405 timecode.minutes = 59;
406 wrap = increment_minutes( timecode, subframes_per_frame );
413 /** Go to lowest absolute value in this hour */
415 hours_floor( Time& timecode )
417 timecode.minutes = 0;
418 timecode.seconds = 0;
420 timecode.subframes = 0;
422 if (Timecode_IS_ZERO(timecode)) {
423 timecode.negative = false;
428 } // namespace Timecode
431 operator<<(std::ostream& ostr, const Timecode::Time& t)
433 return t.print (ostr);