1 /*
2  * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This is free software: you can redistribute it and/or modify
5  * it under the terms of the Artistic License 2.0 as published by
6  * The Perl Foundation.
7  *
8  * This source is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * Artistic License 2.0 for more details.
12  *
13  * You should have received a copy of the Artistic License 2.0
14  * along the source as a COPYING file. If not, obtain it from
15  * http://www.perlfoundation.org/artistic_license_2_0.
16  */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <assert.h>
22 #include <limits.h>
23 #include <math.h>
24 
25 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
26 #	include <pthread_np.h>
27 typedef cpuset_t cpu_set_t;
28 #endif
29 
30 #include <synthpod_bin.h>
31 
32 #include <jack/jack.h>
33 #include <jack/midiport.h>
34 #include <jack/transport.h>
35 #include <jack/session.h>
36 #if defined(JACK_HAS_METADATA_API)
37 #	include <jack/metadata.h>
38 #	include <jack/uuid.h>
39 # include <jackey.h>
40 #endif
41 
42 #include <osc.lv2/forge.h>
43 #include <osc.lv2/writer.h>
44 
45 #define OSC_SIZE 0x800
46 
47 typedef struct _prog_t prog_t;
48 
49 struct _prog_t {
50 	bin_t bin;
51 
52 	LV2_Atom_Forge forge;
53 
54 	uint8_t osc_buf [OSC_SIZE]; //TODO how big?
55 
56 	LV2_OSC_URID osc_urid;
57 
58 	LV2_URID midi_MidiEvent;
59 
60 	LV2_URID time_position;
61 	LV2_URID time_barBeat;
62 	LV2_URID time_bar;
63 	LV2_URID time_beatUnit;
64 	LV2_URID time_beatsPerBar;
65 	LV2_URID time_beatsPerMinute;
66 	LV2_URID time_frame;
67 	LV2_URID time_framesPerSecond;
68 	LV2_URID time_speed;
69 
70 	atomic_int kill;
71 	save_state_t save_state;
72 	atomic_uintptr_t async;
73 
74 	char *server_name;
75 	char *session_id;
76 	jack_client_t *client;
77 	jack_session_event_t *session_event;
78 	uint32_t seq_size;
79 
80 	struct {
81 		jack_transport_state_t rolling;
82 		jack_nframes_t frame;
83 		float beats_per_bar;
84 		float beat_type;
85 		double ticks_per_beat;
86 		double beats_per_minute;
87 	} trans;
88 
89 	LV2_OSC_Schedule osc_sched;
90 	struct timespec cur_ntp;
91 	struct {
92 		jack_nframes_t cur_frames;
93 		jack_nframes_t ref_frames;
94 		jack_time_t cur_usecs;
95 		jack_time_t nxt_usecs;
96 		double dT;
97 		double dTm1;
98 	} cycle;
99 };
100 
101 static LV2_Atom_Forge_Ref
_trans_event(prog_t * prog,LV2_Atom_Forge * forge,int rolling,jack_position_t * pos)102 _trans_event(prog_t *prog,  LV2_Atom_Forge *forge, int rolling, jack_position_t *pos)
103 {
104 	LV2_Atom_Forge_Frame frame;
105 
106 	LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, 0);
107 	if(ref)
108 		ref = lv2_atom_forge_object(forge, &frame, 0, prog->time_position);
109 	{
110 		if(ref)
111 			ref = lv2_atom_forge_key(forge, prog->time_frame);
112 		if(ref)
113 			ref = lv2_atom_forge_long(forge, pos->frame);
114 
115 		if(ref)
116 			ref = lv2_atom_forge_key(forge, prog->time_speed);
117 		if(ref)
118 			ref = lv2_atom_forge_float(forge, rolling ? 1.0 : 0.0);
119 
120 		if(pos->valid & JackPositionBBT)
121 		{
122 			float bar_beat = pos->beat - 1 + (pos->tick / pos->ticks_per_beat);
123 			float bar = pos->bar - 1;
124 
125 			if(ref)
126 				ref = lv2_atom_forge_key(forge, prog->time_barBeat);
127 			if(ref)
128 				ref = lv2_atom_forge_float(forge, bar_beat);
129 
130 			if(ref)
131 				ref = lv2_atom_forge_key(forge, prog->time_bar);
132 			if(ref)
133 				ref = lv2_atom_forge_long(forge, bar);
134 
135 			if(ref)
136 				ref = lv2_atom_forge_key(forge, prog->time_beatUnit);
137 			if(ref)
138 				ref = lv2_atom_forge_int(forge, pos->beat_type);
139 
140 			if(ref)
141 				ref = lv2_atom_forge_key(forge, prog->time_beatsPerBar);
142 			if(ref)
143 				ref = lv2_atom_forge_float(forge, pos->beats_per_bar);
144 
145 			if(ref)
146 				ref = lv2_atom_forge_key(forge, prog->time_beatsPerMinute);
147 			if(ref)
148 				ref = lv2_atom_forge_float(forge, pos->beats_per_minute);
149 		}
150 	}
151 	if(ref)
152 		lv2_atom_forge_pop(forge, &frame);
153 
154 	return ref;
155 }
156 
157 __non_realtime static void
_saved(bin_t * bin,int status)158 _saved(bin_t *bin, int status)
159 {
160 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
161 
162 	if(handle->save_state == SAVE_STATE_NSM)
163 	{
164 		nsmc_saved(bin->nsm, status);
165 	}
166 	else if(handle->save_state == SAVE_STATE_JACK)
167 	{
168 		jack_session_event_t *ev = handle->session_event;
169 		if(ev)
170 		{
171 			if(status != 0)
172 				ev->flags |= JackSessionSaveError;
173 			jack_session_reply(handle->client, ev);
174 			jack_session_event_free(ev);
175 			handle->session_event = NULL;
176 		}
177 	}
178 	handle->save_state = SAVE_STATE_INTERNAL;
179 
180 	if(atomic_load_explicit(&handle->kill, memory_order_relaxed))
181 	{
182 		bin_quit(bin);
183 	}
184 }
185 
186 // rt
187 __realtime static int
_process(jack_nframes_t nsamples,void * data)188 _process(jack_nframes_t nsamples, void *data)
189 {
190 	prog_t *handle = data;
191 	bin_t *bin = &handle->bin;
192 	sp_app_t *app = bin->app;
193 
194 	if(bin->first)
195 	{
196 		bin->dsp_thread = pthread_self();
197 
198 		if(handle->bin.cpu_affinity)
199 		{
200 			cpu_set_t cpuset;
201 			CPU_ZERO(&cpuset);
202 			CPU_SET(0, &cpuset);
203 			if(pthread_setaffinity_np(bin->dsp_thread, sizeof(cpu_set_t), &cpuset))
204 				bin_log_trace(bin, "%s: pthread_setaffinity_np error\n", __func__);
205 		}
206 
207 		bin->first = false;
208 	}
209 
210 	cross_clock_gettime(&bin->clk_real, &handle->cur_ntp);
211 	handle->cur_ntp.tv_sec += JAN_1970; // convert NTP to OSC time
212 	//jack_nframes_t offset = jack_frames_since_cycle_start(handle->client);
213 
214 	float T;
215 	jack_get_cycle_times(handle->client, &handle->cycle.cur_frames,
216 		&handle->cycle.cur_usecs, &handle->cycle.nxt_usecs, &T);
217 	(void)T;
218 
219 	handle->cycle.ref_frames = handle->cycle.cur_frames;
220 
221 	// calculate apparent period
222 	double diff = 1e-6 * (handle->cycle.nxt_usecs - handle->cycle.cur_usecs);
223 
224 	// calculate apparent samples per period
225 	handle->cycle.dT = nsamples / diff;
226 	handle->cycle.dTm1 = 1.0 / handle->cycle.dT;
227 
228 	// get transport position
229 	jack_position_t pos;
230 	jack_transport_state_t rolling = jack_transport_query(handle->client, &pos) == JackTransportRolling;
231 	int trans_changed = (rolling != handle->trans.rolling)
232 		|| (pos.frame != handle->trans.frame)
233 		|| (pos.beats_per_bar != handle->trans.beats_per_bar)
234 		|| (pos.beat_type != handle->trans.beat_type)
235 		|| (pos.ticks_per_beat != handle->trans.ticks_per_beat)
236 		|| (pos.beats_per_minute != handle->trans.beats_per_minute);
237 
238 	const size_t sample_buf_size = sizeof(float) * nsamples;
239 	const sp_app_system_source_t *sources = sp_app_get_system_sources(app);
240 
241 	if(sp_app_bypassed(app)) // aka loading state
242 	{
243 		const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app);
244 
245 		//fprintf(stderr, "app is bypassed\n");
246 
247 		// clear output buffers
248 		for(const sp_app_system_sink_t *sink=sinks;
249 			sink->type != SYSTEM_PORT_NONE;
250 			sink++)
251 		{
252 			switch(sink->type)
253 			{
254 				case SYSTEM_PORT_NONE:
255 				case SYSTEM_PORT_CONTROL:
256 				case SYSTEM_PORT_COM:
257 					break;
258 
259 				case SYSTEM_PORT_AUDIO:
260 				case SYSTEM_PORT_CV:
261 				{
262 					void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
263 					memset(out_buf, 0x0, sample_buf_size);
264 					break;
265 				}
266 				case SYSTEM_PORT_MIDI:
267 				case SYSTEM_PORT_OSC:
268 				{
269 					void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
270 					jack_midi_clear_buffer(out_buf);
271 					break;
272 				}
273 			}
274 		}
275 
276 		bin_process_pre(bin, nsamples, true);
277 		bin_process_post(bin);
278 
279 		return 0;
280 	}
281 
282 	//TODO use __builtin_assume_aligned
283 
284 	// fill input buffers
285 	for(const sp_app_system_source_t *source=sources;
286 		source->type != SYSTEM_PORT_NONE;
287 		source++)
288 	{
289 		switch(source->type)
290 		{
291 			case SYSTEM_PORT_NONE:
292 			case SYSTEM_PORT_CONTROL:
293 				break;
294 
295 			case SYSTEM_PORT_AUDIO:
296 			case SYSTEM_PORT_CV:
297 			{
298 				const void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
299 				memcpy(source->buf, in_buf, sample_buf_size);
300 				break;
301 			}
302 			case SYSTEM_PORT_MIDI:
303 			{
304 				void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
305 				void *seq_in = source->buf;
306 
307 				LV2_Atom_Forge *forge = &handle->forge;
308 				LV2_Atom_Forge_Frame frame;
309 				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
310 				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);
311 
312 				if(ref && trans_changed)
313 					ref = _trans_event(handle, forge, rolling, &pos);
314 
315 				const int n = jack_midi_get_event_count(in_buf);
316 				for(int i=0; i<n; i++)
317 				{
318 					jack_midi_event_t mev;
319 					jack_midi_event_get(&mev, in_buf, i);
320 
321 					if( (mev.buffer[0] & 0x80) != 0x80)
322 						continue; // no MIDI message
323 
324 					//add jack midi event to in_buf
325 					if(ref)
326 						ref = lv2_atom_forge_frame_time(forge, mev.time);
327 					if(ref)
328 						ref = lv2_atom_forge_atom(forge, mev.size, handle->midi_MidiEvent);
329 					// fix up noteOn(vel=0) -> noteOff(vel=0)
330 					if(  (mev.size == 3) && ( (mev.buffer[0] & 0xf0) == 0x90)
331 						&& (mev.buffer[2] == 0x00) )
332 					{
333 						const uint8_t note_off [3] = {
334 							0x80 | (mev.buffer[0] & 0xf),
335 							mev.buffer[1],
336 							0x0
337 						};
338 						if(ref)
339 							ref = lv2_atom_forge_write(forge, note_off, sizeof(note_off));
340 					}
341 					else
342 					{
343 						if(ref)
344 							ref = lv2_atom_forge_write(forge, mev.buffer, mev.size);
345 					}
346 				}
347 				if(ref)
348 					lv2_atom_forge_pop(forge, &frame);
349 				else
350 					lv2_atom_sequence_clear(seq_in);
351 
352 				break;
353 			}
354 
355 			case SYSTEM_PORT_OSC:
356 			{
357 				void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
358 				void *seq_in = source->buf;
359 
360 				LV2_Atom_Forge *forge = &handle->forge;
361 				LV2_Atom_Forge_Frame frame;
362 				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
363 				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);
364 
365 				if(ref && trans_changed)
366 					ref = _trans_event(handle, forge, rolling, &pos);
367 
368 				const int n = jack_midi_get_event_count(in_buf);
369 				for(int i=0; i<n; i++)
370 				{
371 					jack_midi_event_t mev;
372 					jack_midi_event_get(&mev, in_buf, i);
373 
374 					if( (mev.buffer[0] != '/') && (mev.buffer[0] != '#') )
375 						continue; // no OSC message
376 
377 					if(ref)
378 						ref = lv2_atom_forge_frame_time(forge, mev.time);
379 					if(ref)
380 						ref = lv2_osc_forge_packet(forge, &handle->osc_urid, handle->bin.map,
381 							mev.buffer, mev.size); // Note: an invalid packet will return 0
382 				}
383 				if(ref)
384 					lv2_atom_forge_pop(forge, &frame);
385 				else
386 					lv2_atom_sequence_clear(seq_in);
387 
388 				break;
389 			}
390 
391 			case SYSTEM_PORT_COM:
392 			{
393 				void *seq_in = source->buf;
394 
395 				LV2_Atom_Forge *forge = &handle->forge;
396 				LV2_Atom_Forge_Frame frame;
397 				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
398 				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);
399 
400 				const LV2_Atom_Object *obj;
401 				size_t size;
402 				while((obj = varchunk_read_request(bin->app_from_com, &size)))
403 				{
404 					if(ref)
405 						ref = lv2_atom_forge_frame_time(forge, 0);
406 					if(ref)
407 						ref = lv2_atom_forge_write(forge, obj, size);
408 
409 					varchunk_read_advance(bin->app_from_com);
410 				}
411 				if(ref)
412 					lv2_atom_forge_pop(forge, &frame);
413 				else
414 					lv2_atom_sequence_clear(seq_in);
415 
416 				break;
417 			}
418 		}
419 	}
420 
421 	// update transport state
422 	handle->trans.rolling = rolling;
423 	handle->trans.frame = rolling
424 		? handle->trans.frame + nsamples
425 		: pos.frame;
426 	handle->trans.beats_per_bar = pos.beats_per_bar;
427 	handle->trans.beat_type = pos.beat_type;
428 	handle->trans.ticks_per_beat = pos.ticks_per_beat;
429 	handle->trans.beats_per_minute = pos.beats_per_minute;
430 
431 	bin_process_pre(bin, nsamples, false);
432 
433 	const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app);
434 
435 	// fill output buffers
436 	for(const sp_app_system_sink_t *sink=sinks;
437 		sink->type != SYSTEM_PORT_NONE;
438 		sink++)
439 	{
440 		switch(sink->type)
441 		{
442 			case SYSTEM_PORT_NONE:
443 			case SYSTEM_PORT_CONTROL:
444 				break;
445 
446 			case SYSTEM_PORT_AUDIO:
447 			case SYSTEM_PORT_CV:
448 			{
449 				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
450 				memcpy(out_buf, sink->buf, sample_buf_size);
451 				break;
452 			}
453 			case SYSTEM_PORT_MIDI:
454 			{
455 				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
456 				const LV2_Atom_Sequence *seq_out = sink->buf;
457 
458 				// fill midi output buffer
459 				jack_midi_clear_buffer(out_buf);
460 				if(seq_out)
461 				{
462 					LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
463 					{
464 						const LV2_Atom *atom = &ev->body;
465 
466 						if(atom->type != handle->midi_MidiEvent)
467 							continue; // ignore non-MIDI events
468 
469 						jack_midi_event_write(out_buf, ev->time.frames,
470 							LV2_ATOM_BODY_CONST(atom), atom->size);
471 					}
472 				}
473 
474 				break;
475 			}
476 
477 			case SYSTEM_PORT_OSC:
478 			{
479 				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
480 				const LV2_Atom_Sequence *seq_out = sink->buf;
481 
482 				// fill midi output buffer
483 				jack_midi_clear_buffer(out_buf);
484 				if(seq_out)
485 				{
486 					LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
487 					{
488 						const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
489 
490 						if(!lv2_atom_forge_is_object_type(&handle->forge, obj->atom.type))
491 							continue;
492 
493 						if(!lv2_osc_is_message_or_bundle_type(&handle->osc_urid, obj->body.otype))
494 							continue;
495 
496 						LV2_OSC_Writer writer;
497 						lv2_osc_writer_initialize(&writer, handle->osc_buf, OSC_SIZE);
498 						lv2_osc_writer_packet(&writer, &handle->osc_urid, handle->bin.unmap,
499 							obj->atom.size, &obj->body);
500 						size_t size;
501 						uint8_t *osc_buf = lv2_osc_writer_finalize(&writer, &size);
502 
503 						if(size)
504 						{
505 							jack_midi_event_write(out_buf, ev->time.frames,
506 								osc_buf, size);
507 						}
508 					}
509 				}
510 
511 				break;
512 			}
513 
514 			case SYSTEM_PORT_COM:
515 			{
516 				const LV2_Atom_Sequence *seq_out = sink->buf;
517 
518 				LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
519 				{
520 					const LV2_Atom *atom = (const LV2_Atom *)&ev->body;
521 
522 					// try do process events directly
523 					bin->advance_ui = sp_app_from_ui(bin->app, atom);
524 					if(!bin->advance_ui) // queue event in ringbuffer instead
525 					{
526 						//fprintf(stderr, "plugin ui direct is blocked\n");
527 
528 						void *ptr;
529 						size_t size = lv2_atom_total_size(atom);
530 						if((ptr = varchunk_write_request(bin->app_from_app, size)))
531 						{
532 							memcpy(ptr, atom, size);
533 							varchunk_write_advance(bin->app_from_app, size);
534 						}
535 						else
536 						{
537 							bin_log_trace(bin, "%s: app_from_app ringbuffer full\n", __func__);
538 							//FIXME
539 						}
540 					}
541 				}
542 				break;
543 			}
544 		}
545 	}
546 
547 	bin_process_post(bin);
548 
549 	return 0;
550 }
551 
552 __non_realtime static void
_session(jack_session_event_t * ev,void * data)553 _session(jack_session_event_t *ev, void *data)
554 {
555 	prog_t *handle = data;
556 
557 	//printf("_session: %s %s %s\n",
558 	//	ev->session_dir, ev->client_uuid, ev->command_line);
559 
560 	jack_session_event_t *async = (void *)atomic_exchange(&handle->async, (uintptr_t)ev);
561 	if(async)
562 		jack_session_event_free(async);
563 }
564 
565 // rt, but can do non-rt stuff, as process won't be called
566 __non_realtime static int
_buffer_size(jack_nframes_t block_size,void * data)567 _buffer_size(jack_nframes_t block_size, void *data)
568 {
569 	prog_t *handle = data;
570 	bin_t *bin = &handle->bin;
571 
572 	//printf("JACK: new buffer size: %p %u %u\n",
573 	//	handle->app, handle->app_driver.max_block_size, block_size);
574 
575 	if(bin->app)
576 		return sp_app_nominal_block_length(bin->app, block_size);
577 
578 	return 0;
579 }
580 
581 __non_realtime static int
_sample_rate(jack_nframes_t sample_rate,void * data)582 _sample_rate(jack_nframes_t sample_rate, void *data)
583 {
584 	prog_t *handle = data;
585 	bin_t *bin = &handle->bin;
586 
587 	if(bin->app && (sample_rate != bin->app_driver.sample_rate) )
588 		bin_log_error(bin, "%s: synthpod does not support dynamic sample rate changes\n", __func__);
589 
590 	return 0;
591 }
592 
593 void
_replace(char * str,const char * a,const char * b)594 _replace(char* str, const char* a, const char* b)
595 {
596 	const size_t len = strlen(str);
597 	const size_t lena = strlen(a);
598 	const size_t lenb = strlen(b);
599 
600 	for(char *p = str; (p = strstr(p, a)); ++p)
601 	{
602 		if(lena != lenb) // shift end as needed
603 		{
604 			memmove(p+lenb, p+lena, len - (p - str) + lenb);
605 		}
606 		memcpy(p, b, lenb);
607 	}
608 }
609 
610 __non_realtime static void *
_system_port_add(void * data,system_port_t type,const char * short_name,const char * pretty_name,const char * designation,bool input,uint32_t order)611 _system_port_add(void *data, system_port_t type, const char *short_name,
612 	const char *pretty_name, const char *designation, bool input, uint32_t order)
613 {
614 	bin_t *bin = data;
615 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
616 
617 	//printf("_system_port_add: %s\n", short_name);
618 
619 	const size_t len = jack_port_name_size();
620 	char *name = alloca(len);
621 	strncpy(name, short_name, len);
622 
623 	if(strstr(name, "sink"))
624 		_replace(name, "sink", "source");
625 	else if(strstr(name, "source"))
626 		_replace(name, "source", "sink");
627 
628 	jack_port_t *jack_port = NULL;
629 
630 	unsigned long flags = input ? JackPortIsInput : JackPortIsOutput;
631 
632 	switch(type)
633 	{
634 		case SYSTEM_PORT_NONE:
635 		{
636 			// skip
637 			break;
638 		}
639 
640 		case SYSTEM_PORT_CONTROL:
641 		{
642 			// unsupported, skip
643 			break;
644 		}
645 
646 		case SYSTEM_PORT_AUDIO:
647 		{
648 			jack_port = jack_port_register(handle->client, name,
649 				JACK_DEFAULT_AUDIO_TYPE, flags, 0);
650 			break;
651 		}
652 		case SYSTEM_PORT_CV:
653 		{
654 			jack_port = jack_port_register(handle->client, name,
655 				JACK_DEFAULT_AUDIO_TYPE, flags, 0);
656 
657 #if defined(JACK_HAS_METADATA_API)
658 			if(jack_port)
659 			{
660 				jack_uuid_t uuid = jack_port_uuid(jack_port);
661 				if(!jack_uuid_empty(uuid))
662 				{
663 					jack_set_property(handle->client, uuid,
664 						JACKEY_SIGNAL_TYPE, "CV", "text/plain");
665 				}
666 			}
667 #endif
668 			break;
669 		}
670 
671 		case SYSTEM_PORT_MIDI:
672 		{
673 			jack_port = jack_port_register(handle->client, name,
674 				JACK_DEFAULT_MIDI_TYPE, flags, 0);
675 
676 #if defined(JACK_HAS_METADATA_API)
677 			if(jack_port)
678 			{
679 				jack_uuid_t uuid = jack_port_uuid(jack_port);
680 				if(!jack_uuid_empty(uuid))
681 				{
682 					jack_set_property(handle->client, uuid,
683 						JACKEY_EVENT_TYPES, "MIDI", "text/plain");
684 				}
685 			}
686 #endif
687 			break;
688 		}
689 		case SYSTEM_PORT_OSC:
690 		{
691 			jack_port = jack_port_register(handle->client, name,
692 				JACK_DEFAULT_MIDI_TYPE, flags, 0);
693 
694 #if defined(JACK_HAS_METADATA_API)
695 			if(jack_port)
696 			{
697 				jack_uuid_t uuid = jack_port_uuid(jack_port);
698 				if(!jack_uuid_empty(uuid))
699 				{
700 					jack_set_property(handle->client, uuid,
701 						JACKEY_EVENT_TYPES, "OSC", "text/plain");
702 				}
703 			}
704 #endif
705 			break;
706 		}
707 
708 		case SYSTEM_PORT_COM:
709 		{
710 			// unsupported, skip
711 			break;
712 		}
713 	}
714 
715 #if defined(JACK_HAS_METADATA_API)
716 	if(jack_port)
717 	{
718 		jack_uuid_t uuid = jack_port_uuid(jack_port);
719 		if(!jack_uuid_empty(uuid))
720 		{
721 			if(pretty_name)
722 			{
723 				jack_set_property(handle->client, uuid,
724 					JACK_METADATA_PRETTY_NAME, pretty_name, "text/plain");
725 			}
726 
727 			if(designation)
728 			{
729 				jack_set_property(handle->client, uuid,
730 					JACKEY_DESIGNATION, designation, "text/plain");
731 			}
732 
733 			char order_str [32];
734 			sprintf(order_str, "%"PRIu32, order);
735 			jack_set_property(handle->client, uuid,
736 				JACKEY_ORDER, order_str, "http://www.w3.org/2001/XMLSchema#integer");
737 		}
738 	}
739 #endif
740 
741 	return jack_port;
742 }
743 
744 __non_realtime static void
_system_port_del(void * data,void * sys_port)745 _system_port_del(void *data, void *sys_port)
746 {
747 	bin_t *bin = data;
748 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
749 
750 	jack_port_t *jack_port = sys_port;
751 
752 	if(!jack_port || !handle->client)
753 		return;
754 
755 #if defined(JACK_HAS_METADATA_API)
756 	jack_uuid_t uuid = jack_port_uuid(jack_port);
757 	if(!jack_uuid_empty(uuid))
758 		jack_remove_properties(handle->client, uuid);
759 #endif
760 
761 	jack_port_unregister(handle->client, jack_port);
762 }
763 
764 __non_realtime static void
_shutdown(void * data)765 _shutdown(void *data)
766 {
767 	prog_t *handle = data;
768 
769 	//TODO do this asynchronously?
770 	handle->client = NULL; // client has died, didn't it?
771 	bin_quit(&handle->bin);
772 }
773 
774 __non_realtime static int
_xrun(void * data)775 _xrun(void *data)
776 {
777 	prog_t *handle = data;
778 	bin_t *bin = &handle->bin;
779 
780 	//TODO do this asynchronously?
781 	bin_log_warning(bin, "JACK XRun\n");
782 
783 	return 0;
784 }
785 
786 static int
_jack_init(prog_t * handle,const char * id)787 _jack_init(prog_t *handle, const char *id)
788 {
789 	jack_options_t opts = JackNullOption | JackNoStartServer;
790 	if(handle->server_name)
791 		opts |= JackServerName;
792 	if(handle->session_id)
793 		opts |= JackSessionID;
794 
795 	jack_status_t status;
796 	if(!(handle->client = jack_client_open(id, opts, &status,
797 		handle->server_name ? handle->server_name : handle->session_id,
798 		handle->server_name ? handle->session_id : NULL)))
799 	{
800 		return -1;
801 	}
802 
803 	//TODO check status
804 
805 	// set client pretty name
806 #if defined(JACK_HAS_METADATA_API)
807 	jack_uuid_t uuid;
808 	const char *client_name = jack_get_client_name(handle->client);
809 	const char *uuid_str = jack_get_uuid_for_client_name(handle->client, client_name);
810 	if(uuid_str)
811 		jack_uuid_parse(uuid_str, &uuid);
812 	else
813 		jack_uuid_clear(&uuid);
814 
815 	if(!jack_uuid_empty(uuid))
816 	{
817 		jack_set_property(handle->client, uuid,
818 			JACK_METADATA_PRETTY_NAME, "Synthpod", "text/plain");
819 	}
820 #endif
821 
822 	// set client process callback
823 	if(jack_set_process_callback(handle->client, _process, handle))
824 		return -1;
825 	if(jack_set_session_callback(handle->client, _session, handle))
826 		return -1;
827 	if(jack_set_sample_rate_callback(handle->client, _sample_rate, handle))
828 		return -1;
829 	if(jack_set_buffer_size_callback(handle->client, _buffer_size, handle))
830 		return -1;
831 	jack_on_shutdown(handle->client, _shutdown, handle);
832 	jack_set_xrun_callback(handle->client, _xrun, handle);
833 
834 	return 0;
835 }
836 
837 static void
_jack_deinit(prog_t * handle)838 _jack_deinit(prog_t *handle)
839 {
840 	if(handle->client)
841 	{
842 		// remove client properties
843 #if defined(JACK_HAS_METADATA_API)
844 		jack_uuid_t uuid;
845 		const char *client_name = jack_get_client_name(handle->client);
846 		const char *uuid_str = jack_get_uuid_for_client_name(handle->client, client_name);
847 		if(uuid_str)
848 			jack_uuid_parse(uuid_str, &uuid);
849 		else
850 			jack_uuid_clear(&uuid);
851 
852 		if(!jack_uuid_empty(uuid))
853 			jack_remove_properties(handle->client, uuid);
854 #endif
855 
856 		jack_deactivate(handle->client);
857 		jack_client_close(handle->client);
858 		handle->client = NULL;
859 	}
860 }
861 
862 __non_realtime static int
_open(const char * path,const char * name,const char * id,void * data)863 _open(const char *path, const char *name, const char *id, void *data)
864 {
865 	bin_t *bin = data;
866 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
867 	(void)name;
868 
869 	if(bin->path)
870 		free(bin->path);
871 	bin->path = strdup(path);
872 
873 	// jack init
874 	if(_jack_init(handle, id))
875 	{
876 		nsmc_opened(bin->nsm, -1);
877 		return -1;
878 	}
879 
880 	// synthpod init
881 	bin->app_driver.sample_rate = jack_get_sample_rate(handle->client);
882 	bin->app_driver.update_rate = handle->bin.update_rate;
883 	bin->app_driver.max_block_size = jack_get_buffer_size(handle->client);
884 	bin->app_driver.min_block_size = 1;
885 	bin->app_driver.seq_size = MAX(handle->seq_size,
886 		jack_port_type_get_buffer_size(handle->client, JACK_DEFAULT_MIDI_TYPE));
887 	bin->app_driver.num_periods = 1; //FIXME
888 
889 	// app init
890 	bin->app = sp_app_new(NULL, &bin->app_driver, bin);
891 
892 	// jack activate
893 	atomic_init(&handle->kill, 0);
894 	jack_activate(handle->client); //TODO check
895 
896 	bin_bundle_load(bin, bin->path);
897 	nsmc_opened(bin->nsm, 0);
898 
899 	return 0; // success
900 }
901 
902 __non_realtime static int
_save(void * data)903 _save(void *data)
904 {
905 	bin_t *bin = data;
906 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
907 
908 	handle->save_state = SAVE_STATE_NSM;
909 	bin_bundle_save(bin, bin->path);
910 	_saved(bin, 0);
911 
912 	return 0; // success
913 }
914 
915 __non_realtime static int
_show(void * data)916 _show(void *data)
917 {
918 	bin_t *bin = data;
919 
920 	return bin_show(bin);
921 }
922 
923 __non_realtime static int
_hide(void * data)924 _hide(void *data)
925 {
926 	bin_t *bin = data;
927 
928 	return bin_hide(bin);
929 }
930 
931 static const nsmc_driver_t nsm_driver = {
932 	.open = _open,
933 	.save = _save,
934 	.show = _show,
935 	.hide = _hide
936 };
937 
938 // rt
939 __realtime static double
_osc_schedule_osc2frames(LV2_OSC_Schedule_Handle instance,uint64_t timestamp)940 _osc_schedule_osc2frames(LV2_OSC_Schedule_Handle instance, uint64_t timestamp)
941 {
942 	prog_t *handle = instance;
943 
944 	if(timestamp == 1ULL)
945 		return 0; // inject at start of period
946 
947 	const uint64_t time_sec = timestamp >> 32;
948 	const uint64_t time_frac = timestamp & 0xffffffff;
949 
950 	const double diff = (time_sec - handle->cur_ntp.tv_sec)
951 		+ time_frac * 0x1p-32
952 		- handle->cur_ntp.tv_nsec * 1e-9;
953 
954 	const double frames = diff * handle->cycle.dT
955 		- handle->cycle.ref_frames
956 		+ handle->cycle.cur_frames;
957 
958 	return frames;
959 }
960 
961 // rt
962 __realtime static uint64_t
_osc_schedule_frames2osc(LV2_OSC_Schedule_Handle instance,double frames)963 _osc_schedule_frames2osc(LV2_OSC_Schedule_Handle instance, double frames)
964 {
965 	prog_t *handle = instance;
966 
967 	double diff = (frames - handle->cycle.cur_frames + handle->cycle.ref_frames)
968 		* handle->cycle.dTm1;
969 	diff += handle->cur_ntp.tv_nsec * 1e-9;
970 	diff += handle->cur_ntp.tv_sec;
971 
972 	double time_sec_d;
973 	double time_frac_d = modf(diff, &time_sec_d);
974 
975 	uint64_t time_sec = time_sec_d;
976 	uint64_t time_frac = time_frac_d * 0x1p32;
977 	if(time_frac >= 0x100000000ULL) // illegal overflow
978 		time_frac = 0xffffffffULL;
979 
980 	uint64_t timestamp = (time_sec << 32) | time_frac;
981 
982 	return timestamp;
983 }
984 
985 static void
_idle(void * data)986 _idle(void *data)
987 {
988 	prog_t *handle = data;
989 	bin_t *bin = &handle->bin;
990 
991 	jack_session_event_t *async = (void *)atomic_exchange(&handle->async, 0);
992 	if(!async)
993 		return;
994 
995 	//printf("_session_async: %s %s %s\n",
996 	//	async->session_dir, async->client_uuid, async->command_line);
997 
998 	char path [PATH_MAX];
999 	const char *resolvedpath = realpath(async->session_dir, path);
1000 	if(!resolvedpath)
1001 		resolvedpath = async->session_dir; // fall-back
1002 
1003 	// create command line
1004 	char *buf = NULL;
1005 	size_t sz = 0;
1006 	bool ignore = false;
1007 
1008 	for(int i=0; i<bin->optind; i++)
1009 	{
1010 		const char *arg = (i == 0)
1011 			? "synthpod_jack"
1012 			: bin->argv[i];
1013 
1014 		if(ignore)
1015 		{
1016 			ignore = false;
1017 			continue;
1018 		}
1019 
1020 		if(!strcmp(arg, "-u"))
1021 		{
1022 			ignore = true;
1023 			continue;
1024 		}
1025 
1026 		const size_t len = strlen(arg);
1027 		buf = realloc(buf, sz + len);
1028 
1029 		sprintf(&buf[sz], "%s ", arg);
1030 		sz += len + 1;
1031 	}
1032 
1033 	{
1034 		const size_t len = 32;
1035 		buf = realloc(buf, sz + len);
1036 
1037 		sprintf(&buf[sz], "-u %s ${SESSION_DIR}", async->client_uuid);
1038 	}
1039 
1040 	async->command_line = buf;
1041 	handle->session_event = async;
1042 
1043 	switch(async->type)
1044 	{
1045 		case JackSessionSaveAndQuit:
1046 			atomic_store_explicit(&handle->kill, 1, memory_order_relaxed); // quit after saving
1047 			// fall-through
1048 		case JackSessionSave:
1049 			handle->save_state = SAVE_STATE_JACK;
1050 			bin_bundle_save(bin, resolvedpath);
1051 			_saved(bin, 0);
1052 			break;
1053 		case JackSessionSaveTemplate:
1054 			handle->save_state = SAVE_STATE_JACK;
1055 			bin_bundle_new(bin);
1056 			bin_bundle_save(bin, resolvedpath);
1057 			_saved(bin, 0);
1058 			break;
1059 	}
1060 }
1061 
1062 int
main(int argc,char ** argv)1063 main(int argc, char **argv)
1064 {
1065 	mlockall(MCL_CURRENT | MCL_FUTURE);
1066 
1067 	static prog_t handle;
1068 	bin_t *bin = &handle.bin;
1069 
1070 	handle.server_name = NULL;
1071 	handle.session_id = NULL;
1072 	handle.seq_size = SEQ_SIZE;
1073 
1074 	bin->audio_prio = 70; // not used
1075 	bin->worker_prio = 60;
1076 	bin->num_slaves = sysconf(_SC_NPROCESSORS_ONLN) - 1;
1077 	bin->bad_plugins = false;
1078 	bin->has_gui = false;
1079 	bin->kill_gui = false;
1080 	snprintf(bin->socket_path, sizeof(bin->socket_path), "shm:///synthpod-%i", getpid());
1081 	bin->update_rate = 25;
1082 	bin->cpu_affinity = false;
1083 
1084 	fprintf(stderr,
1085 		"Synthpod "SYNTHPOD_VERSION"\n"
1086 		"Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)\n"
1087 		"Released under Artistic License 2.0 by Open Music Kontrollers\n");
1088 
1089 	int c;
1090 	while((c = getopt(argc, argv, "vhgGkKbBaAw:Wl:n:u:s:c:f:")) != -1)
1091 	{
1092 		switch(c)
1093 		{
1094 			case 'v':
1095 				fprintf(stderr,
1096 					"--------------------------------------------------------------------\n"
1097 					"This is free software: you can redistribute it and/or modify\n"
1098 					"it under the terms of the Artistic License 2.0 as published by\n"
1099 					"The Perl Foundation.\n"
1100 					"\n"
1101 					"This source is distributed in the hope that it will be useful,\n"
1102 					"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1103 					"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1104 					"Artistic License 2.0 for more details.\n"
1105 					"\n"
1106 					"You should have received a copy of the Artistic License 2.0\n"
1107 					"along the source as a COPYING file. If not, obtain it from\n"
1108 					"http://www.perlfoundation.org/artistic_license_2_0.\n\n");
1109 				return 0;
1110 			case 'h':
1111 				fprintf(stderr,
1112 					"--------------------------------------------------------------------\n"
1113 					"USAGE\n"
1114 					"   %s [OPTIONS] [BUNDLE_PATH]\n"
1115 					"\n"
1116 					"OPTIONS\n"
1117 					"   [-v]                 print version and full license information\n"
1118 					"   [-h]                 print usage information\n"
1119 					"   [-g]                 load GUI\n"
1120 					"   [-G]                 do NOT load GUI (default)\n"
1121 					"   [-k]                 kill DSP with GUI\n"
1122 					"   [-K]                 do NOT kill DSP with GUI (default)\n"
1123 					"   [-b]                 enable bad plugins\n"
1124 					"   [-B]                 disable bad plugins (default)\n"
1125 					"   [-a]                 enable CPU affinity\n"
1126 					"   [-A]                 disable CPU affinity (default)\n"
1127 					"   [-w] worker-priority worker thread realtime priority (60)\n"
1128 					"   [-W]                 do NOT use worker thread realtime priority\n"
1129 					"   [-l] link-path       socket link path (shm:///synthpod)\n"
1130 					"   [-n] server-name     connect to named JACK daemon\n"
1131 					"   [-u] client-uuid     client UUID for JACK session management\n"
1132 					"   [-s] sequence-size   minimum sequence size (8192)\n"
1133 					"   [-c] slave-cores     number of slave cores (auto)\n"
1134 					"   [-f] update-rate     GUI update rate (25)\n\n"
1135 					, argv[0]);
1136 				return 0;
1137 			case 'g':
1138 				bin->has_gui = true;
1139 				break;
1140 			case 'G':
1141 				bin->has_gui = false;
1142 				break;
1143 			case 'k':
1144 				bin->kill_gui = true;
1145 				break;
1146 			case 'K':
1147 				bin->kill_gui = false;
1148 				break;
1149 			case 'b':
1150 				bin->bad_plugins = true;
1151 				break;
1152 			case 'B':
1153 				bin->bad_plugins = false;
1154 				break;
1155 			case 'a':
1156 				bin->cpu_affinity = true;
1157 				break;
1158 			case 'A':
1159 				bin->cpu_affinity = false;
1160 				break;
1161 			case 'w':
1162 				bin->worker_prio = atoi(optarg);
1163 				break;
1164 			case 'W':
1165 				bin->worker_prio = 0;
1166 				break;
1167 			case 'l':
1168 				snprintf(bin->socket_path, sizeof(bin->socket_path), "%s", optarg);
1169 				break;
1170 			case 'n':
1171 				handle.server_name = optarg;
1172 				break;
1173 			case 'u':
1174 				handle.session_id = optarg;
1175 				break;
1176 			case 's':
1177 				handle.seq_size = MAX(SEQ_SIZE, atoi(optarg));
1178 				break;
1179 			case 'c':
1180 				if(atoi(optarg) < bin->num_slaves)
1181 					bin->num_slaves = atoi(optarg);
1182 				break;
1183 			case 'f':
1184 				bin->update_rate = atoi(optarg);
1185 				break;
1186 			case '?':
1187 				if(  (optopt == 'n') || (optopt == 'u') || (optopt == 's') || (optopt == 'c')
1188 					|| (optopt == 'l') || (optopt == 'f') )
1189 					fprintf(stderr, "Option `-%c' requires an argument.\n", optopt);
1190 				else if(isprint(optopt))
1191 					fprintf(stderr, "Unknown option `-%c'.\n", optopt);
1192 				else
1193 					fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
1194 				return -1;
1195 			default:
1196 				return -1;
1197 		}
1198 	}
1199 
1200 	atomic_init(&handle.async, 0);
1201 
1202 	bin_init(bin, 48000); //FIXME
1203 
1204 	LV2_URID_Map *map = bin->map;
1205 
1206 	lv2_atom_forge_init(&handle.forge, map);
1207 	lv2_osc_urid_init(&handle.osc_urid, map);
1208 
1209 	handle.midi_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
1210 
1211 	handle.time_position = map->map(map->handle, LV2_TIME__Position);
1212 	handle.time_barBeat = map->map(map->handle, LV2_TIME__barBeat);
1213 	handle.time_bar = map->map(map->handle, LV2_TIME__bar);
1214 	handle.time_beatUnit = map->map(map->handle, LV2_TIME__beatUnit);
1215 	handle.time_beatsPerBar = map->map(map->handle, LV2_TIME__beatsPerBar);
1216 	handle.time_beatsPerMinute = map->map(map->handle, LV2_TIME__beatsPerMinute);
1217 	handle.time_frame = map->map(map->handle, LV2_TIME__frame);
1218 	handle.time_framesPerSecond = map->map(map->handle, LV2_TIME__framesPerSecond);
1219 	handle.time_speed = map->map(map->handle, LV2_TIME__speed);
1220 
1221 	bin->app_driver.system_port_add = _system_port_add;
1222 	bin->app_driver.system_port_del = _system_port_del;
1223 
1224 	handle.osc_sched.osc2frames = _osc_schedule_osc2frames;
1225 	handle.osc_sched.frames2osc = _osc_schedule_frames2osc;
1226 	handle.osc_sched.handle = &handle;
1227 	bin->app_driver.osc_sched = &handle.osc_sched;
1228 
1229 	bin->app_driver.features = SP_APP_FEATURE_POWER_OF_2_BLOCK_LENGTH; // always true for JACK
1230 
1231 	// run
1232 	bin_run(bin, argv, &nsm_driver, _idle, &handle);
1233 
1234 	// stop
1235 	bin_stop(bin);
1236 
1237 	jack_session_event_t *async = (void *)atomic_load(&handle.async);
1238 	if(async)
1239 		jack_session_event_free(async);
1240 
1241 	// deinit JACK
1242 	_jack_deinit(&handle);
1243 
1244 	// deinit
1245 	bin_deinit(bin);
1246 
1247 	munlockall();
1248 
1249 	return 0;
1250 }
1251