diff --git a/pipewire-jack/examples/ump-source.c b/pipewire-jack/examples/ump-source.c new file mode 100644 index 000000000..e3cbb8042 --- /dev/null +++ b/pipewire-jack/examples/ump-source.c @@ -0,0 +1,114 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2019 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#include +#include +#include +#include + +#include +#include + +#include + +#define MAX_BUFFERS 64 + +struct data { + const char *path; + + jack_client_t *client; + const char *client_name; + jack_port_t *out_port; + + int cycle; + uint64_t position; + uint64_t next_sample; + uint64_t period; +}; + +static int +process (jack_nframes_t nframes, void *arg) +{ + struct data *d = (struct data*)arg; + void *buf; + uint32_t event[2]; + + buf = jack_port_get_buffer (d->out_port, nframes); + jack_midi_clear_buffer(buf); + + while (d->position >= d->next_sample && d->position + nframes > d->next_sample) { + uint64_t pos = d->position - d->next_sample; + + if (d->cycle == 0) { + /* MIDI 2.0 note on, channel 0, middle C, max velocity, no attribute */ + event[0] = 0x40903c00; + event[1] = 0xffff0000; + } else { + /* MIDI 2.0 note off, channel 0, middle C, max velocity, no attribute */ + event[0] = 0x40803c00; + event[1] = 0xffff0000; + } + + d->cycle ^= 1; + + jack_midi_event_write(buf, pos, (const jack_midi_data_t *) event, sizeof(event)); + + d->next_sample += d->period; + } + d->position += nframes; + return 0; +} + +int main(int argc, char *argv[]) +{ + struct data data = { 0, }; + jack_options_t options = JackNullOption; + jack_status_t status; + + data.client = jack_client_open ("ump-source", options, &status); + if (data.client == NULL) { + fprintf (stderr, "jack_client_open() failed, " + "status = 0x%2.0x\n", status); + if (status & JackServerFailed) { + fprintf (stderr, "Unable to connect to JACK server\n"); + } + exit (1); + } + if (status & JackServerStarted) { + fprintf (stderr, "JACK server started\n"); + } + if (status & JackNameNotUnique) { + data.client_name = jack_get_client_name(data.client); + fprintf (stderr, "unique name `%s' assigned\n", data.client_name); + } + + /* send 2 events per second */ + data.period = jack_get_sample_rate(data.client) / 2; + + jack_set_process_callback (data.client, process, &data); + + /* the UMP port type allows both sending and receiving of UMP + * messages, which can contain MIDI 1.0 and MIDI 2.0 messages. */ + data.out_port = jack_port_register (data.client, "output", + JACK_DEFAULT_UMP_TYPE, + JackPortIsOutput, 0); + + if (data.out_port == NULL) { + fprintf(stderr, "no more JACK ports available\n"); + exit (1); + } + + if (jack_activate (data.client)) { + fprintf (stderr, "cannot activate client"); + exit (1); + } + + while (1) { + sleep (1); + } + + jack_client_close (data.client); + + return 0; +} diff --git a/pipewire-jack/src/meson.build b/pipewire-jack/src/meson.build index b4c2651f4..0630d96a8 100644 --- a/pipewire-jack/src/meson.build +++ b/pipewire-jack/src/meson.build @@ -110,3 +110,11 @@ if sdl_dep.found() link_with: pipewire_jack, ) endif +executable('ump-source', + '../examples/ump-source.c', + include_directories : [jack_inc], + install : installed_tests_enabled, + install_dir : installed_tests_execdir / 'examples' / 'jack', + dependencies : [mathlib], + link_with: pipewire_jack, +)