3 #include "pbd/compose.h"
6 #include "m2controls.h"
7 #include "m2_dev_mikro.h"
9 #include <pangomm/fontdescription.h>
13 static size_t mikro_png_readoff = 0;
15 static Cairo::ErrorStatus maschine_png_read (unsigned char* d, unsigned int s) {
16 if (s + mikro_png_readoff > sizeof (mikro_png)) {
17 return CAIRO_STATUS_READ_ERROR;
19 memcpy (d, &mikro_png[mikro_png_readoff], s);
20 mikro_png_readoff += s;
21 return CAIRO_STATUS_SUCCESS;
24 using namespace ArdourSurface;
26 Maschine2Mikro::Maschine2Mikro () : M2Device ()
28 _surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, 128, 64);
33 Maschine2Mikro::clear (bool splash)
35 M2Device::clear (splash);
37 memset (&ctrl_in, 0, sizeof (ctrl_in));
38 memset (pad, 0, sizeof (pad));
42 for (int l = 0; l < 4; ++l) {
46 Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (_surface);
48 mikro_png_readoff = 0;
49 Cairo::RefPtr<Cairo::ImageSurface> sf = Cairo::ImageSurface::create_from_png_stream (sigc::ptr_fun (maschine_png_read));
50 cr->set_source(sf, 0, 0);
53 cr->set_operator (Cairo::OPERATOR_CLEAR);
55 cr->set_operator (Cairo::OPERATOR_OVER);
57 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (cr);
58 Pango::FontDescription fd ("Sans Bold 18px");
59 layout->set_font_description (fd);
60 layout->set_alignment (Pango::ALIGN_CENTER);
62 layout->set_text (string_compose ("%1\n%2", PROGRAM_NAME, VERSIONSTRING));
64 layout->get_pixel_size (tw, th);
65 cr->move_to (128 - tw * 0.5, 32 - th * 0.5);
66 cr->set_source_rgb (1, 1, 1);
67 layout->show_in_cairo_context(cr);
69 //_surface->write_to_png ("/tmp/amaschine.png");
73 Maschine2Mikro::read (hid_device* handle, M2Contols* ctrl)
78 int res = hid_read (handle, buf, 256);
83 // TODO parse incrementally if chunked at 64
85 if (res > 4 && buf[0] == 0x01) {
86 memcpy (&ctrl_in, &buf[1], sizeof (ctrl_in));
87 assign_controls (ctrl);
89 else if (res > 32 && buf[0] == 0x20) {
90 for (unsigned int i = 0; i < 16; ++i) {
91 uint8_t v0 = buf[1 + 2 * i];
92 uint8_t v1 = buf[2 + 2 * i];
93 uint8_t p = (v1 & 0xf0) >> 4;
94 pad[p] = ((v1 & 0xf) << 8) | v0;
95 unsigned int pid = 15 - ((i & 0xc) + (3 - (i & 0x3)));
96 ctrl->pad (pid)->set_value (pad[p]);
98 // TODO read complete 65 byte msg, expect buf[33] == 0x00
104 Maschine2Mikro::write (hid_device* handle, M2Contols* ctrl)
109 //TODO double-buffer, send changes only if needed
111 /* 30 control buttons, 8-bit brightness,
115 set_lights (ctrl, &buf[1]);
116 set_pads (ctrl, &buf[31]);
117 if (memcmp (_lights, buf, 79)) {
118 hid_write (handle, buf, 79);
119 memcpy (_lights, buf, 79);
122 if (_splashcnt < _splashtime ) {
125 else if (! vblank () /* EMIT SIGNAL*/) {
126 /* check clear/initial draw */
127 if (_img[0][0] != 0xff) {
134 const unsigned char* img = _surface->get_data ();
135 const int stride = _surface->get_stride ();
138 for (int l = 0; l < 4; ++l) {
144 for (int p = 0; p < 256; ++p) {
146 const int y = y0 + p / 16;
147 for (int b = 0; b < 8; ++b) {
148 const int x = (p % 16) * 8 + b;
149 int off = y * stride + x * 4 /* ARGB32 */;
155 /* calculate lightness */
156 uint8_t l = std::max (img[off + 0], std::max (img[off + 1], img[off + 2]));
157 if (l > 0x7e) { // TODO: take alpha channel into account?!
163 if (memcmp (_img[l], buf, 265)) {
164 hid_write (handle, buf, 265);
165 memcpy (_img[l], buf, 265);
171 Maschine2Mikro::assign_controls (M2Contols* ctrl) const
173 ctrl->button (M2Contols::BtnShift, M2Contols::ModNone)->set_active (ctrl_in.trs_shift ? true : false);
174 M2Contols::Modifier mod = ctrl->button (M2Contols::BtnShift, M2Contols::ModNone)->active () ? M2Contols::ModShift : M2Contols::ModNone;
177 #define ASSIGN(BTN, VAR) \
178 change |= ctrl->button (M2Contols:: BTN, mod)->set_active (ctrl_in. VAR ? true : false)
180 ASSIGN (BtnRestart, trs_restart);
181 ASSIGN (BtnStepLeft, trs_left);
182 ASSIGN (BtnStepRight, trs_right);
183 ASSIGN (BtnGrid, trs_grid);
184 ASSIGN (BtnPlay, trs_play);
185 ASSIGN (BtnRec, trs_rec);
186 ASSIGN (BtnErase, trs_erase);
188 ASSIGN (BtnGroupA, group);
189 ASSIGN (BtnBrowse, browse);
190 ASSIGN (BtnSampling, sampling);
191 ASSIGN (BtnNoteRepeat, note_repeat);
192 ASSIGN (BtnWheel, mst_wheel);
194 ASSIGN (BtnTop0, f1);
195 ASSIGN (BtnTop1, f1);
196 ASSIGN (BtnTop2, f3);
198 ASSIGN (BtnControl, control);
199 ASSIGN (BtnNavigate, navigate); // XXX
200 ASSIGN (BtnNavLeft, nav_left);
201 ASSIGN (BtnNavRight, nav_right);
202 ASSIGN (BtnEnter, main);
204 ASSIGN (BtnScene, pads_scene);
205 ASSIGN (BtnPattern, pads_pattern);
206 ASSIGN (BtnPadMode, pads_mode);
207 ASSIGN (BtnNavigate, pads_navigate);
208 ASSIGN (BtnDuplicate, pads_duplicate);
209 ASSIGN (BtnSelect, pads_select);
210 ASSIGN (BtnSolo, pads_solo);
211 ASSIGN (BtnMute, pads_mute);
214 change |= ctrl->encoder (0)->set_value (ctrl_in.mst_wheel_pos);
216 if (change && mod == M2Contols::ModShift) {
217 M2ToggleHoldButton* btn = dynamic_cast<M2ToggleHoldButton*> (ctrl->button (M2Contols::BtnShift, M2Contols::ModNone));
219 btn->unset_active_on_release ();
224 #define LIGHT(BIT, BTN) \
225 b[BIT] = ctrl->button (M2Contols:: BTN, mod)->lightness (_blink_shade)
228 Maschine2Mikro::set_pads (M2Contols* ctrl, uint8_t* b) const
234 for (unsigned int i = 0; i < 16; ++i) {
235 unsigned int pid = 15 - ((i & 0xc) + (3 - (i & 0x3)));
236 ctrl->pad (pid)->color (b[i * 3], b[1 + i * 3], b[2 + i * 3]);
241 Maschine2Mikro::set_lights (M2Contols* ctrl, uint8_t* b) const
247 M2Contols::Modifier mod = ctrl->button (M2Contols::BtnShift, M2Contols::ModNone)->active () ? M2Contols::ModShift : M2Contols::ModNone;
249 LIGHT ( 0, BtnTop0); // F1
250 LIGHT ( 1, BtnTop1); // F2
251 LIGHT ( 2, BtnTop2); // F3
252 LIGHT ( 3, BtnControl);
253 LIGHT ( 4, BtnNavigate); // XXX
254 LIGHT ( 5, BtnNavLeft);
255 LIGHT ( 6, BtnNavRight);
256 LIGHT ( 7, BtnEnter); // Main
258 const uint32_t rgb = ctrl->button (M2Contols::BtnGroupA, mod)->color (_blink_shade);
259 b[8] = (rgb >> 0) & 0xff;
260 b[9] = (rgb >> 8) & 0xff;
261 b[10] = (rgb >> 16) & 0xff;
263 LIGHT (11, BtnBrowse);
264 LIGHT (12, BtnSampling);
265 LIGHT (13, BtnNoteRepeat);
267 LIGHT (14, BtnRestart);
268 LIGHT (15, BtnStepLeft);
269 LIGHT (16, BtnStepRight);
273 LIGHT (20, BtnErase);
274 LIGHT (21, BtnShift);
276 LIGHT (22, BtnScene);
277 LIGHT (23, BtnPattern);
278 LIGHT (24, BtnPadMode);
279 LIGHT (25, BtnNavigate);
280 LIGHT (26, BtnDuplicate);
281 LIGHT (27, BtnSelect);