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