summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-05-20 22:27:44 +0000
committerDavid Robillard <d@drobilla.net>2011-05-20 22:27:44 +0000
commit5499935ae017305a4b08ef7d0c1dc80739bb5aad (patch)
treeace1737dd232ae9da337aa1b066c746167a5d3ce
parent9139dda70547545f9f36ffe526a5fdcc930b1e2a (diff)
downloadpatchage-5499935ae017305a4b08ef7d0c1dc80739bb5aad.tar.gz
patchage-5499935ae017305a4b08ef7d0c1dc80739bb5aad.tar.bz2
patchage-5499935ae017305a4b08ef7d0c1dc80739bb5aad.zip
Preliminary Jack session support in Patchage (as a session manager).
git-svn-id: http://svn.drobilla.net/lad/trunk/patchage@3302 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/JackDriver.cpp4
-rw-r--r--src/Patchage.cpp123
-rw-r--r--src/Patchage.hpp11
-rw-r--r--src/StateManager.hpp2
-rw-r--r--src/patchage.ui17
-rw-r--r--wscript12
6 files changed, 158 insertions, 11 deletions
diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp
index 9c981ec..13403f9 100644
--- a/src/JackDriver.cpp
+++ b/src/JackDriver.cpp
@@ -201,10 +201,8 @@ JackDriver::create_port(boost::shared_ptr<PatchageModule> parent, jack_port_t* p
if (!strcmp(type_str, JACK_DEFAULT_AUDIO_TYPE)) {
port_type = JACK_AUDIO;
-#ifdef HAVE_JACK_MIDI
} else if (!strcmp(type_str, JACK_DEFAULT_MIDI_TYPE)) {
port_type = JACK_MIDI;
-#endif
} else {
Raul::warn << jack_port_name(port) << " has unknown type \'" << type_str << "\'" << endl;
return boost::shared_ptr<PatchagePort>();
@@ -293,10 +291,8 @@ JackDriver::refresh()
if (!strcmp(type_str, JACK_DEFAULT_AUDIO_TYPE)) {
port_type = JACK_AUDIO;
-#ifdef HAVE_JACK_MIDI
} else if (!strcmp(type_str, JACK_DEFAULT_MIDI_TYPE)) {
port_type = JACK_MIDI;
-#endif
} else {
Raul::warn << ports[i] << " has unknown type \'" << type_str << "\'" << endl;
continue;
diff --git a/src/Patchage.cpp b/src/Patchage.cpp
index be8ff23..edb5f53 100644
--- a/src/Patchage.cpp
+++ b/src/Patchage.cpp
@@ -15,12 +15,15 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <stdlib.h>
#include <pthread.h>
#include <cmath>
#include <fstream>
#include <sstream>
+#include <glib.h>
+#include <glib/gstdio.h>
#include <gtk/gtkwindow.h>
#include <gtkmm.h>
#include <libgnomecanvasmm.h>
@@ -42,6 +45,10 @@
#include <jack/statistics.h>
#endif
+#ifdef PATCHAGE_JACK_SESSION
+#include <jack/session.h>
+#endif
+
#ifdef HAVE_ALSA
#include "AlsaDriver.hpp"
#endif
@@ -97,6 +104,8 @@ Patchage::Patchage(int argc, char** argv)
, INIT_WIDGET(_menu_jack_connect)
, INIT_WIDGET(_menu_jack_disconnect)
, INIT_WIDGET(_menu_open_session)
+ , INIT_WIDGET(_menu_save_session)
+ , INIT_WIDGET(_menu_save_close_session)
, INIT_WIDGET(_menu_store_positions)
, INIT_WIDGET(_menu_view_arrange)
, INIT_WIDGET(_menu_view_messages)
@@ -162,6 +171,14 @@ Patchage::Patchage(int argc, char** argv)
_menu_open_session->signal_activate().connect(
sigc::mem_fun(this, &Patchage::show_load_project_dialog));
_menu_view_projects->set_active(true);
+#elif defined(PATCHAGE_JACK_SESSION)
+ _menu_open_session->signal_activate().connect(
+ sigc::mem_fun(this, &Patchage::show_open_session_dialog));
+ _menu_save_session->signal_activate().connect(
+ sigc::mem_fun(this, &Patchage::show_save_session_dialog));
+ _menu_save_close_session->signal_activate().connect(
+ sigc::mem_fun(this, &Patchage::show_save_close_session_dialog));
+
#else
_menu_open_session->set_sensitive(false);
_menu_view_projects->set_active(false);
@@ -533,6 +550,110 @@ Patchage::connect_widgets()
#endif
}
+#ifdef PATCHAGE_JACK_SESSION
+void
+Patchage::show_open_session_dialog()
+{
+ Gtk::FileChooserDialog dialog(*_main_win, "Open Session",
+ Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
+
+ dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ Gtk::Button* open_but = dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
+ open_but->property_has_default() = true;
+
+ if (dialog.run() != Gtk::RESPONSE_OK) {
+ return;
+ }
+
+ const std::string dir = dialog.get_filename();
+ const std::string cmd = dir + "/jack-session";
+
+ if (system(cmd.c_str()) < 0) {
+ Raul::error << "Error executing session load command " << cmd << endl;
+ } else {
+ Raul::info << "Executed session load command " << cmd << endl;
+ }
+}
+
+void
+Patchage::save_session(bool close)
+{
+ Gtk::FileChooserDialog dialog(*_main_win, "Save Session",
+ Gtk::FILE_CHOOSER_ACTION_SAVE);
+
+ dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ Gtk::Button* save_but = dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
+ save_but->property_has_default() = true;
+
+ if (dialog.run() != Gtk::RESPONSE_OK) {
+ return;
+ }
+
+ std::string path = dialog.get_filename();
+ if (g_mkdir_with_parents(path.c_str(), 0740)) {
+ Raul::error << "Failed to create session directory " << path << endl;
+ return;
+ }
+
+ path += '/';
+ jack_session_command_t* cmd = jack_session_notify(
+ _jack_driver->client(),
+ NULL,
+ close ? JackSessionSaveAndQuit : JackSessionSave,
+ path.c_str());
+
+ const std::string script_path = path + "jack-session";
+ std::ofstream script(script_path.c_str());
+ script << "#!/bin/sh" << endl << endl;
+
+ const std::string var("${SESSION_DIR}");
+ for (int c = 0; cmd[c].uuid; ++c) {
+ std::string command = cmd[c].command;
+ const size_t index = command.find(var);
+ if (index != string::npos) {
+ command.replace(index, var.length(), cmd[c].client_name);
+ }
+
+ script << command << " &" << endl;
+ }
+
+ script << endl;
+ script << "sleep 3" << endl;
+ script << endl;
+
+ for (FlowCanvas::ConnectionList::const_iterator c = _canvas->connections().begin();
+ c != _canvas->connections().end(); ++c) {
+ boost::shared_ptr<PatchagePort> src
+ = boost::dynamic_pointer_cast<PatchagePort>((*c)->source().lock());
+ boost::shared_ptr<PatchagePort> dst
+ = boost::dynamic_pointer_cast<PatchagePort>((*c)->dest().lock());
+
+ if (!src || !dst || src->type() == ALSA_MIDI || dst->type() == ALSA_MIDI) {
+ continue;
+ }
+
+ script << "jack_connect '" << src->full_name()
+ << "' '" << dst->full_name() << "' &" << endl;
+ }
+
+ script.close();
+ g_chmod(script_path.c_str(), 0740);
+}
+
+void
+Patchage::show_save_session_dialog()
+{
+ save_session(false);
+}
+
+void
+Patchage::show_save_close_session_dialog()
+{
+ save_session(true);
+}
+
+#endif
+
#ifdef HAVE_LASH
void
Patchage::show_load_project_dialog()
@@ -543,9 +664,7 @@ Patchage::show_load_project_dialog()
LoadProjectDialog dialog(this);
dialog.run(projects);
}
-#endif
-#ifdef HAVE_LASH
void
Patchage::set_lash_available(bool available)
{
diff --git a/src/Patchage.hpp b/src/Patchage.hpp
index 459e361..2a52efb 100644
--- a/src/Patchage.hpp
+++ b/src/Patchage.hpp
@@ -57,6 +57,11 @@ public:
#if defined(HAVE_LASH) || defined(HAVE_JACK_DBUS)
DBus* dbus() const { return _dbus; }
#endif
+#ifdef PATCHAGE_JACK_SESSION
+ void show_open_session_dialog();
+ void show_save_session_dialog();
+ void show_save_close_session_dialog();
+#endif
#ifdef HAVE_LASH
LashProxy* lash_proxy() const { return _lash_proxy; }
@@ -129,6 +134,10 @@ protected:
void menu_alsa_disconnect();
#endif
+#ifdef PATCHAGE_JACK_SESSION
+ void save_session(bool close);
+#endif
+
boost::shared_ptr<PatchageCanvas> _canvas;
std::set< boost::shared_ptr<FlowCanvas::Module> > _pending_resize;
@@ -156,6 +165,8 @@ protected:
Widget<Gtk::MenuItem> _menu_jack_connect;
Widget<Gtk::MenuItem> _menu_jack_disconnect;
Widget<Gtk::MenuItem> _menu_open_session;
+ Widget<Gtk::MenuItem> _menu_save_session;
+ Widget<Gtk::MenuItem> _menu_save_close_session;
Widget<Gtk::MenuItem> _menu_store_positions;
Widget<Gtk::MenuItem> _menu_view_arrange;
Widget<Gtk::CheckMenuItem> _menu_view_messages;
diff --git a/src/StateManager.hpp b/src/StateManager.hpp
index 829a5df..3f92a1c 100644
--- a/src/StateManager.hpp
+++ b/src/StateManager.hpp
@@ -43,7 +43,7 @@ public:
void save(const std::string& filename);
bool get_module_location(const std::string& name, ModuleType type, Coord& loc);
- void set_module_location(const std::string& name, ModuleType type, Coord loc);
+ void set_module_location(const std::string& name, ModuleType type, Coord loc);
void set_module_split(const std::string& name, bool split);
bool get_module_split(const std::string& name, bool default_val) const;
diff --git a/src/patchage.ui b/src/patchage.ui
index 615225c..db75a9e 100644
--- a/src/patchage.ui
+++ b/src/patchage.ui
@@ -30,6 +30,22 @@
</object>
</child>
<child>
+ <object class="GtkImageMenuItem" id="menu_save_session">
+ <property name="label">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menu_save_close_session">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Save and _Close</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
<object class="GtkImageMenuItem" id="menu_store_positions">
<property name="label">Save Positions</property>
<property name="visible">True</property>
@@ -48,6 +64,7 @@
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
+ <accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<signal name="activate" handler="on_quit1_activate"/>
</object>
</child>
diff --git a/wscript b/wscript
index 08f082e..2d102c5 100644
--- a/wscript
+++ b/wscript
@@ -71,12 +71,15 @@ def configure(conf):
autowaf.define(conf, 'HAVE_JACK_DBUS', 1)
else:
autowaf.check_pkg(conf, 'jack', uselib_store='JACK',
- atleast_version='0.107.0', mandatory=False)
+ atleast_version='0.120.0', mandatory=False)
if conf.is_defined('HAVE_JACK'):
autowaf.define(conf, 'PATCHAGE_LIBJACK', 1)
-
- if conf.is_defined('HAVE_JACK') and conf.is_defined('HAVE_JACK_DBUS'):
- autowaf.define(conf, 'HAVE_JACK_MIDI', 1)
+ autowaf.define(conf, 'PATCHAGE_JACK_SESSION', 1)
+ else:
+ autowaf.check_pkg(conf, 'jack', uselib_store='JACK',
+ atleast_version='0.107.0', mandatory=False)
+ if conf.is_defined('HAVE_JACK'):
+ autowaf.define(conf, 'PATCHAGE_LIBJACK', 1)
# Use Alsa if present unless --no-alsa
if not Options.options.no_alsa:
@@ -108,6 +111,7 @@ def configure(conf):
autowaf.display_msg(conf, "Jack (D-Bus)", conf.is_defined('HAVE_JACK_DBUS'))
autowaf.display_msg(conf, "LASH (D-Bus)", conf.is_defined('HAVE_LASH'))
autowaf.display_msg(conf, "Jack (libjack)", conf.is_defined('PATCHAGE_LIBJACK'))
+ autowaf.display_msg(conf, "Jack Session", conf.is_defined('PATCHAGE_JACK_SESSION'))
autowaf.display_msg(conf, "Alsa Sequencer", conf.is_defined('HAVE_ALSA'))
print('')