[specimen] [dubphil at free.fr: here is my patch]
Eric Dantan Rzewnicki
eric at zhevny.com
Fri Apr 2 13:20:20 CDT 2010
Forwarding to list, just to make sure it doesn't get lost in my INBOX
and so others can take a look. -edrz
----- Forwarded message from Dubphil <dubphil at free.fr> -----
Date: Fri, 02 Apr 2010 18:55:36 +0200
From: Dubphil <dubphil at free.fr>
Subject: here is my patch
To: Eric Dantan Rzewnicki <eric at zhevny.com>
Eric,
this is the patch from the SVN trunk (few hours old), Specimen can be
compiled and run well but the functionnality I want to add is not working
yet.
this is what is working :
- run specimen with the parameter -c <nb_stereo_channel> adds the relevant
number of ports pair to jack client
- number of stereo channel can be setted in the audio settings window
- the left and right outputs parameters can be set, saved and load from a
bank, this stands in the SMP tab of a patch
this is what is not working :
- the drop down menus of the "Outputs" section of the SMP patch tab are
not populated by the available jack ports. The code is here but it doesn't
work (I spent almost all this day to find why without success)
- the routing of the sound of a patch to the assigned outputs (I'm very
lost here)
- the -c param is not used to populate the spinbutton of the audioi
settings window, and this parameter is not saved somewhere (I don't know
where to save this).
Hope the design I choose is the good one.
Best.
Philippe
Index: src/beef.c
===================================================================
--- src/beef.c (r??vision 89)
+++ src/beef.c (copie de travail)
@@ -79,6 +79,14 @@
xmlNewTextChild (xmlpatch, NULL, (const xmlChar *) "play_mode",
(const xmlChar *) tmp);
+ sprintf (tmp, "%d", patch_get_lout (id[i]));
+ xmlNewTextChild (xmlpatch, NULL, (const xmlChar *) "lout",
+ (const xmlChar *) tmp);
+
+ sprintf (tmp, "%d", patch_get_rout (id[i]));
+ xmlNewTextChild (xmlpatch, NULL, (const xmlChar *) "rout",
+ (const xmlChar *) tmp);
+
sprintf (tmp, "%d", patch_get_cut (id[i]));
xmlNewTextChild (xmlpatch, NULL, (const xmlChar *) "cut",
(const xmlChar *) tmp);
@@ -442,6 +450,24 @@
patch_set_play_mode (id, atoi ((const char *) key));
}
+ else if (!xmlStrcmp
+ (cur->name, (const xmlChar *) "lout"))
+ {
+ key =
+ xmlNodeListGetString (doc, cur->xmlChildrenNode,
+ 1);
+ patch_set_lout (id, atoi ((const char *) key));
+
+ }
+ else if (!xmlStrcmp
+ (cur->name, (const xmlChar *) "rout"))
+ {
+ key =
+ xmlNodeListGetString (doc, cur->xmlChildrenNode,
+ 1);
+ patch_set_rout (id, atoi ((const char *) key));
+
+ }
else if (!xmlStrcmp (cur->name, (const xmlChar *) "cut"))
{
key =
Index: src/jackdriver.c
===================================================================
--- src/jackdriver.c (r??vision 89)
+++ src/jackdriver.c (copie de travail)
@@ -24,7 +24,7 @@
#include "gui/gui.h"
/* prototypes */
-static int start ( );
+static int start (int nb_schan);
static int stop ( );
/* file-global variables */
@@ -39,6 +39,7 @@
#endif
static jack_client_t* client;
static float* buffer;
+static int nb_schan = 1;
static int rate = 44100;
static int periodsize = 2048;
static int running = 0;
@@ -254,7 +255,7 @@
static void restart ( )
{
stop ( );
- start ( );
+ start (nb_schan);
}
static void cb_sync (GtkToggleButton* button, gpointer data)
@@ -265,11 +266,21 @@
sync_set_method (SYNC_METHOD_MIDI);
}
+static void nb_jack_schan (GtkSpinButton* spinner)
+{
+ nb_schan = gtk_spin_button_get_value_as_int (spinner);
+ return;
+}
+
+
static void init ( )
{
GtkWidget* hbox;
GtkWidget* vbox;
+ GtkWidget* hbox2;
GtkWidget* button;
+ GtkWidget* spinner;
+ GtkWidget* label;
config_frame = gtk_frame_new ("JACK");
@@ -277,6 +288,20 @@
gtk_container_set_border_width (GTK_CONTAINER (vbox), GUI_SPACING);
gtk_container_add (GTK_CONTAINER (config_frame), vbox);
gtk_widget_show (vbox);
+
+ hbox2 = gtk_hbox_new (FALSE, GUI_SPACING);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
+ gtk_widget_show (hbox2);
+
+ label = gtk_label_new ("Number of stereo channel :");
+ gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ spinner = gtk_spin_button_new_with_range (nb_schan, 16.0, 1.0);
+ gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
+ gtk_box_pack_start (GTK_BOX (hbox2), spinner, FALSE, FALSE, 0);
+ gtk_widget_show (spinner);
+ g_signal_connect (G_OBJECT (spinner), "value_changed", G_CALLBACK (nb_jack_schan), NULL);
hbox = gtk_hbox_new (FALSE, GUI_SPACING);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
@@ -307,7 +332,7 @@
(gpointer) button);
}
-static int start (void)
+static int start (int nb_schan)
{
const char** ports;
char* instancename = strdup (get_instance_name ( ));
@@ -334,12 +359,21 @@
#endif
jack_on_shutdown (client, shutdown, 0);
- lport =
- jack_port_register (client, "out_left", JACK_DEFAULT_AUDIO_TYPE,
+ int j;
+ char port_name[80] = "";
+ for (j=1; j<=nb_schan; j++)
+ {
+ sprintf(port_name, "out_%d_left",j);
+ lport =
+ jack_port_register (client, port_name, JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
- rport =
- jack_port_register (client, "out_right", JACK_DEFAULT_AUDIO_TYPE,
+
+ sprintf(port_name, "out_%d_right",j);
+ rport =
+ jack_port_register (client, port_name, JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
+ }
+
#if defined HAVE_JACK_MIDI || defined HAVE_OLD_JACK_MIDI || defined HAVE_OLDEST_JACK_MIDI
midiport =
jack_port_register (client, "midi_input", JACK_DEFAULT_MIDI_TYPE,
@@ -373,7 +407,22 @@
ports = jack_get_ports (client, NULL, NULL,
JackPortIsInput | JackPortIsPhysical);
- if (ports[0] != NULL)
+ int n;
+ for(n=0;ports[n] == NULL;n++)
+ {
+ if (ports[n] != NULL)
+ {
+ if (jack_connect (client, jack_port_name (lport), ports[n]) != 0)
+ errmsg (strcat(strcat("Cannot connect", ports[n]), "\n"));
+ }
+ else
+ {
+ errmsg ("Output ports unavailable\n");
+ }
+ free (ports);
+ }
+
+/* if (ports[0] != NULL)
{
if (jack_connect (client, jack_port_name (lport), ports[0]) != 0)
errmsg ("Cannot connect left output port\n");
@@ -393,7 +442,7 @@
{
errmsg ("Cannot connect output ports\n");
}
-
+*/
debug ("Initialization complete\n");
running = 1;
pthread_mutex_unlock (&running_mutex);
@@ -437,6 +486,22 @@
return "JACK";
}
+static const char** getports ( )
+{
+ const char** ports;
+ if (running)
+ {
+ ports = jack_get_ports (client, NULL, NULL,
+ JackPortIsInput | JackPortIsPhysical);
+
+ return ports;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
static GtkWidget* getwidget ( )
{
return config_frame;
@@ -460,5 +525,6 @@
getperiodsize,
getwidget,
getname,
+ getports,
getid
};
Index: src/driver.c
===================================================================
--- src/driver.c (r??vision 89)
+++ src/driver.c (copie de travail)
@@ -1,3 +1,4 @@
+#include <string.h>
#include "specimen.h"
#include "driver.h"
#include "lfo.h"
@@ -27,7 +28,7 @@
ndrivers = 0;
}
-int driver_start (int id)
+int driver_start (int id, int nb_schan)
{
if (id < 0 || id >= ndrivers)
return DRIVER_ERR_ID;
@@ -41,7 +42,7 @@
curdriver = id;
if(id==0){
- return drivers[id]->start ( );
+ return drivers[id]->start (nb_schan);
}
return drivers[id]->start ( );
}
@@ -67,6 +68,13 @@
return drivers[id]->getname ( );
}
+const char** driver_get_ports (int id)
+{
+
+ return drivers[id]->getports ( );
+}
+
+
GtkWidget* driver_get_widget (int id)
{
if (id < 0 || id >= ndrivers)
Index: src/patch.c
===================================================================
--- src/patch.c (r??vision 89)
+++ src/patch.c (copie de travail)
@@ -130,7 +130,8 @@
float pitch_bend; /* pitch bending factor */
gboolean mono; /* whether patch is monophonic or not */
gboolean legato; /* whether patch is played legato or not */
-
+ int lout; /* left output of the patch */
+ int rout; /* right output of the patch */
PatchPlayMode play_mode; /* how this patch is to be played */
PatchParam vol; /* volume: [0.0, 1.0] */
PatchParam pan; /* panning: [-1.0, 1.0] */
@@ -2557,6 +2558,26 @@
return 0;
}
+/* sets the left output */
+int patch_set_lout (int id, int lout)
+{
+ if (!isok (id))
+ return PATCH_ID_INVALID;
+
+ patches[id].lout = lout;
+ return 0;
+}
+
+/* sets the left output */
+int patch_set_rout (int id, int rout)
+{
+ if (!isok (id))
+ return PATCH_ID_INVALID;
+
+ patches[id].rout = rout;
+ return 0;
+}
+
/* sets the play mode */
int patch_set_play_mode (int id, PatchPlayMode mode)
{
@@ -2883,6 +2904,22 @@
return patches[id].pitch_steps;
}
+/* get the left output */
+int patch_get_lout (int id)
+{
+ if (!isok (id))
+ return PATCH_ID_INVALID;
+ return patches[id].lout;
+}
+
+/* get the right output */
+int patch_get_rout (int id)
+{
+ if (!isok (id))
+ return PATCH_ID_INVALID;
+ return patches[id].rout;
+}
+
/* get the play mode */
PatchPlayMode patch_get_play_mode (int id)
{
Index: src/driver.h
===================================================================
--- src/driver.h (r??vision 89)
+++ src/driver.h (copie de travail)
@@ -26,15 +26,17 @@
int (*getperiodsize) ( );
GtkWidget* (*getwidget) ( );
const char* (*getname) ( );
+ const char** (*getports) ( );
void* (*getid) ( );
}
Driver;
void driver_init ( );
-int driver_start (int id);
+int driver_start (int id, int nb_schan);
void driver_stop ( );
int driver_get_count ( );
const char* driver_get_name (int id);
+const char** driver_get_ports (int id);
GtkWidget* driver_get_widget (int id);
void* driver_get_client_id (int id);
Index: src/gui/audio-settings.c
===================================================================
--- src/gui/audio-settings.c (r??vision 89)
+++ src/gui/audio-settings.c (copie de travail)
@@ -38,7 +38,8 @@
/* start the new sound system */
driver_stop ( );
- driver_start (id);
+ /*FIX ME huggly hack setting 1 instead of getting the configured number of stereo channel nb_schan */
+ driver_start (id, 1);
}
}
Index: src/gui/sampletab.c
===================================================================
--- src/gui/sampletab.c (r??vision 89)
+++ src/gui/sampletab.c (copie de travail)
@@ -1,5 +1,9 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <gtk/gtk.h>
#include "sampletab.h"
+#include "driver.h"
#include "gui.h"
#include "waveform.h"
#include "patch.h"
@@ -86,6 +90,26 @@
}
+static void set_lout (SampleTab* self)
+{
+ int lout;
+
+ lout = gtk_option_menu_get_history(GTK_OPTION_MENU(self->lout_opt));
+
+ patch_set_lout(self->patch, lout);
+}
+
+
+static void set_rout (SampleTab* self)
+{
+ int rout;
+
+ rout = gtk_option_menu_get_history(GTK_OPTION_MENU(self->rout_opt));
+
+ patch_set_rout(self->patch, rout);
+}
+
+
static void set_mode(SampleTab* self)
{
int val;
@@ -117,8 +141,21 @@
patch_set_play_mode(self->patch, mode);
}
+
+static void lout_cb(GtkOptionMenu* opt, SampleTab* self)
+{
+ set_lout(self);
+}
+
+static void rout_cb(GtkOptionMenu* opt, SampleTab* self)
+{
+ set_rout(self);
+}
+
+
+
static void mode_cb(GtkOptionMenu* opt, SampleTab* self)
{
set_mode(self);
@@ -143,6 +180,10 @@
{
g_signal_connect(G_OBJECT(self->waveform), "button-press-event",
G_CALLBACK(waveform_cb), (gpointer) self);
+ g_signal_connect(G_OBJECT(self->lout_opt), "changed",
+ G_CALLBACK(lout_cb), (gpointer) self);
+ g_signal_connect(G_OBJECT(self->rout_opt), "changed",
+ G_CALLBACK(rout_cb), (gpointer) self);
g_signal_connect(G_OBJECT(self->mode_opt), "changed",
G_CALLBACK(mode_cb), (gpointer) self);
g_signal_connect(G_OBJECT(self->reverse_check), "toggled",
@@ -154,6 +195,8 @@
static void block(SampleTab* self)
{
+ g_signal_handlers_block_by_func(self->lout_opt, lout_cb, self);
+ g_signal_handlers_block_by_func(self->rout_opt, rout_cb, self);
g_signal_handlers_block_by_func(self->mode_opt, mode_cb, self);
g_signal_handlers_block_by_func(self->reverse_check, reverse_cb, self);
}
@@ -161,6 +204,8 @@
static void unblock(SampleTab* self)
{
+ g_signal_handlers_unblock_by_func(self->lout_opt, lout_cb, self);
+ g_signal_handlers_unblock_by_func(self->rout_opt, rout_cb, self);
g_signal_handlers_unblock_by_func(self->mode_opt, mode_cb, self);
g_signal_handlers_unblock_by_func(self->reverse_check, reverse_cb, self);
}
@@ -228,6 +273,80 @@
}
+inline static GtkWidget* lout_opt_new(SampleTab* self)
+{
+ GtkWidget* menu;
+ GtkWidget* item;
+ GtkWidget* opt;
+
+ /* lout menu */
+ menu = gtk_menu_new();
+
+ const char** ports;
+ ports = driver_get_ports (0);
+
+ if(ports == NULL)
+ {
+ item = gtk_menu_item_new_with_label("No left port");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show(item);
+ }
+ else
+ {
+ int n;
+ for (n=0;ports[n]==NULL;n++)
+ {
+ item = gtk_menu_item_new_with_label(ports[n]);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show(item);
+ }
+ }
+
+ /* lout option menu */
+ opt = gtk_option_menu_new();
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
+
+ return opt;
+}
+
+
+inline static GtkWidget* rout_opt_new(SampleTab* self)
+{
+ GtkWidget* menu;
+ GtkWidget* item;
+ GtkWidget* opt;
+
+ /* rout menu */
+ menu = gtk_menu_new();
+
+ const char** ports;
+ ports = driver_get_ports (0);
+
+ if(ports == NULL)
+ {
+ item = gtk_menu_item_new_with_label("No right port");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show(item);
+ }
+ else
+ {
+ int n;
+ for (n=0;ports[n]==NULL;n++)
+ {
+ item = gtk_menu_item_new_with_label(ports[n]);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show(item);
+ }
+ }
+
+ /* rout option menu */
+ opt = gtk_option_menu_new();
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
+
+ return opt;
+}
+
+
static void sample_tab_init(SampleTab* self)
{
GtkBox* box = GTK_BOX(self);
@@ -284,6 +403,31 @@
gtk_box_pack_start(GTK_BOX(hbox), self->reverse_check, TRUE, TRUE, 0);
gtk_widget_show(self->reverse_check);
+ /* section padding */
+ pad = gui_vpad_new(GUI_SECSPACE);
+ gtk_box_pack_start(box, pad, FALSE, FALSE, 0);
+ gtk_widget_show(pad);
+
+ /* outputs section */
+ section = gui_section_new("Outputs", &hbox);
+ gtk_box_pack_start(box, section, FALSE, FALSE, 0);
+ gtk_widget_show(section);
+
+ /* lout option menu */
+ self->lout_opt = lout_opt_new(self);
+ gtk_box_pack_start(GTK_BOX(hbox), self->lout_opt, TRUE, TRUE, 0);
+ gtk_widget_show(self->lout_opt);
+
+ /* pad */
+ pad = gui_hpad_new(GUI_SPACING);
+ gtk_box_pack_start(GTK_BOX(hbox), pad, FALSE, FALSE, 0);
+ gtk_widget_show(pad);
+
+ /* rout option menu */
+ self->rout_opt = rout_opt_new(self);
+ gtk_box_pack_start(GTK_BOX(hbox), self->rout_opt, TRUE, TRUE, 0);
+ gtk_widget_show(self->rout_opt);
+
connect(self);
}
@@ -298,6 +442,9 @@
{
PatchPlayMode mode;
+ int lout;
+ int rout;
+
self->patch = patch;
waveform_set_patch(WAVEFORM(self->waveform), patch);
@@ -311,6 +458,12 @@
{
update_file_button(self);
+ lout = patch_get_lout(patch);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(self->lout_opt), lout);
+
+ rout = patch_get_rout(patch);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(self->rout_opt), rout);
+
mode = patch_get_play_mode(patch);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->reverse_check),
Index: src/gui/sampletab.h
===================================================================
--- src/gui/sampletab.h (r??vision 89)
+++ src/gui/sampletab.h (copie de travail)
@@ -22,6 +22,8 @@
int patch;
GtkWidget* waveform;
GtkWidget* mode_opt;
+ GtkWidget* lout_opt;
+ GtkWidget* rout_opt;
GtkWidget* file_label;
GtkWidget* file_button;
GtkWidget* reverse_check;
Index: src/specimen.c
===================================================================
--- src/specimen.c (r??vision 89)
+++ src/specimen.c (copie de travail)
@@ -24,6 +24,7 @@
printf ("Usage: specimen [options] [bankname]\n\n");
printf ("Options:\n");
printf (" -n, --name <name> Specify instance name, defaults to \"specimen\"\n");
+ printf (" -c, --channel <nb_stereo_channel> Specify number of jack stereo channel\n");
printf (" -h, --help Display this help message\n\n");
printf ("For more information, please see:\n");
printf ("http://zhevny.com/specimen/\n");
@@ -42,17 +43,19 @@
#endif
int opt;
+ int nb_schan = 1;
int longopt_index;
static struct option long_options[] =
{
{ "name", 1, 0, 'n'},
+ { "channel", 1, 0, 'c'},
{ "uuid", 1, 0, 'U'},
{ "help", 0, 0, 'h'},
{ 0, 0, 0, 0}
};
/* command line argument processing */
- while((opt = getopt_long(argc, argv, "n:U:h", long_options,
+ while((opt = getopt_long(argc, argv, "n:c:U:h", long_options,
&longopt_index)) > 0)
{
switch (opt)
@@ -60,6 +63,9 @@
case 'n':
instance_name = strdup(optarg);
break;
+ case 'c':
+ nb_schan = atoi(optarg);
+ break;
case 'U':
jackdriver_set_uuid( strdup(optarg) );
break;
@@ -93,7 +99,7 @@
/* start */
midi_start();
- driver_start(0);
+ driver_start(0, nb_schan);
#ifdef HAVE_LASH
lashdriver_start();
lashdriver_set_jack_name((char*)driver_get_client_id(0));
Index: src/patch.h
===================================================================
--- src/patch.h (r??vision 89)
+++ src/patch.h (copie de travail)
@@ -151,6 +151,8 @@
int patch_set_lower_note (int id, int note);
int patch_set_monophonic (int id, gboolean val);
int patch_set_name (int id, const char* name);
+int patch_set_lout (int id, const int lout);
+int patch_set_rout (int id, const int rout);
int patch_set_note (int id, int note);
int patch_set_panning (int id, float pan);
int patch_set_pitch (int id, float pitch);
@@ -179,6 +181,8 @@
int patch_get_lower_note (int id);
gboolean patch_get_monophonic (int id);
char* patch_get_name (int id);
+int patch_get_lout (int id);
+int patch_get_rout (int id);
int patch_get_note (int id);
float patch_get_panning (int id);
float patch_get_pitch (int id);
----- End forwarded message -----
More information about the Specimen
mailing list