AC_ARG_ENABLE(wav, [ --enable-wav enables the builtin wav-loader (default=yes) ])
AC_ARG_ENABLE(xsetpointer, [ --enable-xsetpointer enables executing of xsetpointer (default=auto) ])
AC_ARG_ENABLE(alsa, [ --enable-alsa use ALSA for sound output (default=auto) ])
+AC_ARG_ENABLE(jack, [ --enable-jack use JACK for sound output (default=auto) ])
AC_ARG_ENABLE(oss, [ --enable-oss use OSS for sound output (default=auto) ])
dnl AC_ARG_ENABLE(dga2, [ --enable-dga2 use DGA2 instead of DGA1. (experimental) (default=no) ])
AC_ARG_ENABLE(libxml2, [ --disable-libxml2 use libxml even if verion 2 detected (default=auto) ])
AC_PROG_LN_S
AC_PROG_RANLIB
+OPTION_OSS="no"
+OPTION_ALSA="no"
+OPTION_JACK="no"
OPTION_SOX="no"
OPTION_MPG123="no"
OPTION_MAD="no"
using_alsa=no
using_oss=no
+using_jack=no
if test "$enable_alsa" != "no"; then
AC_CHECK_LIB(asound, snd_pcm_writei,alsalib=yes,alsalib=no)
if test "$alsalib" = "yes"; then
if test "$alsaheader" = "yes"; then
- AC_DEFINE_UNQUOTED([USE_ALSA], 1, [ Define to use ALSA audio backend instead of OSS.])
+ AC_DEFINE_UNQUOTED([USE_ALSA], 1, [ Define to enable ALSA audio backend. ])
LIBS="$LIBS -lasound"
- using_alsa=yes;
+ using_alsa=yes
+ OPTION_ALSA=yes
else
if test "$enable_alsa" = "yes"; then
AC_MSG_ERROR([** Coulnd't find ALSA header file sys/asoundlib.h **])
fi
fi
+if test "$enable_jack" != "no"; then
+ AC_CHECK_LIB(jack,jack_activate,jacklib=yes,jacklib=no)
+ AC_CHECK_HEADERS(jack/jack.h,jackheader=yes,jackheader=no)
+
+ if test "$jacklib" = "yes"; then
+ if test "$jackheader" = "yes"; then
+ AC_DEFINE_UNQUOTED([USE_JACK], 1, [ Define to enable JACK audio backend.])
+ LIBS="$LIBS -ljack"
+ using_jack=yes
+ OPTION_JACK=yes
+ else
+ if test "$enable_jack" = "yes"; then
+ AC_MSG_ERROR([** Coulnd't find JACK header file jack/jack.h **])
+ fi
+ fi
+ else
+ if test "$enable_jack" = "yes"; then
+ AC_MSG_ERROR([** Coulnd'f find JACK library libjack. **])
+ fi
+ fi
+fi
+
+
if test "$enable_oss" != "no"; then
AC_CHECK_HEADERS(sys/ioctl.h sys/soundcard.h,oss=yes,oss=no)
if test "$oss" = "yes"; then
AC_DEFINE_UNQUOTED([USE_OSS], 1, [Use OSS])
+ OPTION_OSS=yes
using_oss=yes;
else
if test "$enable_oss" = "yes"; then
fi
fi
-if test "$using_alsa" = "yes"; then
- AC_MSG_RESULT([termnatorX audiodevice: using ALSA.])
- AC_DEFINE_UNQUOTED([USE_ALSA], 1, [Define for ALSA pcm output])
-else
- if test "$using_oss" = "yes"; then
- AC_MSG_RESULT([termnatorX audiodevice: using OSS.])
- fi
-fi
-
if test "$using_alsa" != "yes"; then
if test "$using_oss" != "yes"; then
- AC_MSG_ERROR([** Found neither OSS nor ALSA! **])
+ if test "$using_jack" != "yes"; then
+ AC_MSG_ERROR([** Found neither OSS, ALSA nor JACK - no output device! **])
+ fi
fi
fi
echo " - and reconfigure terminatorX"
fi
+
+option=oss; option_val=$OPTION_OSS; option_url=http://www.kernel.org
+option_info;
+
+option=alsa; option_val=$OPTION_ALSA; option_url=http://www.alsa-project.org
+option_info;
+
+option=jack; option_val=$OPTION_JACK; option_url=http://jackit.sourceforge.net
+option_info;
+
option=mad; option_val=$OPTION_MAD; option_url=http://www.mars.org/home/rob/proj/mpeg/
option_info;
option_info;
fi
-echo "legacy files supprt: $OPTION_LEGACY"
+echo "legacy files support: $OPTION_LEGACY"
echo "builtin-wav support: $OPTION_WAV"
echo "enhanced scheduling support: $OPTION_SCHEDULER"
+echo "suid-root support: $OPTION_SUIDROOT"
echo "GNOME support: $OPTION_GNOME"
echo
echo You can now run \'make\' to compile terminatorX
#include "tX_endian.h"
#include "tX_types.h"
#include "tX_global.h"
+#include "tX_audiodevice.h"
#include "version.h"
#include "tX_dialog.h"
#include <gtk/gtk.h>
GTimer *my_time;
gint idle_tag;
+#ifdef USE_JACK
+void jack_check()
+{
+ if (!tX_jack_client::get_instance()) {
+ tx_note("Couldn't connect to JACK server - JACK output not available.\n\nIf you want to use JACK, ensure the JACK daemon is running before you start terminatorX.", true);
+ }
+}
+#endif
int idle()
{
g_timer_destroy(my_time);
destroy_about();
display_mastergui();
+#ifdef USE_JACK
+ jack_check();
+#endif
}
return TRUE;
LADSPA_Class :: init();
LADSPA_Plugin :: init();
+#ifdef USE_JACK
+ tX_jack_client :: init();
+#endif
create_mastergui(globals.width, globals.height);
- if (!globals.show_nag) display_mastergui();
+ if (!globals.show_nag) {
+ display_mastergui();
+#ifdef USE_JACK
+ jack_check();
+#endif
+ }
if (globals.startup_set)
{
store_globals();
delete engine;
+#ifdef USE_JACK
+ if (tX_jack_client::get_instance()) {
+ delete tX_jack_client::get_instance();
+ }
+#endif
fprintf(stderr, "Have a nice life.\n");
#else
tX_audiodevice_oss :: tX_audiodevice_oss() : tX_audiodevice(),
fd(0), blocksize(0) {}
-double tX_audiodevice_oss :: get_latency()
-{
- return 0;
-}
-
void tX_audiodevice_oss :: play(int16_t *buffer)
{
#ifdef BIG_ENDIAN_MACHINE
char pcm_name[64];
char foo[PATH_MAX];
- strcpy(pcm_name, globals.alsa_device_id);
+ /* Removing the device ID comment... */
+ for (int i=0; i<strlen(globals.alsa_device_id); i++) {
+ if (globals.alsa_device_id[i]!='#') {
+ pcm_name[i]=globals.alsa_device_id[i];
+ } else {
+ pcm_name[i]=0;
+ break;
+ }
+ }
if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) {
tX_error("ALSA: Failed to access PCM device \"%s\"", pcm_name);
return 0;
}
-double tX_audiodevice_alsa :: get_latency()
-{
- return 0;
-}
-
tX_audiodevice_alsa :: tX_audiodevice_alsa() : tX_audiodevice(),
pcm_handle(NULL) {}
}
#endif //USE_ALSA
+
+#ifdef USE_JACK
+
+tX_jack_client* tX_jack_client::instance=NULL;
+
+void tX_jack_client::init()
+{
+ tX_jack_client *test=new tX_jack_client();
+
+ if (!instance) {
+ delete test;
+ }
+}
+
+tX_jack_client::tX_jack_client():device(NULL)
+{
+ jack_set_error_function(tX_jack_client::error);
+
+ if ((client=jack_client_new("terminatorX"))==0) {
+ tX_error("tX_jack_client() -> failed to connect to jackd.");
+ instance=NULL;
+ } else {
+ instance=this;
+ const char **ports;
+
+ /* Setting up jack callbacks... */
+ jack_set_process_callback(client, tX_jack_client::process, NULL);
+ jack_set_sample_rate_callback(client, tX_jack_client::srate, NULL);
+ jack_on_shutdown (client, tX_jack_client::shutdown, NULL);
+
+ /* Creating the port... */
+ left_port = jack_port_register (client, "output_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ right_port = jack_port_register (client, "output_2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+
+ /* Action... */
+ jack_activate(client);
+
+ /* Connect some ports... */
+ if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) {
+ tX_error("tX_jack_client() no ports to connect to found. Connect manually.");
+ } else if (ports[0] && ports[1]) {
+ if (jack_connect (client, jack_port_name(left_port), ports[0])) {
+ tX_error("tX_jack_client() failed to connect left port.");
+ }
+ if (jack_connect (client, jack_port_name(right_port), ports[1])) {
+ tX_error("tX_jack_client() failed to connect right port.");
+ }
+ free (ports);
+ }
+ }
+}
+
+tX_jack_client::~tX_jack_client()
+{
+ instance=NULL;
+ if (client) jack_client_close(client);
+}
+
+void tX_jack_client::error(const char *desc)
+{
+ tX_error("tX_jack_client::error() jack error: %s.", desc);
+}
+
+int tX_jack_client::srate(jack_nframes_t nframes, void *arg)
+{
+ tX_error("tX_jack_client::srate() jack changed samplerate -> this is bad, stopping audio.");
+ return 0;
+}
+
+void tX_jack_client::shutdown(void *arg)
+{
+ /***AARGH how to handle this?***/
+}
+
+int tX_jack_client::process(jack_nframes_t nframes, void *arg)
+{
+ if (instance) {
+ return instance->play(nframes);
+ }
+
+ /* Hmm, what to do in such a case? */
+ return 0;
+}
+
+int tX_jack_client::play(jack_nframes_t nframes)
+{
+ jack_default_audio_sample_t *left = (jack_default_audio_sample_t *) jack_port_get_buffer (left_port, nframes);
+ jack_default_audio_sample_t *right = (jack_default_audio_sample_t *) jack_port_get_buffer (right_port, nframes);
+
+ if (device) {
+ device->fill_frames(left, right, nframes);
+ } else {
+ memset(left, 0, sizeof (jack_default_audio_sample_t) * nframes);
+ memset(right, 0, sizeof (jack_default_audio_sample_t) * nframes);
+ }
+
+ return 0;
+}
+
+int tX_jack_client::get_sample_rate()
+{
+ return jack_get_sample_rate(client);
+}
+
+/* tX_audiodevice_jack */
+
+tX_audiodevice_jack::tX_audiodevice_jack():tX_audiodevice()
+{
+ client=NULL;
+}
+
+int tX_audiodevice_jack::open()
+{
+ tX_jack_client *jack_client=tX_jack_client::get_instance();
+ sample_rate=jack_client->get_sample_rate();
+
+ if (jack_client) {
+ client=jack_client;
+ is_open=true;
+
+ return 0;
+ }
+
+ return 1;
+}
+
+int tX_audiodevice_jack::close()
+{
+ if (client) {
+ client->set_device(NULL);
+ }
+
+ is_open=false;
+
+ return 0;
+}
+
+void tX_audiodevice_jack::play(int16_t *buffer)
+{
+ tX_error("tX_audiodevice_jack::play()");
+}
+
+void tX_audiodevice_jack::start()
+{
+ tX_debug("activating jack playback");
+ overrun_buffer=new f_prec[vtt_class::samples_in_mix_buffer];
+
+ client->set_device(this);
+ while (!engine->is_stopped()) {
+ usleep(100);
+ }
+ tX_debug("stopping jack playback");
+ client->set_device(NULL);
+
+ delete [] overrun_buffer;
+}
+
+void tX_audiodevice_jack::fill_frames(jack_default_audio_sample_t *left, jack_default_audio_sample_t *right, jack_nframes_t nframes)
+{
+ int outbuffer_pos=0;
+ int sample;
+
+ if (samples_in_overrun_buffer) {
+ for (sample=0; ((sample<samples_in_overrun_buffer) && (outbuffer_pos<nframes));) {
+ left[outbuffer_pos]=overrun_buffer[sample++]/32767.0;
+ right[outbuffer_pos++]=overrun_buffer[sample++]/32767.0;
+ }
+ }
+
+ while (outbuffer_pos<nframes) {
+ engine->render_cycle();
+
+ for (sample=0; ((sample<vtt_class::samples_in_mix_buffer) && (outbuffer_pos<nframes));) {
+ left[outbuffer_pos]=vtt_class::mix_buffer[sample++]/32767.0;
+ right[outbuffer_pos++]=vtt_class::mix_buffer[sample++]/32767.0;
+ }
+
+ if (sample<vtt_class::samples_in_mix_buffer) {
+ samples_in_overrun_buffer=vtt_class::samples_in_mix_buffer-sample;
+ /* There's more data in the mixbuffer... */
+ memcpy(overrun_buffer, &vtt_class::mix_buffer[sample], sizeof(f_prec) * samples_in_overrun_buffer);
+ } else {
+ samples_in_overrun_buffer=0;
+ }
+ }
+}
+
+#endif // USE_JACK
#include <alsa/asoundlib.h>
#endif
+#ifdef USE_JACK
+#include <jack/jack.h>
+#endif
+
class tX_engine;
class tX_audiodevice
tX_audiodevice();
public:
- virtual double get_latency()=0; /* call only valid *after* open() */
int get_buffersize() { return samples_per_buffer; } /* call only valid *after* open() */
int get_sample_rate() { return sample_rate; }
public:
virtual int open();
virtual int close();
-
- virtual double get_latency(); /* call only valid *after* open() */
-
- virtual void play(int16_t*); /* play blocked */
+ virtual void play(int16_t*);
tX_audiodevice_oss();
};
public:
virtual int open();
virtual int close();
-
- virtual double get_latency(); /* call only valid *after* open() */
-
- virtual void play(int16_t*); /* play blocked */
+ virtual void play(int16_t*);
tX_audiodevice_alsa();
};
#endif
+#ifdef USE_JACK
+
+class tX_jack_client;
+
+class tX_audiodevice_jack : public tX_audiodevice
+{
+ private:
+ tX_jack_client *client;
+ jack_default_audio_sample_t *overrun_buffer;
+ int samples_in_overrun_buffer;
+
+ public:
+ virtual int open();
+ virtual int close();
+ virtual void play(int16_t*);
+ virtual void start();
+ void fill_frames(jack_default_audio_sample_t *left, jack_default_audio_sample_t *right, jack_nframes_t nframes);
+
+ tX_audiodevice_jack();
+};
+
+class tX_jack_client
+{
+ public:
+ static void init();
+ static tX_jack_client *get_instance() { return instance; };
+ ~tX_jack_client();
+
+ private:
+ tX_jack_client();
+ static tX_jack_client *instance;
+ static void error(const char *desc);
+ static int srate(jack_nframes_t nframes, void *arg);
+ static void shutdown(void *arg);
+ static int process(jack_nframes_t nframes, void *arg);
+
+ jack_client_t *client;
+ tX_audiodevice_jack *device;
+ jack_port_t *left_port;
+ jack_port_t *right_port;
+ int play(jack_nframes_t nframes);
+
+ public:
+ int get_sample_rate();
+ void set_device(tX_audiodevice_jack *dev) { device=dev; }
+};
+
+#endif
+
#endif
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- File: tX_dialog.c
+ File: tX_dialog.cc
Description: Contains the implementation of the Options and About
Dialogs. (And some really ugly "WE WANT TO
static GtkWidget *last_alsa_device_widget=NULL;
static GtkWidget *alsa_device_entry=NULL;
-static void alsa_device_changed(GtkList *list, GtkWidget *widget, gpointer user_data) {
- if (widget) {
- if (widget != last_alsa_device_widget) {
- last_alsa_device_widget = widget;
- GtkWidget *label=gtk_bin_get_child(GTK_BIN(widget));
-
- if (label) {
- char foo[PATH_MAX];
- char tmp[PATH_MAX];
- int card;
- int device;
-
- sscanf(gtk_label_get_text(GTK_LABEL(label)), "%i-%i: %s", &card, &device, foo);
- sprintf(tmp, "hw:%i,%i", card, device);
-
- gtk_entry_set_text(GTK_ENTRY(alsa_device_entry), tmp);
- }
- }
- }
-}
-
void apply_options(GtkWidget *dialog) {
/* Audio */
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_driver")))) {
strcpy(globals.lrdf_path, gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path"))));
globals.compress_set_files=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "compress_set_files")))==TRUE);
globals.prelis=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")))==TRUE);
+ globals.restore_midi_connections=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "reconnect_enabled")))==TRUE);
}
buffer[PATH_MAX]=0;
if (strlen(buffer)) buffer[strlen(buffer)-1]=0;
if(strstr(buffer, "playback")) {
- alsa_devices=g_list_append (alsa_devices, strdup(buffer));
+ char foo[PATH_MAX];
+ char tmp[PATH_MAX];
+ memset(foo, 0, PATH_MAX);
+ int card;
+ int device;
+
+ sscanf(buffer, "%i-%i: %1024c", &card, &device, foo);
+ sprintf(tmp, "hw:%i,%i# %s", card, device, foo);
+
+ alsa_devices=g_list_append (alsa_devices, strdup(tmp));
}
}
fclose(file);
}
gtk_entry_set_text(GTK_ENTRY(combo->entry), globals.alsa_device_id);
- g_signal_connect(G_OBJECT(combo->list), "select_child", G_CALLBACK(alsa_device_changed), NULL);
-
gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "alsa_buffer_time")), globals.alsa_buffer_time/1000);
gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "alsa_buffer_time"), "Sets the size of the ALSA ring buffer. On slower systems you might have to increase this value (if you hear \"clicks\" or drop-outs). Lower values mean lower latency though.", NULL);
gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "alsa_period_time")), globals.alsa_period_time/1000);
gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path")), globals.lrdf_path);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "compress_set_files")), globals.compress_set_files);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")), globals.prelis);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "reconnect_enabled")), globals.restore_midi_connections);
}
void create_options()
{
opt_dialog=create_tx_options();
- gtk_widget_hide(lookup_widget(opt_dialog, "jack_driver"));
+ //gtk_widget_hide(lookup_widget(opt_dialog, "jack_driver"));
init_tx_options(opt_dialog);
gtk_widget_show(opt_dialog);
}
void raise_about()
{
- if (about)
- gdk_window_raise(about->window);
+ if (about) gdk_window_raise(about->window);
}
void destroy_about()
{
- if (about)
- {
+ if (about) {
gtk_widget_destroy(about);
about=NULL;
}
}
-
-
#define add_about_wid(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN); \
gtk_widget_show(wid);
GtkWidget *scroll;
GdkPixmap *pmap=NULL;
- if (about)
- {
+ /* Only raise the window if it's already open... */
+ if (about) {
gdk_window_raise(about->window);
return;
}
+ /* Create the window... */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_wmclass(GTK_WINDOW(window), "terminatorX", "tX_about");
-
gtk_container_set_border_width(GTK_CONTAINER(window), 5);
-
-// GTK_WINDOW(window)->use_uposition=TRUE;
-
g_object_set (G_OBJECT (window), "type", GTK_WINDOW_TOPLEVEL, NULL);
- if (nag) { gtk_window_set_decorated(GTK_WINDOW(window), FALSE); }
+ gtk_window_set_decorated(GTK_WINDOW(window), nag ? TRUE : FALSE);
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
- //gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
+ gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_title(GTK_WINDOW(window), "terminatorX - About");
- //gtk_widget_set_size_request(window, 640, 210);
- gtk_widget_realize(window);
+ GdkPixbuf *image=gdk_pixbuf_new_from_xpm_data((const char **)logo_xpm);
+ gdk_pixbuf_render_pixmap_and_mask(image, &pmap, &mask, 0);
- style = gtk_widget_get_style( window );
-
- pmap=gdk_pixmap_create_from_xpm_d(window->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar **)logo_xpm);
-
pwid = gtk_pixmap_new( pmap, mask );
if (nag) {
gtk_widget_show(box2);
gtk_widget_show(box);
- gtk_widget_show(window);
gtk_widget_show(pwid);
- while (gtk_events_pending()) gtk_main_iteration();
- }
- else
- {
+ gtk_widget_show(window);
+ } else {
box=gtk_vbox_new(FALSE, 5);
add_about_wid_fix(pwid);
gtk_text_buffer_get_iter_at_offset (tbuffer, &iter, 0);
scroll=gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scroll), text);
gtk_text_buffer_create_tag (tbuffer, "courier", "family", "courier", NULL);
void tX_set_icon(GtkWidget *widget, char *name)
{
- GtkStyle *style;
-
- style = gtk_widget_get_style( widget );
+ GtkStyle *style = gtk_widget_get_style(widget);
- if (!tX_icon_pmap)
- {
+ if (!tX_icon_pmap) {
tX_icon_pmap=gdk_pixmap_create_from_xpm_d(widget->window, &tX_icon_mask, &style->bg[GTK_STATE_NORMAL], (gchar **) tX_icon_xpm );
- //tX_icon_widget = gtk_pixmap_new( tX_icon_pmap, tX_icon_mask );
- //gtk_widget_realize(tX_icon_widget);
}
gdk_window_set_icon(widget->window, NULL, tX_icon_pmap, tX_icon_mask);
}
}
-
void *engine_thread_entry(void *engine_void) {
tX_engine *engine=(tX_engine*) engine_void;
int result;
}
}
+#ifdef USE_JACK
+ /* Create the client now, so the user has something to connect to. */
+ tX_jack_client *jack_client=tX_jack_client::get_instance();
+#endif
+
engine->loop();
tX_debug("engine_thread_entry() - Engine thread terminating.");
result=pthread_create(&thread, &pattr, engine_thread_entry, (void *) this);
} else {
- tX_debug("tX_engine() - Lacking root privileges - no realtime scheduling!");
+ tX_debug("tX_engine() - Lacking root privileges - no realtime scheduling.");
#endif
result=pthread_create(&thread, NULL, engine_thread_entry, (void *) this);
#ifdef USE_SCHEDULER
device=new tX_audiodevice_alsa();
break;
#endif
+
+#ifdef USE_JACK
+ case JACK:
+ device=new tX_audiodevice_jack();
+ break;
+#endif
default:
device=NULL; return ERROR_AUDIO;
GtkWidget *ladspa_rdf_path;
GtkWidget *label33;
GtkWidget *compress_set_files;
+ GtkWidget *label40;
+ GtkWidget *reconnect_enabled;
GtkWidget *label3;
GtkWidget *dialog_action_area3;
GtkWidget *pref_reset;
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 4), label2);
gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
- table3 = gtk_table_new (4, 2, FALSE);
+ table3 = gtk_table_new (5, 2, FALSE);
gtk_widget_show (table3);
gtk_container_add (GTK_CONTAINER (notebook1), table3);
gtk_container_set_border_width (GTK_CONTAINER (table3), 4);
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
+ label40 = gtk_label_new ("Restore MIDI connections:");
+ gtk_widget_show (label40);
+ gtk_table_attach (GTK_TABLE (table3), label40, 0, 1, 4, 5,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (label40), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label40), 0, 0.5);
+
+ reconnect_enabled = gtk_check_button_new_with_mnemonic ("Enabled");
+ gtk_widget_show (reconnect_enabled);
+ gtk_table_attach (GTK_TABLE (table3), reconnect_enabled, 1, 2, 4, 5,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_tooltips_set_tip (tooltips, reconnect_enabled, "When enabled soundfiles will be playedback when selected in a file dialog (before loading them).", NULL);
+
label3 = gtk_label_new ("Misc");
gtk_widget_show (label3);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 5), label3);
GLADE_HOOKUP_OBJECT (tx_options, ladspa_rdf_path, "ladspa_rdf_path");
GLADE_HOOKUP_OBJECT (tx_options, label33, "label33");
GLADE_HOOKUP_OBJECT (tx_options, compress_set_files, "compress_set_files");
+ GLADE_HOOKUP_OBJECT (tx_options, label40, "label40");
+ GLADE_HOOKUP_OBJECT (tx_options, reconnect_enabled, "reconnect_enabled");
GLADE_HOOKUP_OBJECT (tx_options, label3, "label3");
GLADE_HOOKUP_OBJECT_NO_REF (tx_options, dialog_action_area3, "dialog_action_area3");
GLADE_HOOKUP_OBJECT (tx_options, pref_reset, "pref_reset");
tx_global globals;
int _store_compress_xml=0;
+#ifdef USE_ALSA_MIDI_IN
+extern void tX_midiin_store_connections(FILE *rc, char *indent);
+extern void tX_midiin_restore_connections(xmlNodePtr node);
+#endif
+
void get_rc_name(char *buffer)
{
strcpy(buffer,"");
globals.alsa_free_hwstats=1;
globals.filename_length=20;
+ globals.restore_midi_connections=1;
}
int load_globals_xml() {
restore_int("fullscreen_enabled", globals.fullscreen_enabled);
restore_int("confirm_events", globals.confirm_events);
restore_float("vtt_inertia", globals.vtt_inertia);
+ restore_int("restore_midi_connections", globals.restore_midi_connections);
+
+#ifdef USE_ALSA_MIDI_IN
+ if (!elementFound && (xmlStrcmp(cur->name, (xmlChar *) "midi_connections")==0)) {
+ if (globals.restore_midi_connections) {
+ tX_midiin_restore_connections(cur);
+ }
+ elementFound=1;
+ }
+#endif
if (!elementFound) {
fprintf(stderr, "tX: Unhandled XML element: \"%s\"\n", cur->name);
void store_globals() {
char rc_name[PATH_MAX+256]="";
char device_type[16];
- char indent[]="\t";
+ char indent[32]="\t";
FILE *rc=NULL;
gzFile rz=NULL;
char tmp_xml_buffer[4096];
store_float("vtt_inertia", globals.vtt_inertia);
store_string("last_path", globals.current_path);
+ store_int("restore_midi_connections", globals.restore_midi_connections);
+
+#ifdef USE_ALSA_MIDI_IN
+ tX_midiin_store_connections(rc, indent);
+#endif
fprintf(rc,"</terminatorXrc>\n");
}
int alsa_free_hwstats;
int filename_length;
+ int restore_midi_connections;
} tx_global;
extern tx_global globals;
#ifdef USE_ALSA_MIDI_IN
#include "tX_global.h"
#include <iostream>
+#include "tX_engine.h"
using namespace std;
tX_midiin::tX_midiin()
{
-
- int portid;
is_open=false;
sp_to_learn=NULL;
learn_dialog=NULL;
tX_midievent event;
event.is_noteon = false;
bool event_usable = true;
-
+ printf("type: %i\n", ev->type);
switch (ev->type) {
case SND_SEQ_EVENT_CONTROLLER:
+ printf("ctrl: p: %i, v: %i, c: %i\n", ev->data.control.param, ev->data.control.value, ev->data.control.channel);
event.type = tX_midievent::CC;
event.number = ev->data.control.param;
event.value = ev->data.control.value / 127.0;
event.channel = ev->data.control.channel;
break;
case SND_SEQ_EVENT_REGPARAM:
+ printf("rpn: p: %i, v: %i, c: %i\n", ev->data.control.param, ev->data.control.value, ev->data.control.channel);
event.type = tX_midievent::RPN;
event.number = ev->data.control.param;
event.value = ev->data.control.value / 16383.0;
event.channel = ev->data.control.channel;
break;
case SND_SEQ_EVENT_NONREGPARAM:
+ printf("nrpn: p: %i, v: %i, c: %i\n", ev->data.control.param, ev->data.control.value, ev->data.control.channel);
event.type = tX_midievent::NRPN;
event.number = ev->data.control.param;
event.value = ev->data.control.value / 16383.0;
midi->cancel_midi_learn();
}
+void tX_midiin::store_connections(FILE *rc, char *indent)
+{
+ gzFile *rz;
+
+ tX_store("%s<midi_connections>\n", indent);
+ strcat(indent, "\t");
+
+ snd_seq_addr_t my_addr;
+ my_addr.client=snd_seq_client_id(ALSASeqHandle);
+ my_addr.port=portid;
+
+ snd_seq_query_subscribe_t *subs;
+ snd_seq_query_subscribe_alloca(&subs);
+ snd_seq_query_subscribe_set_root(subs, &my_addr);
+ snd_seq_query_subscribe_set_type(subs, SND_SEQ_QUERY_SUBS_WRITE);
+ snd_seq_query_subscribe_set_index(subs, 0);
+
+ while (snd_seq_query_port_subscribers(ALSASeqHandle, subs) >= 0) {
+ const snd_seq_addr_t *addr;
+ addr = snd_seq_query_subscribe_get_addr(subs);
+
+ tX_store("%s<link client=\"%i\" port=\"%i\"/>\n", indent, addr->client, addr->port);
+ snd_seq_query_subscribe_set_index(subs, snd_seq_query_subscribe_get_index(subs) + 1);
+ }
+
+ indent[strlen(indent)-1]=0;
+ tX_store("%s</midi_connections>\n", indent);
+}
+
+void tX_midiin::restore_connections(xmlNodePtr node)
+{
+ snd_seq_addr_t my_addr;
+ my_addr.client=snd_seq_client_id(ALSASeqHandle);
+ my_addr.port=portid;
+
+ if (xmlStrcmp(node->name, (xmlChar *) "midi_connections")==0) {
+ for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (xmlStrcmp(cur->name, (xmlChar *) "link")==0) {
+ char *buffer;
+ int client=-1;
+ int port=-1;
+
+ buffer=(char *) xmlGetProp(cur, (xmlChar *) "client");
+ if (buffer) {
+ sscanf(buffer, "%i", &client);
+ }
+
+ buffer=(char *) xmlGetProp(cur, (xmlChar *) "port");
+ if (buffer) {
+ sscanf(buffer, "%i", &port);
+ }
+
+ if ((port>=0) && (client>=0)) {
+ snd_seq_addr_t sender_addr;
+ sender_addr.client=client;
+ sender_addr.port=port;
+
+ snd_seq_port_subscribe_t *subs;
+ snd_seq_port_subscribe_alloca(&subs);
+ snd_seq_port_subscribe_set_sender(subs, &sender_addr);
+ snd_seq_port_subscribe_set_dest(subs, &my_addr);
+
+ if (snd_seq_subscribe_port(ALSASeqHandle, subs) < 0) {
+ tX_error("tX_midiin::restore_connections() -> failed to connect to: %d:%d.", port, client);
+ }
+ } else {
+ tX_error("tX_midiin::restore_connections() -> invalid port: %d:%d.", port, client);
+ }
+
+ } else {
+ tX_error("tX_midiin::restore_connections() -> invalid element: %s.", cur->name);
+ }
+ }
+ }
+ } else {
+ tX_error("tX_midiin::restore_connections() -> invalid XML element.");
+ }
+}
+
+
+extern "C" {
+ void tX_midiin_store_connections(FILE *rc, char *indent);
+ void tX_midiin_restore_connections(xmlNodePtr node);
+};
+
+void tX_midiin_store_connections(FILE *rc, char *indent)
+{
+ tX_engine::get_instance()->get_midi()->store_connections(rc, indent);
+}
+
+void tX_midiin_restore_connections(xmlNodePtr node)
+{
+ tX_engine::get_instance()->get_midi()->restore_connections(node);
+}
#endif // USE_ALSA_MIDI_IN
#define _tx_midiin_h 1
#include <stdio.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/encoding.h>
class vtt_class;
class tX_seqpar;
bool is_open;
tX_seqpar *sp_to_learn;
GtkWidget *learn_dialog;
+ int portid;
public:
tX_midiin();
void set_midi_learn_sp(tX_seqpar *);
void cancel_midi_learn();
+ void store_connections(FILE *rc, char *indent);
+ void restore_connections(xmlNodePtr node);
static gboolean midi_learn_cancel(GtkWidget *, tX_midiin *);
static gboolean midi_learn_destroy(GtkWidget *, tX_midiin *);
is_mappable=1;
all.push_back(this);
last_event_recorded=NULL;
+
+ midi_lower_bound_set=false;
+ midi_upper_bound_set=false;
}
void tX_seqpar :: set_mapping_parameters(float max, float min, float scale, int mappable)
#ifdef USE_ALSA_MIDI_IN
void tX_seqpar :: handle_midi_input( const tX_midievent& event )
{
- float tmpvalue = -1000;
-
- //event.print( (string(__FUNCTION__) + " - " + get_name()).c_str() );
+ double tmpvalue = -1000;
+ double max=max_value;
+ double min=min_value;
- if( !is_boolean )
- {
+ if (midi_upper_bound_set) {
+ max=midi_upper_bound;
+ }
+
+ if (midi_lower_bound_set) {
+ min=midi_lower_bound;
+ }
+
+ if( !is_boolean ) {
switch (event.type) {
case tX_midievent::CC:
case tX_midievent::CC14:
case tX_midievent::PITCHBEND:
case tX_midievent::RPN:
case tX_midievent::NRPN:
- tmpvalue = event.value * (max_value-min_value) + min_value;
+ tmpvalue = event.value * (max-min) + min;
break;
case tX_midievent::NOTE:
tmpvalue = event.is_noteon;
return;
}
- if (tmpvalue>max_value) tmpvalue=max_value;
- else if (tmpvalue<min_value) tmpvalue=min_value;
- }
- else
- {
+ if (tmpvalue>max) tmpvalue=max;
+ else if (tmpvalue<min) tmpvalue=min;
+ } else {
tmpvalue=event.value;
}
void tX_seqpar :: restore_meta(xmlNodePtr node) {
char *buffer;
+ double temp;
buffer=(char *) xmlGetProp(node, (xmlChar *) "id");
if (buffer) { sscanf(buffer, "%i", &persistence_id); }
else { tX_error("no ID for seqpar %s", this->get_name()); }
+ buffer=(char *) xmlGetProp(node, (xmlChar *) "midiUpperBound");
+ if (buffer) {
+ sscanf(buffer, "%lf", &temp);
+ set_upper_midi_bound(temp);
+ }
+
+ buffer=(char *) xmlGetProp(node, (xmlChar *) "midiLowerBound");
+ if (buffer) {
+ sscanf(buffer, "%lf", &temp);
+ set_lower_midi_bound(temp);
+ }
+
buffer=(char *) xmlGetProp(node, (xmlChar *) "midiType");
if (buffer) {
if (strcmp("cc", buffer)==0) {
}
void tX_seqpar :: store_meta(FILE *rc, gzFile rz) {
- char buffer[256];
+ char buffer[512];
+ char buffer2[256];
if (bound_midi_event.type!=tX_midievent::NONE) {
char *type;
} else {
sprintf(buffer, "id=\"%i\"", persistence_id);
}
+
+ if (midi_upper_bound_set) {
+ sprintf(buffer2, " midiUpperBound=\"%lf\"", midi_upper_bound);
+ strcat(buffer, buffer2);
+ }
+
+ if (midi_lower_bound_set) {
+ sprintf(buffer2, " midiLowerBound=\"%lf\"", midi_lower_bound);
+ strcat(buffer, buffer2);
+ }
+
tX_store(buffer);
}
gtk_widget_set_sensitive(item, FALSE);
}
g_signal_connect(item, "activate", (GCallback) tX_seqpar::remove_midi_binding, sp);
+
+ if (!sp->is_boolean) {
+ item = gtk_menu_item_new();
+ gtk_menu_append(menu, item);
+ gtk_widget_set_sensitive(item, FALSE);
+ gtk_widget_show(item);
+
+ item = gtk_menu_item_new_with_label("Set Upper MIDI Bound");
+ gtk_menu_append(menu, item);
+ gtk_widget_show(item);
+ g_signal_connect(item, "activate", (GCallback) tX_seqpar::set_midi_upper_bound, sp);
+
+ item = gtk_menu_item_new_with_label("Reset Upper MIDI Bound");
+ gtk_menu_append(menu, item);
+ gtk_widget_show(item);
+ g_signal_connect(item, "activate", (GCallback) tX_seqpar::reset_midi_upper_bound, sp);
+
+ if (!sp->midi_upper_bound_set) {
+ gtk_widget_set_sensitive(item, FALSE);
+ }
+
+ item = gtk_menu_item_new_with_label("Set Lower MIDI Bound");
+ gtk_menu_append(menu, item);
+ gtk_widget_show(item);
+ g_signal_connect(item, "activate", (GCallback) tX_seqpar::set_midi_lower_bound, sp);
+
+ item = gtk_menu_item_new_with_label("Reset Lower MIDI Bound");
+ gtk_menu_append(menu, item);
+ gtk_widget_show(item);
+ g_signal_connect(item, "activate", (GCallback) tX_seqpar::reset_midi_lower_bound, sp);
+
+ if (!sp->midi_lower_bound_set) {
+ gtk_widget_set_sensitive(item, FALSE);
+ }
+ }
item = gtk_menu_item_new();
gtk_menu_append(menu, item);
gtk_widget_show(menu);
gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time);
- gtk_grab_remove(gtk_grab_get_current());
+ //gtk_grab_remove(gtk_grab_get_current());
return TRUE;
}
return TRUE;
}
+
+gboolean tX_seqpar::set_midi_upper_bound(GtkWidget *widget, gpointer data) {
+ tX_seqpar *sp=(tX_seqpar *) data;
+ sp->set_upper_midi_bound(sp->get_value());
+
+ return TRUE;
+}
+
+gboolean tX_seqpar::reset_midi_upper_bound(GtkWidget *widget, gpointer data) {
+ tX_seqpar *sp=(tX_seqpar *) data;
+ sp->reset_upper_midi_bound();
+
+ return TRUE;
+}
+
+gboolean tX_seqpar::set_midi_lower_bound(GtkWidget *widget, gpointer data) {
+ tX_seqpar *sp=(tX_seqpar *) data;
+ sp->set_lower_midi_bound(sp->get_value());
+
+ return TRUE;
+}
+
+gboolean tX_seqpar::reset_midi_lower_bound(GtkWidget *widget, gpointer data) {
+ tX_seqpar *sp=(tX_seqpar *) data;
+ sp->reset_lower_midi_bound();
+
+ return TRUE;
+}
float min_value;
float scale_value;
+ bool midi_upper_bound_set;
+ double midi_upper_bound;
+
+ bool midi_lower_bound_set;
+ double midi_lower_bound;
+
bool is_boolean;
public:
void restore_meta(xmlNodePtr node);
void store_meta(FILE *rc, gzFile rz);
+ void set_upper_midi_bound(double val) {
+ midi_upper_bound=val;
+ midi_upper_bound_set=true;
+ }
+
+ void reset_upper_midi_bound() { midi_upper_bound_set=false; }
+
+ void set_lower_midi_bound(double val) {
+ midi_lower_bound=val;
+ midi_lower_bound_set=true;
+ }
+
+ void reset_lower_midi_bound() { midi_lower_bound_set=false; }
+
static gboolean tX_seqpar_press(GtkWidget *widget, GdkEventButton *event, gpointer data);
static gboolean remove_midi_binding(GtkWidget *widget, gpointer data);
- static gboolean learn_midi_binding(GtkWidget *widget, gpointer data);
+ static gboolean learn_midi_binding(GtkWidget *widget, gpointer data);
+
+ static gboolean set_midi_upper_bound(GtkWidget *widget, gpointer data);
+ static gboolean reset_midi_upper_bound(GtkWidget *widget, gpointer data);
+
+ static gboolean set_midi_lower_bound(GtkWidget *widget, gpointer data);
+ static gboolean reset_midi_lower_bound(GtkWidget *widget, gpointer data);
};
class tX_seqpar_update : public tX_seqpar
// printf("mix_out_buffer: %12x\n", mix_out_buffer);
- for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
- {
+ for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
res|=(*vtt)->set_output_buffer_size(no_samples);
}
pthread_mutex_lock(&render_lock);
- if (render_list.size()==0)
- {
- for (sample=0; sample<samples_in_mix_buffer; sample++)
- {
+ if (render_list.size()==0) {
+ for (sample=0; sample<samples_in_mix_buffer; sample++) {
mix_out_buffer[sample]=0;
}
- }
- else
- {
+ } else {
vtt=render_list.begin();
(*vtt)->render();
max=(*vtt)->max_value;
min=max;
- for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
- {
+ for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
temp=(*vtt)->output_buffer[sample];
mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
mix_sample++;
min*=-1.0;
if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
- if ((*vtt)->ec_enable)
- {
- for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
- {
+ if ((*vtt)->ec_enable) {
+ for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
temp=(*vtt)->ec_output_buffer[sample];
mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
}
}
- if (master_triggered)
- {
+ if (master_triggered) {
pthread_mutex_unlock(&render_lock);
- for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
- {
- if ((*vtt)->is_sync_client)
- {
- if ((*vtt)->sync_countdown)
- {
+ for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
+ if ((*vtt)->is_sync_client) {
+ if ((*vtt)->sync_countdown) {
(*vtt)->sync_countdown--;
- }
- else
- {
+ } else {
(*vtt)->sync_countdown=(*vtt)->sync_cycles;
(*vtt)->trigger();
}
}
vtt=render_list.begin();
- for (vtt++; vtt!=render_list.end(); vtt++)
- {
+ for (vtt++; vtt!=render_list.end(); vtt++) {
(*vtt)->render();
max=(*vtt)->max_value;
min=max;
- for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
- {
+ for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
temp=(*vtt)->output_buffer[sample];
mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
mix_sample++;
min*=-1.0;
if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
- if ((*vtt)->ec_enable)
- {
- for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
- {
+ if ((*vtt)->ec_enable) {
+ for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
temp=(*vtt)->ec_output_buffer[sample];
mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
max=mix_max_l;
min=max;
- for (sample=0; sample<samples_in_mix_buffer; sample+=2)
- {
+ for (sample=0; sample<samples_in_mix_buffer; sample+=2) {
temp=mix_buffer[sample];
#ifndef TX_DO_CLIP
max=mix_max_r;
min=max;
- for (sample=1; sample<samples_in_mix_buffer; sample+=2)
- {
+ for (sample=1; sample<samples_in_mix_buffer; sample+=2) {
temp=mix_buffer[sample];
#ifndef TX_DO_CLIP
master_triggered=0;
vtt=render_list.begin();
- while (vtt!=render_list.end())
- {
+ while (vtt!=render_list.end()) {
next=vtt;
next++;
sp_master_volume.do_exec(1.0);
sp_master_volume.do_update_graphics();
+ /* Remove master MIDI mappings... */
+ sp_master_pitch.bound_midi_event.type=tX_midievent::NONE;
+ sp_master_volume.bound_midi_event.type=tX_midievent::NONE;
+
seq_update();
}
}
}
+ sp_master_volume.do_update_graphics();
+ sp_master_pitch.do_update_graphics();
+
ld_destroy();
return(res);
void set_mix_solo(int newstate);
static int get_last_sample_rate() { return last_sample_rate; }
- void calc_mute()
- {
+ void calc_mute() {
res_mute=((mute) || (mix_mute && (!mix_solo)) || ((solo_ctr>0)&&(!mix_solo)));
}
+
+ static f_prec *get_mix_buffer() { return mix_buffer; }
};
#endif
store_int("ladspa_id", ID);
for (sp=controls.begin(); sp!=controls.end(); sp++) {
- store_float_id("param", (*sp)->get_value(), (*sp)->get_persistence_id());
+ store_float_sp("param", (*sp)->get_value(), (*(*sp)));
}
store_bool("panel_hidden", panel->is_hidden());
bool hidden=false;
list <tX_seqpar_vttfx *> :: iterator sp=controls.begin();
int elementFound;
- guint32 pid=0;
double val;
for (xmlNodePtr cur=node->xmlChildrenNode; cur!=NULL; cur=cur->next) {
restore_int("ladspa_id", dummy);
restore_bool("panel_hidden", hidden);
+
if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "param")==0)) {
val=0;
- elementFound=1;
+ elementFound=0;
+ double dvalue;
if (sp==controls.end()) {
tX_warning("found unexpected parameters for ladspa plugin [%i].", dummy);
- } else {
- char *buff=(char *) xmlGetProp(cur, (xmlChar *) "id");
- sscanf(buff, "%i", &pid);
-
- if (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {
- sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%lf", &val);
- }
- (*sp)->set_persistence_id(pid);
- (*sp)->do_exec(val);
+ } else {
+ restore_float_id("param", val, (*(*sp)), (*sp)->do_exec(val));
(*sp)->do_update_graphics();
sp++;
}
<widget class="GtkTable" id="table3">
<property name="border_width">4</property>
<property name="visible">True</property>
- <property name="n_rows">4</property>
+ <property name="n_rows">5</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">2</property>
<property name="y_options"></property>
</packing>
</child>
+
+ <child>
+ <widget class="GtkLabel" id="label40">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Restore MIDI connections:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="reconnect_enabled">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">When enabled soundfiles will be playedback when selected in a file dialog (before loading them).</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Enabled</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="tab_expand">False</property>