4 Created: 03/26/07 20:07:56
8 #include <linux/input.h>
17 #include "pbd/pthread_utils.h"
18 #include "pbd/xml++.h"
19 #include "pbd/error.h"
21 #include "ardour/debug.h"
23 #include "powermate.h"
26 using namespace ARDOUR;
31 #define NUM_VALID_PREFIXES 2
33 static const char *valid_prefix[NUM_VALID_PREFIXES] = {
38 #define NUM_EVENT_DEVICES 16
40 int open_powermate (const char *dev, int mode)
42 if (!Glib::file_test (dev, Glib::FILE_TEST_EXISTS)) {
46 int fd = open(dev, mode);
51 if (errno != EACCES) {
52 error << string_compose ("Unable to open \"%1\": %2", dev, strerror(errno)) << endmsg;
57 /* placate valgrind */
60 if (ioctl (fd, EVIOCGNAME (sizeof(name)), name) < 0) {
61 error << string_compose ("\"%1\": EVIOCGNAME failed: %2", dev, strerror(errno)) << endmsg;
66 // it's the correct device if the prefix matches what we expect it to be:
67 for (i = 0; i < NUM_VALID_PREFIXES; ++i) {
68 if (!strncasecmp (name, valid_prefix[i], strlen (valid_prefix[i]))) {
77 int find_powermate(int mode)
82 for (i = 0; i < NUM_EVENT_DEVICES; i++) {
83 sprintf (devname, "/dev/input/event%d", i);
84 r = open_powermate (devname, mode);
93 PowermateControlProtocol::PowermateControlProtocol (Session& s)
94 : ControlProtocol (s, "powermate", 0 /* XXX need an event loop here */)
98 PowermateControlProtocol::~PowermateControlProtocol ()
104 PowermateControlProtocol::probe ()
106 int port = find_powermate( O_RDONLY );
109 if (errno == ENOENT) {
110 DEBUG_TRACE (DEBUG::ControlProtocols, "Powermate device not found; perhaps you have no powermate connected");
112 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("powermate: Opening of powermate failed - %1\n", strerror(errno)));
122 PowermateControlProtocol::set_active (bool inActivate)
124 if (inActivate != _active) {
128 mPort = find_powermate(O_RDONLY);
134 if (pthread_create_and_store ("Powermate", &mThread, SerialThreadEntry, this) == 0) {
140 printf("Powermate Control Protocol activated\n");
143 pthread_cancel (mThread);
146 printf("Powermate Control Protocol deactivated\n");
154 PowermateControlProtocol::get_state ()
156 XMLNode* node = new XMLNode (X_("Protocol"));
157 node->add_property (X_("name"), _name);
162 PowermateControlProtocol::set_state (const XMLNode& /*node*/, int /*version*/)
169 PowermateControlProtocol::SerialThreadEntry (void* arg)
171 static_cast<PowermateControlProtocol*>(arg)->register_thread ("Powermate");
172 return static_cast<PowermateControlProtocol*>(arg)->SerialThread ();
175 #define BUFFER_SIZE 32
178 bool skippingMarkers = false;
181 PowermateControlProtocol::ProcessEvent(struct input_event *ev)
184 fprintf(stderr, "type=0x%04x, code=0x%04x, value=%d\n",
185 ev->type, ev->code, (int)ev->value);
190 printf("The LED pulse settings were changed; code=0x%04x, value=0x%08x\n", ev->code, ev->value);
193 if(ev->code != REL_DIAL)
194 fprintf(stderr, "Warning: unexpected rotation event; ev->code = 0x%04x\n", ev->code);
197 //click and hold to skip forward and back by markers
198 skippingMarkers = true;;
204 //scale the range so that we can go from +/-8x within 180 degrees, with less precision at the higher speeds
205 float speed = get_transport_speed();
206 speed += (float)ev->value * 0.05;
207 if (speed > 1.5 || speed < -1.5 )
209 set_transport_speed( speed );
214 if(ev->code != BTN_0)
215 fprintf(stderr, "Warning: unexpected key event; ev->code = 0x%04x\n", ev->code);
221 if (skippingMarkers) {
222 skippingMarkers = false;
224 if (get_transport_speed() == 0.0) {
225 set_transport_speed(1.0);
227 set_transport_speed(0.0);
238 PowermateControlProtocol::SerialThread ()
240 struct input_event ibuffer[BUFFER_SIZE];
244 r = read(mPort, ibuffer, sizeof(struct input_event) * BUFFER_SIZE);
246 events = r / sizeof(struct input_event);
247 for(i=0; i<events; i++)
248 ProcessEvent(&ibuffer[i]);
250 fprintf(stderr, "read() failed: %s\n", strerror(errno));