diff --git a/src/gx_engine.cpp b/src/gx_engine.cpp index daf8957..eb10c0a 100644 --- a/src/gx_engine.cpp +++ b/src/gx_engine.cpp @@ -63,7 +63,7 @@ float ffuse; float fskin; /* --- forward definition of useful namespace functions --- */ -void gx_engine_init() +void gx_engine_init( const string *optvar ) { //----- lock the buffer for the oscilloscope const int frag = (const int)gx_jack::jack_bs; @@ -95,7 +95,11 @@ void gx_engine_init() midi.init(gx_jack::jack_sr); faust_init(gx_jack::jack_sr); - gx_preset::gx_recall_main_setting(NULL, NULL); + if( !optvar[LOAD_FILE].empty() ) + gx_preset::gx_recall_settings_file( optvar[LOAD_FILE] ); + else + gx_preset::gx_recall_main_setting(NULL, NULL); + initialized = true; } diff --git a/src/gx_globals.cpp b/src/gx_globals.cpp index c93af1e..b09f0bf 100644 --- a/src/gx_globals.cpp +++ b/src/gx_globals.cpp @@ -237,7 +237,9 @@ const char* shell_var_name[] = "GUITARIX2JACK_OUTPUTS1", "GUITARIX2JACK_OUTPUTS2", "GUITARIX2JACK_MIDI", - "GUITARIX_RC_STYLE" + "GUITARIX_RC_STYLE", + "GUITARIX2JACK_UUID", + "GUITARIX_LOAD_FILE" }; } diff --git a/src/gx_jack.cpp b/src/gx_jack.cpp index 8073492..3f26845 100644 --- a/src/gx_jack.cpp +++ b/src/gx_jack.cpp @@ -53,6 +53,10 @@ using namespace std; #include "guitarix.h" +#ifdef HAVE_JACK_SESSION +#include +#endif + using namespace gx_system; using namespace gx_engine; using namespace gx_jconv; @@ -62,7 +66,7 @@ namespace gx_jack { //----- pop up a dialog for starting jack -bool gx_jack_init() +bool gx_jack_init( const string *optvar ) { jack_status_t jackstat; client_name = "guitarix"; @@ -73,8 +77,14 @@ bool gx_jack_init() AVOIDDENORMALS; +#ifdef HAVE_JACK_SESSION // try to open jack client - client = jack_client_open (client_name.c_str(), JackNoStartServer, &jackstat); + if (! optvar[JACK_UUID].empty()) + + client = jack_client_open (client_name.c_str(), jack_options_t(JackNoStartServer | JackSessionID), &jackstat, optvar[JACK_UUID].c_str()); + else +#endif + client = jack_client_open (client_name.c_str(), JackNoStartServer, &jackstat); if (client == 0) { @@ -85,7 +95,7 @@ bool gx_jack_init() { gx_print_warning("Jack Init", "jackd OK, trying to be a client"); usleep(500000); - return gx_jack_init(); + return gx_jack_init( optvar ); } // start a dialog @@ -163,6 +173,10 @@ void gx_jack_callbacks_and_activate() jack_set_process_callback(client, gx_jack_process, 0); jack_set_port_registration_callback(client, gx_jack_portreg_callback, 0); jack_set_client_registration_callback(client, gx_jack_clientreg_callback, 0); +#ifdef HAVE_JACK_SESSION + if (jack_set_session_callback) + jack_set_session_callback (client, gx_jack_session_callback, 0); +#endif //----- register the midi input channel midi_input_port = @@ -355,16 +369,18 @@ void gx_jack_connection(GtkCheckMenuItem *menuitem, gpointer arg) { if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)) == TRUE) { if (!client) { - if (gx_jack_init()) { - string optvar[NUM_SHELL_VAR]; - gx_assign_shell_var(shell_var_name[JACK_INP], optvar[JACK_INP] ); - gx_assign_shell_var(shell_var_name[JACK_MIDI], optvar[JACK_MIDI] ); - gx_assign_shell_var(shell_var_name[JACK_OUT1], optvar[JACK_OUT1]); - gx_assign_shell_var(shell_var_name[JACK_OUT2], optvar[JACK_OUT2]); + string optvar[NUM_SHELL_VAR]; + gx_assign_shell_var(shell_var_name[JACK_INP], optvar[JACK_INP] ); + gx_assign_shell_var(shell_var_name[JACK_MIDI], optvar[JACK_MIDI] ); + gx_assign_shell_var(shell_var_name[JACK_OUT1], optvar[JACK_OUT1]); + gx_assign_shell_var(shell_var_name[JACK_OUT2], optvar[JACK_OUT2]); + gx_assign_shell_var(shell_var_name[JACK_UUID], optvar[JACK_UUID]); + + if (gx_jack_init(optvar)) { // initialize guitarix engine if necessary if (!gx_engine::initialized) { - gx_engine::gx_engine_init(); + gx_engine::gx_engine_init( optvar ); } gx_jack_callbacks_and_activate(); gx_jack_init_port_connection(optvar); @@ -855,6 +871,32 @@ void gx_jack_clientreg_callback(const char* name, int reg, void* arg) } } +#ifdef HAVE_JACK_SESSION +static int gx_jack_session_callback_helper(gpointer data) { + jack_session_event_t *event = (jack_session_event_t *) data; + string fname( event->session_dir ); + fname += "guitarix.state"; + string cmd( "guitarix -U " ); + cmd += event->client_uuid; + cmd += " -f ${SESSION_DIR}guitarix.state"; + + saveStateToFile( fname ); + + event->command_line = strdup( cmd.c_str() ); + + jack_session_reply( client, event ); + + jack_session_event_free( event ); + + return 0; +} + +void gx_jack_session_callback(jack_session_event_t *event, void *arg) +{ + gtk_idle_add(gx_jack_session_callback_helper, (void *)event); +} +#endif + //---- GTK callback from port item for port connection void gx_jack_port_connect(GtkWidget* wd, gpointer data) { diff --git a/src/gx_main.cpp b/src/gx_main.cpp index a10d0da..e8d5d4c 100644 --- a/src/gx_main.cpp +++ b/src/gx_main.cpp @@ -130,10 +130,10 @@ int main(int argc, char *argv[]) gui->setup(); // ---------------------- initialize jack client ------------------ - if (gx_jack::gx_jack_init()) + if (gx_jack::gx_jack_init(optvar)) { // -------- initialize guitarix engine -------------------------- - gx_engine::gx_engine_init(); + gx_engine::gx_engine_init(optvar); // -------- set jack callbacks and activation ------------------- gx_jack::gx_jack_callbacks_and_activate(); diff --git a/src/gx_preset.cpp b/src/gx_preset.cpp index 8218c85..b46e7ab 100644 --- a/src/gx_preset.cpp +++ b/src/gx_preset.cpp @@ -802,7 +802,7 @@ void gx_recall_main_setting(GtkMenuItem* item, gpointer) { string jname = gx_jack::client_name; - gx_system::recallState(); + gx_system::recallState(gx_user_dir + jname + "_rc"); gtk_window_set_title(GTK_WINDOW(gx_gui::fWindow), jname.c_str()); gx_print_info("Main Setting recalling","Called back main setting"); @@ -811,12 +811,25 @@ void gx_recall_main_setting(GtkMenuItem* item, gpointer) gx_current_preset = ""; } +void gx_recall_settings_file( const string & filename ) +{ + string jname = gx_jack::client_name; + + gx_system::recallState(filename); + gtk_window_set_title(GTK_WINDOW(gx_gui::fWindow), jname.c_str()); + + gx_print_info("loading Settings file","loaded settings file"); + + setting_is_preset = false; + gx_current_preset = ""; +} + // ----- save current setting as main setting void gx_save_main_setting(GtkMenuItem* item, gpointer arg) { string jname = gx_jack::client_name; - if (!saveStateToFile()) { + if (! saveStateToFile(gx_user_dir + jname + "_rc")) { gx_print_error("Main Setting","can't save main setting"); } else if (setting_is_preset) { gx_print_info("Main Setting", diff --git a/src/gx_system.cpp b/src/gx_system.cpp index 34ea62e..d97eefa 100644 --- a/src/gx_system.cpp +++ b/src/gx_system.cpp @@ -595,9 +595,9 @@ void write_jack_connections(JsonWriter& w) } // -- save state including current preset data -bool saveStateToFile() +bool saveStateToFile( const string &filename ) { - string filename = gx_user_dir + client_name + "_rc"; + printf( "wrinting to %s\n", filename.c_str() ); string tmpfile = filename + "_tmp"; ofstream f(tmpfile.c_str()); JsonWriter w(f); @@ -663,9 +663,8 @@ static void read_jack_connections(JsonParser& jp) } // -- recallState(filename) : load state from file -bool recallState() +bool recallState( const string &filename ) { - string filename = gx_user_dir + client_name + "_rc"; ifstream f(filename.c_str()); if (!f.good()) { return false; @@ -827,7 +826,8 @@ void gx_signal_handler(int sig) gboolean gx_ladi_handler(gpointer) { gx_print_warning("signal_handler", "signal USR1 received, save settings"); - saveStateToFile(); + + saveStateToFile(gx_user_dir + client_name + "_rc"); return false; } @@ -896,6 +896,7 @@ void gx_process_cmdline_options(int& argc, char**& argv, string* optvar) gchar* jack_input = NULL; gchar* jack_midi = NULL; gchar** jack_outputs = NULL; + gchar* jack_uuid = NULL; GOptionGroup* optgroup_jack = g_option_group_new("jack", "\033[1;32mJACK configuration options\033[0m", "\033[1;32mJACK configuration options\033[0m", @@ -905,10 +906,25 @@ void gx_process_cmdline_options(int& argc, char**& argv, string* optvar) { "jack-input", 'i', 0, G_OPTION_ARG_STRING, &jack_input, "Guitarix JACK input", "PORT" }, {"jack-output", 'o', 0, G_OPTION_ARG_STRING_ARRAY, &jack_outputs, "Guitarix JACK outputs", "PORT" }, { "jack-midi", 'm', 0, G_OPTION_ARG_STRING, &jack_midi, "Guitarix JACK midi control", "PORT" }, + { "jack-uuid", 'U', 0, G_OPTION_ARG_STRING, &jack_uuid, "JackSession ID", NULL }, { NULL } }; g_option_group_add_entries(optgroup_jack, opt_entries_jack); + // FILE options + gchar* load_file = NULL; + + GOptionGroup* optgroup_file = g_option_group_new("file", + "\033[1;32mFile options\033[0m", + "\033[1;32mFile options\033[0m", + NULL, NULL); + GOptionEntry opt_entries_file[] = + { + { "load-file", 'f', 0, G_OPTION_ARG_STRING, &load_file, "load state file on startup", "FILE" }, + { NULL } + }; + g_option_group_add_entries(optgroup_file, opt_entries_file); + // DEBUG options gchar* builder_dir = NULL; gboolean lterminal = FALSE; @@ -928,6 +944,7 @@ void gx_process_cmdline_options(int& argc, char**& argv, string* optvar) // collecting all option groups g_option_context_add_group(opt_context, optgroup_gtk); g_option_context_add_group(opt_context, optgroup_jack); + g_option_context_add_group(opt_context, optgroup_file); g_option_context_add_group(opt_context, optgroup_debug); // parsing command options @@ -1041,6 +1058,14 @@ void gx_process_cmdline_options(int& argc, char**& argv, string* optvar) optvar[JACK_MIDI] = ""; // leads to no automatic connection } + if (jack_uuid != NULL) + { + optvar[JACK_UUID] = jack_uuid; + g_free(jack_uuid); + } else { + optvar[JACK_UUID] = ""; + } + // *** process jack outputs if (jack_outputs != NULL) { int idx = JACK_OUT1; @@ -1062,6 +1087,13 @@ void gx_process_cmdline_options(int& argc, char**& argv, string* optvar) if (!gx_shellvar_exists(optvar[JACK_OUT2])) optvar[JACK_OUT2] = ""; } + if (load_file != NULL) { + optvar[LOAD_FILE] = load_file; + g_free(load_file); + } else { + optvar[LOAD_FILE] = ""; + } + // rcpath = GX_STYLE_DIR + string("/") + string("guitarix_") + optvar[RC_STYLE] + ".rc"; @@ -1435,7 +1467,7 @@ void gx_clean_exit(GtkWidget* widget, gpointer data) // only save if we are not in a preset context if (!setting_is_preset) - saveStateToFile(); + saveStateToFile(gx_user_dir + client_name + "_rc"); } gx_gui::shownote = -1; diff --git a/src/headers/gx_engine.h b/src/headers/gx_engine.h index 41ae6ae..7be25d7 100644 --- a/src/headers/gx_engine.h +++ b/src/headers/gx_engine.h @@ -300,7 +300,7 @@ inline void turnOffMidi() { audio.midistate = kMidiOff; } inline void turnOnMidi() { audio.midistate = kMidiOn; } /* function declarations */ -void gx_engine_init(); +void gx_engine_init( const std::string *optvar ); void gx_engine_reset(); void faust_init(int samplingFreq); void compute_midi(int len); diff --git a/src/headers/gx_jack.h b/src/headers/gx_jack.h index 12d02f3..5ace5da 100644 --- a/src/headers/gx_jack.h +++ b/src/headers/gx_jack.h @@ -34,6 +34,10 @@ #define AVOIDDENORMALS #endif +#ifdef HAVE_JACK_SESSION +#include +#endif + namespace gx_jack { #ifdef USE_RINGBUFFER @@ -46,7 +50,7 @@ typedef struct #endif /* -------- functions ---------- */ -bool gx_jack_init(); +bool gx_jack_init( const string *optvar ); void gx_jack_callbacks_and_activate(); bool gx_start_jack_dialog(); @@ -66,6 +70,9 @@ int gx_jack_buffersize_callback (jack_nframes_t, void*); void gx_jack_portreg_callback (jack_port_id_t, int, void*); void gx_jack_clientreg_callback (const char*, int, void*); void gx_jack_init_port_connection(const string*); +#ifdef HAVE_JACK_SESSION +void gx_jack_session_callback(jack_session_event_t *event, void *arg); +#endif /* processing */ int gx_jack_process (jack_nframes_t, void*); diff --git a/src/headers/gx_preset.h b/src/headers/gx_preset.h index 4191985..d84a521 100644 --- a/src/headers/gx_preset.h +++ b/src/headers/gx_preset.h @@ -44,6 +44,7 @@ void gx_save_oldpreset (GtkMenuItem*, gpointer); void gx_load_preset (GtkMenuItem*, gpointer); void gx_recall_main_setting(GtkMenuItem*, gpointer); +void gx_recall_settings_file( const std::string & filename ); void gx_save_main_setting(GtkMenuItem*, gpointer); void gx_rename_preset (GtkEntry*); diff --git a/src/headers/gx_system.h b/src/headers/gx_system.h index 4058485..76df93d 100644 --- a/src/headers/gx_system.h +++ b/src/headers/gx_system.h @@ -31,7 +31,10 @@ #define JACK_MIDI (3) #define RC_STYLE (4) -#define NUM_SHELL_VAR (5) +#define JACK_UUID (5) +#define LOAD_FILE (6) + +#define NUM_SHELL_VAR (7) namespace gx_system { @@ -118,8 +121,8 @@ void writeHeader(JsonWriter& jw); bool readHeader(JsonParser& jp, int *major=0, int *minor=0); void write_preset(JsonWriter& w, bool write_midi = true); void read_preset(JsonParser &jp); -bool saveStateToFile(); -bool recallState(); +bool saveStateToFile( const std::string & filename ); +bool recallState( const std::string & filename ); // file format versions const int majorversion = 1; diff --git a/wscript b/wscript index b22b426..9b6a086 100644 --- a/wscript +++ b/wscript @@ -173,6 +173,7 @@ def configure(conf): conf.env['SHAREDIR'] = conf.env['PREFIX'] + '/share' + conf.check(header_name='jack/session.h', define_name='HAVE_JACK_SESSION') # defines for compilation conf.define('GX_STYLE_DIR', os.path.normpath(os.path.join(conf.env['SHAREDIR'], 'guitarix','skins')))