diff options
author | Roy Vegard Ovesen <roy.vegard.ovesen@gmail.com> | 2013-03-21 21:16:48 +0100 |
---|---|---|
committer | Roy Vegard Ovesen <roy.vegard.ovesen@gmail.com> | 2013-03-31 03:59:09 +0200 |
commit | 6ef371745a1b672407cc594b7ec4cd50d721c4c2 (patch) | |
tree | b68062cfc47216a9bd210a3576f6de329c512411 | |
parent | 236360d8ffab9f095fcda9e09b159b2a47feb6af (diff) |
non-session-manager support
Implements open, save and dirtiness.
No error checking, no menu items disabling.
-rw-r--r-- | gtk2_ardour/ardour_ui.cc | 34 | ||||
-rw-r--r-- | gtk2_ardour/ardour_ui.h | 3 | ||||
-rw-r--r-- | gtk2_ardour/nsm.cc | 67 | ||||
-rw-r--r-- | gtk2_ardour/nsm.h | 39 | ||||
-rw-r--r-- | gtk2_ardour/nsmclient.cc | 296 | ||||
-rw-r--r-- | gtk2_ardour/nsmclient.h | 112 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 4 |
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', |