jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
4.1KB

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <assert.h>
  5. #include <jack/jack.h>
  6. #include <jack/midiport.h>
  7. #ifndef WIN32
  8. #include <signal.h>
  9. #endif
  10. static jack_port_t* port;
  11. static int keeprunning = 1;
  12. static int time_format = 0;
  13. static uint64_t monotonic_cnt = 0;
  14. static uint64_t prev_event = 0;
  15. static void
  16. describe (jack_midi_event_t* event, char* buffer, size_t buflen)
  17. {
  18. assert (buflen > 0);
  19. buffer[0] = '\0';
  20. if (event->size == 0) {
  21. return;
  22. }
  23. int type = event->buffer[0] & 0xf0;
  24. int channel = event->buffer[0] & 0xf;
  25. switch (type) {
  26. case 0x90:
  27. assert (event->size == 3);
  28. snprintf (buffer, buflen, "note on (channel %d): pitch %d, velocity %d", channel, event->buffer[1], event->buffer[2]);
  29. break;
  30. case 0x80:
  31. assert (event->size == 3);
  32. snprintf (buffer, buflen, "note off (channel %d): pitch %d, velocity %d", channel, event->buffer[1], event->buffer[2]);
  33. break;
  34. case 0xb0:
  35. assert (event->size == 3);
  36. snprintf (buffer, buflen, "control change (channel %d): controller %d, value %d", channel, event->buffer[1], event->buffer[2]);
  37. break;
  38. default:
  39. break;
  40. }
  41. }
  42. int
  43. process (jack_nframes_t frames, void* arg)
  44. {
  45. void* buffer;
  46. jack_nframes_t N;
  47. jack_nframes_t i;
  48. char description[256];
  49. buffer = jack_port_get_buffer (port, frames);
  50. assert (buffer);
  51. N = jack_midi_get_event_count (buffer);
  52. for (i = 0; i < N; ++i) {
  53. jack_midi_event_t event;
  54. int r;
  55. r = jack_midi_event_get (&event, buffer, i);
  56. if (r == 0) {
  57. size_t j;
  58. switch(time_format) {
  59. case 1:
  60. printf ("%7"PRId64":", event.time + monotonic_cnt);
  61. break;
  62. case 2:
  63. printf ("%+6"PRId64":", event.time + monotonic_cnt - prev_event);
  64. break;
  65. default:
  66. printf ("%4d:", event.time);
  67. break;
  68. }
  69. for (j = 0; j < event.size; ++j) {
  70. printf (" %x", event.buffer[j]);
  71. }
  72. describe (&event, description, sizeof (description));
  73. printf (" %s", description);
  74. printf ("\n");
  75. prev_event = event.time + monotonic_cnt;
  76. }
  77. }
  78. monotonic_cnt += frames;
  79. return 0;
  80. }
  81. static void wearedone(int sig) {
  82. keeprunning = 0;
  83. }
  84. static void usage (int status) {
  85. printf ("jack_midi_dump - JACK MIDI Monitor.\n\n");
  86. printf ("Usage: jack_midi_dump [ OPTIONS ] [CLIENT-NAME]\n\n");
  87. printf ("Options:\n\
  88. -a use absoute timestamps relative to application start\n\
  89. -h display this help and exit\n\
  90. -r use relative timestamps to previous MIDI event\n\
  91. \n");
  92. printf ("\n\
  93. This tool listens for MIDI events on a JACK MIDI port and prints\n\
  94. the message to stdout.\n\
  95. \n\
  96. Note that this tool is not realtime-safe. The events are printed\n\
  97. directly from the process() callback!\n\
  98. \n\
  99. If no client name is given it defaults to 'midi-monitor'.\n\
  100. \n\
  101. See also: jackd(1)\n\
  102. \n");
  103. exit (status);
  104. }
  105. int
  106. main (int argc, char* argv[])
  107. {
  108. jack_client_t* client;
  109. char const default_name[] = "midi-monitor";
  110. char const * client_name;
  111. int r;
  112. int cn = 1;
  113. if (argc > 1) {
  114. if (!strcmp (argv[1], "-a")) { time_format = 1; cn = 2; }
  115. else if (!strcmp (argv[1], "-r")) { time_format = 2; cn = 2; }
  116. else if (!strcmp (argv[1], "-h")) { usage (EXIT_SUCCESS); }
  117. else if (argv[1][0] == '-') { usage (EXIT_FAILURE); }
  118. }
  119. if (argc > cn) {
  120. client_name = argv[cn];
  121. } else {
  122. client_name = default_name;
  123. }
  124. client = jack_client_open (client_name, JackNullOption, NULL);
  125. if (client == NULL) {
  126. fprintf (stderr, "Could not create JACK client.\n");
  127. exit (EXIT_FAILURE);
  128. }
  129. jack_set_process_callback (client, process, 0);
  130. port = jack_port_register (client, "input", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
  131. if (port == NULL) {
  132. fprintf (stderr, "Could not register port.\n");
  133. exit (EXIT_FAILURE);
  134. }
  135. r = jack_activate (client);
  136. if (r != 0) {
  137. fprintf (stderr, "Could not activate client.\n");
  138. exit (EXIT_FAILURE);
  139. }
  140. #ifndef WIN32
  141. signal(SIGHUP, wearedone);
  142. signal(SIGINT, wearedone);
  143. #endif
  144. /* run until interrupted */
  145. while (keeprunning) {
  146. #ifdef WIN32
  147. Sleep(1000);
  148. #else
  149. sleep(1);
  150. #endif
  151. };
  152. jack_deactivate (client);
  153. jack_client_close (client);
  154. return 0;
  155. }