librekontrol-core.c 39.5 KB
Newer Older
brandon's avatar
brandon committed
1
/* 
2
 * librekontrol-core.c --- 
brandon's avatar
brandon committed
3
 * 
4
 * Copyright (C) 2016, 2017, 2019 Brandon Invergo <brandon@invergo.net>
brandon's avatar
brandon committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 
 * Author: Brandon Invergo <brandon@invergo.net>
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

22
#include "librekontrol-core.h"
brandon's avatar
brandon committed
23

brandon's avatar
brandon committed
24
#define _(String) gettext (String)
25 26 27
#define gettext_noop(String) String
#define N_(String) gettext_noop (String)

28 29
static SCM device_type;
static SCM ctl_type;
brandon's avatar
brandon committed
30

31
lk_device_t **lk_device_list = NULL;
32
size_t lk_num_devices = 0;
33
lk_device_ctl_t **lk_ctl_list = NULL;
34 35
size_t lk_num_ctls = 0;

36 37 38 39
struct open_device_req
{
  char *ctl_name_str;
  char *in_name_str;
40
  bool open_midi_seq;
41
  bool open_output_evdev;
42 43 44 45 46
  int err;
};

struct open_ctl_req
{
47
  size_t device_n;
48 49 50 51 52 53
  char *ctl_id_str;
  int err;
};

struct bool_ctl_req
{
54
  size_t ctl_n;
55 56 57 58 59
  bool value;
};

struct int_ctl_req
{
60
  size_t ctl_n;
61 62 63 64 65
  long int value;
};

struct abs_in_req
{
66
  size_t device_n;
67 68 69 70
  unsigned int code;
  int value;
};

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
struct remap_toggle_event_req
{
  size_t device_n;
  unsigned int code;
  unsigned int type;
  bool enable;
  int err;
};

struct remap_set_abs_info_req
{
  size_t device_n;
  unsigned int code;
  int min;
  int max;
  int resolution;
  int fuzz;
  int flat;
  int err;
};

struct finalize_remap_dev_req
{
  size_t device_n;
  int err;
};

struct send_remap_event_req
{
  size_t device_n;
  unsigned int type;
  unsigned int code;
  int value;
  int err;
};

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
struct send_midi_req
{
  size_t device_n;
  unsigned char channel;
  unsigned char note;
  unsigned char velocity;
  unsigned int dur;
};

struct send_midi_param_req
{
  size_t device_n;
  unsigned char channel;
  unsigned int param;
  int value;
};

124 125 126 127
void*
open_device_wrapper (void *data)
{
  struct open_device_req *request = data;
128 129
  if (lk_num_devices == 0)
    {
130 131
      lk_device_list = (lk_device_t **)malloc ((++lk_num_devices)*sizeof (lk_device_t));
      lk_device_list[0] = (lk_device_t *)malloc (sizeof (lk_device_t));
132 133 134
    }
  else
    {
135 136
      lk_device_list = (lk_device_t **)realloc (lk_device_list, (++lk_num_devices)*sizeof (lk_device_t));
      lk_device_list[lk_num_devices-1] = (lk_device_t *)malloc (sizeof (lk_device_t));
137 138 139 140 141 142
    }
  if (!lk_device_list || !lk_device_list[lk_num_devices-1])
    {
      error (EXIT_FAILURE, errno, _("Memory exhausted"));
    }
  request->err = open_device (lk_device_list[lk_num_devices-1], request->ctl_name_str,
143 144
                              request->in_name_str, request->open_midi_seq,
                              request->open_output_evdev);
145 146 147
  if (request->err)
    {
      free (lk_device_list[lk_num_devices-1]);
148 149 150 151 152 153 154 155 156 157 158 159 160 161
      lk_num_devices--;
      if (lk_num_devices > 0)
        {
          lk_device_list = (lk_device_t **)realloc (lk_device_list, lk_num_devices*sizeof (lk_device_t));
          if (!lk_device_list)
            {
              error (EXIT_FAILURE, errno, _("Memory exhausted?"));
            }
        }
      else
        {
          free (lk_device_list);
          lk_device_list = NULL;
        }
162
    }
163 164 165 166 167 168 169
  return (void *)request;
}

void*
open_ctl_wrapper (void *data)
{
  struct open_ctl_req *request = data;
170 171 172 173
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, "Invalid device selected");
    }
174
  lk_device_t *device = lk_device_list[request->device_n];
175 176
  if (lk_num_ctls == 0)
    {
177 178
      lk_ctl_list = (lk_device_ctl_t **)malloc ((++lk_num_ctls)*sizeof (lk_device_ctl_t));
      lk_ctl_list[0] = (lk_device_ctl_t *)malloc (sizeof (lk_device_ctl_t));
179 180 181
    }
  else
    {
182 183
      lk_ctl_list = (lk_device_ctl_t **)realloc (lk_ctl_list, (++lk_num_ctls)*sizeof (lk_device_ctl_t));
      lk_ctl_list[lk_num_ctls-1] = (lk_device_ctl_t *)malloc (sizeof (lk_device_ctl_t));
184 185 186 187 188 189
    }
  if (!lk_ctl_list || !lk_ctl_list[lk_num_ctls-1])
    {
      error (EXIT_FAILURE, errno, _("Memory exhausted"));
    }
  request->err = open_control (lk_ctl_list[lk_num_ctls-1], device,
190
                               request->ctl_id_str);
191 192 193 194 195
  if (request->err)
    {
      free (lk_ctl_list[lk_num_ctls-1]);
      lk_ctl_list[lk_num_ctls-1] = NULL;
    }
196 197 198
  return (void *)request;
}

199 200
void*
set_boolean_ctl_wrapper (void *data)
201 202
{
  struct bool_ctl_req *request = data;
203 204 205 206
  if (request->ctl_n >= lk_num_ctls)
    {
      error (EXIT_FAILURE, 0, _("Invalid ctl selected"));
    }
207
  lk_device_ctl_t *ctl = lk_ctl_list[request->ctl_n];
208
  set_boolean_ctl (ctl, request->value);
209 210 211
  return (void *)request;
}

212 213
void*
get_boolean_ctl_wrapper (void *data)
214 215
{
  struct bool_ctl_req *request = data;
216 217 218 219
  if (request->ctl_n >= lk_num_ctls)
    {
      error (EXIT_FAILURE, 0, _("Invalid ctl selected"));
    }
220
  lk_device_ctl_t *ctl = lk_ctl_list[request->ctl_n];
221 222
  if (ctl)
    request->value = get_boolean_ctl (ctl);
223 224 225
  return (void *)request;
}

226 227
void*
toggle_boolean_ctl_wrapper (void *data)
228 229
{
  struct bool_ctl_req *request = data;
230 231 232 233
  if (request->ctl_n >= lk_num_ctls)
    {
      error (EXIT_FAILURE, 0, _("Invalid ctl selected"));
    }
234
  lk_device_ctl_t *ctl = lk_ctl_list[request->ctl_n];
235
  toggle_boolean_ctl (ctl);
236 237 238
  return (void *)request;
}

239 240
void*
set_integer_ctl_wrapper (void *data)
241
{
242
  struct int_ctl_req *request = data;
243 244 245 246
  if (request->ctl_n >= lk_num_ctls)
    {
      error (EXIT_FAILURE, 0, _("Invalid ctl selected"));
    }
247
  lk_device_ctl_t *ctl = lk_ctl_list[request->ctl_n];
248
  set_integer_ctl (ctl, request->value);
249 250 251
  return (void *)request;
}

252 253
void*
get_integer_ctl_wrapper (void *data)
254
{
255
  struct int_ctl_req *request = data;
256 257 258 259
  if (request->ctl_n >= lk_num_ctls)
    {
      error (EXIT_FAILURE, 0, _("Invalid ctl selected"));
    }
260
  lk_device_ctl_t *ctl = lk_ctl_list[request->ctl_n];
261
  request->value = get_integer_ctl (ctl);
262 263 264
  return (void *)request;
}

265 266
void*
integer_ctl_max_wrapper (void *data)
267
{
268
  struct int_ctl_req *request = data;
269 270 271 272
  if (request->ctl_n >= lk_num_ctls)
    {
      error (EXIT_FAILURE, 0, _("Invalid ctl selected"));
    }
273
  lk_device_ctl_t *ctl = lk_ctl_list[request->ctl_n];
274
  request->value = integer_ctl_max (ctl);
275 276 277
  return (void *)request;
}

278 279
void*
integer_ctl_min_wrapper (void *data)
280
{
281
  struct int_ctl_req *request = data;
282 283 284 285
  if (request->ctl_n >= lk_num_ctls)
    {
      error (EXIT_FAILURE, 0, _("Invalid ctl selected"));
    }
286
  lk_device_ctl_t *ctl = lk_ctl_list[request->ctl_n];
287
  request->value = integer_ctl_min (ctl);
288 289 290
  return (void *)request;
}

291 292
void*
abs_in_max_wrapper (void *data)
293 294
{
  struct abs_in_req *request = data;
295 296 297 298
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
299
  lk_device_t *device = lk_device_list[request->device_n];
300
  request->value = abs_in_max (device, request->code);
301 302 303
  return (void *)request;
}

304 305
void*
abs_in_min_wrapper (void *data)
306 307
{
  struct abs_in_req *request = data;
308 309 310 311
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
312
  lk_device_t *device = lk_device_list[request->device_n];
313
  request->value = abs_in_min (device, request->code);
314 315 316
  return (void *)request;
}

317 318 319 320 321 322 323 324
void*
remap_toggle_event_wrapper (void *data)
{
  struct remap_toggle_event_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
325
  lk_device_t *device = lk_device_list[request->device_n];
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
  if (request->enable)
    {
      request->err = remap_enable_event (device, request->type, request->code);
    }
  else
    {
      request->err = remap_disable_event (device, request->type, request->code);
    }
  return (void *)request;
}

void*
remap_set_abs_info_wrapper (void *data)
{
  struct remap_set_abs_info_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
345
  lk_device_t *device = lk_device_list[request->device_n];
346 347 348 349 350 351 352 353 354 355 356 357 358 359
  request->err = remap_set_abs_info (device, request->code, request->min,
                                     request->max, request->resolution,
                                     request->fuzz, request->flat);
  return (void *)request;
}

void*
finalize_remap_dev_wrapper (void *data)
{
  struct finalize_remap_dev_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
360
  lk_device_t *device = lk_device_list[request->device_n];
361 362 363 364 365 366 367 368 369 370 371 372
  request->err = finalize_remap_dev (device);
  return (void *)request;
}

void*
send_remap_event_wrapper (void *data)
{
  struct send_remap_event_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
373
  lk_device_t *device = lk_device_list[request->device_n];
374 375 376 377 378
  request->err = send_remap_event (device, request->type, request->code,
                                   request->value);
  return (void *)request;
}

379 380 381 382 383 384 385 386
void*
send_midi_keypress_wrapper (void *data)
{
  struct send_midi_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
387
  lk_device_t *device = lk_device_list[request->device_n];
388 389 390 391 392 393 394 395 396 397 398
  send_midi_keypress (device, request->channel, request->note, request->velocity);
}

void*
send_midi_note_wrapper (void *data)
{
  struct send_midi_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
399
  lk_device_t *device = lk_device_list[request->device_n];
400 401 402 403 404 405 406 407 408 409 410 411
  send_midi_note (device, request->channel, request->note, request->velocity,
                      request->dur);
}

void*
send_midi_noteon_wrapper (void *data)
{
  struct send_midi_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
412
  lk_device_t *device = lk_device_list[request->device_n];
413 414 415 416 417 418 419 420 421 422 423
  send_midi_noteon (device, request->channel, request->note, request->velocity);
}

void*
send_midi_noteoff_wrapper (void *data)
{
  struct send_midi_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
424
  lk_device_t *device = lk_device_list[request->device_n];
425 426 427 428 429 430 431 432 433 434 435
  send_midi_noteoff (device, request->channel, request->note, request->velocity);
}

void*
send_midi_pgmchange_wrapper (void *data)
{
  struct send_midi_param_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
436
  lk_device_t *device = lk_device_list[request->device_n];
437 438 439 440 441 442 443 444 445 446 447
  send_midi_pgmchange (device, request->channel, request->value);
}

void*
send_midi_pitchbend_wrapper (void *data)
{
  struct send_midi_param_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
448
  lk_device_t *device = lk_device_list[request->device_n];
449 450 451 452 453 454 455 456 457 458 459
  send_midi_pitchbend (device, request->channel, request->value);
}

void*
send_midi_control_wrapper (void *data)
{
  struct send_midi_param_req *request = data;
  if (request->device_n >= lk_num_devices)
    {
      error (EXIT_FAILURE, 0, _("Invalid device selected"));
    }
460
  lk_device_t *device = lk_device_list[request->device_n];
461 462 463
  send_midi_control (device, request->channel, request->param, request->value);
}

brandon's avatar
brandon committed
464
SCM
465
lk_scm_set_idle_wait (SCM lk_device_s, SCM idle_wait)
brandon's avatar
brandon committed
466
{
467 468 469 470 471 472
  if (scm_is_false (lk_device_s))
    {
      error (0, 0, _("Failed to set idle wait: device not opened."));
      return SCM_BOOL_F;
    }
  scm_assert_foreign_object_type (device_type, lk_device_s);
473 474
  size_t device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0);
  lk_device_t *device = lk_device_list[device_n];
475 476 477 478
  if (!device)
    {
      error (EXIT_FAILURE, 0, _("Lost track of a device, bailing out."));
    }
479 480 481
  SCM s_dev_id = scm_from_latin1_string (device->id);
  SCM s_idle_waits_symbol = scm_c_lookup ("lk-idle-waits");
  SCM s_idle_waits = scm_variable_ref (s_idle_waits_symbol);
482 483
  scm_hash_set_x (s_idle_waits, s_dev_id, idle_wait);
  return SCM_BOOL_T;
brandon's avatar
brandon committed
484 485
}

486 487
void
init_device_type (void)
brandon's avatar
brandon committed
488
{
489 490 491
  SCM name = scm_from_latin1_symbol ("lk-device");
  SCM slots = scm_list_1 (scm_from_latin1_symbol ("lk-device-number"));
  scm_t_struct_finalize finalizer = NULL;
492
  device_type = scm_make_foreign_object_type (name, slots, finalizer);
brandon's avatar
brandon committed
493 494
}

495 496
void
init_ctl_type (void)
brandon's avatar
brandon committed
497
{
498 499 500 501
  SCM name = scm_from_latin1_symbol ("lk-ctl");
  SCM slots = scm_list_2 (scm_from_latin1_symbol ("lk-device-number"),
                          scm_from_latin1_symbol ("lk-ctl-number"));
  scm_t_struct_finalize finalizer = NULL;
502 503

  ctl_type = scm_make_foreign_object_type (name, slots, finalizer);
brandon's avatar
brandon committed
504 505
}

brandon's avatar
brandon committed
506
SCM
507
lk_scm_open_device (SCM controller_name, SCM input_name, SCM open_midi_seq,
508
                       SCM open_output_evdev)
brandon's avatar
brandon committed
509
{
510
  char *ctl_name_str = NULL;
brandon's avatar
brandon committed
511
  char *in_name_str = NULL;
512
  if (!scm_is_false (controller_name))
513 514 515
    {
      ctl_name_str = scm_to_latin1_stringn (controller_name, NULL);
    }
brandon's avatar
brandon committed
516 517 518 519
  if (!scm_is_false (input_name))
    {
      in_name_str = scm_to_latin1_stringn (input_name, NULL);
    }
520 521 522 523 524
  struct open_device_req request = {.ctl_name_str = ctl_name_str,
                                    .in_name_str = in_name_str,
                                    .open_midi_seq = scm_to_bool (open_midi_seq),
                                    .open_output_evdev = scm_to_bool (open_output_evdev),
                                    .err = 0};
525 526
  scm_without_guile (&open_device_wrapper, &request);
  if (request.err < 0)
527 528 529
    {
      return SCM_BOOL_F;
    }
530
  SCM lk_device_s = scm_make_foreign_object_0 (device_type);
531
  scm_foreign_object_unsigned_set_x (lk_device_s, 0, lk_num_devices-1);
532
  scm_permanent_object (lk_device_s);
533
  lk_scm_set_idle_wait (lk_device_s, scm_from_double(1.0));
534

535 536 537
  SCM s_ev_hand_symbol = scm_c_lookup ("lk-event-handlers");
  SCM s_event_handlers = scm_variable_ref (s_ev_hand_symbol);
  SCM s_ev_hand_key = scm_from_latin1_string (lk_device_list[lk_num_devices-1]->id);
538
  scm_hash_set_x (s_event_handlers, s_ev_hand_key, scm_c_make_hash_table (1));
539
  return lk_device_s;
540 541
}

brandon's avatar
brandon committed
542
SCM
543
lk_scm_open_ctl (SCM lk_device_s, SCM ctl_id_num)
brandon's avatar
brandon committed
544
{
545
  char *ctl_id_str;
546
  if (scm_is_false (lk_device_s))
547
    {
548 549
      error (0, 0, _("Failed to open control %s: device not opened."),
             ctl_id_str);
550 551
      return SCM_BOOL_F;
    }
552 553
  SCM ctl_id = scm_simple_format (SCM_BOOL_F, scm_from_latin1_string ("numid=~a"),
                                  scm_list_1 (ctl_id_num));
554
  ctl_id_str = scm_to_latin1_stringn (ctl_id, NULL);
555
  scm_assert_foreign_object_type (device_type, lk_device_s);
556 557 558 559
  size_t device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0);
  struct open_ctl_req request = {.device_n = device_n,
                                 .ctl_id_str = ctl_id_str,
                                 .err = 0};
560 561
  scm_without_guile (&open_ctl_wrapper, &request);
  if (request.err < 0)
562 563 564
    {
      return SCM_BOOL_F;
    }
565
  SCM lk_ctl_s = scm_make_foreign_object_0 (ctl_type);
566 567
  scm_foreign_object_unsigned_set_x (lk_ctl_s, 0, device_n);
  scm_foreign_object_unsigned_set_x (lk_ctl_s, 1, lk_num_ctls-1);
568 569
  scm_permanent_object (lk_ctl_s);
  return lk_ctl_s;
brandon's avatar
brandon committed
570 571 572
}

SCM
573
lk_scm_set_boolean_ctl (SCM lk_ctl_s, SCM value)
brandon's avatar
brandon committed
574
{
575
  if (scm_is_false (lk_ctl_s))
576
    {
577
      error (0, 0, _("Failed to set control: control not opened."));
578 579
      return SCM_BOOL_F;
    }
580
  scm_assert_foreign_object_type (ctl_type, lk_ctl_s);
581 582 583
  size_t ctl_n = scm_foreign_object_unsigned_ref (lk_ctl_s, 1);
  struct bool_ctl_req request = {.ctl_n = ctl_n,
                                 .value = (bool) scm_to_bool (value)};
584
  scm_without_guile (&set_boolean_ctl_wrapper, &request);
585
  return SCM_BOOL_T;
brandon's avatar
brandon committed
586 587 588
}

SCM
589
lk_scm_get_boolean_ctl (SCM lk_ctl_s)
brandon's avatar
brandon committed
590
{
591
  if (scm_is_false (lk_ctl_s))
592
    {
593
      error (0, 0, _("Failed to get control: control not opened."));
594 595
      return SCM_BOOL_F;
    }
596
  scm_assert_foreign_object_type (ctl_type, lk_ctl_s);
597 598
  size_t ctl_n = scm_foreign_object_unsigned_ref (lk_ctl_s, 1);
  struct bool_ctl_req request = {.ctl_n = ctl_n};
599
  scm_without_guile (&get_boolean_ctl_wrapper, &request);
600
  return scm_from_bool ((int) request.value);
brandon's avatar
brandon committed
601 602 603
}

SCM
604
lk_scm_toggle_boolean_ctl (SCM lk_ctl_s)
brandon's avatar
brandon committed
605
{
606
  if (scm_is_false (lk_ctl_s))
607
    {
608
      error (0, 0, _("Failed to toggle control: control not opened."));
609 610
      return SCM_BOOL_F;
    }
611
  scm_assert_foreign_object_type (ctl_type, lk_ctl_s);
612 613
  size_t ctl_n = scm_foreign_object_unsigned_ref (lk_ctl_s, 1);
  struct bool_ctl_req request = {.ctl_n = ctl_n};
614
  scm_without_guile (&toggle_boolean_ctl_wrapper, &request);
615
  return SCM_BOOL_T;
brandon's avatar
brandon committed
616 617 618
}

SCM
619
lk_scm_set_integer_ctl (SCM lk_ctl_s, SCM value)
brandon's avatar
brandon committed
620
{
621
  if (scm_is_false (lk_ctl_s))
622
    {
623
      error (0, 0, _("Failed to set control: control not opened."));
624 625
      return SCM_BOOL_F;
    }
626
  scm_assert_foreign_object_type (ctl_type, lk_ctl_s);
627 628 629
  size_t ctl_n = scm_foreign_object_unsigned_ref (lk_ctl_s, 1);
  struct int_ctl_req request = {.ctl_n = ctl_n,
                                .value = scm_to_long (value)};
630
  scm_without_guile (&set_integer_ctl_wrapper, &request);
631
  return SCM_BOOL_T;
brandon's avatar
brandon committed
632 633 634
}

SCM
635
lk_scm_get_integer_ctl (SCM lk_ctl_s)
brandon's avatar
brandon committed
636
{
637
  if (scm_is_false (lk_ctl_s))
638
    {
639
      error (0, 0, _("Failed to get control: control not opened."));
640 641
      return SCM_BOOL_F;
    }
642
  scm_assert_foreign_object_type (ctl_type, lk_ctl_s);
643 644
  size_t ctl_n = scm_foreign_object_unsigned_ref (lk_ctl_s, 1);
  struct int_ctl_req request = {.ctl_n = ctl_n};
645
  scm_without_guile (&get_integer_ctl_wrapper, &request);
646
  return scm_from_long (request.value);
brandon's avatar
brandon committed
647 648
}

649
SCM
650
lk_scm_integer_ctl_max (SCM lk_ctl_s)
651
{
652
  if (scm_is_false (lk_ctl_s))
653
    {
654
      error (0, 0, _("Failed to get control max: control not opened."));
655 656
      return SCM_BOOL_F;
    }
657
  scm_assert_foreign_object_type (ctl_type, lk_ctl_s);
658 659
  size_t ctl_n = scm_foreign_object_unsigned_ref (lk_ctl_s, 1);
  struct int_ctl_req request = {.ctl_n = ctl_n};
660
  scm_without_guile (&integer_ctl_max_wrapper, &request);
661
  return scm_from_long (request.value);
662 663 664
}

SCM
665
lk_scm_integer_ctl_min (SCM lk_ctl_s)
666
{
667
  if (scm_is_false (lk_ctl_s))
668
    {
669
      error (0, 0, _("Failed to get control min: control not opened."));
670 671
      return SCM_BOOL_F;
    }
672
  scm_assert_foreign_object_type (ctl_type, lk_ctl_s);
673 674
  size_t ctl_n = scm_foreign_object_unsigned_ref (lk_ctl_s, 1);
  struct int_ctl_req request = {.ctl_n = ctl_n};
675
  scm_without_guile (&integer_ctl_min_wrapper, &request);
676
  return scm_from_long (request.value);
677 678
}

679
SCM
680
lk_scm_abs_in_max (SCM lk_device_s, SCM in_code)
681
{
682
  if (scm_is_false (lk_device_s))
683
    {
684
      error (0, 0, _("Failed to get ABS max: device not opened."));
685 686
      return SCM_BOOL_F;
    }
687
  scm_assert_foreign_object_type (device_type, lk_device_s);
688 689 690
  size_t device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0);
  struct abs_in_req request = {.device_n = device_n,
                               .code = scm_to_uint (in_code)};
691 692
  scm_without_guile (&abs_in_max_wrapper, &request);
  return scm_from_int (request.value);
693 694 695
}

SCM
696
lk_scm_abs_in_min (SCM lk_device_s, SCM in_code)
697
{
698
  if (scm_is_false (lk_device_s))
699
    {
700
      error (0, 0, _("Failed to get ABS max: device not opened."));
701 702
      return SCM_BOOL_F;
    }
703
  scm_assert_foreign_object_type (device_type, lk_device_s);
704 705 706
  size_t device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0);
  struct abs_in_req request = {.device_n = device_n,
                               .code = scm_to_uint (in_code)};
707 708
  scm_without_guile (&abs_in_min_wrapper, &request);
  return scm_from_int (request.value);
709 710
}

brandon's avatar
brandon committed
711
SCM
712
lk_scm_send_midi_keypress (SCM lk_device_s, SCM channel, SCM note, SCM velocity)
brandon's avatar
brandon committed
713
{
714
  if (scm_is_false (lk_device_s))
715
    {
716
      error (0, 0, _("Failed to send midi: device not opened."));
717 718
      return SCM_BOOL_F;
    }
719
  scm_assert_foreign_object_type (device_type, lk_device_s);
720 721 722 723
  struct send_midi_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                  .channel = scm_to_uchar (channel),
                                  .note = scm_to_uchar (note),
                                  .velocity = scm_to_uchar (velocity)};
724
  scm_without_guile (&send_midi_keypress_wrapper, &request);
725
  return SCM_BOOL_T;
brandon's avatar
brandon committed
726 727 728
}

SCM
729
lk_scm_send_midi_note (SCM lk_device_s, SCM channel, SCM note, SCM velocity,
brandon's avatar
brandon committed
730 731
                       SCM dur)
{
732
  if (scm_is_false (lk_device_s))
733
    {
734
      error (0, 0, _("Failed to send midi: device not opened."));
735 736
      return SCM_BOOL_F;
    }
737
  scm_assert_foreign_object_type (device_type, lk_device_s);
738 739 740 741 742
  struct send_midi_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                  .channel = scm_to_uchar (channel),
                                  .note = scm_to_uchar (note),
                                  .velocity = scm_to_uchar (velocity),
                                  .dur = scm_to_uint (dur)};
743
  scm_without_guile (&send_midi_note_wrapper, &request);
744
  return SCM_BOOL_T;
brandon's avatar
brandon committed
745 746 747
}

SCM
748
lk_scm_send_midi_noteon (SCM lk_device_s, SCM channel, SCM note, SCM velocity)
brandon's avatar
brandon committed
749
{
750
  if (scm_is_false (lk_device_s))
751
    {
752
      error (0, 0, _("Failed to send midi: device not opened."));
753 754
      return SCM_BOOL_F;
    }
755
  scm_assert_foreign_object_type (device_type, lk_device_s);
756 757 758 759
  struct send_midi_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                  .channel = scm_to_uchar (channel),
                                  .note = scm_to_uchar (note),
                                  .velocity = scm_to_uchar (velocity)};
760
  scm_without_guile (&send_midi_noteon_wrapper, &request);
761
  return SCM_BOOL_T;
brandon's avatar
brandon committed
762 763 764
}

SCM
765
lk_scm_send_midi_noteoff (SCM lk_device_s, SCM channel, SCM note, SCM velocity)
brandon's avatar
brandon committed
766
{
767
  if (scm_is_false (lk_device_s))
768
    {
769
      error (0, 0, _("Failed to send midi: device not opened."));
770 771
      return SCM_BOOL_F;
    }
772
  scm_assert_foreign_object_type (device_type, lk_device_s);
773 774 775 776
  struct send_midi_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                  .channel = scm_to_uchar (channel),
                                  .note = scm_to_uchar (note),
                                  .velocity = scm_to_uchar (velocity)};
777
  scm_without_guile (&send_midi_noteoff_wrapper, &request);
778
  return SCM_BOOL_T;
brandon's avatar
brandon committed
779 780 781
}

SCM
782
lk_scm_send_midi_pgmchange (SCM lk_device_s, SCM channel, SCM value)
brandon's avatar
brandon committed
783
{
784
  if (scm_is_false (lk_device_s))
785
    {
786
      error (0, 0, _("Failed to send midi: device not opened."));
787 788
      return SCM_BOOL_F;
    }
789
  scm_assert_foreign_object_type (device_type, lk_device_s);
790 791 792
  struct send_midi_param_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                        .channel = scm_to_uchar (channel),
                                        .value = scm_to_int (value)};
793
  scm_without_guile (&send_midi_pgmchange_wrapper, &request);
794
  return SCM_BOOL_T;
brandon's avatar
brandon committed
795 796 797
}

SCM
798
lk_scm_send_midi_pitchbend (SCM lk_device_s, SCM channel, SCM value)
brandon's avatar
brandon committed
799
{
800
  if (scm_is_false (lk_device_s))
801
    {
802
      error (0, 0, _("Failed to send midi: device not opened."));
803 804
      return SCM_BOOL_F;
    }
805
  scm_assert_foreign_object_type (device_type, lk_device_s);
806 807 808
  struct send_midi_param_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                        .channel = scm_to_uchar (channel),
                                        .value = scm_to_int (value)};
809
  scm_without_guile (&send_midi_pitchbend_wrapper, &request);
810
  return SCM_BOOL_T;
brandon's avatar
brandon committed
811 812
}

813 814 815 816 817 818 819 820 821
SCM
lk_scm_send_midi_control (SCM lk_device_s, SCM channel, SCM param, SCM value)
{
  if (scm_is_false (lk_device_s))
    {
      error (0, 0, _("Failed to send midi: device not opened."));
      return SCM_BOOL_F;
    }
  scm_assert_foreign_object_type (device_type, lk_device_s);
822 823 824 825
  struct send_midi_param_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                        .channel = scm_to_uchar (channel),
                                        .param = scm_to_uint (param),
                                        .value = scm_to_int (value)};
826
  scm_without_guile (&send_midi_control_wrapper, &request);
827 828 829
  return SCM_BOOL_T;
}

830 831 832 833 834 835 836 837 838
SCM
lk_scm_remap_enable_event (SCM lk_device_s, SCM type, SCM code)
{
  if (scm_is_false (lk_device_s))
    {
      error (0, 0, _("Failed to enable remap event: device not opened."));
      return SCM_BOOL_F;
    }
  scm_assert_foreign_object_type (device_type, lk_device_s);
839 840 841 842
  struct remap_toggle_event_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                           .type = scm_to_uint (type),
                                           .code = scm_to_uint (code),
                                           .enable = true};
843 844 845 846 847 848 849 850 851 852 853 854 855
  scm_without_guile (&remap_toggle_event_wrapper, &request);
  return scm_from_int (request.err);
}

SCM
lk_scm_remap_disable_event (SCM lk_device_s, SCM type, SCM code)
{
  if (scm_is_false (lk_device_s))
    {
      error (0, 0, _("Failed to disable remap event: device not opened."));
      return SCM_BOOL_F;
    }
  scm_assert_foreign_object_type (device_type, lk_device_s);
856 857 858 859
  struct remap_toggle_event_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                           .type = scm_to_uint (type),
                                           .code = scm_to_uint (code),
                                           .enable = false};
860 861 862 863 864 865 866 867 868 869 870 871 872 873
  scm_without_guile (&remap_toggle_event_wrapper, &request);
  return scm_from_int (request.err);
}

SCM
lk_scm_remap_set_abs_info (SCM lk_device_s, SCM code, SCM min, SCM max,
                           SCM resolution, SCM fuzz, SCM flat)
{
  if (scm_is_false (lk_device_s))
    {
      error (0, 0, _("Failed to set remap abs info: device not opened."));
      return SCM_BOOL_F;
    }
  scm_assert_foreign_object_type (device_type, lk_device_s);
874 875 876 877 878 879 880
  struct remap_set_abs_info_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                           .code = scm_to_uint (code),
                                           .min = scm_to_int (min),
                                           .max = scm_to_int (max),
                                           .resolution = scm_to_int (resolution),
                                           .fuzz = scm_to_int (fuzz),
                                           .flat = scm_to_int (flat)};
881 882 883 884 885 886 887 888 889 890 891 892 893
  scm_without_guile (&remap_set_abs_info_wrapper, &request);
  return scm_from_int (request.err);
}

SCM
lk_scm_finalize_remap_dev (SCM lk_device_s)
{
  if (scm_is_false (lk_device_s))
    {
      error (0, 0, _("Failed to finalize remap device: device not opened."));
      return SCM_BOOL_F;
    }
  scm_assert_foreign_object_type (device_type, lk_device_s);
894
  struct finalize_remap_dev_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0)};
895 896 897 898 899 900 901 902 903 904 905 906 907
  scm_without_guile (&finalize_remap_dev_wrapper, &request);
  return scm_from_int (request.err);
}

SCM
lk_scm_send_remap_event (SCM lk_device_s, SCM type, SCM code, SCM value)
{
  if (scm_is_false (lk_device_s))
    {
      error (0, 0, _("Failed to send remap event: device not opened."));
      return SCM_BOOL_F;
    }
  scm_assert_foreign_object_type (device_type, lk_device_s);
908 909 910 911
  struct send_remap_event_req request = {.device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0),
                                         .type = scm_to_uint (type),
                                         .code = scm_to_uint (code),
                                         .value = scm_to_int (value)};
912 913 914 915
  scm_without_guile (&send_remap_event_wrapper, &request);
  return scm_from_int (request.err);
}

916
SCM
917
get_event_handler (SCM lk_device_s, SCM ev_id, bool create)
brandon's avatar
brandon committed
918
{
919
  if (scm_is_false (lk_device_s))
920
    {
921
      error (0, 0, _("Failed to map event: device not opened."));
922 923
      return SCM_BOOL_F;
    }
924
  scm_assert_foreign_object_type (device_type, lk_device_s);
925 926 927
  size_t device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0);
  lk_device_t *device = lk_device_list[device_n];
  SCM s_dev_id = scm_from_latin1_string (device->id);
928 929
  if (scm_is_false (scm_pair_p (ev_id)))
    {
930
      error (0, 0, _("The event ID must be a pair, e.g. '(1 . 2)."));
931 932 933 934
      return SCM_BOOL_F;
    }
  if (scm_is_false (scm_integer_p (scm_car (ev_id))))
    {
935
      error (0, 0, _("The event type must be an integer."));
936 937 938 939
      return SCM_BOOL_F;
    }
  if (scm_is_false (scm_integer_p (scm_cdr (ev_id))))
    {
940
      error (0, 0, _("The event code must be an integer."));
941 942
      return SCM_BOOL_F;
    }
943 944 945
  SCM s_ev_hand_symbol = scm_c_lookup ("lk-event-handlers");
  SCM s_event_handlers = scm_variable_ref (s_ev_hand_symbol);
  SCM s_dev_handlers = scm_hash_ref (s_event_handlers, s_dev_id, SCM_UNDEFINED);
946 947
  if (scm_is_false (s_dev_handlers))
    {
948
      error (EXIT_FAILURE, 0, _("Device event-handler list not found"));
949
    }
950
  SCM s_ev_handler = scm_hash_ref (s_dev_handlers, ev_id, SCM_UNDEFINED);
951
  if (scm_is_false (s_ev_handler) && create)
952 953 954 955
    {
      s_ev_handler = scm_make_hook (scm_from_int(1));
      scm_hash_set_x (s_dev_handlers, ev_id, s_ev_handler);
    }
brandon's avatar
brandon committed
956 957 958 959 960
  else
    {
      error (0, 0, _("No event handler found"));
      return SCM_BOOL_F;
    }
961 962 963 964
  return s_ev_handler;
}

SCM
965
lk_scm_add_event_hook (SCM lk_device_s, SCM ev_id, SCM proc)
966
{
967
  SCM s_ev_handler = get_event_handler (lk_device_s, ev_id, true);
968 969 970 971 972
  scm_add_hook_x (s_ev_handler, proc, SCM_BOOL_T);
  return SCM_BOOL_T;
}

SCM
973
lk_scm_remove_event_hook (SCM lk_device_s, SCM ev_id, SCM proc)
974
{
975
  SCM s_ev_handler = get_event_handler (lk_device_s, ev_id, false);
976 977 978 979 980
  scm_remove_hook_x (s_ev_handler, proc);
  return SCM_BOOL_T;
}

SCM
981
lk_scm_reset_event_hook (SCM lk_device_s, SCM ev_id)
982
{
983
  SCM s_ev_handler = get_event_handler (lk_device_s, ev_id, false);
984
  scm_reset_hook_x (s_ev_handler);
985
  return SCM_BOOL_T;
986 987 988
}

void
Brandon Invergo's avatar
Brandon Invergo committed
989
handle_event (const char *device_id, int type, int code, int value)
990
{
991 992 993 994 995 996 997 998
  SCM s_type = scm_from_int (type);
  SCM s_code = scm_from_int (code);
  SCM s_value = scm_from_int (value);
  SCM s_dev_id = scm_from_latin1_string (device_id);
  SCM s_ev_pair = scm_cons (s_type, s_code);
  SCM s_ev_hand_symbol = scm_c_lookup ("lk-event-handlers");
  SCM s_event_handlers = scm_variable_ref (s_ev_hand_symbol);
  SCM s_dev_handlers = scm_hash_ref (s_event_handlers, s_dev_id, SCM_UNDEFINED);
999 1000
  if (scm_is_false (s_dev_handlers))
    {
1001
      error (EXIT_FAILURE, 0, _("Device event-handler list not found"));
1002
    }
1003
  SCM s_ev_handler = scm_hash_ref (s_dev_handlers, s_ev_pair, SCM_UNDEFINED);
1004 1005
  if (scm_is_false (s_ev_handler))
    {
1006
      error (0, 0, _("No event-handler for event: '(%d . %d)"), type, code);
1007 1008
      return;
    }
1009
  scm_c_run_hook (s_ev_handler, scm_list_1(s_value));
brandon's avatar
brandon committed
1010 1011
}

brandon's avatar
brandon committed
1012
SCM
1013
get_idle_handler (SCM lk_device_s, bool create)
brandon's avatar
brandon committed
1014
{
1015
  if (scm_is_false (lk_device_s))
brandon's avatar
brandon committed
1016 1017 1018 1019
    {
      error (0, 0, _("Failed to map event: device not opened."));
      return SCM_BOOL_F;
    }
1020
  scm_assert_foreign_object_type (device_type, lk_device_s);
1021 1022 1023 1024 1025 1026
  size_t device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0);
  lk_device_t *device = lk_device_list[device_n];
  SCM s_dev_id = scm_from_latin1_string (device->id);
  SCM s_idle_hand_symbol = scm_c_lookup ("lk-idle-handlers");
  SCM s_idle_handlers = scm_variable_ref (s_idle_hand_symbol);
  SCM s_dev_handler = scm_hash_ref (s_idle_handlers, s_dev_id, SCM_UNDEFINED);
1027
  if (scm_is_false (s_dev_handler))
brandon's avatar
brandon committed
1028
    {
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
      if (create)
        {
          s_dev_handler = scm_make_hook (scm_from_int(0));
          scm_hash_set_x (s_idle_handlers, s_dev_id, s_dev_handler);
        }
      else
        {
          error (0, 0, _("No idle-handler for device: %s"), device->str_id);
          return SCM_BOOL_F;
        }
brandon's avatar
brandon committed
1039 1040 1041 1042 1043
    }
  return s_dev_handler;
}

SCM
1044
lk_scm_add_idle_hook (SCM lk_device_s, SCM proc)
brandon's avatar
brandon committed
1045
{
1046
  SCM s_idle_handler = get_idle_handler (lk_device_s, true);
brandon's avatar
brandon committed
1047 1048 1049 1050 1051
  scm_add_hook_x (s_idle_handler, proc, SCM_BOOL_T);
  return SCM_BOOL_T;
}

SCM
1052
lk_scm_remove_idle_hook (SCM lk_device_s, SCM proc)
brandon's avatar
brandon committed
1053
{
1054
  SCM s_idle_handler = get_idle_handler (lk_device_s, false);
brandon's avatar
brandon committed
1055 1056 1057 1058 1059
  scm_remove_hook_x (s_idle_handler, proc);
  return SCM_BOOL_T;
}

SCM
1060
lk_scm_reset_idle_hook (SCM lk_device_s)
brandon's avatar
brandon committed
1061
{
1062
  SCM s_idle_handler = get_idle_handler (lk_device_s, false);
brandon's avatar
brandon committed
1063 1064 1065 1066 1067
  scm_reset_hook_x (s_idle_handler);
  return SCM_BOOL_T;
}

void
Brandon Invergo's avatar
Brandon Invergo committed
1068
run_idle_hook (const char *device_id)
brandon's avatar
brandon committed
1069
{
1070 1071 1072 1073
  SCM s_dev_id = scm_from_latin1_string (device_id);
  SCM s_idle_hand_symbol = scm_c_lookup ("lk-idle-handlers");
  SCM s_idle_handlers = scm_variable_ref (s_idle_hand_symbol);
  SCM s_dev_handler = scm_hash_ref (s_idle_handlers, s_dev_id, SCM_UNDEFINED);
brandon's avatar
brandon committed
1074 1075 1076 1077 1078 1079 1080
  if (!scm_is_false (s_dev_handler))
    {
      scm_c_run_hook (s_dev_handler, scm_list_n (SCM_UNDEFINED));
    }
}

unsigned int
Brandon Invergo's avatar
Brandon Invergo committed
1081
get_idle_wait (const char *device_id)
brandon's avatar
brandon committed
1082
{
1083 1084 1085 1086
  if (!device_id)
    {
      return 0;
    }
1087 1088 1089 1090
  SCM s_dev_id = scm_from_latin1_string (device_id);
  SCM s_idle_waits_symbol = scm_c_lookup ("lk-idle-waits");
  SCM s_idle_waits = scm_variable_ref (s_idle_waits_symbol);
  SCM s_dev_idle_wait = scm_hash_ref (s_idle_waits, s_dev_id, SCM_UNDEFINED);
brandon's avatar
brandon committed
1091 1092
  if (!scm_is_false (s_dev_idle_wait))
    {
1093
      return (unsigned int) (scm_to_double (s_dev_idle_wait) * 1e6);
brandon's avatar
brandon committed
1094 1095 1096
    }
  else
    {
1097
      return 0;
brandon's avatar
brandon committed
1098 1099 1100
    }
}

brandon's avatar
brandon committed
1101
SCM
1102
get_exit_handler (SCM lk_device_s, bool create)
brandon's avatar
brandon committed
1103
{
1104
  if (scm_is_false (lk_device_s))
brandon's avatar
brandon committed
1105 1106 1107 1108
    {
      error (0, 0, _("Failed to map event: device not opened."));
      return SCM_BOOL_F;
    }
1109
  scm_assert_foreign_object_type (device_type, lk_device_s);
1110 1111 1112 1113 1114 1115
  size_t device_n = scm_foreign_object_unsigned_ref (lk_device_s, 0);
  lk_device_t *device = lk_device_list[device_n];
  SCM s_dev_id = scm_from_latin1_string (device->id);
  SCM s_exit_hand_symbol = scm_c_lookup ("lk-exit-handlers");
  SCM s_exit_handlers = scm_variable_ref (s_exit_hand_symbol);
  SCM s_dev_handler = scm_hash_ref (s_exit_handlers, s_dev_id, SCM_UNDEFINED);
1116
  if (scm_is_false (s_dev_handler))
brandon's avatar
brandon committed
1117
    {
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
      if (create)
        {
          s_dev_handler = scm_make_hook (scm_from_int(0));
          scm_hash_set_x (s_exit_handlers, s_dev_id, s_dev_handler);
        }
      else
        {
          error (0, 0, _("No exit-handler for device: %s"), device->str_id);
          return SCM_BOOL_F;
        }
brandon's avatar
brandon committed
1128 1129 1130 1131 1132
    }
  return s_dev_handler;
}

SCM
1133
lk_scm_add_exit_hook (SCM lk_device_s, SCM proc)
brandon's avatar
brandon committed
1134
{
1135
  SCM s_exit_handler = get_exit_handler (lk_device_s, true);
brandon's avatar
brandon committed
1136 1137 1138 1139 1140
  scm_add_hook_x (s_exit_handler, proc, SCM_BOOL_T);
  return SCM_BOOL_T;
}

SCM
1141
lk_scm_remove_exit_hook (SCM lk_device_s, SCM proc)
brandon's avatar
brandon committed
1142
{
1143
  SCM s_exit_handler = get_exit_handler (lk_device_s, false);
brandon's avatar
brandon committed
1144 1145 1146 1147 1148
  scm_remove_hook_x (s_exit_handler, proc);
  return SCM_BOOL_T;
}

SCM
1149
lk_scm_reset_exit_hook (SCM lk_device_s)
brandon's avatar
brandon committed
1150
{
1151
  SCM s_exit_handler = get_exit_handler (lk_device_s, false);
brandon's avatar
brandon committed
1152 1153 1154 1155 1156
  scm_reset_hook_x (s_exit_handler);
  return SCM_BOOL_T;
}

void
Brandon Invergo's avatar
Brandon Invergo committed
1157
run_exit_hook (const char *device_id)
brandon's avatar
brandon committed
1158
{
1159 1160 1161 1162
  SCM s_dev_id = scm_from_latin1_string (device_id);
  SCM s_exit_hand_symbol = scm_c_lookup ("lk-exit-handlers");
  SCM s_exit_handlers = scm_variable_ref (s_exit_hand_symbol);
  SCM s_dev_handler = scm_hash_ref (s_exit_handlers, s_dev_id, SCM_UNDEFINED);
brandon's avatar
brandon committed
1163 1164 1165 1166 1167 1168
  if (!scm_is_false (s_dev_handler))
    {
      scm_c_run_hook (s_dev_handler, scm_list_n (SCM_UNDEFINED));
    }
}

1169 1170
void
init_lk_core_module (void *data)
brandon's avatar
brandon committed
1171
{
1172 1173
  init_device_type ();
  init_ctl_type ();
brandon's avatar
brandon committed
1174

1175 1176
  scm_c_define_gsubr ("open-device", 4, 0, 0, lk_scm_open_device);
  scm_c_define_gsubr ("open-ctl", 2, 0, 0, lk_scm_open_ctl);
1177
  scm_c_export ("open-device", "open-ctl", NULL);
1178

brandon's avatar
brandon committed
1179 1180 1181 1182
  scm_c_define_gsubr ("set-boolean-ctl", 2, 0, 0, lk_scm_set_boolean_ctl);
  scm_c_define_gsubr ("get-boolean-ctl", 1, 0, 0, lk_scm_get_boolean_ctl);
  scm_c_define_gsubr ("toggle-boolean-ctl", 1, 0, 0, lk_scm_toggle_boolean_ctl);
  scm_c_define_gsubr ("set-integer-ctl", 2, 0, 0, lk_scm_set_integer_ctl);
1183
  scm_c_define_gsubr ("get-integer-ctl", 1, 0, 0, lk_scm_get_integer_ctl);
1184 1185
  scm_c_define_gsubr ("integer-ctl-max", 1, 0, 0, lk_scm_integer_ctl_max);
  scm_c_define_gsubr ("integer-ctl-min", 1, 0, 0, lk_scm_integer_ctl_min);
1186 1187
  scm_c_define_gsubr ("abs-input-max", 2, 0, 0, lk_scm_abs_in_max);
  scm_c_define_gsubr ("abs-input-min", 2, 0, 0, lk_scm_abs_in_min);
1188 1189 1190
  scm_c_export ("set-boolean-ctl", "get-boolean-ctl", "toggle-boolean-ctl",
                "set-integer-ctl", "get-integer-ctl", "integer-ctl-max",
                "integer-ctl-min", "abs-input-max", "abs-input-min", NULL);
1191

brandon's avatar
brandon committed
1192 1193 1194 1195 1196 1197
  scm_c_define_gsubr ("send-midi-keypress", 4, 0, 0, lk_scm_send_midi_keypress);
  scm_c_define_gsubr ("send-midi-note", 5, 0, 0, lk_scm_send_midi_note);
  scm_c_define_gsubr ("send-midi-noteon", 4, 0, 0, lk_scm_send_midi_noteon);
  scm_c_define_gsubr ("send-midi-noteoff", 4, 0, 0, lk_scm_send_midi_noteoff);
  scm_c_define_gsubr ("send-midi-pgmchange", 3, 0, 0, lk_scm_send_midi_pgmchange);
  scm_c_define_gsubr ("send-midi-pitchbend", 3, 0, 0, lk_scm_send_midi_pitchbend);
1198
  scm_c_define_gsubr ("send-midi-control", 4, 0, 0, lk_scm_send_midi_control);
1199 1200
  scm_c_export ("send-midi-keypress", "send-midi-note", "send-midi-noteon",
                "send-midi-noteoff", "send-midi-pgmchange", "send-midi-pichbend",
1201
                "send-midi-control", NULL);
1202 1203 1204 1205 1206 1207

  scm_c_define_gsubr ("remap-enable-event", 3, 0, 0, lk_scm_remap_enable_event);
  scm_c_define_gsubr ("remap-disable-event", 3, 0, 0, lk_scm_remap_disable_event);
  scm_c_define_gsubr ("remap-set-abs-info", 7, 0, 0, lk_scm_remap_set_abs_info);
  scm_c_define_gsubr ("finalize-remap-dev", 1, 0, 0, lk_scm_finalize_remap_dev);
  scm_c_define_gsubr ("send-remap-event", 4, 0, 0, lk_scm_send_remap_event);
1208 1209
  scm_c_export ("remap-enable-event", "remap-disable-event", "remap-set-abs-info",
                "finalize-remap-dev", "send-remap-event", NULL);
1210

1211 1212 1213
  scm_c_define_gsubr ("add-event-hook!", 3, 0, 0, lk_scm_add_event_hook);
  scm_c_define_gsubr ("remove-event-hook!", 3, 0, 0, lk_scm_remove_event_hook);
  scm_c_define_gsubr ("reset-event-hook!", 3, 0, 0, lk_scm_reset_event_hook);
brandon's avatar
brandon committed
1214 1215
  scm_c_define_gsubr ("add-idle-hook!", 2, 0, 0, lk_scm_add_idle_hook);
  scm_c_define_gsubr ("remove-idle-hook!", 2, 0, 0, lk_scm_remove_idle_hook);
1216
  scm_c_define_gsubr ("reset-idle-hook!", 1, 0, 0, lk_scm_reset_idle_hook);
brandon's avatar
brandon committed
1217
  scm_c_define_gsubr ("set-idle-wait!", 2, 0, 0, lk_scm_set_idle_wait);
brandon's avatar
brandon committed
1218 1219
  scm_c_define_gsubr ("add-exit-hook!", 2, 0, 0, lk_scm_add_exit_hook);
  scm_c_define_gsubr ("remove-exit-hook!", 2, 0, 0, lk_scm_remove_exit_hook);
1220
  scm_c_define_gsubr ("reset-exit-hook!", 1, 0, 0, lk_scm_reset_exit_hook);
1221 1222 1223 1224
  scm_c_export ("add-event-hook!", "remove-event-hook!", "reset-event-hook!",
                "add-idle-hook!", "remove-idle-hook!", "reset-idle-hook!",
                "set-idle-wait!", "add-exit-hook!", "remove-exit-hook!",
                "reset-exit-hook!", NULL);
brandon's avatar
brandon committed
1225

brandon's avatar
brandon committed
1226
  scm_permanent_object
brandon's avatar
brandon committed
</