dynamic discovery & loading of keybindings

git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3055 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2008-02-14 01:59:28 +00:00
parent 3e50efd133
commit 26bffbce44
16 changed files with 326 additions and 149 deletions

View file

@ -417,9 +417,13 @@ else:
keybindings_dict['%LEVEL4%'] = 'Mod2'
keybindings_dict['%WINDOW%'] = 'Alt'
ardourbindings = env.SubstInFile ('ardour.bindings', 'ardour.bindings.in', SUBST_DICT = keybindings_dict);
ardoursaeDEbindings = env.SubstInFile ('ardour-sae-de.bindings', 'ardour-sae-de.bindings.in', SUBST_DICT = keybindings_dict);
ardoursaeANSIbindings = env.SubstInFile ('ardour-sae-ansi.bindings', 'ardour-sae-ansi.bindings.in', SUBST_DICT = keybindings_dict);
bindings = { }
for b in [ 'SAE-de', 'SAE-us', 'mnemonic-us', 'ergonomic-us' ]:
target_file = b + '.bindings'
src_file = target_file + '.in'
bindings[b] = env.SubstInFile (target_file, src_file, SUBST_DICT = keybindings_dict);
Default (bindings[b])
my_subst_dict['%INSTALL_PREFIX%'] = final_prefix
my_subst_dict['%LIBDIR%'] = env['LIBDIR']
@ -431,9 +435,6 @@ env.AddPostAction (ardoursh, Chmod ('$TARGET', 0755))
ardourdev = env.SubstInFile ('ardev_common.sh','ardev_common.sh.in', SUBST_DICT = my_subst_dict);
env.AddPostAction (ardourdev, Chmod ('$TARGET', 0755))
Default(ardourbindings)
Default(ardoursaeDEbindings)
Default(ardoursaeANSIbindings)
Default(ardourdev)
Default(ardoursh)
Default(ardour_dark_theme)

View file

@ -3,6 +3,7 @@ cd `dirname "$0"`/..
#export G_DEBUG=fatal_criticals
export ARDOUR_PATH=gtk2_ardour/icons:gtk2_ardour/pixmaps:gtk2_ardour:.
export ARDOUR_DATA_PATH=gtk2_ardour:.
export GTK_PATH=libs/clearlooks
export VAMP_PATH=libs/vamp-plugins:$VAMP_PATH

View file

@ -199,14 +199,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
session_loaded = false;
last_speed_displayed = -1.0f;
keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
/* all changes go to the user directory */
user_keybindings_path = get_user_ardour_path ();
user_keybindings_path += '/';
user_keybindings_path += "ardour.bindings";
can_save_keybindings = false;
last_configure_time.tv_sec = 0;
last_configure_time.tv_usec = 0;
@ -530,7 +522,7 @@ ARDOUR_UI::save_ardour_state ()
Config->add_instant_xml (mnode, get_user_ardour_path());
}
save_keybindings ();
Keyboard::save_keybindings ();
}
gint
@ -3173,27 +3165,13 @@ ARDOUR_UI::record_state_changed ()
}
}
void
ARDOUR_UI::set_keybindings_path (string path)
{
keybindings_path = path;
}
void
ARDOUR_UI::save_keybindings ()
{
if (can_save_keybindings) {
AccelMap::save (user_keybindings_path);
}
}
bool
ARDOUR_UI::first_idle ()
{
if (session) {
session->allow_auto_play (true);
}
can_save_keybindings = true;
Keyboard::set_can_save_keybindings (true);
return false;
}

View file

