]> git.tdb.fi Git - libs/gui.git/blob - source/input/control.cpp
Use constexpr instead of enum to define "typeless" constants
[libs/gui.git] / source / input / control.cpp
1 #include "control.h"
2 #include <sigc++/bind_return.h>
3 #include <msp/strings/lexicalcast.h>
4 #include "binarycontrol.h"
5 #include "device.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace Input {
11
12 ControlSource::ControlSource(Device &d, ControlSrcType t, unsigned i):
13         dev(&d),
14         type(t),
15         index(i)
16 { }
17
18 std::string ControlSource::str() const
19 {
20         if(type==BUTTON)
21                 return dev->get_button_name(index);
22         else if(type==AXIS_POS)
23                 return dev->get_axis_name(index)+" +";
24         else if(type==AXIS_NEG)
25                 return dev->get_axis_name(index)+" -";
26         else if(type==NO_SOURCE)
27                 return "None";
28
29         return lexical_cast<string>(index);
30 }
31
32
33 Control::Control(const ControlSource &s):
34         src(s)
35 { }
36
37 Control::Control(Device &d, ControlSrcType t, unsigned i):
38         src(d, t, i)
39 {
40         connect_signals();
41 }
42
43 Control::~Control()
44 { }
45
46 void Control::capture(Device &d)
47 {
48         notify_callbacks();
49         capture_dev = &d;
50         capture_dev->signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &Control::button_press), false));
51         capture_dev->signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Control::axis_motion), false));
52 }
53
54 void Control::cancel_capture()
55 {
56         notify_callbacks();
57         capture_dev = 0;
58         connect_signals();
59 }
60
61 void Control::set_source(Device &d, ControlSrcType t, unsigned i)
62 {
63         set_source(ControlSource(d, t, i));
64 }
65
66 void Control::set_source(const ControlSource &s)
67 {
68         notify_callbacks();
69         src = s;
70         connect_signals();
71 }
72
73 void Control::set_activator(BinaryControl *ctrl)
74 {
75         notify_callbacks();
76         activator = ctrl;
77         connect_signals();
78 }
79
80 void Control::reset_edges()
81 {
82         rising_edge = false;
83         falling_edge = false;
84 }
85
86 void Control::connect_signals()
87 {
88         switch(src.type)
89         {
90         case NO_SOURCE:
91                 break;
92         case BUTTON:
93                 src.dev->signal_button_press.connect(sigc::bind_return(sigc::mem_fun(this, &Control::button_press), false));
94                 src.dev->signal_button_release.connect(sigc::bind_return(sigc::mem_fun(this, &Control::button_release), false));
95                 break;
96         case AXIS_POS:
97         case AXIS_NEG:
98                 src.dev->signal_axis_motion.connect(sigc::bind_return(sigc::mem_fun(this, &Control::axis_motion), false));
99                 break;
100         }
101
102         if(activator)
103                 activator->signal_release.connect(sigc::mem_fun(this, &Control::deactivate));
104 }
105
106 void Control::button_press(unsigned i)
107 {
108         if(capture_dev)
109         {
110                 src.dev = capture_dev;
111                 src.type = BUTTON;
112                 src.index = i;
113
114                 notify_callbacks();
115                 capture_dev = 0;
116                 connect_signals();
117                 signal_capture_complete.emit();
118         }
119         else if(src.type==BUTTON && i==src.index && (!activator || activator->get_state()))
120                 on_press();
121 }
122
123 void Control::button_release(unsigned i)
124 {
125         if(src.type==BUTTON && i==src.index && (!activator || activator->get_state()))
126                 on_release();
127 }
128
129 void Control::axis_motion(unsigned i, float v, float r)
130 {
131         if(capture_dev)
132         {
133                 ControlSrcType type = NO_SOURCE;
134                 if(v<-0.9)
135                         type = AXIS_NEG;
136                 else if(v>0.9)
137                         type = AXIS_POS;
138
139                 if(type!=NO_SOURCE)
140                 {
141                         src.dev = capture_dev;
142                         src.type = type;
143                         src.index = i;
144
145                         notify_callbacks();
146                         capture_dev = 0;
147                         connect_signals();
148                         signal_capture_complete.emit();
149                 }
150         }
151         else if(activator && !activator->get_state() && i==src.index)
152                 origin = v;
153         else if(src.type==AXIS_POS && i==src.index && v>=origin)
154                 on_motion(v-origin, r);
155         else if(src.type==AXIS_NEG && i==src.index && v<=origin)
156                 on_motion(origin-v, -r);
157 }
158
159 void Control::deactivate()
160 {
161         if(src.type==BUTTON)
162                 on_release();
163         else if(src.type==AXIS_POS || src.type==AXIS_NEG)
164         {
165                 float v = src.dev->get_axis_value(src.index);
166                 on_motion(0, (src.type==AXIS_POS ? origin-v : v-origin));
167                 origin = v;
168         }
169 }
170
171 } // namespace Input
172 } // namespace Msp