From 6ef371745a1b672407cc594b7ec4cd50d721c4c2 Mon Sep 17 00:00:00 2001 From: Roy Vegard Ovesen Date: Thu, 21 Mar 2013 21:16:48 +0100 Subject: [PATCH 1/5] non-session-manager support Implements open, save and dirtiness. No error checking, no menu items disabling. --- gtk2_ardour/ardour_ui.cc | 34 ++++- gtk2_ardour/ardour_ui.h | 3 + gtk2_ardour/nsm.cc | 67 +++++++++ gtk2_ardour/nsm.h | 39 ++++++ gtk2_ardour/nsmclient.cc | 296 +++++++++++++++++++++++++++++++++++++++ gtk2_ardour/nsmclient.h | 112 +++++++++++++++ gtk2_ardour/wscript | 4 +- 7 files changed, 553 insertions(+), 2 deletions(-) create mode 100644 gtk2_ardour/nsm.cc create mode 100644 gtk2_ardour/nsm.h create mode 100644 gtk2_ardour/nsmclient.cc create mode 100644 gtk2_ardour/nsmclient.h diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index e24ec69abd..c520018a96 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -649,7 +649,7 @@ void ARDOUR_UI::startup () { Application* app = Application::instance (); - + char *nsm_url; app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish)); app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load)); @@ -659,6 +659,25 @@ ARDOUR_UI::startup () app->ready (); + nsm_url = getenv ("NSM_URL"); + + if (nsm_url) { + nsm = new NSM_Client; + if (!nsm->init (nsm_url)) { + nsm->announce (PROGRAM_NAME, ":dirty:", "ardour3"); + + do { + nsm->check (); + usleep (10); + } while (!nsm->client_id ()); + + } + else { + delete nsm; + nsm = 0; + } + } + if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) { exit (1); } @@ -928,6 +947,19 @@ ARDOUR_UI::every_second () update_buffer_load (); update_disk_space (); update_timecode_format (); + + if (nsm) { + nsm->check (); + + if (!_was_dirty && _session->dirty ()) { + nsm->is_dirty (); + _was_dirty = true; + } + else if (_was_dirty && !_session->dirty ()){ + nsm->is_clean (); + _was_dirty = false; + } + } return TRUE; } diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 6c7edff1ba..40b71cea78 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -72,6 +72,7 @@ #include "ardour_dialog.h" #include "ardour_button.h" #include "editing.h" +#include "nsm.h" #include "ui_config.h" #include "window_proxy.h" #include "enums.h" @@ -310,6 +311,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr ArdourStartup* _startup; ARDOUR::AudioEngine *engine; Gtk::Tooltips _tooltips; + NSM_Client *nsm; + bool _was_dirty; void goto_editor_window (); void goto_mixer_window (); diff --git a/gtk2_ardour/nsm.cc b/gtk2_ardour/nsm.cc new file mode 100644 index 0000000000..295022ac9a --- /dev/null +++ b/gtk2_ardour/nsm.cc @@ -0,0 +1,67 @@ + +/*******************************************************************************/ +/* Copyright (C) 2012 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + + +#include "nsm.h" +#include "opts.h" +#include "ardour_ui.h" + +#include +#include +#include +#include + + +NSM_Client::NSM_Client() +{ +} + +int +NSM_Client::command_save(char **out_msg) +{ + (void) out_msg; + + ARDOUR_UI::instance()->save_state(); + int r = ERR_OK; + + return r; +} + +int +NSM_Client::command_open(const char *name, + const char *display_name, + const char *client_id, + char **out_msg) +{ + int r = ERR_OK; + struct stat buffer; + + ARDOUR_COMMAND_LINE::new_session = true; + ARDOUR_COMMAND_LINE::session_name = name; + ARDOUR_COMMAND_LINE::jack_client_name = client_id; + + int f = stat(name, &buffer); + + if (f == 0 && S_ISDIR(buffer.st_mode)) + { + ARDOUR_COMMAND_LINE::new_session = false; + } + + return r; +} diff --git a/gtk2_ardour/nsm.h b/gtk2_ardour/nsm.h new file mode 100644 index 0000000000..5491e1985f --- /dev/null +++ b/gtk2_ardour/nsm.h @@ -0,0 +1,39 @@ + +/*******************************************************************************/ +/* Copyright (C) 2012 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#pragma once + +#include "nsmclient.h" + +class NSM_Client:public NSM::Client +{ + public: + + NSM_Client(); + ~NSM_Client() { } + + protected: + + int command_open(const char *name, + const char *display_name, + const char *client_id, + char **out_msg); + int command_save(char **out_msg); +}; + diff --git a/gtk2_ardour/nsmclient.cc b/gtk2_ardour/nsmclient.cc new file mode 100644 index 0000000000..76e18bc629 --- /dev/null +++ b/gtk2_ardour/nsmclient.cc @@ -0,0 +1,296 @@ + +/*******************************************************************************/ +/* Copyright (C) 2012 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include "nsmclient.h" +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-parameter" + +namespace NSM +{ + +/************************/ +/* OSC Message Handlers */ +/************************/ + +#undef OSC_REPLY +#undef OSC_REPLY_ERR + +#define OSC_REPLY( value ) lo_send_from( ((NSM::Client*)user_data)->nsm_addr, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/reply", "ss", path, value ) + +#define OSC_REPLY_ERR( errcode, value ) lo_send_from( ((NSM::Client*)user_data)->nsm_addr, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/error", "sis", path, errcode, value ) + + Client::Client ( ) + { + nsm_addr = 0; + _nsm_client_id = 0; + _nsm_client_path = 0; + _session_manager_name = 0; + nsm_url = ""; + nsm_is_active = false; + _server = 0; + _st = 0; + } + + Client::~Client ( ) + { + if ( _st ) + stop(); + + if ( _st ) + lo_server_thread_free( _st ); + else + lo_server_free ( _server ); + } + + void + Client::announce ( const char *application_name, const char *capabilities, const char *process_name ) + { + + lo_address to = lo_address_new_from_url( nsm_url ); + + if ( ! to ) + { + return; + } + + int pid = (int)getpid(); + + lo_send_from( to, _server, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii", + application_name, + capabilities, + process_name, + 1, /* api_major_version */ + 0, /* api_minor_version */ + pid ); + + lo_address_free( to ); + } + + void + Client::progress ( float p ) + { + if ( nsm_is_active ) + { + lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/progress", "f", p ); + } + } + + void + Client::is_dirty ( void ) + { + if ( nsm_is_active ) + { + lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_dirty", "" ); + } + } + + void + Client::is_clean ( void ) + { + if ( nsm_is_active ) + { + lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_clean", "" ); + } + } + + void + Client::message ( int priority, const char *msg ) + { + if ( nsm_is_active ) + { + lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/message", "is", priority, msg ); + } + } + + + void + Client::broadcast ( lo_message msg ) + { + if ( nsm_is_active ) + { + lo_send_message_from( nsm_addr, _server, "/nsm/server/broadcast", msg ); + } + } + + void + Client::check ( int timeout ) + { + if ( lo_server_wait( _server, timeout ) ) + while ( lo_server_recv_noblock( _server, 0 ) ) {} + } + + void + Client::start ( ) + { + lo_server_thread_start( _st ); + } + + void + Client::stop ( ) + { + lo_server_thread_stop( _st ); + } + + int + Client::init ( const char *nsm_url ) + { + this->nsm_url = nsm_url; + + lo_address addr = lo_address_new_from_url( nsm_url ); + int proto = lo_address_get_protocol( addr ); + lo_address_free( addr ); + + _server = lo_server_new_with_proto( NULL, proto, NULL ); + + if ( ! _server ) + return -1; + + lo_server_add_method( _server, "/error", "sis", &Client::osc_error, this ); + lo_server_add_method( _server, "/reply", "ssss", &Client::osc_announce_reply, this ); + lo_server_add_method( _server, "/nsm/client/open", "sss", &Client::osc_open, this ); + lo_server_add_method( _server, "/nsm/client/save", "", &Client::osc_save, this ); + lo_server_add_method( _server, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this ); + lo_server_add_method( _server, NULL, NULL, &Client::osc_broadcast, this ); + + return 0; + } + + int + Client::init_thread ( const char *nsm_url ) + { + this->nsm_url = nsm_url; + + lo_address addr = lo_address_new_from_url( nsm_url ); + int proto = lo_address_get_protocol( addr ); + lo_address_free( addr ); + + _st = lo_server_thread_new_with_proto( NULL, proto, NULL ); + _server = lo_server_thread_get_server( _st ); + + if ( ! _server || ! _st ) + return -1; + + lo_server_thread_add_method( _st, "/error", "sis", &Client::osc_error, this ); + lo_server_thread_add_method( _st, "/reply", "ssss", &Client::osc_announce_reply, this ); + lo_server_thread_add_method( _st, "/nsm/client/open", "sss", &Client::osc_open, this ); + lo_server_thread_add_method( _st, "/nsm/client/save", "", &Client::osc_save, this ); + lo_server_thread_add_method( _st, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this ); + lo_server_thread_add_method( _st, NULL, NULL, &Client::osc_broadcast, this ); + + return 0; + } + +/************************/ +/* OSC Message Handlers */ +/************************/ + + int + Client::osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + return ((NSM::Client*)user_data)->command_broadcast( path, msg ); + } + + int + Client::osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + char *out_msg = NULL; + + int r = ((NSM::Client*)user_data)->command_save(&out_msg); + + if ( r ) + OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") ); + else + OSC_REPLY( "OK" ); + + if ( out_msg ) + free( out_msg ); + + return 0; + } + + int + Client::osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + char *out_msg = NULL; + + NSM::Client *nsm = (NSM::Client*)user_data; + + nsm->_nsm_client_id = strdup( &argv[2]->s ); + nsm->_nsm_client_path = strdup( &argv[0]->s ); + + int r = ((NSM::Client*)user_data)->command_open( &argv[0]->s, &argv[1]->s, &argv[2]->s, &out_msg); + + if ( r ) + OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") ); + else + OSC_REPLY( "OK" ); + + if ( out_msg ) + free( out_msg ); + + return 0; + } + + int + Client::osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + NSM::Client *nsm = (NSM::Client*)user_data; + + nsm->command_session_is_loaded(); + + return 0; + } + + int + Client::osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) ) + return -1; + + NSM::Client *nsm = (NSM::Client*)user_data; + + + nsm->nsm_is_active = false; + + nsm->command_active( nsm->nsm_is_active ); + + return 0; + } + + int + Client::osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) ) + return -1; + + NSM::Client *nsm = (NSM::Client*)user_data; + + nsm->nsm_is_active = true; + nsm->_session_manager_name = strdup( &argv[2]->s ); + nsm->nsm_addr = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) )); + + nsm->command_active( nsm->nsm_is_active ); + + return 0; + } +}; diff --git a/gtk2_ardour/nsmclient.h b/gtk2_ardour/nsmclient.h new file mode 100644 index 0000000000..ce55e64e3f --- /dev/null +++ b/gtk2_ardour/nsmclient.h @@ -0,0 +1,112 @@ + +/*******************************************************************************/ +/* Copyright (C) 2012 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#pragma once + +#include + +namespace NSM +{ + + class Client + { + + private: + + const char *nsm_url; + + lo_server _server; + lo_server_thread _st; + lo_address nsm_addr; + + bool nsm_is_active; + char *_nsm_client_id; + char *_session_manager_name; + char *_nsm_client_path; + + public: + + enum + { + ERR_OK = 0, + ERR_GENERAL = -1, + ERR_INCOMPATIBLE_API = -2, + ERR_BLACKLISTED = -3, + ERR_LAUNCH_FAILED = -4, + ERR_NO_SUCH_FILE = -5, + ERR_NO_SESSION_OPEN = -6, + ERR_UNSAVED_CHANGES = -7, + ERR_NOT_NOW = -8 + }; + + Client ( ); + virtual ~Client ( ); + + bool is_active ( void ) { return nsm_is_active; } + + const char *session_manager_name ( void ) { return _session_manager_name; } + const char *client_id ( void ) { return _nsm_client_id; } + const char *client_path ( void ) { return _nsm_client_path; } + + /* Client->Server methods */ + void is_dirty ( void ); + void is_clean ( void ); + void progress ( float f ); + void message( int priority, const char *msg ); + void announce ( const char *appliction_name, const char *capabilities, const char *process_name ); + + void broadcast ( lo_message msg ); + + /* init without threading */ + int init ( const char *nsm_url ); + /* init with threading */ + int init_thread ( const char *nsm_url ); + + /* call this periodically to check for new messages */ + void check ( int timeout = 0 ); + + /* or call these to start and stop a thread (must do your own locking in handler!) */ + void start ( void ); + void stop ( void ); + + protected: + + /* Server->Client methods */ + virtual int command_open ( const char *name, const char *display_name, const char *client_id, char **out_msg ) = 0; + virtual int command_save ( char **out_msg ) = 0; + + virtual void command_active ( bool ) { } + + virtual void command_session_is_loaded ( void ) { } + + /* invoked when an unrecognized message is received. Should return 0 if you handled it, -1 otherwise. */ + virtual int command_broadcast ( const char *, lo_message ) { return -1; } + + private: + + /* osc handlers */ + static int osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + static int osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + + }; +}; diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 5beeebb74d..605266b0a2 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -161,6 +161,8 @@ gtk2_ardour_sources = [ 'new_plugin_preset_dialog.cc', 'normalize_dialog.cc', 'note_player.cc', + 'nsm.cc', + 'nsmclient.cc', 'option_editor.cc', 'opts.cc', 'panner2d.cc', @@ -397,7 +399,7 @@ def build(bld): obj.uselib = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD GTK OGG ALSA CURL DL' obj.uselib += ' GTKMM GNOMECANVASMM GNOMECANVAS ' - obj.uselib += ' AUDIOUNITS OSX GTKOSX ' + obj.uselib += ' AUDIOUNITS OSX GTKOSX LO ' obj.use = [ 'libpbd', 'libmidipp', 'libtaglib', From 43b94f7aa72ae3017672242a026af21421c08c1a Mon Sep 17 00:00:00 2001 From: Roy Vegard Ovesen Date: Sat, 30 Mar 2013 18:15:57 +0100 Subject: [PATCH 2/5] Prevent the new session dialog from appearing --- gtk2_ardour/ardour_ui.cc | 8 ++++++-- gtk2_ardour/nsm.cc | 12 +----------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index c520018a96..edd57251b2 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -2447,7 +2447,7 @@ ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::s { BusProfile bus_profile; - if (Profile->get_sae()) { + if (nsm || Profile->get_sae()) { bus_profile.master_out_channels = 2; bus_profile.input_ac = AutoConnectPhysical; @@ -2591,6 +2591,10 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri session_name = _startup->session_name (likely_new); + if (nsm) { + likely_new = true; + } + string::size_type suffix = session_name.find (statefile_suffix); if (suffix != string::npos) { @@ -2642,7 +2646,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { - if (likely_new) { + if (likely_new && !nsm) { std::string existing = Glib::build_filename (session_path, session_name); diff --git a/gtk2_ardour/nsm.cc b/gtk2_ardour/nsm.cc index 295022ac9a..bd27fe532c 100644 --- a/gtk2_ardour/nsm.cc +++ b/gtk2_ardour/nsm.cc @@ -23,8 +23,6 @@ #include "ardour_ui.h" #include -#include -#include #include @@ -50,18 +48,10 @@ NSM_Client::command_open(const char *name, char **out_msg) { int r = ERR_OK; - struct stat buffer; - ARDOUR_COMMAND_LINE::new_session = true; + ARDOUR_COMMAND_LINE::new_session = false; ARDOUR_COMMAND_LINE::session_name = name; ARDOUR_COMMAND_LINE::jack_client_name = client_id; - int f = stat(name, &buffer); - - if (f == 0 && S_ISDIR(buffer.st_mode)) - { - ARDOUR_COMMAND_LINE::new_session = false; - } - return r; } From 81a343ff7f1e456210d85b918e4a2979e73204d9 Mon Sep 17 00:00:00 2001 From: Roy Vegard Ovesen Date: Sat, 30 Mar 2013 19:12:31 +0100 Subject: [PATCH 3/5] Make sure every imported file is copied to the session path --- gtk2_ardour/ardour_ui.cc | 3 +++ gtk2_ardour/sfdb_ui.cc | 5 +++-- libs/ardour/ardour/session.h | 3 +++ libs/ardour/session.cc | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index edd57251b2..3d148a9735 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -682,6 +682,9 @@ ARDOUR_UI::startup () exit (1); } + if (_session && nsm) { + _session->set_nsm_state( true ); + } use_config (); goto_editor_window (); diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index 3383cf3ff9..8916a53971 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -1339,8 +1339,9 @@ SoundFileOmega::reset_options () src_combo.set_sensitive (false); } - /* We must copy MIDI files or those from Freesound */ - bool const must_copy = have_a_midi_file || notebook.get_current_page() == 2; + /* We must copy MIDI files or those from Freesound + * or any file if we are under nsm control */ + bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2; if (Config->get_only_copy_imported_files()) { diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index cb7f0ee015..f0a2fd1189 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -392,6 +392,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void rename_state (std::string old_name, std::string new_name); void remove_pending_capture_state (); int rename (const std::string&); + bool get_nsm_state () const { return _under_nsm_control; } + void set_nsm_state (bool state) { _under_nsm_control = state; } PBD::Signal1 StateSaved; PBD::Signal0 StateReady; @@ -925,6 +927,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi uint32_t _solo_isolated_cnt; bool _writable; bool _was_seamless; + bool _under_nsm_control; void initialize_latencies (); void set_worst_io_latencies (); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 75303251d8..0e03efa945 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -133,6 +133,7 @@ Session::Session (AudioEngine &eng, : _engine (eng) , _target_transport_speed (0.0) , _requested_return_frame (-1) + , _under_nsm_control (false) , _session_dir (new SessionDirectory(fullpath)) , state_tree (0) , _state_of_the_state (Clean) From 2806828962e63a2b2ad078ed6328dbd64e02e3eb Mon Sep 17 00:00:00 2001 From: Roy Vegard Ovesen Date: Sun, 31 Mar 2013 03:46:07 +0200 Subject: [PATCH 4/5] Better start up Don't reply to nsm server until ardour project is finished loading --- gtk2_ardour/ardour_ui.cc | 23 ++++++++++++++++++----- gtk2_ardour/nsm.cc | 12 +++++++++++- gtk2_ardour/nsm.h | 5 +++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 3d148a9735..d42bdcdd4f 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -666,11 +666,27 @@ ARDOUR_UI::startup () if (!nsm->init (nsm_url)) { nsm->announce (PROGRAM_NAME, ":dirty:", "ardour3"); + // wait for announce reply from nsm server + do { + nsm->check (); + usleep (10); + } while (!nsm->is_active ()); + // wait for open command from nsm server do { nsm->check (); usleep (10); } while (!nsm->client_id ()); + if (_session && nsm) { + _session->set_nsm_state( nsm->is_active() ); + } + + // wait for session is loaded reply from nsm server + do { + nsm->check (); + usleep (10); + } while (!nsm->session_loaded ()); + } else { delete nsm; @@ -678,13 +694,10 @@ ARDOUR_UI::startup () } } - if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) { + else if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) { exit (1); } - if (_session && nsm) { - _session->set_nsm_state( true ); - } use_config (); goto_editor_window (); @@ -951,7 +964,7 @@ ARDOUR_UI::every_second () update_disk_space (); update_timecode_format (); - if (nsm) { + if (nsm && nsm->is_active () && nsm->session_loaded ()) { nsm->check (); if (!_was_dirty && _session->dirty ()) { diff --git a/gtk2_ardour/nsm.cc b/gtk2_ardour/nsm.cc index bd27fe532c..09449c5630 100644 --- a/gtk2_ardour/nsm.cc +++ b/gtk2_ardour/nsm.cc @@ -28,6 +28,7 @@ NSM_Client::NSM_Client() { + _session_loaded = false; } int @@ -49,9 +50,18 @@ NSM_Client::command_open(const char *name, { int r = ERR_OK; - ARDOUR_COMMAND_LINE::new_session = false; ARDOUR_COMMAND_LINE::session_name = name; ARDOUR_COMMAND_LINE::jack_client_name = client_id; + ARDOUR_COMMAND_LINE::no_connect_ports = true; + if (ARDOUR_UI::instance()->get_session_parameters(true, false, "")) { + return ERR_GENERAL; + } return r; } + +void +NSM_Client::command_session_is_loaded ( void ) +{ + _session_loaded = true; +} diff --git a/gtk2_ardour/nsm.h b/gtk2_ardour/nsm.h index 5491e1985f..a2b0c11151 100644 --- a/gtk2_ardour/nsm.h +++ b/gtk2_ardour/nsm.h @@ -28,12 +28,17 @@ class NSM_Client:public NSM::Client NSM_Client(); ~NSM_Client() { } + bool session_loaded(void) { return _session_loaded; } + protected: + bool _session_loaded; + int command_open(const char *name, const char *display_name, const char *client_id, char **out_msg); int command_save(char **out_msg); + void command_session_is_loaded (void); }; From 91080c31db427c6ded5beab86f7c50c6e7dfe52b Mon Sep 17 00:00:00 2001 From: Roy Vegard Ovesen Date: Sun, 31 Mar 2013 15:28:29 +0200 Subject: [PATCH 5/5] Disable some actions that are not allowed while under nsm --- gtk2_ardour/ardour_ui.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index d42bdcdd4f..12d73b9f51 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -681,6 +681,23 @@ ARDOUR_UI::startup () _session->set_nsm_state( nsm->is_active() ); } + // nsm requires these actions disabled + vector action_names; + action_names.push_back("Snapshot"); + action_names.push_back("SaveAs"); + action_names.push_back("Rename"); + action_names.push_back("New"); + action_names.push_back("Open"); + action_names.push_back("Recent"); + action_names.push_back("Close"); + + for (vector::const_iterator n = action_names.begin(); n != action_names.end(); ++n) { + Glib::RefPtr act = ActionManager::get_action (X_("Main"), X_(n.base()->c_str())); + if (act) { + act->set_sensitive (false); + } + } + // wait for session is loaded reply from nsm server do { nsm->check ();