@ -227,9 +227,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void set_native_file_header_format (ARDOUR::HeaderFormat sf);
void set_native_file_data_format (ARDOUR::SampleFormat sf);
void set_keybindings_path (std::string path);
void save_keybindings ();
void setup_profile ();
void setup_theme ();
@ -593,10 +590,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void connect_dependents_to_session (ARDOUR::Session *);
void we_have_dependents ();
std::string keybindings_path;
std::string user_keybindings_path;
void setup_keybindings ();
void setup_session_options ();
guint32 last_key_press_time;
@ -748,7 +741,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_control_protocol (ARDOUR::ControlProtocolInfo*);
void toggle_control_protocol_feedback (ARDOUR::ControlProtocolInfo*, const char* group_name, std::string action_name);
bool can_save_keybindings;
bool first_idle ();
void no_memory_warning ();

View file

@ -23,8 +23,6 @@
#include <cstdio>
#include <gtkmm/accelmap.h>
#include <pbd/error.h>
#include "ardour_ui.h"
@ -33,6 +31,7 @@
#include "keyboard.h"
#include "splash.h"
#include "route_params_ui.h"
#include "opts.h"
#include "i18n.h"
using namespace sigc;
@ -60,43 +59,13 @@ ARDOUR_UI::shutdown ()
void
ARDOUR_UI::we_have_dependents ()
{
setup_keybindings ();
editor->UpdateAllTransportClocks.connect (mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
}
static void
accel_map_changed (GtkAccelMap* map,
gchar* path,
guint key,
GdkModifierType mod,
gpointer arg)
{
static_cast<ARDOUR_UI*>(arg)->save_keybindings ();
}
void
ARDOUR_UI::setup_keybindings ()
{
install_actions ();
RedirectBox::register_actions ();
cerr << "loading bindings from " << keybindings_path << endl;
try {
AccelMap::load (keybindings_path);
} catch (...) {
error << string_compose (_("Ardour key bindings file not found at \"%1\" or contains errors."), keybindings_path)
<< endmsg;
}
/* catch changes */
GtkAccelMap* accelmap = gtk_accel_map_get();
g_signal_connect (accelmap, "changed", (GCallback) accel_map_changed, this);
Keyboard::setup_keybindings ();
editor->UpdateAllTransportClocks.connect (mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
}
void

View file

@ -17,6 +17,8 @@
*/
#include <ardour/ardour.h>
#include "ardour_ui.h"
#include <algorithm>
@ -25,15 +27,19 @@
#include <ctype.h>
#include <gtkmm/accelmap.h>
#include <gdk/gdkkeysyms.h>
#include <pbd/error.h>
#include "keyboard.h"
#include "gui_thread.h"
#include "opts.h"
#include "i18n.h"
using namespace PBD;
using namespace ARDOUR;
#define KBD_DEBUG 0
bool debug_keyboard = false;
@ -62,6 +68,11 @@ Keyboard* Keyboard::_the_keyboard = 0;
Gtk::Window* Keyboard::current_window = 0;
bool Keyboard::_some_magic_widget_has_focus = false;
std::string Keyboard::user_keybindings_path;
bool Keyboard::can_save_keybindings = false;
map<string,string> Keyboard::binding_files;
std::string Keyboard::_current_binding_name = _("Unknown");
/* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
GdkModifierType Keyboard::RelevantModifierKeyMask;
@ -360,3 +371,180 @@ Keyboard::selection_type (guint state)
return Selection::Set;
}
}
static void
accel_map_changed (GtkAccelMap* map,
gchar* path,
guint key,
GdkModifierType mod,
gpointer arg)
{
Keyboard::save_keybindings ();
}
void
Keyboard::set_can_save_keybindings (bool yn)
{
can_save_keybindings = yn;
}
void
Keyboard::save_keybindings ()
{
if (can_save_keybindings) {
Gtk::AccelMap::save (user_keybindings_path);
}
}
void
Keyboard::setup_keybindings ()
{
using namespace ARDOUR_COMMAND_LINE;
std::string default_bindings = "mnemonic-us.bindings";
std::string path;
vector<string> strs;
ARDOUR::find_bindings_files (binding_files);
/* set up the per-user bindings path */
strs.push_back (Glib::get_home_dir());
strs.push_back (".ardour2");
strs.push_back ("ardour.bindings");
user_keybindings_path = Glib::build_filename (strs);
/* check to see if they gave a style name ("SAE", "ergonomic") or
an actual filename (*.bindings)
*/
if (!keybindings_path.empty() && keybindings_path.find (".bindings") == string::npos) {
// just a style name - allow user to
// specify the layout type.
char* layout;
if ((layout = getenv ("ARDOUR_KEYBOARD_LAYOUT")) != 0 && layout[0] != '\0') {
/* user-specified keyboard layout */
keybindings_path += '-';
keybindings_path += layout;
} else {
/* default to US/ANSI - we have to pick something */
keybindings_path += "-us";
}
keybindings_path += ".bindings";
}
if (keybindings_path.empty()) {
/* no path or binding name given: check the user one first */
if (!Glib::file_test (user_keybindings_path, Glib::FILE_TEST_EXISTS)) {
keybindings_path = "";
} else {
keybindings_path = user_keybindings_path;
}
}
/* if we still don't have a path at this point, use the default */
if (keybindings_path.empty()) {
keybindings_path = default_bindings;
}
while (true) {
if (!Glib::path_is_absolute (keybindings_path)) {
/* not absolute - look in the usual places */
path = find_config_file (keybindings_path);
if (path.empty()) {
if (keybindings_path == default_bindings) {
error << _("Default keybindings not found - Ardour will be hard to use!") << endmsg;
return;
} else {
warning << string_compose (_("Key bindings file \"%1\" not found. Default bindings used instead"),
keybindings_path)
<< endmsg;
keybindings_path = default_bindings;
}
} else {
/* use it */
keybindings_path = path;
break;
}
} else {
/* path is absolute already */
if (!Glib::file_test (keybindings_path, Glib::FILE_TEST_EXISTS)) {
if (keybindings_path == default_bindings) {
error << _("Default keybindings not found - Ardour will be hard to use!") << endmsg;
return;
} else {
warning << string_compose (_("Key bindings file \"%1\" not found. Default bindings used instead"),
keybindings_path)
<< endmsg;
keybindings_path = default_bindings;
}
} else {
break;
}
}
}
load_keybindings (keybindings_path);
/* catch changes */
GtkAccelMap* accelmap = gtk_accel_map_get();
g_signal_connect (accelmap, "changed", (GCallback) accel_map_changed, 0);
}
bool
Keyboard::load_keybindings (string path)
{
try {
cerr << "loading bindings from " << path << endl;
Gtk::AccelMap::load (path);
_current_binding_name = _("Unknown");
for (map<string,string>::iterator x = binding_files.begin(); x != binding_files.end(); ++x) {
if (path == x->second) {
_current_binding_name = x->first;
break;
}
}
return true;
} catch (...) {
error << string_compose (_("Ardour key bindings file not found at \"%1\" or contains errors."), path)
<< endmsg;
return false;
}
}

View file

@ -110,6 +110,13 @@ class Keyboard : public sigc::trackable, Stateful
static void magic_widget_grab_focus ();
static void magic_widget_drop_focus ();
static void setup_keybindings ();
static void save_keybindings ();
static bool load_keybindings (std::string path);
static void set_can_save_keybindings (bool yn);
static std::string current_binding_name () { return _current_binding_name; }
static std::map<std::string,std::string> binding_files;
private:
static Keyboard* _the_keyboard;
@ -122,6 +129,9 @@ class Keyboard : public sigc::trackable, Stateful
static guint delete_mod;
static guint snap_mod;
static Gtk::Window* current_window;
static std::string user_keybindings_path;
static bool can_save_keybindings;
static std::string _current_binding_name;
static gint _snooper (GtkWidget*, GdkEventKey*, gpointer);
gint snooper (GtkWidget*, GdkEventKey*);

View file

@ -211,59 +211,6 @@ fixup_bundle_environment ()
#endif
static void
setup_keybindings (ARDOUR_UI* ui)
{
Glib::ustring path;
if (keybindings_path.empty()) {
keybindings_path = "ardour";
}
std::string kbpath;
if (keybindings_path.find (".bindings") == string::npos) {
// just a style name - allow user to
// specify the layout type.
char* layout;
if ((layout = getenv ("ARDOUR_KEYBOARD_LAYOUT")) != 0) {
keybindings_path += '-';
keybindings_path += layout;
}
keybindings_path += ".bindings";
}
// XXX timbyr - we need a portable test for "is-absolute" here
if (keybindings_path[0] != '/' && keybindings_path[0] != '.') {
/* not absolute - look in the usual places */
path = find_config_file (keybindings_path);
if (path.empty()) {
warning << string_compose (_("Key bindings file \"%1\" not found. Default bindings used instead"),
keybindings_path)
<< endmsg;
}
} else {
// absolute path from user - use it as is
path = keybindings_path;
}
if (!path.empty()) {
ui->set_keybindings_path (path);
}
}
#ifdef VST_SUPPORT
/* this is called from the entry point of a wine-compiled
executable that is linked against gtk2_ardour built
@ -345,12 +292,6 @@ int main (int argc, char* argv[])
exit (1);
}
BootMessage (_("Loading keybindings"));
setup_keybindings (ui);
BootMessage (_("Start UI event handler"));
ui->run (text_receiver);
ui = 0;

View file

@ -19,6 +19,7 @@
#include <pbd/whitespace.h>
#include <ardour/ardour.h>
#include <ardour/session.h>
#include <ardour/audioengine.h>
#include <ardour/configuration.h>
@ -100,7 +101,7 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
/* kbd/mouse */
keyboard_mouse_table (3, 4),
keyboard_mouse_table (4, 4),
delete_button_adjustment (3, 1, 5),
delete_button_spin (delete_button_adjustment),
edit_button_adjustment (3, 1, 5),
@ -1196,6 +1197,39 @@ OptionEditor::setup_keyboard_options ()
keyboard_mouse_table.attach (*label, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, FILL);
keyboard_mouse_table.attach (snap_modifier_combo, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, FILL);
vector<string> strs;
for (std::map<std::string,std::string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
strs.push_back (bf->first);
}
set_popdown_strings (keyboard_layout_selector, strs);
keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
keyboard_layout_selector.signal_changed().connect (mem_fun (*this, &OptionEditor::bindings_changed));
label = manage (new Label (_("Keyboard layout")));
label->set_name ("OptionsLabel");
label->set_alignment (1.0, 0.5);
keyboard_mouse_table.attach (*label, 0, 1, 3, 4, Gtk::FILL|Gtk::EXPAND, FILL);
keyboard_mouse_table.attach (keyboard_layout_selector, 1, 2, 3, 4, Gtk::FILL|Gtk::EXPAND, FILL);
}
void
OptionEditor::bindings_changed ()
{
string txt;
txt = keyboard_layout_selector.get_active_text();
for (std::map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
if (txt == i->first) {
if (Keyboard::load_keybindings (i->second)) {
Keyboard::save_keybindings ();
}
}
}
}
void

