Re: [Jack-Devel] Proposal: JACK MIDI API extension for system exclusive messages
On Fri, Apr 1, 2011 at 1:00 AM, Stéphane Letz <[hidden]> wrote:
> I guess I would help to understand the new API if you provide some
> "pseudo" example of a JACK client using it.
Good idea. :)
Here's an example that sends out an identify request message to a BOSS
GT-10, and waits for an identity reply containing the software
revision level on the GT-10. I've omitted error checking to simplify
the code.
I obviously haven't compiled this code. Please forgive any errors.
----------
#include <stdio.h>
#include <string.h>
#include <semaphore.h>
#include <jack/jack.h>
#include <jack/midiport.h>
int blob_reclaimed;
sem_t blob_semaphore;
jack_client_t *client;
jack_midi_blob_t *identity_request_blob;
jack_port_t *in_port;
jack_port_t *out_port;
sem_t reply_semaphore;
int reply_sent;
int request_sent;
jack_midi_data_t software_revision_level[4];
int
process(jack_nframes_t frames, void *arg)
{
jack_nframes_t event_count;
jack_nframes_t i;
void *port_buffer = jack_port_get_buffer(out_port, frames);
jack_midi_clear_buffer(port_buffer);
if (reply_sent) {
return 0;
}
if (! request_sent) {
jack_midi_event_write_blob(port_buffer, 0, identity_request_blob);
request_sent = 1;
return 0;
}
port_buffer = jack_port_get_buffer(in_port, frames);
event_count = jack_midi_get_event_count(port_buffer);
for (i = 0; i < event_count; i++) {
jack_midi_data_t data[15];
jack_midi_event_t event;
jack_midi_event_get(&event, port_buffer, i);
if (! event.size) {
// We have a blob.
const jack_midi_blob_t *blob = event.blob;
jack_midi_blobstream_t stream;
if (jack_midi_blob_size(blob) != 15) {
continue;
}
jack_midi_blobstream_open_read(&stream, blob);
jack_midi_blobstream_read(&stream, data, 15);
jack_midi_blobstream_close(&stream);
} else if (event.size == 15) {
// There probably shouldn't be two ways to receive this message.
memcpy(data, event.buffer, 15 * sizeof(jack_midi_data_t));
} else {
continue;
}
// We're searching for an identity reply message.
if ((data[0] == 0xf0) && (data[1] == 0x7e) && (data[2] == 0x0) &&
(data[3] == 0x6) && (data[4] == 0x2) && (data[5] == 0x41) &&
(data[6] == 0x2f) && (data[7] == 0x2) && (data[8] == 0x0) &&
(data[9] == 0x0)) {
// Found it!
software_revision_level[0] = data[10];
software_revision_level[1] = data[11];
software_revision_level[2] = data[12];
software_revision_level[3] = data[13];
reply_sent = 1;
// Inform the main thread.
sem_post(&reply_semaphore);
return 0;
}
}
return 0;
}
void
reclaim_blob(jack_midi_blob_t *blob, void *arg)
{
sem_post(&blob_semaphore);
}
int
main(void)
{
// Identity request for a BOSS GT-10 with device ID '0'. The MIDI
// implementation for the GT-10 is here:
//
// http://media.rolandus.com/manuals/GT-10_MI.pdf
jack_midi_data_t identity_request[6] = {0xf0, 0x7e, 0x0, 0x6, 0x1, 0xf7};
jack_midi_blobstream_t stream;
// Initialization
client = jack_client_open("gt10-finder", JackNullOption, NULL);
in_port = jack_port_register(client, "in", JACK_DEFAULT_MIDI_TYPE,
JackPortIsInput, 0);
out_port = jack_port_register(client, "out", JACK_DEFAULT_MIDI_TYPE,
JackPortIsOutput, 0);
jack_set_midi_blob_callback(client, reclaim_blob, NULL);
jack_set_process_callback(client, process, NULL);
identity_request_blob = jack_midi_blob_create(client, 6);
jack_midi_blobstream_open_write(&stream, identity_request_blob);
jack_midi_blobstream_write(&stream, identity_request, 6);
jack_midi_blobstream_close(&stream);
sem_init(&blob_semaphore, 0, 0);
sem_init(&reply_semaphore, 0, 0);
blob_reclaimed = 0;
reply_sent = 0;
request_sent = 0;
jack_activate(client);
sem_wait(&reply_semaphore);
unsigned int major_version =
(((unsigned int) software_revision_level[0]) << 7) |
((unsigned int) software_revision_level[1]);
unsigned int minor_version =
(((unsigned int) software_revision_level[2]) << 7) |
((unsigned int) software_revision_level[3]);
printf("Found a BOSS GT-10 with software revision level: %d.%d",
major_version, minor_version);
printf("Waiting for clients to finish using our MIDI blob ...");
sem_wait(&blob_semaphore);
// Cleanup
jack_deactivate(client);
sem_destroy(&reply_semaphore);
sem_destroy(&blob_semaphore);
jack_midi_blob_free(identity_request_blob);
jack_client_close(client);
return 0;
}
----------
--
Devin Anderson
devin (at) charityfinders (dot) com
CharityFinders - http://www.charityfinders.com/
synthclone - http://synthclone.googlecode.com/
1301681661.9504_0.ltw:2,a <AANLkTikqreeBRYmo0uxN6MZbzMy2wee=us_oU-7GauGJ at mail dot gmail dot com>