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