summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_ui.cc34
-rw-r--r--gtk2_ardour/ardour_ui.h3
-rw-r--r--gtk2_ardour/nsm.cc67
-rw-r--r--gtk2_ardour/nsm.h39
-rw-r--r--gtk2_ardour/nsmclient.cc296
-rw-r--r--gtk2_ardour/nsmclient.h112
-rw-r--r--gtk2_ardour/wscript4
7 files changed, 553 insertions, 2 deletions
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 <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+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 <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#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 <lo/lo.h>
+
+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',