View file

@ -1,3 +1,6 @@
#ifndef __gtk_ardour_option_editor_h__
#define __gtk_ardour_option_editor_h__
/*
Copyright (C) 2001 Paul Davis
@ -17,8 +20,7 @@
*/
#ifndef __gtk_ardour_option_editor_h__
#define __gtk_ardour_option_editor_h__
#include <vector>
#include <gtkmm/notebook.h>
#include <gtkmm/checkbutton.h>
@ -203,6 +205,7 @@ class OptionEditor : public ArdourDialog
/* keyboard/mouse */
Gtk::Table keyboard_mouse_table;
Gtk::ComboBoxText keyboard_layout_selector;
Gtk::ComboBoxText edit_modifier_combo;
Gtk::ComboBoxText delete_modifier_combo;
Gtk::ComboBoxText snap_modifier_combo;
@ -211,12 +214,15 @@ class OptionEditor : public ArdourDialog
Gtk::Adjustment edit_button_adjustment;
Gtk::SpinButton edit_button_spin;
std::map<std::string,std::string> bindings_files;
void setup_keyboard_options ();
void delete_modifier_chosen ();
void edit_modifier_chosen ();
void snap_modifier_chosen ();
void edit_button_changed ();
void delete_button_changed ();
void bindings_changed ();
void fixup_combo_size (Gtk::ComboBoxText&, std::vector<std::string>& strings);
};

