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 SMPTE_IS_AROUND_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours)
20 #define SMPTE_IS_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours && !(sm.subframes))
22 #include <control_protocol/smpte.h>
23 #include <ardour/configuration.h>
27 FPS Time::default_rate = MTC_30_FPS;
30 /** Increment @a smpte by exactly one frame (keep subframes value).
32 * @return true if seconds wrap.
35 increment( Time& smpte )
40 if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) {
41 // We have a zero transition involving only subframes
42 smpte.subframes = ARDOUR::Config->get_subframes_per_frame() - smpte.subframes;
43 smpte.negative = false;
47 smpte.negative = false;
48 wrap = decrement( smpte );
49 if (!SMPTE_IS_ZERO( smpte )) {
50 smpte.negative = true;
57 if (smpte.frames == 23) {
63 if (smpte.frames == 24) {
69 if (smpte.frames == 29) {
70 if ( ((smpte.minutes + 1) % 10) && (smpte.seconds == 59) ) {
80 if (smpte.frames == 29) {
87 if (wrap == SECONDS) {
88 if (smpte.seconds == 59) {
91 if (smpte.minutes == 59) {
109 /** Decrement @a smpte by exactly one frame (keep subframes value)
111 * @return true if seconds wrap. */
113 decrement( Time& smpte )
118 if (smpte.negative || SMPTE_IS_ZERO(smpte)) {
119 smpte.negative = false;
120 wrap = increment( smpte );
121 smpte.negative = true;
123 } else if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) {
124 // We have a zero transition involving only subframes
125 smpte.subframes = ARDOUR::Config->get_subframes_per_frame() - smpte.subframes;
126 smpte.negative = true;
130 switch (smpte.rate) {
132 if (smpte.frames == 0) {
138 if (smpte.frames == 0) {
143 case MTC_30_FPS_DROP:
144 if ((smpte.minutes % 10) && (smpte.seconds == 0)) {
145 if (smpte.frames <= 2) {
149 } else if (smpte.frames == 0) {
155 if (smpte.frames == 0) {
162 if (wrap == SECONDS) {
163 if (smpte.seconds == 0) {
166 if (smpte.minutes == 0) {
181 if (SMPTE_IS_ZERO( smpte )) {
182 smpte.negative = false;
189 /** Go to lowest absolute subframe value in this frame (set to 0 :-) ) */
191 frames_floor( Time& smpte )
194 if (SMPTE_IS_ZERO(smpte)) {
195 smpte.negative = false;
200 /** Increment @a smpte by one subframe */
202 increment_subframes( Time& smpte )
206 if (smpte.negative) {
207 smpte.negative = false;
208 wrap = decrement_subframes( smpte );
209 if (!SMPTE_IS_ZERO(smpte)) {
210 smpte.negative = true;
216 if (smpte.subframes >= ARDOUR::Config->get_subframes_per_frame()) {
225 /** Decrement @a smpte by one subframe */
227 decrement_subframes( Time& smpte )
231 if (smpte.negative) {
232 smpte.negative = false;
233 wrap = increment_subframes( smpte );
234 smpte.negative = true;
238 if (smpte.subframes <= 0) {
240 if (SMPTE_IS_ZERO(smpte)) {
241 smpte.negative = true;
246 smpte.subframes = 79;
251 if (SMPTE_IS_ZERO(smpte)) {
252 smpte.negative = false;
259 /** Go to next whole second (frames == 0 or frames == 2) */
261 increment_seconds( Time& smpte )
266 frames_floor( smpte );
268 if (smpte.negative) {
269 // Wrap second if on second boundary
270 wrap = increment(smpte);
271 // Go to lowest absolute frame value
272 seconds_floor( smpte );
273 if (SMPTE_IS_ZERO(smpte)) {
274 smpte.negative = false;
277 // Go to highest possible frame in this second
278 switch (smpte.rate) {
285 case MTC_30_FPS_DROP:
291 // Increment by one frame
292 wrap = increment( smpte );
299 /** Go to lowest (absolute) frame value in this second
300 * Doesn't care about positive/negative */
302 seconds_floor( Time& smpte )
305 frames_floor( smpte );
307 // Go to lowest possible frame in this second
308 switch (smpte.rate) {
314 case MTC_30_FPS_DROP:
315 if ((smpte.minutes % 10) && (smpte.seconds == 0)) {
323 if (SMPTE_IS_ZERO(smpte)) {
324 smpte.negative = false;
329 /** Go to next whole minute (seconds == 0, frames == 0 or frames == 2) */
331 increment_minutes( Time& smpte )
336 frames_floor( smpte );
338 if (smpte.negative) {
339 // Wrap if on minute boundary
340 wrap = increment_seconds( smpte );
341 // Go to lowest possible value in this minute
342 minutes_floor( smpte );
344 // Go to highest possible second
346 // Wrap minute by incrementing second
347 wrap = increment_seconds( smpte );
354 /** Go to lowest absolute value in this minute */
356 minutes_floor( Time& smpte )
358 // Go to lowest possible second
360 // Go to lowest possible frame
361 seconds_floor( smpte );
363 if (SMPTE_IS_ZERO(smpte)) {
364 smpte.negative = false;
369 /** Go to next whole hour (minute = 0, second = 0, frame = 0) */
371 increment_hours( Time& smpte )
378 if (smpte.negative) {
379 // Wrap if on hour boundary
380 wrap = increment_minutes( smpte );
381 // Go to lowest possible value in this hour
382 hours_floor( smpte );
385 wrap = increment_minutes( smpte );
392 /** Go to lowest absolute value in this hour */
394 hours_floor( Time& smpte )
401 if (SMPTE_IS_ZERO(smpte)) {
402 smpte.negative = false;