1 /*
2 * Copyright (C) 2004 2005 2006 2008 2009 2011 2012, Magnus Hjorth
3 *
4 * This file is part of mhWaveEdit.
5 *
6 * mhWaveEdit is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * mhWaveEdit is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with mhWaveEdit; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21
22 /* JACK sound driver */
23
24 #include <jack/jack.h>
25 #include <jack/ringbuffer.h>
26
27 #include "int_box.h"
28 #include "gettext.h"
29
30 /* All variables/functions prefixed with mhjack_ since the jack library
31 * already uses the jack_ prefix */
32
33 #define MHJACK_PLAY 0x80000000
34 #define MHJACK_STOP 0x40000000
35 #define MHJACK_REC 0x20000000
36 #define MHJACK_SKIPREQ(x) (((x) >> 24) & 15)
37 #define MHJACK_SKIPPOS(x) ((x) & 0xFFFFFF)
38 #define MHJACK_NEWSKIP(x,p) (((x) & 0xF0000000) | (((x) + 0x01000000) & 0x0F000000) | (p))
39
40 static struct {
41 gchar *client_name;
42 jack_client_t *myself;
43 gboolean is_activated,autoconnect_input,autoconnect_output;
44 guint maxoutports, maxinports;
45 gchar *inportnames[8],*outportnames[8];
46 jack_port_t *inports[8],*outports[8];
47 volatile guint32 procctrl;
48 volatile unsigned int xrun_count;
49 volatile off_t played_bytes;
50 int cb_skipcount;
51 Dataformat current_format;
52 size_t buffer_size;
53 jack_ringbuffer_t *buffers[8];
54 gboolean refill;
55 guint refillframes, refillpos;
56 } mhjack = { 0 };
57
58 struct mhjack_prefdlg {
59 GtkWindow *wnd;
60 GtkEntry *client_name;
61 struct {
62 Intbox *maxports;
63 GtkEntry *portnames[8];
64 GtkToggleButton *autoconnect;
65 } ports[2];
66 };
67
68 /* static int dumpfile; */
69
70 static void mhjack_register_ports(void);
71
mhjack_read_config(void)72 static void mhjack_read_config(void)
73 {
74 guint i;
75 gchar *c,*d;
76
77 if (mhjack.client_name != NULL) return;
78
79 /* Read config from inifile */
80 mhjack.client_name = g_strdup(inifile_get("jackClientName","mhwe"));
81 mhjack.maxoutports = (guint)inifile_get_guint32("jackMaxportsOut",2);
82 if (mhjack.maxoutports < 0 || mhjack.maxoutports > 8)
83 mhjack.maxoutports = 2;
84 mhjack.maxinports = (guint)inifile_get_guint32("jackMaxportsIn",2);
85 if (mhjack.maxinports < 0 || mhjack.maxinports > 8)
86 mhjack.maxinports = 2;
87 for (i=0; i<8; i++) {
88 c = g_strdup_printf("jackOutport%d",i+1);
89 d = inifile_get(c,NULL);
90 if (d != NULL) d = g_strdup(d);
91 else d = g_strdup_printf("out%c",channel_char(i));
92 mhjack.outportnames[i] = d;
93 g_free(c);
94 c = g_strdup_printf("jackInport%d",i+1);
95 d = inifile_get(c,NULL);
96 if (d != NULL) d = g_strdup(d);
97 else d = g_strdup_printf("in%c",channel_char(i));
98 mhjack.inportnames[i] = d;
99 g_free(c);
100 }
101 mhjack.autoconnect_input = inifile_get_gboolean("jackAutoconnectInput",
102 TRUE);
103 mhjack.autoconnect_output = inifile_get_gboolean("jackAutoconnectOutput",
104 TRUE);
105 }
106
mhjack_preferences_ok(GtkButton * button,gpointer user_data)107 static void mhjack_preferences_ok(GtkButton *button, gpointer user_data)
108 {
109 struct mhjack_prefdlg *dlg = (struct mhjack_prefdlg *)user_data;
110 const gchar *c;
111 guint i;
112 gchar buf[32];
113 /* Validate input */
114 if (intbox_check(dlg->ports[0].maxports) ||
115 intbox_check(dlg->ports[1].maxports)) return;
116 if (dlg->ports[0].maxports->val > 8 || dlg->ports[0].maxports->val < 0) {
117 user_error(_("Invalid number of input ports."));
118 return;
119 }
120 if (dlg->ports[1].maxports->val > 8 || dlg->ports[1].maxports->val < 0) {
121 user_error(_("Invalid number of output ports."));
122 return;
123 }
124 /* Apply settings */
125 c = gtk_entry_get_text(dlg->client_name);
126 if (mhjack.myself != NULL && strcmp(c, mhjack.client_name)) {
127 g_free(mhjack.client_name);
128 mhjack.client_name = g_strdup(c);
129 inifile_set("jackClientName",(gchar *)c);
130 user_info(_("The client name change won't take effect until you "
131 "restart the program."));
132 }
133 mhjack.maxinports = (guint)dlg->ports[0].maxports->val;
134 inifile_set_guint32("jackMaxportsIn",mhjack.maxinports);
135 mhjack.maxoutports = (guint)dlg->ports[1].maxports->val;
136 inifile_set_guint32("jackMaxportsOut",mhjack.maxoutports);
137 for (i=0; i<8; i++) {
138 g_free(mhjack.inportnames[i]);
139 mhjack.inportnames[i] =
140 g_strdup(gtk_entry_get_text(dlg->ports[0].portnames[i]));
141 g_snprintf(buf,sizeof(buf),"jackInport%d",i+1);
142 inifile_set(buf,mhjack.inportnames[i]);
143 if (mhjack.myself != NULL && mhjack.inports[i] != NULL) {
144 if (i<mhjack.maxinports) {
145 /* printf("jack_port_set_name #%d %s\n",i,
146 mhjack.inportnames[i]); */
147 jack_port_set_name(mhjack.inports[i],
148 mhjack.inportnames[i]);
149 } else {
150 /* printf("unregister inport #%d\n",i); */
151 jack_port_unregister(mhjack.myself,mhjack.inports[i]);
152 mhjack.inports[i] = NULL;
153 }
154 }
155 g_free(mhjack.outportnames[i]);
156 mhjack.outportnames[i] =
157 g_strdup(gtk_entry_get_text(dlg->ports[1].portnames[i]));
158 g_snprintf(buf,sizeof(buf),"jackOutport%d",i+1);
159 inifile_set(buf,mhjack.outportnames[i]);
160 if (mhjack.myself != NULL && mhjack.outports[i] != NULL) {
161 if (i<mhjack.maxoutports)
162 jack_port_set_name(mhjack.outports[i],
163 mhjack.outportnames[i]);
164 else {
165 jack_port_unregister(mhjack.myself,mhjack.outports[i]);
166 mhjack.outports[i] = NULL;
167 }
168 }
169 }
170 mhjack.autoconnect_input =
171 gtk_toggle_button_get_active(dlg->ports[0].autoconnect);
172 mhjack.autoconnect_output =
173 gtk_toggle_button_get_active(dlg->ports[1].autoconnect);
174 inifile_set_gboolean("jackAutoconnectInput",mhjack.autoconnect_input);
175 inifile_set_gboolean("jackAutoconnectOutput",mhjack.autoconnect_output);
176
177 if (mhjack.myself != NULL) mhjack_register_ports();
178
179 gtk_widget_destroy(GTK_WIDGET(dlg->wnd));
180 }
181
mhjack_preferences(void)182 static void mhjack_preferences(void)
183 {
184 GtkWidget *a,*b,*c,*d,*e,*f,*g;
185 struct mhjack_prefdlg *dlg;
186 gchar *titles[2] = {
187 N_(" Input ports "),
188 N_(" Output ports "),
189 };
190 guint i,j;
191 gchar buf[16];
192 mhjack_read_config();
193 dlg = g_malloc(sizeof(*dlg));
194 a = gtk_window_new(GTK_WINDOW_DIALOG);
195 dlg->wnd = GTK_WINDOW(a);
196 gtk_window_set_modal(GTK_WINDOW(a),TRUE);
197 gtk_window_set_title(GTK_WINDOW(a),_("Jack Preferences"));
198 gtk_window_set_position(GTK_WINDOW(a),GTK_WIN_POS_CENTER);
199 gtk_container_set_border_width(GTK_CONTAINER(a),8);
200 gtk_signal_connect_object(GTK_OBJECT(a),"destroy",GTK_SIGNAL_FUNC(g_free),
201 (GtkObject *)dlg);
202 b = gtk_vbox_new(FALSE,5);
203 gtk_container_add(GTK_CONTAINER(a),b);
204 c = gtk_hbox_new(FALSE,3);
205 gtk_box_pack_start(GTK_BOX(b),c,FALSE,FALSE,0);
206 d = gtk_label_new(_("Client name: "));
207 gtk_box_pack_start(GTK_BOX(c),d,FALSE,FALSE,0);
208 d = gtk_entry_new();
209 gtk_box_pack_start(GTK_BOX(c),d,FALSE,FALSE,0);
210 dlg->client_name = GTK_ENTRY(d);
211 gtk_entry_set_max_length(dlg->client_name, jack_client_name_size());
212 gtk_entry_set_text(dlg->client_name, mhjack.client_name);
213 c = gtk_hbox_new(TRUE,12);
214 gtk_box_pack_start(GTK_BOX(b),c,TRUE,TRUE,0);
215 for (i=0; i<2; i++) {
216 d = gtk_frame_new(_(titles[i]));
217 gtk_box_pack_start(GTK_BOX(c),d,TRUE,TRUE,0);
218 e = gtk_vbox_new(FALSE,4);
219 gtk_container_add(GTK_CONTAINER(d),e);
220 gtk_container_set_border_width(GTK_CONTAINER(e),6);
221 f = gtk_hbox_new(FALSE,0);
222 gtk_box_pack_start(GTK_BOX(e),f,TRUE,TRUE,0);
223 g = gtk_label_new(_("Number of ports (0-8): "));
224 gtk_box_pack_start(GTK_BOX(f),g,FALSE,FALSE,0);
225 g = intbox_new(i>0 ? mhjack.maxoutports : mhjack.maxinports);
226 gtk_box_pack_start(GTK_BOX(f),g,FALSE,FALSE,0);
227 dlg->ports[i].maxports = INTBOX(g);
228 f = gtk_table_new(8,2,FALSE);
229 gtk_box_pack_start(GTK_BOX(e),f,FALSE,FALSE,0);
230 for (j=0; j<8; j++) {
231 g_snprintf(buf,sizeof(buf),_("Port #%d"),j+1);
232 attach_label(buf,f,j,0);
233 g = gtk_entry_new();
234 gtk_table_attach(GTK_TABLE(f),g,1,2,j,j+1,GTK_EXPAND|GTK_FILL,0,
235 0,0);
236 dlg->ports[i].portnames[j] = GTK_ENTRY(g);
237 gtk_entry_set_max_length(GTK_ENTRY(g),jack_port_name_size());
238 gtk_entry_set_text(GTK_ENTRY(g),i>0 ? mhjack.outportnames[j] :
239 mhjack.inportnames[j]);
240 }
241 gtk_table_set_row_spacings(GTK_TABLE(f),2);
242 gtk_table_set_col_spacings(GTK_TABLE(f),2);
243 }
244 c = gtk_check_button_new_with_label(_("Automatically connect input "
245 "ports on startup"));
246 dlg->ports[0].autoconnect = GTK_TOGGLE_BUTTON(c);
247 gtk_toggle_button_set_active(dlg->ports[0].autoconnect,
248 mhjack.autoconnect_input);
249 gtk_box_pack_start(GTK_BOX(b),c,FALSE,FALSE,0);
250 c = gtk_check_button_new_with_label(_("Automatically connect output "
251 "ports on startup"));
252 dlg->ports[1].autoconnect = GTK_TOGGLE_BUTTON(c);
253 gtk_toggle_button_set_active(dlg->ports[1].autoconnect,
254 mhjack.autoconnect_output);
255 gtk_box_pack_start(GTK_BOX(b),c,FALSE,FALSE,0);
256
257
258 c = gtk_hbutton_box_new();
259 gtk_box_pack_end(GTK_BOX(b),c,FALSE,FALSE,0);
260 d = gtk_button_new_with_label(_("OK"));
261 gtk_signal_connect(GTK_OBJECT(d),"clicked",
262 GTK_SIGNAL_FUNC(mhjack_preferences_ok),dlg);
263 gtk_container_add(GTK_CONTAINER(c),d);
264 d = gtk_button_new_with_label(_("Close"));
265 gtk_signal_connect_object(GTK_OBJECT(d),"clicked",
266 GTK_SIGNAL_FUNC(gtk_widget_destroy),
267 GTK_OBJECT(a));
268 gtk_container_add(GTK_CONTAINER(c),d);
269 gtk_widget_show_all(a);
270 }
271
mhjack_register_ports(void)272 static void mhjack_register_ports(void)
273 {
274 guint i;
275
276 /* If jack_port_register fails, the NULL value will be stored in
277 * mhjack.in/outports, so we can check for this or re-register later. */
278 for (i=0; i < mhjack.maxinports; i++)
279 if (mhjack.inports[i] == NULL)
280 mhjack.inports[i] =
281 jack_port_register(mhjack.myself, mhjack.inportnames[i],
282 JACK_DEFAULT_AUDIO_TYPE,
283 JackPortIsInput|JackPortIsTerminal, 0);
284 for (i=0; i< mhjack.maxoutports; i++)
285 if (mhjack.outports[i] == NULL)
286 mhjack.outports[i] =
287 jack_port_register(mhjack.myself, mhjack.outportnames[i],
288 JACK_DEFAULT_AUDIO_TYPE,
289 JackPortIsOutput|JackPortIsTerminal, 0);
290
291 }
292
293
294 /* Makes sure the ring buffers are allocated and at least 4x the JACK buffer
295 * size and at least one second long. */
mhjack_setup_buffers(void)296 static int mhjack_setup_buffers(void)
297 {
298 jack_nframes_t nframes;
299 size_t sz;
300 guint i;
301
302 nframes = jack_get_buffer_size(mhjack.myself);
303 sz = 4 * nframes * sizeof(float);
304
305 if (sz < jack_get_sample_rate(mhjack.myself)*sizeof(float))
306 sz=jack_get_sample_rate(mhjack.myself)*sizeof(float);
307 for (i=0; i<MAX(mhjack.maxinports,mhjack.maxoutports); i++) {
308
309 /* Remove too small buffers */
310 if (mhjack.buffers[i] != NULL && sz > mhjack.buffer_size) {
311 jack_ringbuffer_free(mhjack.buffers[i]);
312 mhjack.buffers[i] = NULL;
313 }
314
315 /* Create new buffer if no-one exists */
316 if (mhjack.buffers[i] == NULL)
317 mhjack.buffers[i] = jack_ringbuffer_create(sz);
318
319 /* Reset the buffer */
320 if (mhjack.buffers[i] != NULL)
321 jack_ringbuffer_reset(mhjack.buffers[i]);
322 }
323
324 mhjack.buffer_size = sz;
325 return 0;
326 }
327
mhjack_xrun_callback(void * arg)328 static int mhjack_xrun_callback(void *arg)
329 {
330 mhjack.xrun_count ++;
331 return 0;
332 }
333
334 /* Move read pointer ahead to position pos, but only if pos is within the
335 * readable part of the buffer */
mhjack_jrb_skipto(jack_ringbuffer_t * rb,size_t pos)336 static void mhjack_jrb_skipto(jack_ringbuffer_t *rb, size_t pos)
337 {
338 size_t w,r;
339 w = rb->write_ptr;
340 r = rb->read_ptr;
341 if (w >= r) {
342 if (pos > r && pos <= w)
343 rb->read_ptr = pos;
344 } else {
345 if (pos > r || pos <= w)
346 rb->read_ptr = pos;
347 }
348 }
349
mhjack_process_callback(jack_nframes_t nframes,void * arg)350 static int mhjack_process_callback(jack_nframes_t nframes, void *arg)
351 {
352 guint i,first_silent_port=0,skippos;
353 gboolean xrun = FALSE, first = TRUE, do_skip=FALSE;
354 size_t sz = nframes * sizeof(float), sz2;
355 gchar *p;
356 int pctrl;
357 pctrl = mhjack.procctrl;
358 if ((pctrl & MHJACK_PLAY) != 0) {
359 i = MHJACK_SKIPREQ(pctrl);
360 if (i != mhjack.cb_skipcount) {
361 mhjack.cb_skipcount = i;
362 do_skip = TRUE;
363 skippos = MHJACK_SKIPPOS(pctrl);
364 }
365 for (i=0; i<mhjack.current_format.channels; i++) {
366 if (mhjack.outports[i] == NULL) continue;
367 if (do_skip) {
368 mhjack_jrb_skipto(mhjack.buffers[i],skippos);
369 }
370 p = jack_port_get_buffer(mhjack.outports[i],nframes);
371 sz2 = jack_ringbuffer_read(mhjack.buffers[i],p,sz);
372 if (sz2 < sz) {
373 xrun = TRUE;
374 memset(p+sz2,0,sz-sz2);
375 }
376 /* Make sure bytes_played always follow the same port. For
377 * simplicity, we use the first one. */
378 if (first) {
379 mhjack.played_bytes += sz2;
380 first = FALSE;
381 }
382 }
383 first_silent_port = mhjack.current_format.channels;
384 }
385
386 for (i=first_silent_port; i<mhjack.maxoutports; i++) {
387 if (mhjack.outports[i] == NULL) continue;
388 p = jack_port_get_buffer(mhjack.outports[i],nframes);
389 memset(p,0,sz);
390 }
391
392 if ((pctrl & MHJACK_REC) != 0) {
393 for (i=0; i<mhjack.current_format.channels; i++) {
394 if (mhjack.inports[i] == NULL) continue;
395 p = jack_port_get_buffer(mhjack.inports[i],nframes);
396 sz2 = jack_ringbuffer_write(mhjack.buffers[i],p,sz);
397 if (sz2 < sz)
398 xrun = TRUE;
399 }
400 }
401 if (xrun && ((pctrl&MHJACK_REC) != 0 || (pctrl&MHJACK_STOP) == 0)) {
402 console_message(_("Over/underrun in JACK driver"));
403 mhjack.xrun_count ++;
404 }
405 return 0;
406 }
407
mhjack_autoconnect(jack_port_t ** ports,int typeflag,gboolean silent)408 static void mhjack_autoconnect(jack_port_t **ports, int typeflag,
409 gboolean silent)
410 {
411 const char **c,*p1,*p2;
412 char *d;
413 int i,j;
414 c = jack_get_ports(mhjack.myself,NULL,NULL,typeflag|JackPortIsPhysical);
415 if (c == NULL) {
416 /* This should not happen */
417 if (!silent) user_error(_("jack_get_ports returned NULL"));
418 return;
419 }
420 for (i=0; i<8; i++) {
421 if (c[i] == NULL) break;
422 if (typeflag == JackPortIsInput) {
423 if (i >= mhjack.maxoutports) break;
424 p1=jack_port_name(ports[i]);
425 p2=c[i];
426 } else {
427 if (i >= mhjack.maxinports) break;
428 p1=c[i];
429 p2=jack_port_name(ports[i]);
430 }
431 j = jack_connect(mhjack.myself,p1,p2);
432 if (j<0 && !silent) {
433 d = g_strdup_printf(_("Connection from %s to %s failed: %s"),
434 p1,p2,strerror(j));
435 user_error(d);
436 g_free(d);
437 }
438 }
439 g_free(c);
440 }
441
silent_error_callback(const char * msg)442 static void silent_error_callback(const char *msg)
443 {
444 }
445
normal_error_callback(const char * msg)446 static void normal_error_callback(const char *msg)
447 {
448 fprintf(stderr,"%s\n",msg);
449 }
450
mhjack_connect(gboolean silent)451 static void mhjack_connect(gboolean silent)
452 {
453 gchar *c;
454 jack_status_t s;
455 if (mhjack.myself == NULL) {
456
457 if (silent)
458 jack_set_error_function(silent_error_callback);
459
460 /* Connect to the JACK server */
461 mhjack.myself = jack_client_open(mhjack.client_name,
462 JackNoStartServer|JackUseExactName,
463 &s);
464 /* All versions of Jack don't seem to set JackNameNotUnique properly.
465 * Testing with Jack 1.9.4 gave JackServerError|JackFailure even
466 * though JackUseExactName was the cause of the error */
467 if (mhjack.myself == NULL /* && (s & JackNameNotUnique) != 0 */ ) {
468 c = g_strdup_printf("%s%d",mhjack.client_name,getpid());
469 if (!silent)
470 fprintf(stderr,"Retrying with Jack client name %s\n",c);
471 mhjack.myself = jack_client_open(c,JackNoStartServer,&s);
472 g_free(c);
473 }
474
475 if (silent)
476 jack_set_error_function(normal_error_callback);
477
478 if (mhjack.myself == NULL) {
479 if (!silent)
480 user_error(_("Could not connect to the JACK server."));
481 return;
482 }
483
484 jack_set_xrun_callback(mhjack.myself,mhjack_xrun_callback,NULL);
485 jack_set_process_callback(mhjack.myself,mhjack_process_callback,
486 NULL);
487
488 mhjack_register_ports();
489 }
490
491 if (!mhjack.is_activated) {
492 if (jack_activate(mhjack.myself)) {
493 if (!silent)
494 user_error(_("Activation failed!"));
495 return;
496 }
497
498 mhjack.is_activated = TRUE;
499
500 if (mhjack.autoconnect_input)
501 mhjack_autoconnect(mhjack.inports,JackPortIsOutput,silent);
502 if (mhjack.autoconnect_output)
503 mhjack_autoconnect(mhjack.outports,JackPortIsInput,silent);
504 }
505 }
506
mhjack_ringbuffer_space(gboolean input,gboolean readspace)507 static guint mhjack_ringbuffer_space(gboolean input, gboolean readspace)
508 {
509 guint i,j;
510 guint w = 1024*1024; /* Just a very high number */
511
512 for (i=0; i<mhjack.current_format.channels; i++)
513 if ((!input && mhjack.outports[i] != NULL) ||
514 (input && mhjack.inports[i] != NULL)) {
515 if (readspace)
516 j = jack_ringbuffer_read_space(mhjack.buffers[i]);
517 else
518 j = jack_ringbuffer_write_space(mhjack.buffers[i]);
519 if (w > j) w=j;
520 }
521 return w;
522 }
523
mhjack_init(gboolean silent)524 static gboolean mhjack_init(gboolean silent)
525 {
526 mhjack_read_config();
527 mhjack_connect(silent);
528 /* dumpfile = open("jackdump.dat",O_WRONLY|O_CREAT); */
529 return (mhjack.myself != NULL);
530 }
531
mhjack_quit(void)532 static void mhjack_quit(void)
533 {
534 if (mhjack.myself != NULL)
535 jack_client_close(mhjack.myself);
536 }
537
538 /* Output */
539
mhjack_output_select_format(Dataformat * format,gboolean silent,GVoidFunc ready_func)540 static gint mhjack_output_select_format(Dataformat *format, gboolean silent,
541 GVoidFunc ready_func)
542 {
543 /* Make sure we're connected before we check the format. This is
544 * to make sure that the error message is displayed. Note that
545 * mhjack_connect call is cheap when we're already connected */
546 mhjack_connect(silent);
547 if (!mhjack.is_activated) return silent ? -1 : +1;
548
549 if (format->type != DATAFORMAT_FLOAT ||
550 format->samplesize != sizeof(float) ||
551 XOR(format->bigendian,ieee_be_compatible))
552 return -1;
553
554 if (format->samplerate != jack_get_sample_rate(mhjack.myself)) return -1;
555
556 memcpy(&(mhjack.current_format),format,sizeof(Dataformat));
557 mhjack.xrun_count = 0;
558 mhjack.played_bytes = 0;
559
560 mhjack_setup_buffers();
561
562 mhjack.refill = TRUE;
563 mhjack.refillpos = 0;
564 mhjack.refillframes = 0;
565
566 return 0;
567 }
568
mhjack_output_suggest_format(Dataformat * format,Dataformat * result)569 static gboolean mhjack_output_suggest_format(Dataformat *format,
570 Dataformat *result)
571 {
572 mhjack_connect(TRUE);
573 if (!mhjack.is_activated) return FALSE;
574
575 memcpy(result,format,sizeof(Dataformat));
576 result->type = DATAFORMAT_FLOAT;
577 result->samplesize = sizeof(float);
578 result->bigendian = ieee_be_compatible;
579 result->samplebytes = result->samplesize * result->channels;
580 result->samplerate = jack_get_sample_rate(mhjack.myself);
581 result->packing = 0;
582 return TRUE;
583 }
584
585 /* We have two different buffer modes during playback:
586 * Normal mode:
587 * Keep the buffer filled to capacity minus 1/2 second
588 * Refill mode:
589 * Write 1/2 second of data into the buffer and then switch into
590 * normal mode. When switching over, playback is started if it
591 * was stopped, and a skip request (for dropping data) can be sent.
592 *
593 * The mode only matters to the user side, the playback thread plays what's
594 * in the ring buffer.
595 *
596 * Playback skipping without gaps or underruns is implemented as follows:
597 * - When output_clear_buffers is called, we switch to refill mode but the
598 * callback thread keeps playing from the >0.5 s of old sound currently in
599 * the ring buffers.
600 * - When enough new data has been written into the ring buffers, a skip
601 * request is sent to the callback thread with the new data's starting
602 * position in the ring buffer.
603 * - The next time the player thread wakes up it sees the skip request and
604 * jumps the read position ahead to the new data. If it has already
605 * played past that point, it ignores the skip request.
606 */
607
mhjack_writable(void)608 static guint mhjack_writable(void)
609 {
610 int writable,i,s;
611 writable = s = mhjack_ringbuffer_space(FALSE,FALSE) / sizeof(float);
612 i = (mhjack.buffer_size / 2) / sizeof(float);
613 if (mhjack.refill) {
614 /* Return remaining part of refill before switching to normal */
615 if (i > mhjack.refillframes) i-=mhjack.refillframes; else i=0;
616 if (writable > i) writable=i;
617 } else {
618 /* Leave half the buffer for refilling later */
619 if (writable > i) writable-=i; else writable=0;
620 }
621 /* if (writable > 0)
622 printf("writable: s=%d refill=%d refillframes=%d -> %d\n",s,
623 mhjack.refill,mhjack.refillframes,writable); */
624 return writable;
625 }
626
mhjack_output_play(gchar * buffer,guint bufsize)627 static guint mhjack_output_play(gchar *buffer, guint bufsize)
628 {
629 guint writable,frames,i,j;
630 float fbuf[1024],fbuf2[512];
631 int pctrl = mhjack.procctrl;
632
633 if (bufsize == 0) {
634 if ((pctrl&MHJACK_PLAY) == 0 && mhjack_ringbuffer_space(FALSE,TRUE)==0)
635 return 0;
636 /* The caller wants to drain the buffers, therefore set the
637 * is_stopping flag so underrun messages aren't displayed. */
638 pctrl |= (MHJACK_PLAY | MHJACK_STOP);
639 mhjack.procctrl = pctrl;
640 return mhjack_ringbuffer_space(FALSE,TRUE);
641 }
642
643 /* write(dumpfile, buffer, bufsize); */
644
645 /* Calculate room in the ring buffers */
646 writable = mhjack_writable();
647
648 /* Calculate how many frames we can write out */
649 frames = bufsize / mhjack.current_format.samplebytes;
650 if (frames > ARRAY_LENGTH(fbuf2)) frames=ARRAY_LENGTH(fbuf2);
651 if (frames > writable) frames = writable;
652
653 if (frames == 0) return 0;
654
655 /* Convert data to floats */
656 convert_array(buffer,&(mhjack.current_format),fbuf,&dataformat_single,
657 frames*mhjack.current_format.channels,DITHER_NONE,NULL);
658
659 /* De-interleave and write data to the different ring buffers. */
660
661 if (mhjack.current_format.channels == 1) {
662 /* Special case - mono output */
663 if (mhjack.outports[0] != NULL)
664 jack_ringbuffer_write(mhjack.buffers[0],(char *)fbuf,
665 frames*sizeof(float));
666 } else {
667 for (i=0; i<mhjack.current_format.channels; i++) {
668 if (mhjack.outports[i] == NULL) continue;
669 /* De-interleave */
670 for (j=0; j<frames; j++)
671 fbuf2[j] = fbuf[j*mhjack.current_format.channels+i];
672 /* Write */
673 /* We already checked free space, so we assume we can
674 * write all data here. */
675 jack_ringbuffer_write(mhjack.buffers[i],(char *)fbuf2,
676 frames*sizeof(float));
677 }
678 }
679
680 mhjack.refillframes += frames;
681 writable -= frames;
682
683 if (writable < 64) {
684 if (mhjack.refill) {
685 pctrl = MHJACK_NEWSKIP(pctrl,mhjack.refillpos);
686 mhjack.refill = FALSE;
687 }
688 if ((pctrl&MHJACK_PLAY)==0) {
689 /* Let the processing function work next time it's called */
690 pctrl |= MHJACK_PLAY;
691 pctrl &= ~MHJACK_STOP;
692 }
693 mhjack.procctrl = pctrl;
694 }
695
696 return frames * mhjack.current_format.samplebytes;
697 }
698
mhjack_clear_buffers(void)699 static void mhjack_clear_buffers(void)
700 {
701 mhjack.refill = TRUE;
702 mhjack.refillframes = 0;
703 mhjack.refillpos = mhjack.buffers[0]->write_ptr;
704 }
705
mhjack_output_stop(gboolean must_flush)706 static gboolean mhjack_output_stop(gboolean must_flush)
707 {
708 int pctrl = mhjack.procctrl,w;
709 if ((pctrl&MHJACK_PLAY)==0) {
710 if (mhjack_ringbuffer_space(FALSE,TRUE) == 0)
711 return TRUE;
712 }
713 if (!must_flush) {
714 w = mhjack.buffers[0]->write_ptr;
715 pctrl = MHJACK_NEWSKIP(pctrl, w);
716 }
717 pctrl |= (MHJACK_STOP | MHJACK_PLAY);
718 mhjack.procctrl = pctrl;
719 while (mhjack_ringbuffer_space(FALSE,TRUE) > 0) do_yield(FALSE);
720 pctrl &= ~MHJACK_PLAY;
721 mhjack.procctrl = pctrl;
722 return must_flush;
723 }
724
mhjack_output_want_data(void)725 static gboolean mhjack_output_want_data(void)
726 {
727 return (mhjack_writable() > 0);
728 }
729
730 /* Input */
731
mhjack_input_store(Ringbuf * buffer)732 static void mhjack_input_store(Ringbuf *buffer)
733 {
734 guint readable,frames,i,j;
735 float fbuf[512],fbuf2[1024];
736 gchar sbuf[4096];
737 size_t s;
738
739 readable = mhjack_ringbuffer_space(TRUE,TRUE) / sizeof(float);
740 if (readable == 0) return;
741
742 frames = ringbuf_freespace(buffer) / mhjack.current_format.samplebytes;
743 if (frames > readable) frames = readable;
744 if (frames > ARRAY_LENGTH(fbuf2)/mhjack.current_format.channels)
745 frames = ARRAY_LENGTH(fbuf2)/mhjack.current_format.channels;
746
747 /* Read data, then interleave it. */
748 if (mhjack.current_format.channels == 1) {
749 /* Special case - one channel */
750 if (mhjack.inports[0] != NULL) {
751 s = jack_ringbuffer_read(mhjack.buffers[0],(char *)fbuf2,
752 frames*sizeof(float));
753 g_assert(s == frames*sizeof(float));
754 } else
755 memset(fbuf2,0,frames*sizeof(float));
756 } else {
757 for (i=0; i<mhjack.current_format.channels; i++) {
758 if (mhjack.inports[i] == NULL)
759 memset(fbuf,0,frames*sizeof(float));
760 else {
761 /* Read data */
762 s = jack_ringbuffer_read(mhjack.buffers[i],(char *)fbuf,
763 frames*sizeof(float));
764 g_assert(s == frames*sizeof(float));
765 /* printf("Read %ld bytes\n",(long int)s); */
766 /* Interleave */
767 for (j=0; j<frames; j++)
768 fbuf2[j*mhjack.current_format.channels+i] = fbuf[j];
769 }
770 }
771 }
772 /* Convert data (in case sample_t == double, otherwise, convert_array
773 * just does a memcpy). Dithering never matters in this conversion. */
774 convert_array(fbuf2,&dataformat_single,sbuf,&(mhjack.current_format),
775 frames*mhjack.current_format.channels,DITHER_NONE,NULL);
776 /* Add to ring buffer */
777 s = ringbuf_enqueue(buffer,sbuf,frames*mhjack.current_format.samplebytes);
778 g_assert(s == frames*mhjack.current_format.samplebytes);
779 }
780
mhjack_get_xrun_count(void)781 static int mhjack_get_xrun_count(void)
782 {
783 return mhjack.xrun_count;
784 }
785
mhjack_input_supported_formats(gboolean * complete)786 static GList *mhjack_input_supported_formats(gboolean *complete)
787 {
788 Dataformat *fmt;
789 GList *l = NULL;
790 int i,r;
791
792 if (mhjack.myself == NULL)
793 mhjack_connect(TRUE);
794 if (mhjack.myself == NULL) {
795 *complete = TRUE;
796 return NULL;
797 }
798
799 r = jack_get_sample_rate(mhjack.myself);
800 for (i=1; i<=mhjack.maxinports; i++) {
801 fmt = g_malloc(sizeof(*fmt));
802 fmt->type = DATAFORMAT_FLOAT;
803 fmt->samplesize = sizeof(float);
804 fmt->packing = 0;
805 fmt->channels = i;
806 fmt->samplebytes = fmt->samplesize * fmt->channels;
807 fmt->samplerate = r;
808 fmt->bigendian = ieee_be_compatible;
809 l = g_list_append(l, fmt);
810 }
811 *complete = TRUE;
812 return l;
813 }
814
mhjack_input_select_format(Dataformat * format,gboolean silent,GVoidFunc ready_func)815 static gint mhjack_input_select_format(Dataformat *format, gboolean silent,
816 GVoidFunc ready_func)
817 {
818 gchar *c;
819 mhjack_connect(silent);
820 if (!mhjack.is_activated) return silent ? -1 : +1;
821
822 if (format->samplerate != jack_get_sample_rate(mhjack.myself) ||
823 (mhjack_output_select_format(format,TRUE,ready_func))) {
824 if (!silent) {
825 c = g_strdup_printf(_("With JACK, the only supported recording "
826 "format is "
827 "Floating-point, single precision, %d Hz"),
828 jack_get_sample_rate(mhjack.myself));
829 user_error(c);
830 g_free(c);
831 return 1;
832 } else
833 return -1;
834 }
835 mhjack.procctrl |= MHJACK_REC;
836 return 0;
837 }
838
839 /* Also used as input_stop_hint */
mhjack_input_stop(void)840 static void mhjack_input_stop(void)
841 {
842 mhjack.procctrl &= ~MHJACK_REC;
843 }
844