13
0
This commit is contained in:
Paul Davis 2013-04-01 18:54:41 -04:00
commit 11ca19ed8f
10 changed files with 605 additions and 7 deletions

View File

@ -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,7 +659,59 @@ ARDOUR_UI::startup ()
app->ready ();
if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
nsm_url = getenv ("NSM_URL");
if (nsm_url) {
nsm = new NSM_Client;
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() );
}
// nsm requires these actions disabled
vector<string> 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<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
Glib::RefPtr<Action> 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 ();
usleep (10);
} while (!nsm->session_loaded ());
}
else {
delete nsm;
nsm = 0;
}
}
else if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
exit (1);
}
@ -928,6 +980,19 @@ ARDOUR_UI::every_second ()
update_buffer_load ();
update_disk_space ();
update_timecode_format ();
if (nsm && nsm->is_active () && nsm->session_loaded ()) {
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;
}
@ -2415,7 +2480,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;
@ -2559,6 +2624,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) {
@ -2610,7 +2679,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);

View File

@ -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 ();

67
gtk2_ardour/nsm.cc Normal file
View File

@ -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 <unistd.h>
NSM_Client::NSM_Client()
{
_session_loaded = false;
}
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;
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;
}

44
gtk2_ardour/nsm.h Normal file
View File

@ -0,0 +1,44 @@
/*******************************************************************************/
/* 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() { }
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);
};

296
gtk2_ardour/nsmclient.cc Normal file
View File

@ -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;
}
};

112
gtk2_ardour/nsmclient.h Normal file
View File

@ -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 );
};
};

View File

@ -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()) {

View File

@ -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',

View File

@ -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<void,std::string> StateSaved;
PBD::Signal0<void> 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 ();

View File

@ -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)