1 /*
2  * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see http://www.gnu.org/licenses.
16  */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <ctype.h>
22 #include <math.h>
23 
24 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
25 #	include <pthread_np.h>
26 typedef cpuset_t cpu_set_t;
27 #endif
28 
29 #include <asoundlib.h>
30 #include <pcmi.h>
31 
32 #include <synthpod_bin.h>
33 
34 #define MIDI_SEQ_SIZE 2048
35 #define NANO_SECONDS 1000000000
36 
37 typedef enum _chan_type_t chan_type_t;
38 typedef struct _prog_t prog_t;
39 typedef struct _chan_t chan_t;
40 
41 enum _chan_type_t {
42 	CHAN_TYPE_PCMI,
43 	CHAN_TYPE_MIDI
44 };
45 
46 struct _chan_t {
47 	chan_type_t type;
48 
49 	union {
50 		struct {
51 			//TODO
52 		} audio;
53 		struct {
54 			int port;
55 			snd_midi_event_t *trans;
56 
57 			LV2_Atom_Forge forge;
58 			LV2_Atom_Forge_Frame frame;
59 			LV2_Atom_Forge_Ref ref;
60 			LV2_Atom_Sequence *seq_in;
61 			int64_t last;
62 		} midi;
63 	};
64 };
65 
66 struct _prog_t {
67 	bin_t bin;
68 
69 	LV2_Atom_Forge forge;
70 
71 	LV2_URID midi_MidiEvent;
72 
73 	pcmi_t *pcmi;
74 	snd_seq_t *seq;
75 	int queue;
76 	uint8_t m [MIDI_SEQ_SIZE];
77 
78 	save_state_t save_state;
79 	atomic_int kill;
80 	pthread_t thread;
81 
82 	uint32_t srate;
83 	uint32_t frsize;
84 	uint32_t nfrags;
85 	bool twochan;
86 	bool debug;
87 	bool do_play;
88 	bool do_capt;
89 	uint32_t seq_size;
90 
91 	const char *io_name;
92 	const char *play_name;
93 	const char *capt_name;
94 
95 	LV2_OSC_Schedule osc_sched;
96 	struct timespec cur_ntp;
97 	struct timespec nxt_ntp;
98 	struct {
99 		uint64_t cur_frames;
100 		uint64_t ref_frames;
101 		double dT;
102 		double dTm1;
103 	} cycle;
104 };
105 
106 static inline void
_ntp_now(cross_clock_t * clk,struct timespec * ntp)107 _ntp_now(cross_clock_t *clk, struct timespec *ntp)
108 {
109 	cross_clock_gettime(clk, ntp);
110 	ntp->tv_sec += JAN_1970; // convert NTP to OSC time
111 }
112 
113 static inline void
_ntp_clone(struct timespec * dst,struct timespec * src)114 _ntp_clone(struct timespec *dst, struct timespec *src)
115 {
116 	dst->tv_sec = src->tv_sec;
117 	dst->tv_nsec = src->tv_nsec;
118 }
119 
120 static inline void
_ntp_add_nanos(struct timespec * ntp,uint64_t nanos)121 _ntp_add_nanos(struct timespec *ntp, uint64_t nanos)
122 {
123 	ntp->tv_nsec += nanos;
124 	while(ntp->tv_nsec >= NANO_SECONDS) // has overflowed
125 	{
126 		ntp->tv_sec += 1;
127 		ntp->tv_nsec -= NANO_SECONDS;
128 	}
129 }
130 
131 static inline double
_ntp_diff(struct timespec * from,struct timespec * to)132 _ntp_diff(struct timespec *from, struct timespec *to)
133 {
134 	double diff = to->tv_sec;
135 	diff -= from->tv_sec;
136 	diff += 1e-9 * to->tv_nsec;
137 	diff -= 1e-9 * from->tv_nsec;
138 
139 	return diff;
140 }
141 
142 __realtime static inline void
_process(prog_t * handle)143 _process(prog_t *handle)
144 {
145 	pcmi_t *pcmi = handle->pcmi;
146 	bin_t *bin = &handle->bin;
147 	sp_app_t *app = bin->app;
148 
149 	const uint32_t nsamples = handle->frsize;
150 	int nplay = pcmi_nplay(pcmi);
151 	int ncapt = pcmi_ncapt(pcmi);
152 	int play_num;
153 	int capt_num;
154 
155 	const uint64_t nanos_per_period = (uint64_t)nsamples * NANO_SECONDS / handle->srate;
156 	handle->cycle.cur_frames = 0; // initialize frame counter
157 	_ntp_now(&bin->clk_real, &handle->nxt_ntp);
158 
159 	snd_seq_queue_status_t *stat = NULL;
160 	const snd_seq_real_time_t *real_time = NULL;
161 	snd_seq_real_time_t ref_time;
162 	snd_seq_queue_status_malloc(&stat);
163 
164 	pcmi_pcm_start(handle->pcmi);
165 	while(!atomic_load_explicit(&handle->kill, memory_order_relaxed))
166 	{
167 		uint32_t na = pcmi_pcm_wait(pcmi);
168 
169 		// current time is next time from last cycle
170 		_ntp_clone(&handle->cur_ntp, &handle->nxt_ntp);
171 
172 		// extrapolate new nxt_ntp
173 		struct timespec nxt_ntp;
174 		_ntp_now(&bin->clk_real, &nxt_ntp);
175 		_ntp_clone(&handle->nxt_ntp, &nxt_ntp);
176 
177 		// reset ref_frames
178 		handle->cycle.ref_frames = handle->cycle.cur_frames;
179 
180 		// calculate apparent period
181 		_ntp_add_nanos(&nxt_ntp, nanos_per_period);
182 		double diff = _ntp_diff(&handle->cur_ntp, &nxt_ntp);
183 
184 		// calculate apparent samples per period
185 		handle->cycle.dT = nsamples / diff;
186 		handle->cycle.dTm1 = 1.0 / handle->cycle.dT;
187 
188 		// get ALSA sequencer reference timestamp
189 		snd_seq_get_queue_status(handle->seq, handle->queue, stat);
190 		real_time = snd_seq_queue_status_get_real_time(stat);
191 		ref_time.tv_sec = real_time->tv_sec;
192 		ref_time.tv_nsec = real_time->tv_nsec;
193 
194 		uint32_t pos = 0;
195 		for( ; na >= nsamples;
196 				na -= nsamples,
197 				handle->cycle.ref_frames += nsamples,
198 				pos += nsamples,
199 				_ntp_add_nanos(&handle->nxt_ntp, nanos_per_period) )
200 		{
201 			const sp_app_system_source_t *sources = sp_app_get_system_sources(app);
202 
203 			if(sp_app_bypassed(app))
204 			{
205 				//const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app);
206 
207 				//fprintf(stderr, "app is bypassed\n");
208 
209 				pcmi_pcm_idle(pcmi, nsamples);
210 
211 				bin_process_pre(bin, nsamples, true);
212 				bin_process_post(bin);
213 
214 				continue;
215 			}
216 
217 			// fill input buffers
218 			if(ncapt)
219 				pcmi_capt_init(pcmi, nsamples);
220 			capt_num = 0;
221 			for(const sp_app_system_source_t *source=sources;
222 				source->type != SYSTEM_PORT_NONE;
223 				source++)
224 			{
225 				chan_t *chan = source->sys_port;
226 
227 				switch(source->type)
228 				{
229 					case SYSTEM_PORT_NONE:
230 					case SYSTEM_PORT_CONTROL:
231 					case SYSTEM_PORT_CV:
232 					case SYSTEM_PORT_OSC:
233 						break;
234 
235 					case SYSTEM_PORT_AUDIO:
236 					{
237 
238 						if(capt_num < ncapt)
239 							pcmi_capt_chan(pcmi, capt_num++, source->buf, nsamples);
240 
241 						break;
242 					}
243 
244 					case SYSTEM_PORT_MIDI:
245 					{
246 						void *seq_in = source->buf;
247 
248 						// initialize LV2 event port
249 						LV2_Atom_Forge *forge = &chan->midi.forge;
250 						chan->midi.seq_in = seq_in; // needed for lv2_atom_sequence_clear
251 						lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
252 						chan->midi.ref = lv2_atom_forge_sequence_head(forge, &chan->midi.frame, 0);
253 						chan->midi.last = 0;
254 
255 						break;
256 					}
257 
258 					case SYSTEM_PORT_COM:
259 					{
260 						void *seq_in = source->buf;
261 
262 						LV2_Atom_Forge *forge = &handle->forge;
263 						LV2_Atom_Forge_Frame frame;
264 						lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
265 						LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);
266 
267 						const LV2_Atom_Object *obj;
268 						size_t size;
269 						while((obj = varchunk_read_request(bin->app_from_com, &size)))
270 						{
271 							if(ref)
272 								ref = lv2_atom_forge_frame_time(forge, 0);
273 							if(ref)
274 								ref = lv2_atom_forge_write(forge, obj, size);
275 
276 							varchunk_read_advance(bin->app_from_com);
277 						}
278 						if(ref)
279 							lv2_atom_forge_pop(forge, &frame);
280 						else
281 							lv2_atom_sequence_clear(seq_in);
282 
283 						break;
284 					}
285 				}
286 			}
287 
288 			// read incoming MIDI and dispatch to corresponding MIDI port
289 			{
290 				snd_seq_event_t *sev;
291 				while(snd_seq_event_input_pending(handle->seq, 1) > 0)
292 				{
293 					chan_t *chan = NULL;
294 
295 					// get event
296 					snd_seq_event_input(handle->seq, &sev);
297 
298 					// search for matching port
299 					for(const sp_app_system_source_t *source=sources;
300 						source->type != SYSTEM_PORT_NONE;
301 						source++)
302 					{
303 						if(source->type == SYSTEM_PORT_MIDI)
304 						{
305 							chan_t *_chan = source->sys_port;
306 
307 							if(_chan->midi.port == sev->dest.port)
308 							{
309 								chan = _chan;
310 								break; // right port found, break out of loop
311 							}
312 						}
313 					}
314 
315 					if(chan)
316 					{
317 						long len;
318 						if((len = snd_midi_event_decode(chan->midi.trans, handle->m,
319 							MIDI_SEQ_SIZE, sev)) > 0)
320 						{
321 							LV2_Atom_Forge *forge = &chan->midi.forge;
322 
323 							const bool is_real = snd_seq_ev_is_real(sev);
324 							const bool is_abs = snd_seq_ev_is_abstime(sev);
325 							assert(is_real);
326 
327 							volatile double dd = sev->time.time.tv_sec;
328 							if(is_abs) // calculate relative time difference
329 								dd -= ref_time.tv_sec;
330 							dd += sev->time.time.tv_nsec * 1e-9;
331 							if(is_abs) // calculate relative time difference
332 								dd -= ref_time.tv_nsec * 1e-9;
333 
334 							int64_t frames = dd * handle->srate - pos;
335 							if(frames < 0)
336 								frames = 0;
337 							else if(frames >= nsamples)
338 								frames = nsamples - 1; //TODO report this
339 
340 							if(frames < chan->midi.last)
341 								frames = chan->midi.last; // frame time must be increasing
342 							else
343 								chan->midi.last = frames;
344 
345 							// fix up noteOn(vel=0) -> noteOff(vel=0)
346 							if(  (len == 3) && ( (handle->m[0] & 0xf0) == 0x90)
347 								&& (handle->m[2] == 0x0) )
348 							{
349 								handle->m[0] = 0x80 | (handle->m[0] & 0x0f);
350 								handle->m[2] = 0x0;
351 							}
352 
353 							if(chan->midi.ref)
354 								chan->midi.ref = lv2_atom_forge_frame_time(forge, frames);
355 							if(chan->midi.ref)
356 								chan->midi.ref = lv2_atom_forge_atom(forge, len, handle->midi_MidiEvent);
357 							if(chan->midi.ref)
358 								chan->midi.ref = lv2_atom_forge_write(forge, handle->m, len);
359 						}
360 						else
361 						{
362 							bin_log_trace(bin, "%s: MIDI event decode failed\n", __func__);
363 						}
364 					}
365 					else
366 					{
367 						bin_log_trace(bin, "%s: no matching port for MIDI event\n", __func__);
368 					}
369 
370 					if(snd_seq_free_event(sev))
371 					{
372 						bin_log_trace(bin, "%s: MIDI event free failed\n", __func__);
373 					}
374 				}
375 			}
376 
377 			for(const sp_app_system_source_t *source=sources;
378 				source->type != SYSTEM_PORT_NONE;
379 				source++)
380 			{
381 				chan_t *chan = source->sys_port;
382 
383 				if(source->type == SYSTEM_PORT_MIDI)
384 				{
385 					LV2_Atom_Forge *forge = &chan->midi.forge;
386 
387 					// finalize LV2 event port
388 					if(chan->midi.ref)
389 						lv2_atom_forge_pop(forge, &chan->midi.frame);
390 					else
391 						lv2_atom_sequence_clear(chan->midi.seq_in);
392 				}
393 			}
394 			if(ncapt)
395 				pcmi_capt_done(pcmi, nsamples);
396 
397 			bin_process_pre(bin, nsamples, false);
398 
399 			const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app);
400 
401 			// fill output buffers
402 			if(nplay)
403 				pcmi_play_init(pcmi, nsamples);
404 			play_num = 0;
405 			for(const sp_app_system_sink_t *sink=sinks;
406 				sink->type != SYSTEM_PORT_NONE;
407 				sink++)
408 			{
409 				chan_t *chan = sink->sys_port;
410 
411 				switch(sink->type)
412 				{
413 					case SYSTEM_PORT_NONE:
414 					case SYSTEM_PORT_CONTROL:
415 					case SYSTEM_PORT_CV:
416 					case SYSTEM_PORT_OSC:
417 						break;
418 
419 					case SYSTEM_PORT_AUDIO:
420 					{
421 
422 						if(play_num < nplay)
423 							pcmi_play_chan(pcmi, play_num++, sink->buf, nsamples);
424 
425 						break;
426 					}
427 
428 					case SYSTEM_PORT_MIDI:
429 					{
430 						const LV2_Atom_Sequence *seq_out = sink->buf;
431 
432 						LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
433 						{
434 							const LV2_Atom *atom = &ev->body;
435 
436 							if(atom->type != handle->midi_MidiEvent)
437 								continue; // ignore non-MIDI events
438 
439 							snd_seq_event_t sev;
440 							snd_seq_ev_clear(&sev);
441 							long consumed;
442 							const uint8_t *buf = LV2_ATOM_BODY_CONST(atom);
443 							if( (consumed = snd_midi_event_encode(chan->midi.trans, buf, atom->size, &sev)) != atom->size)
444 							{
445 								bin_log_trace(bin, "%s: MIDI encode event failed: %li\n", __func__, consumed);
446 								continue;
447 							}
448 
449 							// absolute timestamp
450 							volatile double dd = (double)(ev->time.frames + pos) / handle->srate;
451 							double sec;
452 							double nsec = modf(dd, &sec);
453 							struct snd_seq_real_time rtime = {
454 								.tv_sec = ref_time.tv_sec + sec,
455 								.tv_nsec = ref_time.tv_nsec + nsec
456 							};
457 							while(rtime.tv_nsec >= NANO_SECONDS) // handle overflow
458 							{
459 								rtime.tv_sec += 1;
460 								rtime.tv_nsec -= NANO_SECONDS;
461 							}
462 
463 							// schedule midi
464 							snd_seq_ev_set_source(&sev, chan->midi.port);
465 							snd_seq_ev_set_subs(&sev); // set broadcasting to subscribers
466 							snd_seq_ev_schedule_real(&sev, handle->queue, 0, &rtime); // absolute scheduling
467 							snd_seq_event_output(handle->seq, &sev);
468 							//snd_seq_drain_output(handle->seq);
469 						}
470 
471 						break;
472 					}
473 
474 					case SYSTEM_PORT_COM:
475 					{
476 						const LV2_Atom_Sequence *seq_out = sink->buf;
477 
478 						LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
479 						{
480 							const LV2_Atom *atom = &ev->body;
481 
482 							// try do process events directly
483 							bin->advance_ui = sp_app_from_ui(bin->app, atom);
484 							if(!bin->advance_ui) // queue event in ringbuffer instead
485 							{
486 								//fprintf(stderr, "plugin ui direct is blocked\n");
487 
488 								void *ptr;
489 								size_t size = lv2_atom_total_size(atom);
490 								if((ptr = varchunk_write_request(bin->app_from_app, size)))
491 								{
492 									memcpy(ptr, atom, size);
493 									varchunk_write_advance(bin->app_from_app, size);
494 								}
495 								else
496 								{
497 									bin_log_trace(bin, "%s: app_from_app ringbuffer full\n", __func__);
498 									//FIXME
499 								}
500 							}
501 						}
502 						break;
503 					}
504 				}
505 			}
506 			snd_seq_drain_output(handle->seq); //TODO is this rt-safe?
507 
508 			// clear unused output channels
509 			while(play_num<nplay)
510 			{
511 				pcmi_clear_chan(pcmi, play_num++, nsamples);
512 			}
513 
514 			if(nplay)
515 				pcmi_play_done(pcmi, nsamples);
516 
517 			bin_process_post(bin);
518 		}
519 
520 		// increase cur_frames
521 		handle->cycle.cur_frames = handle->cycle.ref_frames;
522 		//sched_yield();
523 	}
524 	pcmi_pcm_stop(handle->pcmi);
525 
526 	snd_seq_queue_status_free(stat);
527 }
528 
529 __non_realtime static void *
_rt_thread(void * data)530 _rt_thread(void *data)
531 {
532 	prog_t *handle = data;
533 	bin_t *bin = &handle->bin;
534 
535 	bin->dsp_thread = pthread_self();
536 
537 	if(handle->bin.audio_prio)
538 	{
539 		struct sched_param schedp;
540 		memset(&schedp, 0, sizeof(struct sched_param));
541 		schedp.sched_priority = handle->bin.audio_prio;
542 
543 		if(schedp.sched_priority)
544 		{
545 			if(pthread_setschedparam(bin->dsp_thread, SCHED_FIFO, &schedp))
546 				bin_log_error(bin, "%s: pthread_setschedparam failed\n", __func__);
547 		}
548 	}
549 
550 	if(handle->bin.cpu_affinity)
551 	{
552 		cpu_set_t cpuset;
553 		CPU_ZERO(&cpuset);
554 		CPU_SET(0, &cpuset);
555 		if(pthread_setaffinity_np(bin->dsp_thread, sizeof(cpu_set_t), &cpuset))
556 			bin_log_error(bin, "%s: pthread_setaffinity_np failed\n", __func__);
557 	}
558 
559 	_process(handle);
560 
561 	return NULL;
562 }
563 
564 __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)565 _system_port_add(void *data, system_port_t type, const char *short_name,
566 	const char *pretty_name, const char *designation, bool input, uint32_t order)
567 {
568 	bin_t *bin = data;
569 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
570 
571 	chan_t *chan = NULL;
572 
573 	switch(type)
574 	{
575 		case SYSTEM_PORT_NONE:
576 		{
577 			// skip
578 			break;
579 		}
580 
581 		case SYSTEM_PORT_CONTROL:
582 		{
583 			// unsupported, skip
584 			break;
585 		}
586 
587 		case SYSTEM_PORT_AUDIO:
588 		{
589 			chan = calloc(1, sizeof(chan_t));
590 			if(chan)
591 			{
592 				chan->type = CHAN_TYPE_PCMI;
593 				//TODO
594 			}
595 
596 			break;
597 		}
598 		case SYSTEM_PORT_CV:
599 		{
600 			// unsupported, skip
601 			break;
602 		}
603 
604 		case SYSTEM_PORT_MIDI:
605 		{
606 			chan = calloc(1, sizeof(chan_t));
607 			if(chan)
608 			{
609 				chan->type = CHAN_TYPE_MIDI;
610 				memcpy(&chan->midi.forge, &handle->forge, sizeof(LV2_Atom_Forge)); // initialize forge
611 
612 				snd_seq_port_info_t *pinfo;
613 				snd_seq_port_info_malloc(&pinfo);
614 
615 				snd_seq_port_info_set_name(pinfo, short_name);
616 				snd_seq_port_info_set_capability(pinfo, input
617 					? SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE
618 					: SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ);
619 				snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
620 				snd_seq_port_info_set_midi_channels(pinfo, 16);
621 				snd_seq_port_info_set_midi_voices(pinfo, 64);
622 				snd_seq_port_info_set_synth_voices(pinfo, 0);
623 				snd_seq_port_info_set_timestamping(pinfo, 1);
624 				snd_seq_port_info_set_timestamp_real(pinfo, 1);
625 				snd_seq_port_info_set_timestamp_queue(pinfo, handle->queue);
626 
627 				snd_seq_create_port(handle->seq, pinfo);
628 				chan->midi.port = snd_seq_port_info_get_port(pinfo);
629 				if(chan->midi.port < 0)
630 					bin_log_error(bin, "%s: could not create MIDI port\n", __func__);
631 
632 				snd_seq_port_info_free(pinfo);
633 
634 				if(snd_midi_event_new(MIDI_SEQ_SIZE, &chan->midi.trans))
635 					bin_log_error(bin, "%s: could not create MIDI event translator\n", __func__);
636 				snd_midi_event_init(chan->midi.trans);
637 				if(input)
638 					snd_midi_event_reset_encode(chan->midi.trans);
639 				else
640 					snd_midi_event_reset_decode(chan->midi.trans);
641 				snd_midi_event_no_status(chan->midi.trans, 1);
642 			}
643 
644 			break;
645 		}
646 		case SYSTEM_PORT_OSC:
647 		{
648 			// unsupported, skip
649 			break;
650 		}
651 		case SYSTEM_PORT_COM:
652 		{
653 			// unsupported, skip
654 			break;
655 		}
656 	}
657 
658 	return chan;
659 }
660 
661 __non_realtime static void
_system_port_del(void * data,void * sys_port)662 _system_port_del(void *data, void *sys_port)
663 {
664 	bin_t *bin = data;
665 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
666 
667 	chan_t *chan = sys_port;
668 
669 	if(!chan)
670 		return;
671 
672 	switch(chan->type)
673 	{
674 		case CHAN_TYPE_PCMI:
675 		{
676 			//TODO
677 
678 			break;
679 		}
680 		case CHAN_TYPE_MIDI:
681 		{
682 			snd_midi_event_free(chan->midi.trans);
683 			if(handle->seq)
684 				snd_seq_delete_simple_port(handle->seq, chan->midi.port);
685 
686 			break;
687 		}
688 	}
689 
690 	free(chan);
691 }
692 
693 __non_realtime static void
_saved(bin_t * bin,int status)694 _saved(bin_t *bin, int status)
695 {
696 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
697 
698 	if(handle->save_state == SAVE_STATE_NSM)
699 	{
700 		nsmc_saved(bin->nsm, status);
701 	}
702 	handle->save_state = SAVE_STATE_INTERNAL;
703 
704 	if(atomic_load_explicit(&handle->kill, memory_order_relaxed))
705 	{
706 		bin_quit(bin);
707 	}
708 }
709 
710 static int
_alsa_init(prog_t * handle,const char * id)711 _alsa_init(prog_t *handle, const char *id)
712 {
713 	bin_t *bin = &handle->bin;
714 
715 	// init alsa sequencer
716 	if(snd_seq_open(&handle->seq, "hw", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK))
717 		bin_log_error(bin, "%s: could not open sequencer\n", __func__);
718 	if(snd_seq_set_client_name(handle->seq, id))
719 		bin_log_error(bin, "%s: could not set name\n", __func__);
720 	handle->queue = snd_seq_alloc_queue(handle->seq);
721 	if(handle->queue < 0)
722 		bin_log_error(bin, "%s: could not allocate queue\n", __func__);
723 	snd_seq_start_queue(handle->seq, handle->queue, NULL);
724 
725 	// init alsa pcm
726 	handle->pcmi = pcmi_new(handle->play_name, handle->capt_name,
727 		handle->srate, handle->frsize, handle->nfrags, handle->twochan, handle->debug);
728 	if(!handle->pcmi)
729 		return -1;
730 	pcmi_printinfo(handle->pcmi);
731 
732 	return 0;
733 }
734 
735 static void
_alsa_deinit(prog_t * handle)736 _alsa_deinit(prog_t *handle)
737 {
738 	bin_t *bin = &handle->bin;
739 
740 	if(handle->thread)
741 	{
742 		atomic_store_explicit(&handle->kill, 1, memory_order_relaxed);
743 		pthread_join(handle->thread, NULL);
744 	}
745 
746 	if(handle->pcmi)
747 	{
748 		pcmi_free(handle->pcmi);
749 
750 		handle->pcmi = NULL;
751 	}
752 
753 	if(handle->seq)
754 	{
755 		if(snd_seq_drain_output(handle->seq))
756 			bin_log_error(bin, "%s: draining output failed\n", __func__);
757 		snd_seq_stop_queue(handle->seq, handle->queue, NULL);
758 		if(snd_seq_free_queue(handle->seq, handle->queue))
759 			bin_log_error(bin, "%s: freeing queue failed\n", __func__);
760 		if(snd_seq_close(handle->seq))
761 			bin_log_error(bin, "%s: close sequencer failed\n", __func__);
762 
763 		handle->seq = NULL;
764 		handle->queue = 0;
765 	}
766 }
767 
768 __non_realtime static int
_open(const char * path,const char * name,const char * id,void * data)769 _open(const char *path, const char *name, const char *id, void *data)
770 {
771 	bin_t *bin = data;
772 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
773 	(void)name;
774 
775 	if(bin->path)
776 		free(bin->path);
777 	bin->path = strdup(path);
778 
779 	// alsa init
780 	if(_alsa_init(handle, id))
781 	{
782 		nsmc_opened(bin->nsm, -1);
783 		return -1;
784 	}
785 
786 	// synthpod init
787 	bin->app_driver.sample_rate = handle->srate;
788 	bin->app_driver.update_rate = handle->bin.update_rate;
789 	bin->app_driver.max_block_size = handle->frsize;
790 	bin->app_driver.min_block_size = 1;
791 	bin->app_driver.seq_size = handle->seq_size;
792 	bin->app_driver.num_periods = handle->nfrags;
793 
794 	// app init
795 	bin->app = sp_app_new(NULL, &bin->app_driver, bin);
796 
797 	// alsa activate
798 	atomic_init(&handle->kill, 0);
799 	if(pthread_create(&handle->thread, NULL, _rt_thread, handle))
800 		bin_log_error(bin, "%s: creation of realtime thread failed\n", __func__);
801 
802 	bin_bundle_load(bin, bin->path);
803 	nsmc_opened(bin->nsm, 0);
804 
805 	return 0; // success
806 }
807 
808 __non_realtime static int
_save(void * data)809 _save(void *data)
810 {
811 	bin_t *bin = data;
812 	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
813 
814 	handle->save_state = SAVE_STATE_NSM;
815 	bin_bundle_save(bin, bin->path);
816 	_saved(bin, 0);
817 
818 	return 0; // success
819 }
820 
821 __non_realtime static int
_show(void * data)822 _show(void *data)
823 {
824 	bin_t *bin = data;
825 
826 	return bin_show(bin);
827 }
828 
829 __non_realtime static int
_hide(void * data)830 _hide(void *data)
831 {
832 	bin_t *bin = data;
833 
834 	return bin_hide(bin);
835 }
836 
837 static const nsmc_driver_t nsm_driver = {
838 	.open = _open,
839 	.save = _save,
840 	.show = _show,
841 	.hide = _hide
842 };
843 
844 // rt
845 __realtime static double
_osc_schedule_osc2frames(LV2_OSC_Schedule_Handle instance,uint64_t timestamp)846 _osc_schedule_osc2frames(LV2_OSC_Schedule_Handle instance, uint64_t timestamp)
847 {
848 	prog_t *handle = instance;
849 
850 	if(timestamp == 1ULL)
851 		return 0; // inject at start of period
852 
853 	const uint64_t time_sec = timestamp >> 32;
854 	const uint64_t time_frac = timestamp & 0xffffffff;
855 
856 	const double diff = (time_sec - handle->cur_ntp.tv_sec)
857 		+ time_frac * 0x1p-32
858 		- handle->cur_ntp.tv_nsec * 1e-9;
859 
860 	const double frames = diff * handle->cycle.dT
861 		- handle->cycle.ref_frames
862 		+ handle->cycle.cur_frames;
863 
864 	return frames;
865 }
866 
867 // rt
868 __realtime static uint64_t
_osc_schedule_frames2osc(LV2_OSC_Schedule_Handle instance,double frames)869 _osc_schedule_frames2osc(LV2_OSC_Schedule_Handle instance, double frames)
870 {
871 	prog_t *handle = instance;
872 
873 	double diff = (frames - handle->cycle.cur_frames + handle->cycle.ref_frames)
874 		* handle->cycle.dTm1;
875 	diff += handle->cur_ntp.tv_nsec * 1e-9;
876 	diff += handle->cur_ntp.tv_sec;
877 
878 	double time_sec_d;
879 	double time_frac_d = modf(diff, &time_sec_d);
880 
881 	uint64_t time_sec = time_sec_d;
882 	uint64_t time_frac = time_frac_d * 0x1p32;
883 	if(time_frac >= 0x100000000ULL) // illegal overflow
884 		time_frac = 0xffffffffULL;
885 
886 	uint64_t timestamp = (time_sec << 32) | time_frac;
887 
888 	return timestamp;
889 }
890 
891 int
main(int argc,char ** argv)892 main(int argc, char **argv)
893 {
894 	mlockall(MCL_CURRENT | MCL_FUTURE);
895 
896 	static prog_t handle;
897 	bin_t *bin = &handle.bin;
898 
899 	handle.srate = 48000;
900 	handle.frsize = 1024;
901 	handle.nfrags = 3;
902 	handle.twochan = false;
903 	handle.debug = false;
904 	handle.do_play = true;
905 	handle.do_capt = true;
906 	handle.seq_size = SEQ_SIZE;
907 
908 	const char *def = "hw:0";
909 	handle.io_name = def;
910 	handle.play_name = NULL;
911 	handle.capt_name = NULL;
912 
913 	bin->audio_prio = 70;
914 	bin->worker_prio = 60;
915 	bin->num_slaves = sysconf(_SC_NPROCESSORS_ONLN) - 1;
916 	bin->bad_plugins = false;
917 	bin->has_gui = false;
918 	bin->kill_gui = false;
919 	snprintf(bin->socket_path, sizeof(bin->socket_path), "shm:///synthpod-%i", getpid());
920 	bin->update_rate = 25;
921 	bin->cpu_affinity = false;
922 
923 	fprintf(stderr,
924 		"Synthpod "SYNTHPOD_VERSION"\n"
925 		"Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)\n"
926 		"Released under GNU General Public License 3 by Open Music Kontrollers\n");
927 
928 	// read local configuration if present
929 	/*FIXME
930 	Efreet_Ini *ini = _read_config(&handle);
931 	*/
932 
933 	int c;
934 	while((c = getopt(argc, argv, "vhgGbkKBaAIOtTxXy:Yw:Wl:d:i:o:r:p:n:s:c:f:")) != -1)
935 	{
936 		switch(c)
937 		{
938 			case 'v':
939 				fprintf(stderr,
940 					"--------------------------------------------------------------------\n"
941 					"This program is free software; you can redistribute it and/or modify\n"
942 					"it under the terms of the GNU General Public License as published by\n"
943 					"the Free Software Foundation; either version 3 of the License, or\n"
944 					"(at your option) any later version.\n"
945 					"\n"
946 					"This program is distributed in the hope that it will be useful,\n"
947 					"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
948 					"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
949 					"GNU General Public License for more details.\n"
950 					"\n"
951 					"You should have received a copy of the GNU General Public License\n"
952 					"along with this program.  If not, see http://www.gnu.org/licenses.\n\n");
953 				return 0;
954 			case 'h':
955 				fprintf(stderr,
956 					"--------------------------------------------------------------------\n"
957 					"USAGE\n"
958 					"   %s [OPTIONS] [BUNDLE_PATH]\n"
959 					"\n"
960 					"OPTIONS\n"
961 					"   [-v]                 print version and full license information\n"
962 					"   [-h]                 print usage information\n"
963 					"   [-g]                 load GUI\n"
964 					"   [-G]                 do NOT load GUI (default)\n"
965 					"   [-k]                 kill DSP with GUI\n"
966 					"   [-K]                 do NOT kill DSP with GUI (default)\n"
967 					"   [-b]                 enable bad plugins\n"
968 					"   [-B]                 disable bad plugins (default)\n"
969 					"   [-a]                 enable CPU affinity\n"
970 					"   [-A]                 disable CPU affinity (default)\n"
971 					"   [-I]                 disable capture\n"
972 					"   [-O]                 disable playback\n"
973 					"   [-t]                 force 2 channel mode\n"
974 					"   [-T]                 do NOT force 2 channel mode (default)\n"
975 					"   [-x]                 notify about XRuns\n"
976 					"   [-X]                 do NOT notify about XRuns (default)\n"
977 					"   [-y] audio-priority  audio thread realtime priority (70)\n"
978 					"   [-Y]                 do NOT use audio thread realtime priority\n"
979 					"   [-w] worker-priority worker thread realtime priority (60)\n"
980 					"   [-W]                 do NOT use worker thread realtime priority\n"
981 					"   [-l] link-path       socket link path (shm:///synthpod)\n"
982 					"   [-d] device          capture/playback device (\"hw:0\")\n"
983 					"   [-i] capture-device  capture device (\"hw:0\")\n"
984 					"   [-o] playback-device playback device (\"hw:0\")\n"
985 					"   [-r] sample-rate     sample rate (48000)\n"
986 					"   [-p] sample-period   frames per period (1024)\n"
987 					"   [-n] period-number   number of periods of playback latency (3)\n"
988 					"   [-s] sequence-size   minimum sequence size (8192)\n"
989 					"   [-c] slave-cores     number of slave cores (auto)\n"
990 					"   [-f] update-rate     GUI update rate (25)\n\n"
991 					, argv[0]);
992 				return 0;
993 			case 'g':
994 				bin->has_gui = true;
995 				break;
996 			case 'G':
997 				bin->has_gui = false;
998 				break;
999 			case 'k':
1000 				bin->kill_gui = true;
1001 				break;
1002 			case 'K':
1003 				bin->kill_gui = false;
1004 				break;
1005 			case 'b':
1006 				bin->bad_plugins = true;
1007 				break;
1008 			case 'B':
1009 				bin->bad_plugins = false;
1010 				break;
1011 			case 'a':
1012 				bin->cpu_affinity = true;
1013 				break;
1014 			case 'A':
1015 				bin->cpu_affinity = false;
1016 				break;
1017 			case 'I':
1018 				handle.do_capt = false;
1019 				break;
1020 			case 'O':
1021 				handle.do_play = false;
1022 				break;
1023 			case 't':
1024 				handle.twochan = true;
1025 				break;
1026 			case 'T':
1027 				handle.twochan = false;
1028 				break;
1029 			case 'x':
1030 				handle.debug = true;
1031 				break;
1032 			case 'X':
1033 				handle.debug = false;
1034 				break;
1035 			case 'y':
1036 				bin->audio_prio = atoi(optarg);
1037 				break;
1038 			case 'Y':
1039 				bin->audio_prio = 0;
1040 				break;
1041 			case 'w':
1042 				bin->worker_prio = atoi(optarg);
1043 				break;
1044 			case 'W':
1045 				bin->worker_prio = 0;
1046 				break;
1047 			case 'l':
1048 				snprintf(bin->socket_path, sizeof(bin->socket_path), "%s", optarg);
1049 				break;
1050 			case 'd':
1051 				handle.do_capt = optarg != NULL;
1052 				handle.do_play = optarg != NULL;
1053 				handle.io_name = optarg;
1054 				break;
1055 			case 'i':
1056 				handle.do_capt = optarg != NULL;
1057 				handle.capt_name = optarg;
1058 				break;
1059 			case 'o':
1060 				handle.do_play = optarg != NULL;
1061 				handle.play_name = optarg;
1062 				break;
1063 			case 'r':
1064 				handle.srate = atoi(optarg);
1065 				break;
1066 			case 'p':
1067 				handle.frsize = atoi(optarg);
1068 				break;
1069 			case 'n':
1070 				handle.nfrags = atoi(optarg);
1071 				break;
1072 			case 's':
1073 				handle.seq_size = MAX(SEQ_SIZE, atoi(optarg));
1074 				break;
1075 			case 'c':
1076 				if(atoi(optarg) < bin->num_slaves)
1077 					bin->num_slaves = atoi(optarg);
1078 				break;
1079 			case 'f':
1080 				bin->update_rate = atoi(optarg);
1081 				break;
1082 			case '?':
1083 				if( (optopt == 'd') || (optopt == 'i') || (optopt == 'o') || (optopt == 'r')
1084 					|| (optopt == 'p') || (optopt == 'n') || (optopt == 's') || (optopt == 'c')
1085 					|| (optopt == 'l') || (optopt == 'f') )
1086 					fprintf(stderr, "Option `-%c' requires an argument.\n", optopt);
1087 				else if(isprint(optopt))
1088 					fprintf(stderr, "Unknown option `-%c'.\n", optopt);
1089 				else
1090 					fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
1091 				return -1;
1092 			default:
1093 				return -1;
1094 		}
1095 	}
1096 
1097 	if(!handle.capt_name && handle.do_capt)
1098 		handle.capt_name = handle.io_name;
1099 	if(!handle.play_name && handle.do_play)
1100 		handle.play_name = handle.io_name;
1101 
1102 	bin_init(bin, handle.srate);
1103 
1104 	LV2_URID_Map *map = bin->map;
1105 
1106 	lv2_atom_forge_init(&handle.forge, map);
1107 
1108 	handle.midi_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
1109 
1110 	bin->app_driver.system_port_add = _system_port_add;
1111 	bin->app_driver.system_port_del = _system_port_del;
1112 
1113 	handle.osc_sched.osc2frames = _osc_schedule_osc2frames;
1114 	handle.osc_sched.frames2osc = _osc_schedule_frames2osc;
1115 	handle.osc_sched.handle = &handle;
1116 	bin->app_driver.osc_sched = &handle.osc_sched;
1117 	bin->app_driver.features = SP_APP_FEATURE_FIXED_BLOCK_LENGTH; // always true for ALSA
1118   if(handle.frsize && !(handle.frsize & (handle.frsize - 1))) // check for powerOf2
1119 		bin->app_driver.features |= SP_APP_FEATURE_POWER_OF_2_BLOCK_LENGTH;
1120 
1121 	// run
1122 	bin_run(bin, argv, &nsm_driver, NULL, NULL);
1123 
1124 	// stop
1125 	bin_stop(bin);
1126 
1127 	// deinit alsa
1128 	_alsa_deinit(&handle);
1129 
1130 	// deinit
1131 	bin_deinit(bin);
1132 
1133 	/*FIXME
1134 	if(ini)
1135 		efreet_ini_free(ini);
1136 	*/
1137 
1138 	munlockall();
1139 
1140 	return 0;
1141 }
1142