Ardour  8.12
bbt_time.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2010 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 by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  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 Lesser General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public License
15  along with this program; if not, write to the Free Software Foundation,
16  Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 #ifndef __libtemporal_bbt_time_h__
20 #define __libtemporal_bbt_time_h__
21 
22 #include <ostream>
23 #include <istream>
24 #include <sstream>
25 #include <stdint.h>
26 #include <iomanip>
27 #include <exception>
28 #include <cmath>
29 #include <limits>
30 #include <cstdio>
31 
32 #include "pbd/failed_constructor.h"
33 #include "pbd/string_convert.h"
34 
35 #include "temporal/visibility.h"
36 #include "temporal/types.h"
37 
38 namespace Temporal {
39 
40 struct IllegalBBTTimeException : public std::exception {
41  virtual const char* what() const throw() { return "illegal BBT time (bars or beats were zero, or ticks was too large)"; }
42 };
43 
44 struct BBT_Offset;
45 
48 {
49  /* note that it is illegal for BBT_Time to have bars==0 or
50  * beats==0. The "neutral" or "default" value is 1|1|0
51  */
52 
53  int32_t bars;
54  int32_t beats;
55  int32_t ticks;
56 
57  int64_t as_integer() const;
58  static BBT_Time from_integer (int64_t);
59 
60  bool is_bar() const { return beats == 1 && ticks == 0; }
61  bool is_beat() const { return ticks == 0; }
62 
63  BBT_Time () : bars (1), beats (1), ticks (0) {}
64  BBT_Time (int32_t ba, uint32_t be, uint32_t t) : bars (ba), beats (be), ticks (t) {
65  if (!bars || !beats) {
67  }
68  }
69 
70  bool operator< (const BBT_Time& other) const {
71  return bars < other.bars ||
72  (bars == other.bars && beats < other.beats) ||
73  (bars == other.bars && beats == other.beats && ticks < other.ticks);
74  }
75 
76  bool operator<= (const BBT_Time& other) const {
77  return bars < other.bars ||
78  (bars <= other.bars && beats < other.beats) ||
79  (bars <= other.bars && beats <= other.beats && ticks <= other.ticks);
80  }
81 
82  bool operator> (const BBT_Time& other) const {
83  return bars > other.bars ||
84  (bars == other.bars && beats > other.beats) ||
85  (bars == other.bars && beats == other.beats && ticks > other.ticks);
86  }
87 
88  bool operator>= (const BBT_Time& other) const {
89  return bars > other.bars ||
90  (bars >= other.bars && beats > other.beats) ||
91  (bars >= other.bars && beats >= other.beats && ticks >= other.ticks);
92  }
93 
94  bool operator== (const BBT_Time& other) const {
95  return bars == other.bars && beats == other.beats && ticks == other.ticks;
96  }
97 
98  bool operator!= (const BBT_Time& other) const {
99  return bars != other.bars || beats != other.beats || ticks != other.ticks;
100  }
101 
102  bool operator< (const BBT_Offset& other) const;
103  bool operator<= (const BBT_Offset& other) const;
104  bool operator> (const BBT_Offset& other) const;
105  bool operator>= (const BBT_Offset& other) const;
106  bool operator== (const BBT_Offset& other) const;
107  bool operator!= (const BBT_Offset& other) const;
108 
109  /* it would be nice to provide +,-,* and / operators for BBT_Time but
110  * this math requires knowledge of the meter (time signature) used to
111  * define 1 bar, and so cannot be carried out with only two BBT_Time
112  * values.
113  */
114 
115  BBT_Time round_to_beat () const { return ticks >= (ticks_per_beat/2) ? BBT_Time (bars, beats+1, 0) : BBT_Time (bars, beats, 0); }
116  BBT_Time round_down_to_beat () const { return BBT_Time (bars, beats, 0); }
117  BBT_Time round_up_to_beat () const { return ticks ? BBT_Time (bars, beats+1, 0) : *this; }
118  BBT_Time round_up_to_beat_div (int beat_div) const;
119 
120  /* cannot implement round_to_bar() without knowing meter (time
121  * signature) information, since it requires knowing how many beats
122  * are in a bar, in order to decide if we are closer to the previous or
123  * next bar time.
124  */
125 
127  BBT_Time round_down_to_bar () const { return BBT_Time (bars, 1, 0); }
128  BBT_Time next_bar () const { return (bars == -1) ? BBT_Time (1, 1, 0) : BBT_Time (bars+1, 1, 0); }
129  BBT_Time prev_bar () const { return (bars == 1) ? BBT_Time (-1, 1, 0) : BBT_Time (bars-1, 1, 0); }
130 
131  void print_padded (std::ostream& o) const {
132  o << std::setfill ('0') << std::right
133  << std::setw (3) << bars << "|"
134  << std::setw (2) << beats << "|"
135  << std::setw (4) << ticks;
136  }
137 
138  std::string str () const {
139  std::ostringstream os;
140  os << bars << '|' << beats << '|' << ticks;
141  return os.str ();
142  }
143 
144 };
145 
147 {
148  int32_t bars;
149  int32_t beats;
150  int32_t ticks;
151 
152  /* this is a variant for which bars==0 and/or beats==0 is legal. It
153  * represents an offset from a given BBT_Time and is used when doing
154  * add/subtract operations on a BBT_Time.
155  */
156 
157  BBT_Offset () : bars (0), beats (0), ticks (0) {}
158  BBT_Offset (int32_t ba, uint32_t be, uint32_t t) : bars (ba), beats (be), ticks (t) {}
159  BBT_Offset (BBT_Time const & bbt) : bars (bbt.bars), beats (bbt.beats), ticks (bbt.ticks) {}
160  explicit BBT_Offset (double beats);
161 
162  /* unlike BBT_Time, we can define +,-,* and / operators for BBT_Offset
163  * because there is no requirement that the result is "well-formed" or
164  * reflect the structure of a tempo map. It is just as valid to talk
165  * about an offset of 18 beats as an offset of 4 bars and 2 beats.
166  */
167 
168  BBT_Offset operator+(const BBT_Offset& other) const {
169  return BBT_Offset (bars+other.bars, beats+other.beats, ticks+other.ticks);
170  }
171 
173  return BBT_Offset (-bars, -beats, -ticks);
174  }
175 
176  BBT_Offset operator-(const BBT_Offset& other) const {
177  return BBT_Offset (bars-other.bars, beats-other.beats, ticks-other.ticks);
178  }
179 
180  BBT_Offset & operator+=(const BBT_Offset& other) {
181  bars += other.bars;
182  beats += other.beats;
183  ticks += other.ticks;
184  return *this;
185  }
186 
187  BBT_Offset & operator-=(const BBT_Offset& other) {
188  bars -= other.bars;
189  beats -= other.beats;
190  ticks -= other.ticks;
191  return *this;
192  }
193 
194  BBT_Offset & operator*=(int factor) {
195  bars *= factor;
196  beats *= factor;
197  ticks *= factor;
198  return *this;
199  }
200 
201  BBT_Offset & operator*=(double factor) {
202  bars = (int32_t) lrint (bars * factor);
203  beats = (int32_t) lrint (beats * factor);
204  ticks = (int32_t) lrint (ticks * factor);
205  return *this;
206  }
207 
208  BBT_Offset & operator/=(int factor) {
209  bars /= factor;
210  beats /= factor;
211  ticks /= factor;
212  return *this;
213  }
214 
215  BBT_Offset & operator/=(double factor) {
216  bars = (int32_t) lrint (bars / factor);
217  beats = (int32_t) lrint (beats / factor);
218  ticks = (int32_t) lrint (ticks / factor);
219  return *this;
220  }
221 
222  bool operator< (const BBT_Offset& other) const {
223  return bars < other.bars ||
224  (bars == other.bars && beats < other.beats) ||
225  (bars == other.bars && beats == other.beats && ticks < other.ticks);
226  }
227 
228  bool operator<= (const BBT_Offset& other) const {
229  return bars < other.bars ||
230  (bars <= other.bars && beats <= other.beats) ||
231  (bars <= other.bars && beats <= other.beats && ticks <= other.ticks);
232  }
233 
234  bool operator> (const BBT_Offset& other) const {
235  return bars > other.bars ||
236  (bars == other.bars && beats > other.beats) ||
237  (bars == other.bars && beats == other.beats && ticks > other.ticks);
238  }
239 
240  bool operator>= (const BBT_Offset& other) const {
241  return bars > other.bars ||
242  (bars >= other.bars && beats >= other.beats) ||
243  (bars >= other.bars && beats >= other.beats && ticks >= other.ticks);
244  }
245 
246  bool operator== (const BBT_Offset& other) const {
247  return bars == other.bars && beats == other.beats && ticks == other.ticks;
248  }
249 
250  bool operator!= (const BBT_Offset& other) const {
251  return bars != other.bars || beats != other.beats || ticks != other.ticks;
252  }
253 
254  operator bool() const {
255  return bars == 0 && beats == 0 && ticks == 0;
256  }
257 
258  std::string str () const {
259  std::ostringstream os;
260  os << bars << '|' << beats << '|' << ticks;
261  return os.str ();
262  }
263 };
264 
266  return Temporal::BBT_Offset (a.bars - b.bars, a.beats - b.beats, a.ticks - b.ticks);
267 }
268 
269 inline bool
270 BBT_Time::operator< (const BBT_Offset& other) const
271 {
272  return bars < other.bars ||
273  (bars == other.bars && beats < other.beats) ||
274  (bars == other.bars && beats == other.beats && ticks < other.ticks);
275 }
276 
277 inline bool
278 BBT_Time::operator<= (const BBT_Offset& other) const
279 {
280  return bars < other.bars ||
281  (bars <= other.bars && beats <= other.beats) ||
282  (bars <= other.bars && beats <= other.beats && ticks <= other.ticks);
283 }
284 
285 inline bool
286 BBT_Time::operator> (const BBT_Offset& other) const
287 {
288  return bars > other.bars ||
289  (bars == other.bars && beats > other.beats) ||
290  (bars == other.bars && beats == other.beats && ticks > other.ticks);
291 }
292 
293 inline bool
295 {
296  return bars > other.bars ||
297  (bars >= other.bars && beats >= other.beats) ||
298  (bars >= other.bars && beats >= other.beats && ticks >= other.ticks);
299 }
300 
301 inline bool
303 {
304  return bars == other.bars && beats == other.beats && ticks == other.ticks;
305 }
306 
307 inline bool
309 {
310  return bars != other.bars || beats != other.beats || ticks != other.ticks;
311 }
312 
313 } /* end of namespace Temporal */
314 
315 /* Putting these into std:: seems wrong, but g++ is unable to find them
316  * otherwise
317  */
318 
319 namespace std {
320 
321 LIBTEMPORAL_API std::ostream& operator<< (std::ostream& o, Temporal::BBT_Time const & bbt);
322 LIBTEMPORAL_API std::ostream& operator<< (std::ostream& o, Temporal::BBT_Offset const & bbt);
323 LIBTEMPORAL_API std::istream& operator>> (std::istream& i, Temporal::BBT_Time& bbt);
324 LIBTEMPORAL_API std::istream& operator>> (std::istream& i, Temporal::BBT_Offset& bbt);
325 
326 template<>
327 struct numeric_limits<Temporal::BBT_Time> {
329  return Temporal::BBT_Time(1, 1, 0);
330  }
332  return Temporal::BBT_Time(1, 1, 0);
333  }
334 
336  return Temporal::BBT_Time(std::numeric_limits<int32_t>::max(),
337  std::numeric_limits<int32_t>::max(),
338  std::numeric_limits<int32_t>::max());
339  }
340 };
341 
342 template<>
343 struct numeric_limits<Temporal::BBT_Offset> {
345  return Temporal::BBT_Time(0, 0, 0);
346  }
347 
349  return Temporal::BBT_Time(0, 0, 0);
350  }
351 
353  return Temporal::BBT_Time(std::numeric_limits<int32_t>::max(),
354  std::numeric_limits<int32_t>::max(),
355  std::numeric_limits<int32_t>::max());
356  }
357 };
358 
359 
360 } /* end of namespace std */
361 
362 namespace PBD {
363 
364 template<>
365 inline bool to_string (Temporal::BBT_Time val, std::string & str)
366 {
367  std::ostringstream ostr;
368  ostr << val;
369  str = ostr.str();
370  return true;
371 }
372 
373 template<>
374 inline std::string to_string (Temporal::BBT_Time val)
375 {
376  std::ostringstream ostr;
377  ostr << val;
378  return ostr.str();
379 }
380 
381 template<>
382 inline bool string_to (std::string const & str, Temporal::BBT_Time & val)
383 {
384  std::istringstream istr (str);
385  istr >> val;
386  return (bool) istr;
387 }
388 
389 template<>
390 inline Temporal::BBT_Time string_to (std::string const & str)
391 {
392  Temporal::BBT_Time tmp;
393  string_to (str, tmp);
394  return tmp;
395 }
396 
397 template<>
398 inline bool to_string (Temporal::BBT_Offset val, std::string & str)
399 {
400  std::ostringstream ostr;
401  ostr << val;
402  str = ostr.str();
403  return true;
404 }
405 
406 template<>
407 inline std::string to_string (Temporal::BBT_Offset val)
408 {
409  std::ostringstream ostr;
410  ostr << val;
411  return ostr.str();
412 }
413 
414 template<>
415 inline bool string_to (std::string const & str, Temporal::BBT_Offset & val)
416 {
417  std::istringstream istr (str);
418  istr >> val;
419  return (bool) istr;
420 }
421 
422 template<>
423 inline Temporal::BBT_Offset string_to (std::string const & str)
424 {
426  string_to (str, tmp);
427  return tmp;
428 }
429 
430 } /* end namespace PBD */
431 
432 #endif /* __libtemporal_bbt_time_h__ */
Definition: axis_view.h:42
std::string to_string(ARDOUR::timepos_t val)
ARDOUR::timepos_t string_to(std::string const &str)
BBT_Offset bbt_delta(Temporal::BBT_Time const &a, Temporal::BBT_Time const &b)
Definition: bbt_time.h:265
static const int32_t ticks_per_beat
bool operator==(const ProcessorSelection &a, const ProcessorSelection &b)
BBT_Offset operator+(const BBT_Offset &other) const
Definition: bbt_time.h:168
BBT_Offset & operator/=(double factor)
Definition: bbt_time.h:215
BBT_Offset & operator*=(double factor)
Definition: bbt_time.h:201
BBT_Offset & operator/=(int factor)
Definition: bbt_time.h:208
BBT_Offset(int32_t ba, uint32_t be, uint32_t t)
Definition: bbt_time.h:158
BBT_Offset & operator+=(const BBT_Offset &other)
Definition: bbt_time.h:180
BBT_Offset operator-(const BBT_Offset &other) const
Definition: bbt_time.h:176
std::string str() const
Definition: bbt_time.h:258
BBT_Offset operator-() const
Definition: bbt_time.h:172
BBT_Offset & operator*=(int factor)
Definition: bbt_time.h:194
BBT_Offset(BBT_Time const &bbt)
Definition: bbt_time.h:159
BBT_Offset & operator-=(const BBT_Offset &other)
Definition: bbt_time.h:187
BBT_Offset(double beats)
BBT_Time round_up_to_beat() const
Definition: bbt_time.h:117
void print_padded(std::ostream &o) const
Definition: bbt_time.h:131
int64_t as_integer() const
BBT_Time(int32_t ba, uint32_t be, uint32_t t)
Definition: bbt_time.h:64
BBT_Time round_down_to_beat() const
Definition: bbt_time.h:116
BBT_Time round_up_to_beat_div(int beat_div) const
bool operator<(const BBT_Time &other) const
Definition: bbt_time.h:70
BBT_Time round_down_to_bar() const
Definition: bbt_time.h:127
static BBT_Time from_integer(int64_t)
std::string str() const
Definition: bbt_time.h:138
bool operator<=(const BBT_Time &other) const
Definition: bbt_time.h:76
BBT_Time round_to_beat() const
Definition: bbt_time.h:115
bool is_bar() const
Definition: bbt_time.h:60
BBT_Time round_up_to_bar() const
BBT_Time prev_bar() const
Definition: bbt_time.h:129
bool operator==(const BBT_Time &other) const
Definition: bbt_time.h:94
bool operator>(const BBT_Time &other) const
Definition: bbt_time.h:82
bool is_beat() const
Definition: bbt_time.h:61
bool operator>=(const BBT_Time &other) const
Definition: bbt_time.h:88
bool operator!=(const BBT_Time &other) const
Definition: bbt_time.h:98
BBT_Time next_bar() const
Definition: bbt_time.h:128
virtual const char * what() const
Definition: bbt_time.h:41
static Temporal::BBT_Offset min()
Definition: bbt_time.h:348
static Temporal::BBT_Time max()
Definition: bbt_time.h:352
static Temporal::BBT_Offset lowest()
Definition: bbt_time.h:344
static Temporal::BBT_Time min()
Definition: bbt_time.h:331
static Temporal::BBT_Time max()
Definition: bbt_time.h:335
static Temporal::BBT_Time lowest()
Definition: bbt_time.h:328
#define LIBTEMPORAL_API