Advertisement
Guest User

rigkontrol3-linux-midicontroller

a guest
Feb 16th, 2017
1,032
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.04 KB | None | 0 0
  1. /*
  2.  * This utility converts RigKontrol3 Input Events to ALSA MIDI events.
  3.  *
  4.  * The RigKontrol3 sends key events (from the snd_usb_caiaq ALSA module).  This
  5.  * utility runs as a daemon to grab the events so they don't go anywhere else
  6.  * and sends them as MIDI events thru an ALSA sequencer port.  The expression
  7.  * pedal is capable of sending values with more detail than the range of
  8.  * 0...127.  Output is converted to the range of 0...127 by default, set the
  9.  * HIGHRES setting to change that.
  10.  *
  11.  *
  12.  * AUTHOR: Xendarboh <xendarboh@gmail.com>
  13.  * SOURCE: https://code.google.com/p/rigkontrol3-linux-midicontroller/
  14.  * BIRTHDATE: 2012-12-15 20:40:39
  15.  * References:
  16.  *  http://permalink.gmane.org/gmane.linux.audio.devel/18481
  17.  *  http://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
  18.  *  http://www.itp.uzh.ch/~dpotter/howto/daemonize
  19. */
  20.  
  21.  
  22. #include <linux/input.h>
  23. #include <alsa/asoundlib.h>
  24. #include <fcntl.h>
  25. #include <stdio.h>
  26. #include <math.h>
  27. #include <unistd.h>
  28. #include <sys/types.h>
  29. #include <regex.h>
  30.  
  31. #define CLIENT_NAME "RigKontrol3"
  32. #define PORT_NAME   "Events"
  33. #define CHANNEL 0
  34.  
  35. /* Buttons output MIDI notes */
  36. #define BUTTON_1 1
  37. #define BUTTON_2 2
  38. #define BUTTON_3 3
  39. #define BUTTON_4 4
  40. #define BUTTON_5 5
  41. #define BUTTON_6 6
  42. #define BUTTON_7 7
  43. #define BUTTON_8 8
  44.  
  45. /* Pedal MIDI output */
  46. #define BUTTON_9 9
  47. #define EXPRESSION_FINE   43
  48. #define EXPRESSION_COARSE 11
  49.  
  50. /* return coarse or fine values from the expression pedal, set to 1 to enable
  51.  * higher values than the standard coarse range of 0...127 */
  52. #define HIGHRES 0
  53.  
  54. #define convertRange(oldMin, oldMax, newMin, newMax, oldVal) ((((oldVal - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin)
  55.  
  56. static void daemonize(void)
  57. {
  58.     pid_t pid, sid;
  59.  
  60.     /* already a daemon */
  61.     if ( getppid() == 1 ) return;
  62.  
  63.     /* Fork off the parent process */
  64.     pid = fork();
  65.     if (pid < 0)
  66.         exit(1);
  67.  
  68.     /* If we got a good PID, then we can exit the parent process. */
  69.     if (pid > 0)
  70.         exit(0);
  71.  
  72.     /* At this point we are executing as the child process */
  73.  
  74.     /* Change the file mode mask */
  75.     umask(0);
  76.  
  77.     /* Create a new SID for the child process */
  78.     sid = setsid();
  79.     if (sid < 0)
  80.         exit(1);
  81.  
  82.     /* Change the current working directory.  This prevents the current
  83.     directory from being locked; hence not being able to remove it. */
  84.     if ((chdir("/")) < 0)
  85.         exit(1);
  86.  
  87.     /* Redirect standard files to /dev/null */
  88.     freopen( "/dev/null", "r", stdin);
  89.     freopen( "/dev/null", "w", stdout);
  90.     freopen( "/dev/null", "w", stderr);
  91. }
  92.  
  93. int main(int argc, char *argv[])
  94. {
  95.     struct input_event ie;
  96.     int fd, port, err;
  97.     snd_seq_t *seq;
  98.     snd_seq_event_t ev;
  99.     int val;
  100.    
  101.     /* min and max values to calibrate expression pedal to a range starting from 0.
  102.     actual values usually appear near the range of 60...450 (on my device) */
  103.     int expressionPedalMax = 400;
  104.     int expressionPedalMin = 64;
  105.  
  106.     /* prevent sending consecutive events of the same value */
  107.     int expressionPedalLastVal = -1;
  108.  
  109.  
  110.     if (argc < 2)
  111.     {
  112.         fprintf(stderr, "Input Device Required\nUSAGE: %s </dev/input/eventXX>\n", argv[0]);
  113.         return 1;
  114.     }
  115.     regex_t regex;
  116.     int reti = regcomp(&regex, "^/dev/input/event", 0);
  117.     if (reti)
  118.     {
  119.         fprintf(stderr, "Could not compile regex\n");
  120.         return 1;
  121.     }
  122.         reti = regexec(&regex, argv[1], 0, NULL, 0);
  123.     if (reti)
  124.     {
  125.         fprintf(stderr, "Device must be an input event, exiting.\n");
  126.         return 1;
  127.     }
  128.     regfree(&regex);
  129.  
  130.  
  131.     fd = open(argv[1], O_RDONLY);
  132.     if (fd == -1)
  133.     {
  134.         perror(argv[1]);
  135.         return 1;
  136.     }
  137.  
  138.     /* grab input to avoid leaking key events */
  139.     err = ioctl(fd, EVIOCGRAB, 1);
  140.     if (err != 0)
  141.     {
  142.         fprintf(stderr, "RigKontrol3 Events could not be grabbed.\n");
  143.         return 1;
  144.     }
  145.  
  146.     err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0);
  147.     if (err < 0)
  148.     {
  149.         fprintf(stderr, "cannot open sequencer: %s\n", snd_strerror(err));
  150.         return 1;
  151.     }
  152.     snd_seq_set_client_name(seq, CLIENT_NAME);
  153.     port = snd_seq_create_simple_port(seq, PORT_NAME,
  154.                       SND_SEQ_PORT_CAP_READ |
  155.                       SND_SEQ_PORT_CAP_SUBS_READ,
  156.                       SND_SEQ_PORT_TYPE_MIDI_GENERIC |
  157.                       SND_SEQ_PORT_TYPE_SOFTWARE);
  158.     if (port < 0)
  159.     {
  160.         fprintf(stderr, "cannot create port: %s\n", snd_strerror(port));
  161.         return 1;
  162.     }
  163.  
  164.     /* now that startup was sucessful, become a daemon */
  165.     daemonize();
  166.  
  167.     snd_seq_ev_clear(&ev);
  168.     snd_seq_ev_set_source(&ev, port);
  169.     snd_seq_ev_set_subs(&ev);
  170.     snd_seq_ev_set_direct(&ev);
  171.     for (;;)
  172.     {
  173.         if (read(fd, &ie, sizeof(ie)) != sizeof(ie))
  174.         {
  175.             fprintf(stderr, "exiting\n");
  176.             break;
  177.         }
  178.         ev.type = SND_SEQ_EVENT_NONE;
  179.         switch (ie.type)
  180.         {
  181.         case EV_KEY:
  182.             switch (ie.code)
  183.             {
  184.             case KEY_1:
  185.                 if (ie.value)
  186.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_5, 127);
  187.                 else
  188.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_5, 64);
  189.                 break;
  190.             case KEY_2:
  191.                 if (ie.value)
  192.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_6, 127);
  193.                 else
  194.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_6, 64);
  195.                 break;
  196.             case KEY_3:
  197.                 if (ie.value)
  198.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_7, 127);
  199.                 else
  200.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_7, 64);
  201.                 break;
  202.             case KEY_4:
  203.                 if (ie.value)
  204.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_8, 127);
  205.                 else
  206.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_8, 64);
  207.                 break;
  208.             case KEY_5:
  209.                 if (ie.value)
  210.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_1, 127);
  211.                 else
  212.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_1, 64);
  213.                 break;
  214.             case KEY_6:
  215.                 if (ie.value)
  216.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_2, 127);
  217.                 else
  218.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_2, 64);
  219.                 break;
  220.             case KEY_7:
  221.                 if (ie.value)
  222.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_3, 127);
  223.                 else
  224.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_3, 64);
  225.                 break;
  226.             case KEY_8:
  227.                 if (ie.value)
  228.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_4, 127);
  229.                 else
  230.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_4, 64);
  231.                 break;
  232.             case KEY_9:
  233.                 if (ie.value)
  234.                     snd_seq_ev_set_noteon(&ev, CHANNEL, BUTTON_9, 127);
  235.                 else
  236.                     snd_seq_ev_set_noteoff(&ev, CHANNEL, BUTTON_9, 64);
  237.                 break;
  238.             }
  239.             break;
  240.  
  241.         case EV_ABS:
  242.             switch (ie.code)
  243.             {
  244.             case ABS_Z:
  245.                 val = ie.value;
  246.                 if (val > expressionPedalMax)
  247.                     val = expressionPedalMax;
  248.  
  249.                 if (val < expressionPedalMin)
  250.                     val = expressionPedalMin;
  251.  
  252.                 if (HIGHRES)
  253.                 {
  254.                     /* adjust lowest value to 0 */
  255.                     val = val - expressionPedalMin;
  256.                     if (val != expressionPedalLastVal)
  257.                         snd_seq_ev_set_controller(&ev, CHANNEL, EXPRESSION_FINE, val);
  258.                 } else
  259.                 {
  260.                     /* normalize value into the range of 0..127 */
  261.                     val = (int) convertRange(expressionPedalMin, expressionPedalMax, 0, 127, val);
  262.                     if (val != expressionPedalLastVal)
  263.                         snd_seq_ev_set_controller(&ev, CHANNEL, EXPRESSION_COARSE, val);
  264.                 }
  265.                 expressionPedalLastVal = val;
  266.                 break;
  267.             }
  268.             break;
  269.  
  270.         }
  271.         if (ev.type != SND_SEQ_EVENT_NONE)
  272.             snd_seq_event_output_direct(seq, &ev);
  273.     }
  274.     snd_seq_close(seq);
  275.     close(fd);
  276.     return 0;
  277. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement