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