mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	
		
			
	
	
		
			115 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			115 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* PipeWire */
							 | 
						||
| 
								 | 
							
								/* SPDX-FileCopyrightText: Copyright © 2019 Wim Taymans */
							 | 
						||
| 
								 | 
							
								/* SPDX-License-Identifier: MIT */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include <sys/mman.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <jack/jack.h>
							 | 
						||
| 
								 | 
							
								#include <jack/midiport.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <pipewire-jack-extensions.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#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;
							 | 
						||
| 
								 | 
							
								}
							 |