Skip to content

Commit 7cf014d

Browse files
committed
Import jack1 alsa_midi driver as internal client
Signed-off-by: falkTX <falktx@falktx.com>
1 parent 0620b1b commit 7cf014d

File tree

16 files changed

+2973
-1
lines changed

16 files changed

+2973
-1
lines changed

meson.build

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ os = build_machine.system()
1010
cc = meson.get_compiler('c')
1111

1212
alsa_required = false
13-
if get_option('alsa_in_out').enabled() or get_option('zalsa').enabled()
13+
if get_option('alsa_in_out').enabled() or get_option('alsa_midi').enabled() or get_option('zalsa').enabled()
1414
alsa_required = true
1515
endif
1616

@@ -144,6 +144,13 @@ if get_option('alsa_in_out').enabled() or (
144144
build_alsa_in_out = true
145145
endif
146146

147+
build_alsa_midi = false
148+
if get_option('alsa_midi').enabled() or (
149+
get_option('alsa_midi').auto() and dep_alsa.found() and has_jack2_internal_client
150+
)
151+
build_alsa_midi = true
152+
endif
153+
147154
build_jack_net = false
148155
if get_option('jack_net').enabled() or (get_option('jack_net').auto() and lib_jacknet_dep.found())
149156
build_jack_net = true
@@ -178,6 +185,7 @@ endif
178185

179186

180187
message('Build alsa_in and alsa_out executables: ' + build_alsa_in_out.to_string())
188+
message('Build alsa_midi internal client: ' + build_alsa_midi.to_string())
181189
message('Build jack_net_master and jack_net_slave executables: ' + build_jack_net.to_string())
182190
message('Build jack_netsource executable: ' + build_jack_netsource.to_string())
183191
if build_jack_netsource

meson_options.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
option('alsa_in_out', type: 'feature', value: 'auto', description: 'Build the alsa_in and alsa_out executables (default: auto)')
2+
option('alsa_midi', type: 'feature', value: 'auto', description: 'Build the alsa_midi internal client (default: auto)')
23
option('jack_net', type: 'feature', value: 'auto', description: 'Build the jack_net_master and jack_net_slave executables (default: auto)')
34
option('jack_netsource', type: 'feature', value: 'auto', description: 'Build the jack_netsource executable (default: auto)')
45
option('jack_rec', type: 'feature', value: 'auto', description: 'Build the jack_rec executable (default: auto)')

tools/alsa_midi/a2j.h

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/* -*- Mode: C ; c-basic-offset: 2 -*- */
2+
/*
3+
* ALSA SEQ < - > JACK MIDI bridge
4+
*
5+
* Copyright (c) 2006,2007 Dmitry S. Baikov <c0ff@konstruktiv.org>
6+
* Copyright (c) 2007,2008,2009 Nedko Arnaudov <nedko@arnaudov.name>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation; version 2 of the License.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20+
*/
21+
22+
#ifndef __jack_alsa_midi_h__
23+
#define __jack_alsa_midi_h__
24+
25+
#include <stdbool.h>
26+
#include <semaphore.h>
27+
#include <jack/midiport.h>
28+
#include <jack/ringbuffer.h>
29+
30+
#ifdef ALSA_MIDI_INTERNAL_CLIENT
31+
#define JACK_DRIVER_DECL
32+
typedef struct jack_engine_t jack_engine_t;
33+
#else
34+
#include "driver.h"
35+
#endif
36+
37+
#include "list.h"
38+
39+
#define JACK_INVALID_PORT NULL
40+
41+
#define MAX_PORTS 2048
42+
#define MAX_EVENT_SIZE 1024
43+
44+
#define PORT_HASH_BITS 4
45+
#define PORT_HASH_SIZE (1 << PORT_HASH_BITS)
46+
47+
/* Beside enum use, these are indeces for (struct a2j).stream array */
48+
#define A2J_PORT_CAPTURE 0 // ALSA playback port -> JACK capture port
49+
#define A2J_PORT_PLAYBACK 1 // JACK playback port -> ALSA capture port
50+
51+
typedef struct a2j_port * a2j_port_hash_t[PORT_HASH_SIZE];
52+
53+
struct alsa_midi_driver;
54+
55+
struct a2j_port {
56+
struct a2j_port * next; /* hash - jack */
57+
struct list_head siblings; /* list - main loop */
58+
struct alsa_midi_driver * driver_ptr;
59+
bool is_dead;
60+
char name[64];
61+
snd_seq_addr_t remote;
62+
jack_port_t * jack_port;
63+
64+
jack_ringbuffer_t * inbound_events; // alsa_midi_event_t + data
65+
int64_t last_out_time;
66+
67+
void * jack_buf;
68+
};
69+
70+
struct a2j_stream {
71+
snd_midi_event_t *codec;
72+
73+
jack_ringbuffer_t *new_ports;
74+
75+
a2j_port_hash_t port_hash;
76+
struct list_head list;
77+
};
78+
79+
typedef struct alsa_midi_driver {
80+
JACK_DRIVER_DECL;
81+
82+
jack_client_t * jack_client;
83+
84+
snd_seq_t *seq;
85+
pthread_t alsa_input_thread;
86+
pthread_t alsa_output_thread;
87+
int client_id;
88+
int port_id;
89+
int queue;
90+
bool freewheeling;
91+
bool running;
92+
bool finishing;
93+
94+
jack_ringbuffer_t* port_del; // struct a2j_port*
95+
jack_ringbuffer_t* outbound_events; // struct a2j_delivery_event
96+
jack_nframes_t cycle_start;
97+
98+
sem_t output_semaphore;
99+
100+
struct a2j_stream stream[2];
101+
102+
} alsa_midi_driver_t;
103+
104+
#define NSEC_PER_SEC ((int64_t)1000 * 1000 * 1000)
105+
106+
struct a2j_alsa_midi_event {
107+
int64_t time;
108+
int size;
109+
};
110+
111+
#define MAX_JACKMIDI_EV_SIZE 64
112+
113+
struct a2j_delivery_event {
114+
struct list_head siblings;
115+
116+
/* a jack MIDI event, plus the port its destined for: everything
117+
the ALSA output thread needs to deliver the event. time is
118+
part of the jack_event.
119+
*/
120+
jack_midi_event_t jack_event;
121+
jack_nframes_t time; /* realtime, not offset time */
122+
struct a2j_port* port;
123+
char midistring[MAX_JACKMIDI_EV_SIZE];
124+
};
125+
126+
void a2j_error(const char* fmt, ...);
127+
128+
#define A2J_DEBUG
129+
/*#undef A2J_DEBUG*/
130+
131+
#ifdef A2J_DEBUG
132+
extern bool a2j_do_debug;
133+
extern void _a2j_debug(const char* fmt, ...);
134+
#define a2j_debug(fmt, ...) if (a2j_do_debug) { _a2j_debug ((fmt), ## __VA_ARGS__); }
135+
#else
136+
#define a2j_debug(fmt, ...)
137+
#endif
138+
139+
#endif /* __jack_alsa_midi_h__ */

0 commit comments

Comments
 (0)