View file

@ -77,7 +77,7 @@ ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[])
if (getenv ("ARDOUR_SAE")) {
menus_file = "ardour-sae.menus";
keybindings_path = "ardour-sae";
keybindings_path = "SAE";
}
if (execname == 0) {

View file

@ -20,8 +20,10 @@
#ifndef __ardour_ardour_h__
#define __ardour_ardour_h__
#include <limits.h>
#include <map>
#include <string>
#include <limits.h>
#include <signal.h>
#include <pbd/error.h>
@ -56,6 +58,7 @@ namespace ARDOUR {
std::string find_config_file (std::string name);
std::string find_data_file (std::string name, std::string subdir = "" );
void find_bindings_files (std::map<std::string,std::string>&);
const layer_t max_layer = UCHAR_MAX;

View file

@ -36,6 +36,7 @@
#endif
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
#include <lrdf.h>
@ -43,6 +44,7 @@
#include <pbd/id.h>
#include <pbd/strsplit.h>
#include <pbd/fpu.h>
#include <pbd/pathscanner.h>
#include <midi++/port.h>
#include <midi++/manager.h>
@ -499,24 +501,76 @@ find_file (string name, string dir, string subdir = "")
return path;
}
/* 3rd attempt: dir/... */
path = dir;
path += "/ardour2/";
if (subdir.length()) {
path += subdir + "/";
}
path += name;
if (access (path.c_str(), R_OK) == 0) {
return path;
if (dir.length()) {
/* 3rd attempt: dir/... */
path = dir;
path += "/ardour2/";
if (subdir.length()) {
path += subdir + "/";
}
path += name;
if (access (path.c_str(), R_OK) == 0) {
return path;
}
}
return "";
}
static bool sae_binding_filter (const string& str, void* arg)
{
/* Not a dotfile, has a prefix before a period, suffix is ".bindings" and contains -sae- */
return str[0] != '.' && str.length() > 13 && str.find (".bindings") == (str.length() - 9)
&& str.find ("SAE-") != string::npos;
}
static bool binding_filter (const string& str, void* arg)
{
/* Not a dotfile, has a prefix before a period, suffix is ".bindings" and contains -sae- */
return str[0] != '.' && str.length() > 9 && str.find (".bindings") == (str.length() - 9);
}
void
ARDOUR::find_bindings_files (map<string,string>& files)
{
PathScanner scanner;
vector<string*> *found;
string full_path;
full_path = get_user_ardour_path ();
full_path += ':';
full_path = get_system_data_path ();
if (getenv ("ARDOUR_SAE")) {
found = scanner (full_path, sae_binding_filter, 0, false, true);
} else {
found = scanner (full_path, binding_filter, 0, false, true);
}
if (!found) {
return;
}
for (vector<string*>::iterator x = found->begin(); x != found->end(); ++x) {
string path = *(*x);
pair<string,string> namepath;
namepath.second = path;
path = Glib::path_get_basename (path);
namepath.first = path.substr (0, path.find_first_of ('.'));
files.insert (namepath);
delete *x;
}
delete found;
}
string
ARDOUR::find_config_file (string name)
{