diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-10-07 06:50:04 +0200 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-10-07 06:50:04 +0200 |
| commit | 988f5d2b5343850e19ad1512cefe6c53953aa02e (patch) | |
| tree | 1ff29934294e73b2575488c06df91866ce251dbe /portmidi/pm_test/mm.c | |
| parent | 9b5839c58a2e1df8bddf6b98805998508ea417d5 (diff) | |
| download | ttdaw-988f5d2b5343850e19ad1512cefe6c53953aa02e.tar.gz | |
Added bunch of examples
Diffstat (limited to 'portmidi/pm_test/mm.c')
| -rwxr-xr-x | portmidi/pm_test/mm.c | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/portmidi/pm_test/mm.c b/portmidi/pm_test/mm.c new file mode 100755 index 0000000..ab9d32e --- /dev/null +++ b/portmidi/pm_test/mm.c | |||
| @@ -0,0 +1,595 @@ | |||
| 1 | /* mm.c -- midi monitor */ | ||
| 2 | |||
| 3 | /***************************************************************************** | ||
| 4 | * Change Log | ||
| 5 | * Date | Change | ||
| 6 | *-----------+----------------------------------------------------------------- | ||
| 7 | * 7-Apr-86 | Created changelog | ||
| 8 | * 31-Jan-90 | GWL : use new cmdline | ||
| 9 | * 5-Apr-91 | JDW : Further changes | ||
| 10 | * 16-Feb-92 | GWL : eliminate label mmexit:; add error recovery | ||
| 11 | * 18-May-92 | GWL : continuous clocks, etc. | ||
| 12 | * 17-Jan-94 | GWL : option to display notes | ||
| 13 | * 20-Nov-06 | RBD : port mm.c from CMU Midi Toolkit to PortMidi | ||
| 14 | * | mm.c -- revealing MIDI secrets for over 20 years! | ||
| 15 | *****************************************************************************/ | ||
| 16 | |||
| 17 | #include "stdlib.h" | ||
| 18 | #include "ctype.h" | ||
| 19 | #include "string.h" | ||
| 20 | #include "stdio.h" | ||
| 21 | #include "porttime.h" | ||
| 22 | #include "portmidi.h" | ||
| 23 | |||
| 24 | #define STRING_MAX 80 | ||
| 25 | |||
| 26 | #define MIDI_CODE_MASK 0xf0 | ||
| 27 | #define MIDI_CHN_MASK 0x0f | ||
| 28 | /*#define MIDI_REALTIME 0xf8 | ||
| 29 | #define MIDI_CHAN_MODE 0xfa */ | ||
| 30 | #define MIDI_OFF_NOTE 0x80 | ||
| 31 | #define MIDI_ON_NOTE 0x90 | ||
| 32 | #define MIDI_POLY_TOUCH 0xa0 | ||
| 33 | #define MIDI_CTRL 0xb0 | ||
| 34 | #define MIDI_CH_PROGRAM 0xc0 | ||
| 35 | #define MIDI_TOUCH 0xd0 | ||
| 36 | #define MIDI_BEND 0xe0 | ||
| 37 | |||
| 38 | #define MIDI_SYSEX 0xf0 | ||
| 39 | #define MIDI_Q_FRAME 0xf1 | ||
| 40 | #define MIDI_SONG_POINTER 0xf2 | ||
| 41 | #define MIDI_SONG_SELECT 0xf3 | ||
| 42 | #define MIDI_TUNE_REQ 0xf6 | ||
| 43 | #define MIDI_EOX 0xf7 | ||
| 44 | #define MIDI_TIME_CLOCK 0xf8 | ||
| 45 | #define MIDI_START 0xfa | ||
| 46 | #define MIDI_CONTINUE 0xfb | ||
| 47 | #define MIDI_STOP 0xfc | ||
| 48 | #define MIDI_ACTIVE_SENSING 0xfe | ||
| 49 | #define MIDI_SYS_RESET 0xff | ||
| 50 | |||
| 51 | #define MIDI_ALL_SOUND_OFF 0x78 | ||
| 52 | #define MIDI_RESET_CONTROLLERS 0x79 | ||
| 53 | #define MIDI_LOCAL 0x7a | ||
| 54 | #define MIDI_ALL_OFF 0x7b | ||
| 55 | #define MIDI_OMNI_OFF 0x7c | ||
| 56 | #define MIDI_OMNI_ON 0x7d | ||
| 57 | #define MIDI_MONO_ON 0x7e | ||
| 58 | #define MIDI_POLY_ON 0x7f | ||
| 59 | |||
| 60 | |||
| 61 | #define private static | ||
| 62 | |||
| 63 | #ifndef false | ||
| 64 | #define false 0 | ||
| 65 | #define true 1 | ||
| 66 | #endif | ||
| 67 | |||
| 68 | typedef int boolean; | ||
| 69 | |||
| 70 | int debug = false; /* never set, but referenced by userio.c */ | ||
| 71 | PmStream *midi_in; /* midi input */ | ||
| 72 | boolean active = false; /* set when midi_in is ready for reading */ | ||
| 73 | boolean in_sysex = false; /* we are reading a sysex message */ | ||
| 74 | boolean inited = false; /* suppress printing during command line parsing */ | ||
| 75 | boolean done = false; /* when true, exit */ | ||
| 76 | boolean notes = true; /* show notes? */ | ||
| 77 | boolean controls = true; /* show continuous controllers */ | ||
| 78 | boolean bender = true; /* record pitch bend etc.? */ | ||
| 79 | boolean excldata = true; /* record system exclusive data? */ | ||
| 80 | boolean verbose = true; /* show text representation? */ | ||
| 81 | boolean realdata = true; /* record real time messages? */ | ||
| 82 | boolean clksencnt = true; /* clock and active sense count on */ | ||
| 83 | boolean chmode = true; /* show channel mode messages */ | ||
| 84 | boolean pgchanges = true; /* show program changes */ | ||
| 85 | boolean flush = false; /* flush all pending MIDI data */ | ||
| 86 | |||
| 87 | uint32_t filter = 0; /* remember state of midi filter */ | ||
| 88 | |||
| 89 | uint32_t clockcount = 0; /* count of clocks */ | ||
| 90 | uint32_t actsensecount = 0; /* cout of active sensing bytes */ | ||
| 91 | uint32_t notescount = 0; /* #notes since last request */ | ||
| 92 | uint32_t notestotal = 0; /* total #notes */ | ||
| 93 | |||
| 94 | char val_format[] = " Val %d\n"; | ||
| 95 | |||
| 96 | /***************************************************************************** | ||
| 97 | * Imported variables | ||
| 98 | *****************************************************************************/ | ||
| 99 | |||
| 100 | extern int abort_flag; | ||
| 101 | |||
| 102 | /***************************************************************************** | ||
| 103 | * Routines local to this module | ||
| 104 | *****************************************************************************/ | ||
| 105 | |||
| 106 | private void mmexit(int code); | ||
| 107 | private void output(PmMessage data); | ||
| 108 | private int put_pitch(int p); | ||
| 109 | private void showhelp(); | ||
| 110 | private void showbytes(PmMessage data, int len, boolean newline); | ||
| 111 | private void showstatus(boolean flag); | ||
| 112 | private void doascii(char c); | ||
| 113 | private int get_number(const char *prompt); | ||
| 114 | |||
| 115 | |||
| 116 | /* read a number from console */ | ||
| 117 | /**/ | ||
| 118 | int get_number(const char *prompt) | ||
| 119 | { | ||
| 120 | int n = 0, i; | ||
| 121 | fputs(prompt, stdout); | ||
| 122 | while (n != 1) { | ||
| 123 | n = scanf("%d", &i); | ||
| 124 | while (getchar() != '\n') ; | ||
| 125 | } | ||
| 126 | return i; | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 130 | void receive_poll(PtTimestamp timestamp, void *userData) | ||
| 131 | { | ||
| 132 | PmEvent event; | ||
| 133 | int count; | ||
| 134 | if (!active) return; | ||
| 135 | while ((count = Pm_Read(midi_in, &event, 1))) { | ||
| 136 | if (count == 1) output(event.message); | ||
| 137 | else puts(Pm_GetErrorText(count)); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | |||
| 142 | /**************************************************************************** | ||
| 143 | * main | ||
| 144 | * Effect: prompts for parameters, starts monitor | ||
| 145 | ****************************************************************************/ | ||
| 146 | |||
| 147 | int main(int argc, char **argv) | ||
| 148 | { | ||
| 149 | char *argument; | ||
| 150 | int inp; | ||
| 151 | PmError err; | ||
| 152 | int i; | ||
| 153 | if (argc > 1) { /* first arg can change defaults */ | ||
| 154 | argument = argv[1]; | ||
| 155 | while (*argument) doascii(*argument++); | ||
| 156 | } | ||
| 157 | showhelp(); | ||
| 158 | /* use porttime callback to empty midi queue and print */ | ||
| 159 | Pt_Start(1, receive_poll, 0); | ||
| 160 | /* list device information */ | ||
| 161 | puts("MIDI input devices:"); | ||
| 162 | for (i = 0; i < Pm_CountDevices(); i++) { | ||
| 163 | const PmDeviceInfo *info = Pm_GetDeviceInfo(i); | ||
| 164 | if (info->input) printf("%d: %s, %s\n", i, info->interf, info->name); | ||
| 165 | } | ||
| 166 | inp = get_number("Type input device number: "); | ||
| 167 | err = Pm_OpenInput(&midi_in, inp, NULL, 512, NULL, NULL); | ||
| 168 | if (err) { | ||
| 169 | puts(Pm_GetErrorText(err)); | ||
| 170 | Pt_Stop(); | ||
| 171 | mmexit(1); | ||
| 172 | } | ||
| 173 | Pm_SetFilter(midi_in, filter); | ||
| 174 | inited = true; /* now can document changes, set filter */ | ||
| 175 | printf("Midi Monitor ready.\n"); | ||
| 176 | active = true; | ||
| 177 | while (!done) { | ||
| 178 | doascii(getchar()); | ||
| 179 | while (getchar() != '\n') ; | ||
| 180 | } | ||
| 181 | active = false; | ||
| 182 | Pm_Close(midi_in); | ||
| 183 | Pt_Stop(); | ||
| 184 | Pm_Terminate(); | ||
| 185 | mmexit(0); | ||
| 186 | return 0; // make the compiler happy be returning a value | ||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 | /**************************************************************************** | ||
| 191 | * doascii | ||
| 192 | * Inputs: | ||
| 193 | * char c: input character | ||
| 194 | * Effect: interpret to revise flags | ||
| 195 | ****************************************************************************/ | ||
| 196 | |||
| 197 | private void doascii(char c) | ||
| 198 | { | ||
| 199 | if (isupper(c)) c = tolower(c); | ||
| 200 | if (c == 'q') done = true; | ||
| 201 | else if (c == 'b') { | ||
| 202 | bender = !bender; | ||
| 203 | filter ^= PM_FILT_PITCHBEND; | ||
| 204 | if (inited) | ||
| 205 | printf("Pitch Bend, etc. %s\n", (bender ? "ON" : "OFF")); | ||
| 206 | } else if (c == 'c') { | ||
| 207 | controls = !controls; | ||
| 208 | filter ^= PM_FILT_CONTROL; | ||
| 209 | if (inited) | ||
| 210 | printf("Control Change %s\n", (controls ? "ON" : "OFF")); | ||
| 211 | } else if (c == 'h') { | ||
| 212 | pgchanges = !pgchanges; | ||
| 213 | filter ^= PM_FILT_PROGRAM; | ||
| 214 | if (inited) | ||
| 215 | printf("Program Changes %s\n", (pgchanges ? "ON" : "OFF")); | ||
| 216 | } else if (c == 'n') { | ||
| 217 | notes = !notes; | ||
| 218 | filter ^= PM_FILT_NOTE; | ||
| 219 | if (inited) | ||
| 220 | printf("Notes %s\n", (notes ? "ON" : "OFF")); | ||
| 221 | } else if (c == 'x') { | ||
| 222 | excldata = !excldata; | ||
| 223 | filter ^= PM_FILT_SYSEX; | ||
| 224 | if (inited) | ||
| 225 | printf("System Exclusive data %s\n", (excldata ? "ON" : "OFF")); | ||
| 226 | } else if (c == 'r') { | ||
| 227 | realdata = !realdata; | ||
| 228 | filter ^= (PM_FILT_PLAY | PM_FILT_RESET | PM_FILT_TICK | PM_FILT_UNDEFINED); | ||
| 229 | if (inited) | ||
| 230 | printf("Real Time messages %s\n", (realdata ? "ON" : "OFF")); | ||
| 231 | } else if (c == 'k') { | ||
| 232 | clksencnt = !clksencnt; | ||
| 233 | if (inited) { | ||
| 234 | printf("Clock and Active Sense Counting %s\n", (clksencnt ? "ON" : "OFF")); | ||
| 235 | printf("Resetting Clock and Active Sense counts.\n"); | ||
| 236 | clockcount = actsensecount = 0; | ||
| 237 | } | ||
| 238 | } else if (c == 's') { | ||
| 239 | if (inited) { | ||
| 240 | printf("Clock Count %ld\nActive Sense Count %ld\n", | ||
| 241 | (long) clockcount, (long) actsensecount); | ||
| 242 | } | ||
| 243 | } else if (c == 't') { | ||
| 244 | notestotal+=notescount; | ||
| 245 | if (inited) | ||
| 246 | printf("This Note Count %ld\nTotal Note Count %ld\n", | ||
| 247 | (long) notescount, (long) notestotal); | ||
| 248 | notescount=0; | ||
| 249 | } else if (c == 'v') { | ||
| 250 | verbose = !verbose; | ||
| 251 | if (inited) | ||
| 252 | printf("Verbose %s\n", (verbose ? "ON" : "OFF")); | ||
| 253 | } else if (c == 'm') { | ||
| 254 | chmode = !chmode; | ||
| 255 | if (inited) | ||
| 256 | printf("Channel Mode Messages %s", (chmode ? "ON" : "OFF")); | ||
| 257 | } else { | ||
| 258 | if (inited) { | ||
| 259 | if (c == ' ') { | ||
| 260 | PmEvent event; | ||
| 261 | while (Pm_Read(midi_in, &event, 1)) ; /* flush midi input */ | ||
| 262 | printf("...FLUSHED MIDI INPUT\n\n"); | ||
| 263 | } else showhelp(); | ||
| 264 | } | ||
| 265 | } | ||
| 266 | if (inited) Pm_SetFilter(midi_in, filter); | ||
| 267 | } | ||
| 268 | |||
| 269 | |||
| 270 | |||
| 271 | private void mmexit(int code) | ||
| 272 | { | ||
| 273 | /* if this is not being run from a console, maybe we should wait for | ||
| 274 | * the user to read error messages before exiting | ||
| 275 | */ | ||
| 276 | exit(code); | ||
| 277 | } | ||
| 278 | |||
| 279 | |||
| 280 | /**************************************************************************** | ||
| 281 | * output | ||
| 282 | * Inputs: | ||
| 283 | * data: midi message buffer holding one command or 4 bytes of sysex msg | ||
| 284 | * Effect: format and print midi data | ||
| 285 | ****************************************************************************/ | ||
| 286 | |||
| 287 | char vel_format[] = " Vel %d\n"; | ||
| 288 | |||
| 289 | private void output(PmMessage data) | ||
| 290 | { | ||
| 291 | int command; /* the current command */ | ||
| 292 | int chan; /* the midi channel of the current event */ | ||
| 293 | int len; /* used to get constant field width */ | ||
| 294 | |||
| 295 | /* printf("output data %8x; ", data); */ | ||
| 296 | |||
| 297 | command = Pm_MessageStatus(data) & MIDI_CODE_MASK; | ||
| 298 | chan = Pm_MessageStatus(data) & MIDI_CHN_MASK; | ||
| 299 | |||
| 300 | if (in_sysex || Pm_MessageStatus(data) == MIDI_SYSEX) { | ||
| 301 | #define sysex_max 16 | ||
| 302 | int i; | ||
| 303 | PmMessage data_copy = data; | ||
| 304 | in_sysex = true; | ||
| 305 | /* look for MIDI_EOX in first 3 bytes | ||
| 306 | * if realtime messages are embedded in sysex message, they will | ||
| 307 | * be printed as if they are part of the sysex message | ||
| 308 | */ | ||
| 309 | for (i = 0; (i < 4) && ((data_copy & 0xFF) != MIDI_EOX); i++) | ||
| 310 | data_copy >>= 8; | ||
| 311 | if (i < 4) { | ||
| 312 | in_sysex = false; | ||
| 313 | i++; /* include the EOX byte in output */ | ||
| 314 | } | ||
| 315 | showbytes(data, i, verbose); | ||
| 316 | if (verbose) printf("System Exclusive\n"); | ||
| 317 | } else if (command == MIDI_ON_NOTE && Pm_MessageData2(data) != 0) { | ||
| 318 | notescount++; | ||
| 319 | if (notes) { | ||
| 320 | showbytes(data, 3, verbose); | ||
| 321 | if (verbose) { | ||
| 322 | printf("NoteOn Chan %2d Key %3d ", chan, Pm_MessageData1(data)); | ||
| 323 | len = put_pitch(Pm_MessageData1(data)); | ||
| 324 | printf(vel_format + len, Pm_MessageData2(data)); | ||
| 325 | } | ||
| 326 | } | ||
| 327 | } else if ((command == MIDI_ON_NOTE /* && Pm_MessageData2(data) == 0 */ || | ||
| 328 | command == MIDI_OFF_NOTE)) { | ||
| 329 | if (notes) { | ||
| 330 | showbytes(data, 3, verbose); | ||
| 331 | if (verbose) { | ||
| 332 | printf("NoteOff Chan %2d Key %3d ", chan, | ||
| 333 | Pm_MessageData1(data)); | ||
| 334 | len = put_pitch(Pm_MessageData1(data)); | ||
| 335 | printf(vel_format + len, Pm_MessageData2(data)); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | } else if (command == MIDI_CH_PROGRAM) { | ||
| 339 | if (pgchanges) { | ||
| 340 | showbytes(data, 2, verbose); | ||
| 341 | if (verbose) { | ||
| 342 | printf(" ProgChg Chan %2d Prog %2d\n", chan, | ||
| 343 | Pm_MessageData1(data) + 1); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | } else if (command == MIDI_CTRL) { | ||
| 347 | /* controls 121 (MIDI_RESET_CONTROLLER) to 127 are channel | ||
| 348 | * mode messages. */ | ||
| 349 | if (Pm_MessageData1(data) < MIDI_ALL_SOUND_OFF) { | ||
| 350 | if (controls) { | ||
| 351 | showbytes(data, 3, verbose); | ||
| 352 | if (verbose) { | ||
| 353 | printf("CtrlChg Chan %2d Ctrl %2d Val %2d\n", | ||
| 354 | chan, Pm_MessageData1(data), Pm_MessageData2(data)); | ||
| 355 | } | ||
| 356 | } else /* channel mode */ if (chmode) { | ||
| 357 | showbytes(data, 3, verbose); | ||
| 358 | if (verbose) { | ||
| 359 | switch (Pm_MessageData1(data)) { | ||
| 360 | case MIDI_ALL_SOUND_OFF: | ||
| 361 | printf("All Sound Off, Chan %2d\n", chan); | ||
| 362 | break; | ||
| 363 | case MIDI_RESET_CONTROLLERS: | ||
| 364 | printf("Reset All Controllers, Chan %2d\n", chan); | ||
| 365 | break; | ||
| 366 | case MIDI_LOCAL: | ||
| 367 | printf("LocCtrl Chan %2d %s\n", | ||
| 368 | chan, Pm_MessageData2(data) ? "On" : "Off"); | ||
| 369 | break; | ||
| 370 | case MIDI_ALL_OFF: | ||
| 371 | printf("All Off Chan %2d\n", chan); | ||
| 372 | break; | ||
| 373 | case MIDI_OMNI_OFF: | ||
| 374 | printf("OmniOff Chan %2d\n", chan); | ||
| 375 | break; | ||
| 376 | case MIDI_OMNI_ON: | ||
| 377 | printf("Omni On Chan %2d\n", chan); | ||
| 378 | break; | ||
| 379 | case MIDI_MONO_ON: | ||
| 380 | printf("Mono On Chan %2d\n", chan); | ||
| 381 | if (Pm_MessageData2(data)) | ||
| 382 | printf(" to %d received channels\n", | ||
| 383 | Pm_MessageData2(data)); | ||
| 384 | else | ||
| 385 | printf(" to all received channels\n"); | ||
| 386 | break; | ||
| 387 | case MIDI_POLY_ON: | ||
| 388 | printf("Poly On Chan %2d\n", chan); | ||
| 389 | break; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | } else if (command == MIDI_POLY_TOUCH) { | ||
| 395 | if (bender) { | ||
| 396 | showbytes(data, 3, verbose); | ||
| 397 | if (verbose) { | ||
| 398 | printf("P.Touch Chan %2d Key %2d ", chan, | ||
| 399 | Pm_MessageData1(data)); | ||
| 400 | len = put_pitch(Pm_MessageData1(data)); | ||
| 401 | printf(val_format + len, Pm_MessageData2(data)); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | } else if (command == MIDI_TOUCH) { | ||
| 405 | if (bender) { | ||
| 406 | showbytes(data, 2, verbose); | ||
| 407 | if (verbose) { | ||
| 408 | printf(" A.Touch Chan %2d Val %2d\n", chan, | ||
| 409 | Pm_MessageData1(data)); | ||
| 410 | } | ||
| 411 | } | ||
| 412 | } else if (command == MIDI_BEND) { | ||
| 413 | if (bender) { | ||
| 414 | showbytes(data, 3, verbose); | ||
| 415 | if (verbose) { | ||
| 416 | printf("P.Bend Chan %2d Val %2d\n", chan, | ||
| 417 | (Pm_MessageData1(data) + (Pm_MessageData2(data)<<7))); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | } else if (Pm_MessageStatus(data) == MIDI_SONG_POINTER) { | ||
| 421 | showbytes(data, 3, verbose); | ||
| 422 | if (verbose) { | ||
| 423 | printf(" Song Position %d\n", | ||
| 424 | (Pm_MessageData1(data) + (Pm_MessageData2(data)<<7))); | ||
| 425 | } | ||
| 426 | } else if (Pm_MessageStatus(data) == MIDI_SONG_SELECT) { | ||
| 427 | showbytes(data, 2, verbose); | ||
| 428 | if (verbose) { | ||
| 429 | printf(" Song Select %d\n", Pm_MessageData1(data)); | ||
| 430 | } | ||
| 431 | } else if (Pm_MessageStatus(data) == MIDI_TUNE_REQ) { | ||
| 432 | showbytes(data, 1, verbose); | ||
| 433 | if (verbose) { | ||
| 434 | printf(" Tune Request\n"); | ||
| 435 | } | ||
| 436 | } else if (Pm_MessageStatus(data) == MIDI_Q_FRAME) { | ||
| 437 | if (realdata) { | ||
| 438 | showbytes(data, 2, verbose); | ||
| 439 | if (verbose) { | ||
| 440 | printf(" Time Code Quarter Frame Type %d Values %d\n", | ||
| 441 | (Pm_MessageData1(data) & 0x70) >> 4, | ||
| 442 | Pm_MessageData1(data) & 0xf); | ||
| 443 | } | ||
| 444 | } | ||
| 445 | } else if (Pm_MessageStatus(data) == MIDI_START) { | ||
| 446 | if (realdata) { | ||
| 447 | showbytes(data, 1, verbose); | ||
| 448 | if (verbose) { | ||
| 449 | printf(" Start\n"); | ||
| 450 | } | ||
| 451 | } | ||
| 452 | } else if (Pm_MessageStatus(data) == MIDI_CONTINUE) { | ||
| 453 | if (realdata) { | ||
| 454 | showbytes(data, 1, verbose); | ||
| 455 | if (verbose) { | ||
| 456 | printf(" Continue\n"); | ||
| 457 | } | ||
| 458 | } | ||
| 459 | } else if (Pm_MessageStatus(data) == MIDI_STOP) { | ||
| 460 | if (realdata) { | ||
| 461 | showbytes(data, 1, verbose); | ||
| 462 | if (verbose) { | ||
| 463 | printf(" Stop\n"); | ||
| 464 | } | ||
| 465 | } | ||
| 466 | } else if (Pm_MessageStatus(data) == MIDI_SYS_RESET) { | ||
| 467 | if (realdata) { | ||
| 468 | showbytes(data, 1, verbose); | ||
| 469 | if (verbose) { | ||
| 470 | printf(" System Reset\n"); | ||
| 471 | } | ||
| 472 | } | ||
| 473 | } else if (Pm_MessageStatus(data) == MIDI_TIME_CLOCK) { | ||
| 474 | clockcount++; | ||
| 475 | if (clksencnt) { | ||
| 476 | showbytes(data, 1, verbose); | ||
| 477 | if (verbose) { | ||
| 478 | printf(" Clock\n"); | ||
| 479 | } | ||
| 480 | } | ||
| 481 | } else if (Pm_MessageStatus(data) == MIDI_ACTIVE_SENSING) { | ||
| 482 | actsensecount++; | ||
| 483 | if (clksencnt) { | ||
| 484 | showbytes(data, 1, verbose); | ||
| 485 | if (verbose) { | ||
| 486 | printf(" Active Sensing\n"); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | } else showbytes(data, 3, verbose); | ||
| 490 | fflush(stdout); | ||
| 491 | } | ||
| 492 | |||
| 493 | |||
| 494 | /**************************************************************************** | ||
| 495 | * put_pitch | ||
| 496 | * Inputs: | ||
| 497 | * int p: pitch number | ||
| 498 | * Effect: write out the pitch name for a given number | ||
| 499 | ****************************************************************************/ | ||
| 500 | |||
| 501 | private int put_pitch(int p) | ||
| 502 | { | ||
| 503 | char result[8]; | ||
| 504 | static char *ptos[] = { | ||
| 505 | "c", "cs", "d", "ef", "e", "f", "fs", "g", | ||
| 506 | "gs", "a", "bf", "b" }; | ||
| 507 | /* note octave correction below */ | ||
| 508 | sprintf(result, "%s%d", ptos[p % 12], (p / 12) - 1); | ||
| 509 | fputs(result, stdout); | ||
| 510 | return (int) strlen(result); | ||
| 511 | } | ||
| 512 | |||
| 513 | |||
| 514 | /**************************************************************************** | ||
| 515 | * showbytes | ||
| 516 | * Effect: print hex data, precede with newline if asked | ||
| 517 | ****************************************************************************/ | ||
| 518 | |||
| 519 | char nib_to_hex[] = "0123456789ABCDEF"; | ||
| 520 | |||
| 521 | private void showbytes(PmMessage data, int len, boolean newline) | ||
| 522 | { | ||
| 523 | int count = 0; | ||
| 524 | int i; | ||
| 525 | |||
| 526 | /* if (newline) { | ||
| 527 | putchar('\n'); | ||
| 528 | count++; | ||
| 529 | } */ | ||
| 530 | for (i = 0; i < len; i++) { | ||
| 531 | putchar(nib_to_hex[(data >> 4) & 0xF]); | ||
| 532 | putchar(nib_to_hex[data & 0xF]); | ||
| 533 | count += 2; | ||
| 534 | if (count > 72) { | ||
| 535 | putchar('.'); | ||
| 536 | putchar('.'); | ||
| 537 | putchar('.'); | ||
| 538 | break; | ||
| 539 | } | ||
| 540 | data >>= 8; | ||
| 541 | } | ||
| 542 | putchar(' '); | ||
| 543 | } | ||
| 544 | |||
| 545 | |||
| 546 | |||
| 547 | /**************************************************************************** | ||
| 548 | * showhelp | ||
| 549 | * Effect: print help text | ||
| 550 | ****************************************************************************/ | ||
| 551 | |||
| 552 | private void showhelp() | ||
| 553 | { | ||
| 554 | printf("\n"); | ||
| 555 | printf(" Item Reported Range Item Reported Range\n"); | ||
| 556 | printf(" ------------- ----- ------------- -----\n"); | ||
| 557 | printf(" Channels 1 - 16 Programs 1 - 128\n"); | ||
| 558 | printf(" Controllers 0 - 127 After Touch 0 - 127\n"); | ||
| 559 | printf(" Loudness 0 - 127 Pitch Bend 0 - 16383, " | ||
| 560 | "center = 8192\n"); | ||
| 561 | printf(" Pitches 0 - 127, 60 = c4 = middle C\n"); | ||
| 562 | printf(" \n"); | ||
| 563 | printf("n toggles notes"); | ||
| 564 | showstatus(notes); | ||
| 565 | printf("t displays noteon count since last t\n"); | ||
| 566 | printf("b toggles pitch bend, aftertouch"); | ||
| 567 | showstatus(bender); | ||
| 568 | printf("c toggles continuous control"); | ||
| 569 | showstatus(controls); | ||
| 570 | printf("h toggles program changes"); | ||
| 571 | showstatus(pgchanges); | ||
| 572 | printf("x toggles system exclusive"); | ||
| 573 | showstatus(excldata); | ||
| 574 | printf("k toggles clock and sense messages, clears counts"); | ||
| 575 | showstatus(clksencnt); | ||
| 576 | printf("r toggles other real time messages & SMPTE"); | ||
| 577 | showstatus(realdata); | ||
| 578 | printf("s displays clock and sense count since last k\n"); | ||
| 579 | printf("m toggles channel mode messages"); | ||
| 580 | showstatus(chmode); | ||
| 581 | printf("v toggles verbose text"); | ||
| 582 | showstatus(verbose); | ||
| 583 | printf("q quits\n"); | ||
| 584 | printf("\n"); | ||
| 585 | } | ||
| 586 | |||
| 587 | /**************************************************************************** | ||
| 588 | * showstatus | ||
| 589 | * Effect: print status of flag | ||
| 590 | ****************************************************************************/ | ||
| 591 | |||
| 592 | private void showstatus(boolean flag) | ||
| 593 | { | ||
| 594 | printf(", now %s\n", flag ? "ON" : "OFF"); | ||
| 595 | } | ||
