Skeleton for NI Maschine2 Surface
[ardour.git] / libs / surfaces / maschine2 / m2_encoder.h
1 /*
2  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #ifndef _ardour_surfaces_m2encoder_h_
20 #define _ardour_surfaces_m2encoder_h_
21
22 #include <stdint.h>
23 #include "pbd/signals.h"
24
25 namespace ArdourSurface {
26
27 class M2EncoderInterface
28 {
29         public:
30                 M2EncoderInterface () {}
31                 virtual ~M2EncoderInterface () {}
32
33                 /* user API */
34                 PBD::Signal1<void, int> changed;
35                 virtual float value () const { return 0.f; }
36                 virtual float range () const { return 0.f; }
37
38                 /* internal API - called from device thread */
39                 virtual bool set_value (unsigned int v) { return false; }
40 };
41
42 class M2Encoder : public M2EncoderInterface
43 {
44         public:
45                 M2Encoder (unsigned int upper = 1000)
46                         : M2EncoderInterface ()
47                         , _upper (upper /* limit, exclusive. eg [0..15]: 16 */)
48                         , _value (0)
49                         , _initialized (false)
50                 {
51                         assert (_upper > 7);
52                         _wrapcnt = std::max (3U, upper / 6);
53                 }
54
55                 float value () const { return _value / (_upper - 1.f); }
56                 float range () const { return (_upper - 1.f); }
57
58                 bool set_value (unsigned int v) {
59                         if (!_initialized) {
60                                 _initialized = true;
61                                 _value = v;
62                                 return false;
63                         }
64
65                         if (v == _value) {
66                                 return false;
67                         }
68
69                         int delta;
70                         if (v < _wrapcnt && _value > _upper - _wrapcnt) {
71                                 // wrap around max -> min
72                                 delta = v + _upper - _value;
73                         }
74                         else if (_value < _wrapcnt && v > _upper - _wrapcnt) {
75                                 // wrap around min -> max
76                                 delta = v - _upper - _value;
77                         }
78                         else {
79                                 delta = v - _value;
80                         }
81
82                         _value = v;
83                         changed (delta);
84                         return true;
85                 }
86
87         protected:
88                 unsigned int _upper;
89                 unsigned int _value;
90                 unsigned int _wrapcnt;
91                 bool _initialized;
92 };
93
94 } /* namespace */
95 #endif /* _ardour_surfaces_m2encoder_h_ */
96
97