rollback to 3428, before the mysterious removal of libs/* at 3431/3432
[ardour.git] / libs / surfaces / control_protocol / smpte.cc
1 /*
2         Copyright (C) 2006 Paul Davis
3         
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.
8         
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
12         for more details.
13         
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.
17 */
18
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))
21
22 #include <control_protocol/smpte.h>
23 #include <ardour/configuration.h>
24
25 namespace SMPTE {
26
27 float Time::default_rate = 30.0;
28
29
30 /** Increment @a smpte by exactly one frame (keep subframes value).
31  * Realtime safe.
32  * @return true if seconds wrap.
33  */
34 Wrap
35 increment( Time& smpte )
36 {
37         Wrap wrap = NONE;
38
39         if (smpte.negative) {
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;
44                         return SECONDS;
45                 }
46     
47                 smpte.negative = false;
48                 wrap = decrement( smpte );
49                 if (!SMPTE_IS_ZERO( smpte )) {
50                         smpte.negative = true;
51                 }
52                 return wrap;
53         }
54
55         switch ((int)ceil(smpte.rate)) {
56         case 24:
57                 if (smpte.frames == 23) {
58                         smpte.frames = 0;
59                         wrap = SECONDS;
60                 }
61                 break;
62         case 25:
63                 if (smpte.frames == 24) {
64                         smpte.frames = 0;
65                         wrap = SECONDS;
66                 }
67                 break;
68         case 30:
69                 if (smpte.drop) {
70                        if (smpte.frames == 29) {
71                               if ( ((smpte.minutes + 1) % 10) && (smpte.seconds == 59) ) {
72                                      smpte.frames = 2;
73                               }
74                               else {
75                                      smpte.frames = 0;
76                               }
77                               wrap = SECONDS;
78                        }
79                 } else {
80
81                        if (smpte.frames == 29) {
82                               smpte.frames = 0;
83                               wrap = SECONDS;
84                        }
85                 }
86                 break;
87         case 60:
88                 if (smpte.frames == 59) {
89                         smpte.frames = 0;
90                         wrap = SECONDS;
91                 }
92                 break;
93         }
94   
95         if (wrap == SECONDS) {
96                 if (smpte.seconds == 59) {
97                         smpte.seconds = 0;
98                         wrap = MINUTES;
99                         if (smpte.minutes == 59) {
100                                 smpte.minutes = 0;
101                                 wrap = HOURS;
102                                 smpte.hours++;
103                         } else {
104                                 smpte.minutes++;
105                         }
106                 } else {
107                         smpte.seconds++;
108                 }
109         } else {
110                 smpte.frames++;
111         }
112   
113         return wrap;
114 }
115
116
117 /** Decrement @a smpte by exactly one frame (keep subframes value)
118  * Realtime safe.
119  * @return true if seconds wrap. */
120 Wrap
121 decrement( Time& smpte )
122 {
123         Wrap wrap = NONE;
124   
125   
126         if (smpte.negative || SMPTE_IS_ZERO(smpte)) {
127                 smpte.negative = false;
128                 wrap = increment( smpte );
129                 smpte.negative = true;
130                 return wrap;
131         } else if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) {
132                 // We have a zero transition involving only subframes
133                 smpte.subframes = ARDOUR::Config->get_subframes_per_frame() - smpte.subframes;
134                 smpte.negative = true;
135                 return SECONDS;
136         }
137   
138         switch ((int)ceil(smpte.rate)) {
139         case 24:
140                 if (smpte.frames == 0) {
141                         smpte.frames = 23;
142                         wrap = SECONDS;
143                 }
144                 break;
145         case 25:
146                 if (smpte.frames == 0) {
147                         smpte.frames = 24;
148                         wrap = SECONDS;
149                 }
150                 break;
151         case 30:
152                 if (smpte.drop) {
153                         if ((smpte.minutes % 10) && (smpte.seconds == 0)) {
154                                 if (smpte.frames <= 2) {
155                                         smpte.frames = 29;
156                                         wrap = SECONDS;
157                                 }
158                         } else if (smpte.frames == 0) {
159                                 smpte.frames = 29;
160                                 wrap = SECONDS;
161                         }
162                         
163                 } else {
164                         if (smpte.frames == 0) {
165                                 smpte.frames = 29;
166                                 wrap = SECONDS;
167                         }
168                 }
169                 break;
170         case 60:
171                 if (smpte.frames == 0) {
172                         smpte.frames = 59;
173                         wrap = SECONDS;
174                 }
175                 break;
176         }
177   
178         if (wrap == SECONDS) {
179                 if (smpte.seconds == 0) {
180                         smpte.seconds = 59;
181                         wrap = MINUTES;
182                         if (smpte.minutes == 0) {
183                                 smpte.minutes = 59;
184                                 wrap = HOURS;
185                                 smpte.hours--;
186                         }
187                         else {
188                                 smpte.minutes--;
189                         }
190                 } else {
191                         smpte.seconds--;
192                 }
193         } else {
194                 smpte.frames--;
195         }
196   
197         if (SMPTE_IS_ZERO( smpte )) {
198                 smpte.negative = false;
199         }
200   
201         return wrap;
202 }
203
204
205 /** Go to lowest absolute subframe value in this frame (set to 0 :-) ) */
206 void
207 frames_floor( Time& smpte )
208 {
209         smpte.subframes = 0;
210         if (SMPTE_IS_ZERO(smpte)) {
211                 smpte.negative = false;
212         }
213 }
214
215
216 /** Increment @a smpte by one subframe */
217 Wrap
218 increment_subframes( Time& smpte )
219 {
220         Wrap wrap = NONE;
221   
222         if (smpte.negative) {
223                 smpte.negative = false;
224                 wrap = decrement_subframes( smpte );
225                 if (!SMPTE_IS_ZERO(smpte)) {
226                         smpte.negative = true;
227                 }
228                 return wrap;
229         }
230   
231         smpte.subframes++;
232         if (smpte.subframes >= ARDOUR::Config->get_subframes_per_frame()) {
233                 smpte.subframes = 0;
234                 increment( smpte );
235                 return FRAMES;
236         }
237         return NONE;
238 }
239
240
241 /** Decrement @a smpte by one subframe */
242 Wrap
243 decrement_subframes( Time& smpte )
244 {
245         Wrap wrap = NONE;
246   
247         if (smpte.negative) {
248                 smpte.negative = false;
249                 wrap = increment_subframes( smpte );
250                 smpte.negative = true;
251                 return wrap;
252         }
253   
254         if (smpte.subframes <= 0) {
255                 smpte.subframes = 0;
256                 if (SMPTE_IS_ZERO(smpte)) {
257                         smpte.negative = true;
258                         smpte.subframes = 1;
259                         return FRAMES;
260                 } else {
261                         decrement( smpte );
262                         smpte.subframes = 79;
263                         return FRAMES;
264                 }
265         } else {
266                 smpte.subframes--;
267                 if (SMPTE_IS_ZERO(smpte)) {
268                         smpte.negative = false;
269                 }
270                 return NONE;
271         }
272 }
273
274
275 /** Go to next whole second (frames == 0 or frames == 2) */
276 Wrap
277 increment_seconds( Time& smpte )
278 {
279         Wrap wrap = NONE;
280   
281         // Clear subframes
282         frames_floor( smpte );
283   
284         if (smpte.negative) {
285                 // Wrap second if on second boundary
286                 wrap = increment(smpte);
287                 // Go to lowest absolute frame value
288                 seconds_floor( smpte );
289                 if (SMPTE_IS_ZERO(smpte)) {
290                         smpte.negative = false;
291                 }
292         } else {
293                 // Go to highest possible frame in this second
294           switch ((int)ceil(smpte.rate)) {
295                 case 24:
296                         smpte.frames = 23;
297                         break;
298                 case 25:
299                         smpte.frames = 24;
300                         break;
301                 case 30:
302                         smpte.frames = 29;
303                         break;
304                 case 60:
305                         smpte.frames = 59;
306                         break;
307                 }
308     
309                 // Increment by one frame
310                 wrap = increment( smpte );
311         }
312   
313         return wrap;
314 }
315
316
317 /** Go to lowest (absolute) frame value in this second
318  * Doesn't care about positive/negative */
319 void
320 seconds_floor( Time& smpte )
321 {
322         // Clear subframes
323         frames_floor( smpte );
324   
325         // Go to lowest possible frame in this second
326         switch ((int)ceil(smpte.rate)) {
327         case 24:
328         case 25:
329         case 30:
330         case 60:
331                 if (!(smpte.drop)) {
332                         smpte.frames = 0;
333                 } else {
334
335                         if ((smpte.minutes % 10) && (smpte.seconds == 0)) {
336                                 smpte.frames = 2;
337                         } else {
338                                 smpte.frames = 0;
339                         }
340                 }
341                 break;
342         }
343   
344         if (SMPTE_IS_ZERO(smpte)) {
345                 smpte.negative = false;
346         }
347 }
348
349
350 /** Go to next whole minute (seconds == 0, frames == 0 or frames == 2) */
351 Wrap
352 increment_minutes( Time& smpte )
353 {
354         Wrap wrap = NONE;
355   
356         // Clear subframes
357         frames_floor( smpte );
358   
359         if (smpte.negative) {
360                 // Wrap if on minute boundary
361                 wrap = increment_seconds( smpte );
362                 // Go to lowest possible value in this minute
363                 minutes_floor( smpte );
364         } else {
365                 // Go to highest possible second
366                 smpte.seconds = 59;
367                 // Wrap minute by incrementing second
368                 wrap = increment_seconds( smpte );
369         }
370   
371         return wrap;
372 }
373
374
375 /** Go to lowest absolute value in this minute */
376 void
377 minutes_floor( Time& smpte )
378 {
379         // Go to lowest possible second
380         smpte.seconds = 0;
381         // Go to lowest possible frame
382         seconds_floor( smpte );
383
384         if (SMPTE_IS_ZERO(smpte)) {
385                 smpte.negative = false;
386         }
387 }
388
389
390 /** Go to next whole hour (minute = 0, second = 0, frame = 0) */
391 Wrap
392 increment_hours( Time& smpte )
393 {
394         Wrap wrap = NONE;
395   
396         // Clear subframes
397         frames_floor(smpte);
398   
399         if (smpte.negative) {
400                 // Wrap if on hour boundary
401                 wrap = increment_minutes( smpte );
402                 // Go to lowest possible value in this hour
403                 hours_floor( smpte );
404         } else {
405                 smpte.minutes = 59;
406                 wrap = increment_minutes( smpte );
407         }
408   
409         return wrap;
410 }
411
412
413 /** Go to lowest absolute value in this hour */
414 void
415 hours_floor( Time& smpte )
416 {
417         smpte.minutes = 0;
418         smpte.seconds = 0;
419         smpte.frames = 0;
420         smpte.subframes = 0;
421   
422         if (SMPTE_IS_ZERO(smpte)) {
423                 smpte.negative = false;
424         }
425 }
426
427
428 } // namespace SMPTE