commits 6001-6525 inclusive from 2.X applied to 3.0

git-svn-id: svn://localhost/ardour2/branches/3.0@6942 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-04-21 02:24:38 +00:00
parent cf77196698
commit d9cebc2edf
26 changed files with 361 additions and 99 deletions

View file

@ -8,6 +8,7 @@
<menuitem action='Close'/> <menuitem action='Close'/>
<separator/> <separator/>
<menuitem action='Save'/> <menuitem action='Save'/>
<menuitem action='SaveAs'/>
<menuitem action='Snapshot'/> <menuitem action='Snapshot'/>
<menuitem action='SaveTemplate'/> <menuitem action='SaveTemplate'/>
<menu name='Metadata' action='Metadata'> <menu name='Metadata' action='Metadata'>

View file

@ -343,9 +343,10 @@ ARDOUR_UI::create_engine ()
engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context()); engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context()); engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
engine->Halted.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this), gui_context());
engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context()); engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
post_engine (); post_engine ();
return 0; return 0;
@ -726,10 +727,11 @@ void
ARDOUR_UI::finish() ARDOUR_UI::finish()
{ {
if (_session) { if (_session) {
int tries = 0;
if (_session->transport_rolling()) { if (_session->transport_rolling() && (++tries < 8)) {
_session->request_stop (); _session->request_stop (false, true);
usleep (250000); usleep (10000);
} }
if (_session->dirty()) { if (_session->dirty()) {
@ -1444,14 +1446,14 @@ ARDOUR_UI::transport_stop ()
return; return;
} }
_session->request_stop (); _session->request_stop (false, true);
} }
void void
ARDOUR_UI::transport_stop_and_forget_capture () ARDOUR_UI::transport_stop_and_forget_capture ()
{ {
if (_session) { if (_session) {
_session->request_stop (true); _session->request_stop (true, true);
} }
} }
@ -1519,7 +1521,12 @@ ARDOUR_UI::transport_roll ()
bool rolling = _session->transport_rolling(); bool rolling = _session->transport_rolling();
if (_session->get_play_loop()) { if (_session->get_play_loop()) {
/* XXX it is not possible to just leave seamless loop and keep
playing at present (nov 4th 2009)
*/
if (!Config->get_seamless_loop()) {
_session->request_play_loop (false, true); _session->request_play_loop (false, true);
}
} else if (_session->get_play_range () && !join_play_range_button.get_active()) { } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
/* stop playing a range if we currently are */ /* stop playing a range if we currently are */
_session->request_play_range (0, true); _session->request_play_range (0, true);
@ -1826,23 +1833,46 @@ ARDOUR_UI::engine_running ()
} }
void void
ARDOUR_UI::engine_halted () ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
{ {
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted) if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
/* we can't rely on the original string continuing to exist when we are called
again in the GUI thread, so make a copy and note that we need to
free it later.
*/
char *copy = strdup (reason);
Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
return;
}
ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
update_sample_rate (0); update_sample_rate (0);
MessageDialog msg (*editor, string msgstr;
_("\
/* if the reason is a non-empty string, it means that the backend was shutdown
rather than just Ardour.
*/
if (strlen (reason)) {
msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
} else {
msgstr = _("\
JACK has either been shutdown or it\n\ JACK has either been shutdown or it\n\
disconnected Ardour because Ardour\n\ disconnected Ardour because Ardour\n\
was not fast enough. Try to restart\n\ was not fast enough. Try to restart\n\
JACK, reconnect and save the session.")); JACK, reconnect and save the session.");
}
MessageDialog msg (*editor, msgstr);
pop_back_splash (); pop_back_splash ();
msg.run (); msg.run ();
if (free_reason) {
free ((char*) reason);
}
} }
int32_t int32_t
@ -1940,11 +1970,20 @@ ARDOUR_UI::stop_blinking ()
/** Ask the user for the name of a new shapshot and then take it. /** Ask the user for the name of a new shapshot and then take it.
*/ */
void void
ARDOUR_UI::snapshot_session () ARDOUR_UI::snapshot_session (bool switch_to_it)
{ {
ArdourPrompter prompter (true); ArdourPrompter prompter (true);
string snapname; string snapname;
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_title (_("Take Snapshot"));
prompter.set_title (_("Take Snapshot"));
prompter.set_prompt (_("Name of New Snapshot"));
if (!switch_to_it) {
char timebuf[128]; char timebuf[128];
time_t n; time_t n;
struct tm local_time; struct tm local_time;
@ -1952,12 +1991,8 @@ ARDOUR_UI::snapshot_session ()
time (&n); time (&n);
localtime_r (&n, &local_time); localtime_r (&n, &local_time);
strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time); strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_title (_("Take Snapshot"));
prompter.set_prompt (_("Name of New Snapshot"));
prompter.set_initial_text (timebuf); prompter.set_initial_text (timebuf);
}
again: again:
switch (prompter.run()) { switch (prompter.run()) {
@ -2000,7 +2035,7 @@ ARDOUR_UI::snapshot_session ()
} }
if (do_save) { if (do_save) {
save_state (snapname); save_state (snapname, switch_to_it);
} }
break; break;
} }
@ -2011,13 +2046,13 @@ ARDOUR_UI::snapshot_session ()
} }
void void
ARDOUR_UI::save_state (const string & name) ARDOUR_UI::save_state (const string & name, bool switch_to_it)
{ {
save_state_canfail (name); save_state_canfail (name, switch_to_it);
} }
int int
ARDOUR_UI::save_state_canfail (string name) ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
{ {
if (_session) { if (_session) {
int ret; int ret;
@ -2026,7 +2061,7 @@ ARDOUR_UI::save_state_canfail (string name)
name = _session->snap_name(); name = _session->snap_name();
} }
if ((ret = _session->save_state (name)) != 0) { if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
return ret; return ret;
} }
} }

View file

@ -147,8 +147,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
int unload_session (bool hide_stuff = false); int unload_session (bool hide_stuff = false);
void close_session(); void close_session();
int save_state_canfail (std::string state_name = ""); int save_state_canfail (std::string state_name = "", bool switch_to_it = false);
void save_state (const std::string & state_name = ""); void save_state (const std::string & state_name = "", bool switch_to_it = false);
static double gain_to_slider_position (ARDOUR::gain_t g); static double gain_to_slider_position (ARDOUR::gain_t g);
static ARDOUR::gain_t slider_position_to_gain (double pos); static ARDOUR::gain_t slider_position_to_gain (double pos);
@ -282,7 +282,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void map_transport_state (); void map_transport_state ();
int32_t do_engine_start (); int32_t do_engine_start ();
void engine_halted (); void engine_halted (const char* reason, bool free_reason);
void engine_stopped (); void engine_stopped ();
void engine_running (); void engine_running ();
@ -567,7 +567,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
guint32 last_key_press_time; guint32 last_key_press_time;
void snapshot_session (); void snapshot_session (bool switch_to_it);
Mixer_UI *mixer; Mixer_UI *mixer;
int create_mixer (); int create_mixer ();
@ -694,6 +694,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
Glib::RefPtr<Gtk::TextBuffer::Tag> ptag, Glib::RefPtr<Gtk::TextBuffer::Tag> mtag, Glib::RefPtr<Gtk::TextBuffer::Tag> ptag, Glib::RefPtr<Gtk::TextBuffer::Tag> mtag,
const char *msg); const char *msg);
Gtk::Label status_bar_label; Gtk::Label status_bar_label;
bool status_bar_button_press (GdkEventButton*);
Gtk::ToggleButton error_log_button; Gtk::ToggleButton error_log_button;
void loading_message (const std::string& msg); void loading_message (const std::string& msg);

View file

@ -76,12 +76,21 @@ ARDOUR_UI::setup_windows ()
#ifdef TOP_MENUBAR #ifdef TOP_MENUBAR
HBox* status_bar_packer = manage (new HBox); HBox* status_bar_packer = manage (new HBox);
EventBox* status_bar_event_box = manage (new EventBox);
status_bar_event_box->add (status_bar_label);
status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
status_bar_label.set_size_request (300, -1); status_bar_label.set_size_request (300, -1);
status_bar_packer->pack_start (status_bar_label, true, true, 6); status_bar_packer->pack_start (*status_bar_event_box, true, true, 6);
status_bar_packer->pack_start (error_log_button, false, false); status_bar_packer->pack_start (error_log_button, false, false);
error_log_button.signal_clicked().connect (sigc::mem_fun (*this, &UI::toggle_errors)); status_bar_label.show ();
status_bar_event_box->show ();
status_bar_packer->show ();
error_log_button.show ();
error_log_button.signal_clicked().connect (mem_fun (*this, &UI::toggle_errors));
status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press));
editor->get_status_bar_packer().pack_start (*status_bar_packer, true, true); editor->get_status_bar_packer().pack_start (*status_bar_packer, true, true);
editor->get_status_bar_packer().pack_start (menu_bar_base, false, false, 6); editor->get_status_bar_packer().pack_start (menu_bar_base, false, false, 6);
@ -133,6 +142,23 @@ ARDOUR_UI::setup_tooltips ()
editor->setup_tooltips (); editor->setup_tooltips ();
} }
bool
ARDOUR_UI::status_bar_button_press (GdkEventButton* ev)
{
bool handled = false;
switch (ev->button) {
case 1:
status_bar_label.set_text ("");
handled = true;
break;
default:
break;
}
return handled;
}
void void
ARDOUR_UI::display_message (const char *prefix, gint prefix_len, RefPtr<TextBuffer::Tag> ptag, RefPtr<TextBuffer::Tag> mtag, const char *msg) ARDOUR_UI::display_message (const char *prefix, gint prefix_len, RefPtr<TextBuffer::Tag> ptag, RefPtr<TextBuffer::Tag> mtag, const char *msg)
{ {

View file

@ -136,7 +136,11 @@ ARDOUR_UI::install_actions ()
#endif #endif
act = ActionManager::register_action (main_actions, X_("Snapshot"), _("Snapshot..."), sigc::mem_fun(*this, &ARDOUR_UI::snapshot_session)); act = ActionManager::register_action (main_actions, X_("Snapshot"), _("Snapshot..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::snapshot_session), false));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("SaveAs"), _("SaveAs ..."), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::snapshot_session), true));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act); ActionManager::write_sensitive_actions.push_back (act);
@ -237,7 +241,7 @@ ARDOUR_UI::install_actions ()
//act = ActionManager::register_action (common_actions, X_("AddMidiBus"), _("Add Midi Bus"), sigc::mem_fun(*this, &ARDOUR_UI::session_add_midi_bus)); //act = ActionManager::register_action (common_actions, X_("AddMidiBus"), _("Add Midi Bus"), sigc::mem_fun(*this, &ARDOUR_UI::session_add_midi_bus));
//ActionManager::session_sensitive_actions.push_back (act); //ActionManager::session_sensitive_actions.push_back (act);
#endif #endif
act = ActionManager::register_action (common_actions, X_("Save"), _("Save"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""))); act = ActionManager::register_action (common_actions, X_("Save"), _("Save"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""), false));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act); ActionManager::write_sensitive_actions.push_back (act);
act = ActionManager::register_action (common_actions, X_("RemoveLastCapture"), _("Remove Last Capture"), sigc::mem_fun(*this, &ARDOUR_UI::remove_last_capture)); act = ActionManager::register_action (common_actions, X_("RemoveLastCapture"), _("Remove Last Capture"), sigc::mem_fun(*this, &ARDOUR_UI::remove_last_capture));

View file

@ -1493,7 +1493,7 @@ Editor::build_track_region_context_menu (nframes64_t frame)
boost::shared_ptr<Region> dummy_region; // = NULL boost::shared_ptr<Region> dummy_region; // = NULL
add_region_context_items (rtv->view(), dummy_region, edit_items); add_region_context_items (rtv->view(), dummy_region, edit_items);
} else { } else {
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) {
add_region_context_items (rtv->view(), (*i), edit_items); add_region_context_items (rtv->view(), (*i), edit_items);
} }
} }
@ -1541,7 +1541,7 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame)
boost::shared_ptr<Region> dummy_region; // = NULL boost::shared_ptr<Region> dummy_region; // = NULL
add_region_context_items (atv->audio_view(), dummy_region, edit_items); add_region_context_items (atv->audio_view(), dummy_region, edit_items);
} else { } else {
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) {
add_region_context_items (atv->audio_view(), (*i), edit_items); add_region_context_items (atv->audio_view(), (*i), edit_items);
} }
} }

View file

@ -20,7 +20,7 @@
#define _LIBGETTEXT_H 1 #define _LIBGETTEXT_H 1
/* NLS can be disabled through the configure --disable-nls option. */ /* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS #ifdef ENABLE_NLS
/* Get declarations of GNU message catalog functions. */ /* Get declarations of GNU message catalog functions. */
# include <libintl.h> # include <libintl.h>

View file

@ -586,7 +586,7 @@ PluginSelector::build_plugin_menu ()
delete _plugin_menu; delete _plugin_menu;
_plugin_menu = new Menu; _plugin_menu = manage (new Menu);
_plugin_menu->set_name("ArdourContextMenu"); _plugin_menu->set_name("ArdourContextMenu");
MenuList& items = _plugin_menu->items(); MenuList& items = _plugin_menu->items();

View file

@ -1242,11 +1242,27 @@ ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
case Gtk::RESPONSE_ACCEPT: case Gtk::RESPONSE_ACCEPT:
name_prompter.get_result (result); name_prompter.get_result (result);
if (result.length()) { if (result.length()) {
if (_session->route_by_name (result)) {
ARDOUR_UI::instance()->popup_error (_("A track already exists with that name.")); int tries = 0;
return; string test = result;
while (tries < 100) {
if (_session->io_name_is_legal (test)) {
result = test;
break;
} }
tries++;
test = string_compose ("%1-%2", result, tries);
}
if (tries < 100) {
processor->set_name (result); processor->set_name (result);
} else {
/* unlikely! */
ARDOUR_UI::instance()->popup_error
(string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result));
}
} }
break; break;
} }

View file

@ -504,12 +504,6 @@ set_color (Gdk::Color& c, int rgb)
c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256); c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
} }
#ifdef GTKOSX
extern "C" {
gboolean gdk_quartz_possibly_forward (GdkEvent*);
}
#endif
bool bool
relay_key_press (GdkEventKey* ev, Gtk::Window* win) relay_key_press (GdkEventKey* ev, Gtk::Window* win)
{ {
@ -526,6 +520,73 @@ forward_key_press (GdkEventKey* ev)
return PublicEditor::instance().on_key_press_event(ev); return PublicEditor::instance().on_key_press_event(ev);
} }
#ifdef GTKOSX
static guint
osx_keyval_without_alt (guint accent_keyval)
{
switch (accent_keyval) {
case GDK_oe:
return GDK_q;
case GDK_registered:
return GDK_r;
case GDK_dagger:
return GDK_t;
case GDK_yen:
return GDK_y;
case GDK_diaeresis:
return GDK_u;
case GDK_oslash:
return GDK_o;
case GDK_Greek_pi:
return GDK_p;
case GDK_leftdoublequotemark:
return GDK_bracketleft;
case GDK_leftsinglequotemark:
return GDK_bracketright;
case GDK_guillemotleft:
return GDK_backslash;
case GDK_aring:
return GDK_a;
case GDK_ssharp:
return GDK_s;
case GDK_partialderivative:
return GDK_d;
case GDK_function:
return GDK_f;
case GDK_copyright:
return GDK_g;
case GDK_abovedot:
return GDK_h;
case GDK_notsign:
return GDK_l;
case GDK_ellipsis:
return GDK_semicolon;
case GDK_ae:
return GDK_apostrophe;
case GDK_Greek_OMEGA:
return GDK_z;
case GDK_ccedilla:
return GDK_c;
case GDK_radical:
return GDK_v;
case GDK_integral:
return GDK_b;
case GDK_mu:
return GDK_m;
case GDK_lessthanequal:
return GDK_comma;
case GDK_greaterthanequal:
return GDK_period;
case GDK_division:
return GDK_slash;
default:
break;
}
return GDK_VoidSymbol;
}
#endif
bool bool
key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
{ {
@ -595,6 +656,24 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
all "normal text" accelerators. all "normal text" accelerators.
*/ */
#ifdef GTKOSX
if (!special_handling_of_unmodified_accelerators) {
if (ev->state & GDK_MOD1_MASK) {
/* we're not in a text entry or "magic focus" widget so we don't want OS X "special-character"
text-style handling of alt-<key>. change the keyval back to what it would be without
the alt key. this way, we see <alt>-v rather than <alt>-radical and so on.
*/
guint keyval_without_alt = osx_keyval_without_alt (ev->keyval);
if (keyval_without_alt != GDK_VoidSymbol) {
#ifdef DEBUG_ACCELERATOR_HANDLING
cerr << "Remapped " << gdk_keyval_name (ev->keyval) << " to " << gdk_keyval_name (keyval_without_alt) << endl;
#endif ev->keyval = keyval_without_alt;
}
}
}
#endif
if (!special_handling_of_unmodified_accelerators) { if (!special_handling_of_unmodified_accelerators) {
@ -609,17 +688,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) { if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) {
return true; return true;
} }
#ifdef GTKOSX
if (allow_activating) {
int oldval = ev->keyval;
ev->keyval = fakekey;
if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
return true;
}
ev->keyval = oldval;
}
#endif
} }
} }
@ -638,11 +706,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
#endif #endif
if (allow_activating) { if (allow_activating) {
#ifdef GTKOSX
if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
return true;
}
#endif
if (gtk_window_activate_key (win, ev)) { if (gtk_window_activate_key (win, ev)) {
return true; return true;
} }
@ -671,12 +734,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
#endif #endif
if (allow_activating) { if (allow_activating) {
#ifdef GTKOSX
if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
return true;
}
#endif
return gtk_window_activate_key (win, ev); return gtk_window_activate_key (win, ev);
} }

View file

@ -224,7 +224,7 @@ _ the regular process() call to session->process() is not made.
/* this signal is sent if JACK ever disconnects us */ /* this signal is sent if JACK ever disconnects us */
PBD::Signal0<void> Halted; PBD::Signal1<void,const char*> Halted;
/* these two are emitted when the engine itself is /* these two are emitted when the engine itself is
started and stopped started and stopped
@ -306,6 +306,7 @@ _ the regular process() call to session->process() is not made.
int connect_to_jack (std::string client_name, std::string session_uuid); int connect_to_jack (std::string client_name, std::string session_uuid);
static void halted (void *); static void halted (void *);
static void halted_info (jack_status_t,const char*,void *);
void meter_thread (); void meter_thread ();
void start_metering_thread (); void start_metering_thread ();

View file

@ -188,6 +188,7 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou
bool processor_is_prefader (boost::shared_ptr<Processor> p); bool processor_is_prefader (boost::shared_ptr<Processor> p);
bool has_io_processor_named (const std::string&);
ChanCount max_processor_streams () const { return processor_max_streams; } ChanCount max_processor_streams () const { return processor_max_streams; }
/* special processors */ /* special processors */

View file

@ -240,6 +240,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
template<class T> void foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>)); template<class T> void foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>));
template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg); template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg);
bool io_name_is_legal (const std::string&);
boost::shared_ptr<Route> route_by_name (std::string); boost::shared_ptr<Route> route_by_name (std::string);
boost::shared_ptr<Route> route_by_id (PBD::ID); boost::shared_ptr<Route> route_by_id (PBD::ID);
boost::shared_ptr<Route> route_by_remote_id (uint32_t id); boost::shared_ptr<Route> route_by_remote_id (uint32_t id);
@ -356,7 +357,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
#ifdef HAVE_JACK_SESSION #ifdef HAVE_JACK_SESSION
void jack_session_event (jack_session_event_t* event); void jack_session_event (jack_session_event_t* event);
#endif #endif
int save_state (std::string snapshot_name, bool pending = false); int save_state (std::string snapshot_name, bool pending = false, bool switch_to_snapshot = false);
int restore_state (std::string snapshot_name); int restore_state (std::string snapshot_name);
int save_template (std::string template_name); int save_template (std::string template_name);
int save_history (std::string snapshot_name = ""); int save_history (std::string snapshot_name = "");

View file

@ -145,6 +145,19 @@ _thread_init_callback (void * /*arg*/)
MIDI::JACK_MidiPort::set_process_thread (pthread_self()); MIDI::JACK_MidiPort::set_process_thread (pthread_self());
} }
typedef void (*_JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg);
static void (*on_info_shutdown)(jack_client_t*, _JackInfoShutdownCallback, void *);
extern void jack_on_info_shutdown (jack_client_t*, _JackInfoShutdownCallback, void *) __attribute__((weak));
static void check_jack_symbols () __attribute__((constructor));
void check_jack_symbols ()
{
/* use weak linking to see if we really have various late-model JACK function */
on_info_shutdown = jack_on_info_shutdown;
}
static void static void
ardour_jack_error (const char* msg) ardour_jack_error (const char* msg)
{ {
@ -183,7 +196,11 @@ AudioEngine::start ()
_processed_frames = 0; _processed_frames = 0;
last_monitor_check = 0; last_monitor_check = 0;
if (on_info_shutdown) {
jack_on_info_shutdown (_priv_jack, halted_info, this);
} else {
jack_on_shutdown (_priv_jack, halted, this); jack_on_shutdown (_priv_jack, halted, this);
}
jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this); jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this); jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this);
// jack_set_process_callback (_priv_jack, _process_callback, this); // jack_set_process_callback (_priv_jack, _process_callback, this);
@ -968,6 +985,36 @@ AudioEngine::get_ports (const string& port_name_pattern, const string& type_name
return jack_get_ports (_priv_jack, port_name_pattern.c_str(), type_name_pattern.c_str(), flags); return jack_get_ports (_priv_jack, port_name_pattern.c_str(), type_name_pattern.c_str(), flags);
} }
void
AudioEngine::halted_info (jack_status_t code, const char* reason, void *arg)
{
/* called from jack shutdown handler */
AudioEngine* ae = static_cast<AudioEngine *> (arg);
bool was_running = ae->_running;
ae->stop_metering_thread ();
ae->_running = false;
ae->_buffer_size = 0;
ae->_frame_rate = 0;
ae->_jack = 0;
if (was_running) {
#ifdef HAVE_JACK_ON_INFO_SHUTDOWN
switch (code) {
case JackBackendError:
ae->Halted(reason); /* EMIT SIGNAL */
break;
default:
ae->Halted(""); /* EMIT SIGNAL */
}
#else
ae->Halted(""); /* EMIT SIGNAL */
#endif
}
}
void void
AudioEngine::halted (void *arg) AudioEngine::halted (void *arg)
{ {
@ -983,9 +1030,10 @@ AudioEngine::halted (void *arg)
ae->_running = false; ae->_running = false;
ae->_buffer_size = 0; ae->_buffer_size = 0;
ae->_frame_rate = 0; ae->_frame_rate = 0;
ae->_jack = 0;
if (was_running) { if (was_running) {
ae->Halted(); /* EMIT SIGNAL */ ae->Halted(""); /* EMIT SIGNAL */
MIDI::JACK_MidiPort::JackHalted (); /* EMIT SIGNAL */ MIDI::JACK_MidiPort::JackHalted (); /* EMIT SIGNAL */
} }
} }

View file

@ -20,7 +20,7 @@
#define _LIBGETTEXT_H 1 #define _LIBGETTEXT_H 1
/* NLS can be disabled through the configure --disable-nls option. */ /* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS #ifdef ENABLE_NLS
/* Get declarations of GNU message catalog functions. */ /* Get declarations of GNU message catalog functions. */
# include <libintl.h> # include <libintl.h>

View file

@ -691,6 +691,7 @@ LadspaPluginInfo::load (Session& session)
if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg; error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg;
error << dlerror() << endmsg; error << dlerror() << endmsg;
return PluginPtr ((Plugin*) 0);
} else { } else {
plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate())); plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate()));
} }

View file

@ -1004,7 +1004,7 @@ Playlist::partition_internal (framepos_t start, framepos_t end, bool cutting, Re
current->suspend_property_changes (); current->suspend_property_changes ();
thawlist.push_back (current); thawlist.push_back (current);
current->cut_end (pos2, this); current->cut_end (pos2 - 1, this);
} else if (overlap == OverlapEnd) { } else if (overlap == OverlapEnd) {
@ -1043,7 +1043,7 @@ Playlist::partition_internal (framepos_t start, framepos_t end, bool cutting, Re
current->suspend_property_changes (); current->suspend_property_changes ();
thawlist.push_back (current); thawlist.push_back (current);
current->cut_end (pos2, this); current->cut_end (pos2 - 1, this);
} else if (overlap == OverlapStart) { } else if (overlap == OverlapStart) {
@ -2490,22 +2490,48 @@ void
Playlist::raise_region_to_top (boost::shared_ptr<Region> region) Playlist::raise_region_to_top (boost::shared_ptr<Region> region)
{ {
/* does nothing useful if layering mode is later=higher */ /* does nothing useful if layering mode is later=higher */
if ((_session.config.get_layer_model() == MoveAddHigher) || switch (_session.config.get_layer_model()) {
(_session.config.get_layer_model() == AddHigher)) { case LaterHigher:
timestamp_layer_op (region); return;
relayer (); default:
break;
} }
layer_t top = regions.size() - 1;
if (region->layer() >= top) {
/* already on the top */
return;
}
move_region_to_layer (top, region, 1);
/* mark the region's last_layer_op as now, so that it remains on top when
doing future relayers (until something else takes over)
*/
timestamp_layer_op (region);
} }
void void
Playlist::lower_region_to_bottom (boost::shared_ptr<Region> region) Playlist::lower_region_to_bottom (boost::shared_ptr<Region> region)
{ {
/* does nothing useful if layering mode is later=higher */ /* does nothing useful if layering mode is later=higher */
if ((_session.config.get_layer_model() == MoveAddHigher) || switch (_session.config.get_layer_model()) {
(_session.config.get_layer_model() == AddHigher)) { case LaterHigher:
region->set_last_layer_op (0); return;
relayer (); default:
break;
} }
if (region->layer() == 0) {
/* already on the bottom */
return;
}
move_region_to_layer (0, region, -1);
/* force region's last layer op to zero so that it stays at the bottom
when doing future relayers
*/
region->set_last_layer_op (0);
} }
int int
@ -2688,8 +2714,6 @@ Playlist::set_frozen (bool yn)
void void
Playlist::timestamp_layer_op (boost::shared_ptr<Region> region) Playlist::timestamp_layer_op (boost::shared_ptr<Region> region)
{ {
// struct timeval tv;
// gettimeofday (&tv, 0);
region->set_last_layer_op (++layer_op_counter); region->set_last_layer_op (++layer_op_counter);
} }

View file

@ -269,7 +269,7 @@ Route::ensure_track_or_route_name(string name, Session &session)
{ {
string newname = name; string newname = name;
while (session.route_by_name (newname) != NULL) { while (!session.io_name_is_legal (newname)) {
newname = bump_name_once (newname); newname = bump_name_once (newname);
} }
@ -3252,3 +3252,21 @@ Route::nth_send (uint32_t n)
return boost::shared_ptr<Processor> (); return boost::shared_ptr<Processor> ();
} }
bool
Route::has_io_processor_named (const string& name)
{
Glib::RWLock::ReaderLock lm (_processor_lock);
ProcessorList::iterator i;
for (i = _processors.begin(); i != _processors.end(); ++i) {
if (boost::dynamic_pointer_cast<Send> (*i) ||
boost::dynamic_pointer_cast<PortInsert> (*i)) {
if ((*i)->name() == name) {
return true;
}
}
}
return false;
}

View file

@ -2304,6 +2304,24 @@ Session::get_routes_with_internal_returns() const
return rl; return rl;
} }
bool
Session::io_name_is_legal (const std::string& name)
{
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if ((*i)->name() == name) {
return false;
}
if ((*i)->has_io_processor_named (name)) {
return false;
}
}
return true;
}
shared_ptr<Route> shared_ptr<Route>
Session::route_by_name (string name) Session::route_by_name (string name)
{ {

View file

@ -748,7 +748,7 @@ Session::jack_session_event (jack_session_event_t * event)
#endif #endif
int int
Session::save_state (string snapshot_name, bool pending) Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
{ {
XMLTree tree; XMLTree tree;
sys::path xml_path(_session_dir->root_path()); sys::path xml_path(_session_dir->root_path());
@ -773,6 +773,8 @@ Session::save_state (string snapshot_name, bool pending)
if (snapshot_name.empty()) { if (snapshot_name.empty()) {
snapshot_name = _current_snapshot_name; snapshot_name = _current_snapshot_name;
} else if (switch_to_snapshot) {
_current_snapshot_name = snapshot_name;
} }
if (!pending) { if (!pending) {

View file

@ -230,7 +230,8 @@ Session::realtime_stop (bool abort, bool clear_state)
_clear_event_type (SessionEvent::RangeStop); _clear_event_type (SessionEvent::RangeStop);
_clear_event_type (SessionEvent::RangeLocate); _clear_event_type (SessionEvent::RangeLocate);
disable_record (true); /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
disable_record (true, (!Config->get_latched_record_enable() && clear_state));
reset_slave_state (); reset_slave_state ();

View file

@ -245,6 +245,12 @@ def configure(conf):
conf.check(header_name='jack/session.h', define_name='HAVE_JACK_SESSION') conf.check(header_name='jack/session.h', define_name='HAVE_JACK_SESSION')
conf.check_cc(fragment = "#include <jack/jack.h>\nvoid callback (int code, const char* reason, void* arg) { return; }\nint main(int argc, char **argv) { jack_client_t* c; jack_on_info_shutdown (c, callback, (void*) 0); return 0; }\n",
linkflags = ['-ljack'],
msg = 'Checking for jack_on_info_shutdown',
define_name = 'HAVE_JACK_ON_INFO_SHUTDOWN',
okmsg = 'ok')
if flac_supported(): if flac_supported():
conf.define ('HAVE_FLAC', 1) conf.define ('HAVE_FLAC', 1)
autowaf.display_msg(conf, 'Checking for FLAC support', True) autowaf.display_msg(conf, 'Checking for FLAC support', True)

View file

@ -20,7 +20,7 @@
#define _LIBGETTEXT_H 1 #define _LIBGETTEXT_H 1
/* NLS can be disabled through the configure --disable-nls option. */ /* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS #ifdef ENABLE_NLS
/* Get declarations of GNU message catalog functions. */ /* Get declarations of GNU message catalog functions. */
# include <libintl.h> # include <libintl.h>

View file

@ -602,7 +602,7 @@ UI::handle_fatal (const char *message)
} }
void void
UI::popup_error (const char *text) UI::popup_error (const string& text)
{ {
PopUp *pup; PopUp *pup;

View file

@ -109,7 +109,7 @@ class UI : public Receiver, public AbstractUI<UIRequest>
void run (Receiver &old_receiver); void run (Receiver &old_receiver);
void set_state (Gtk::Widget *w, Gtk::StateType state); void set_state (Gtk::Widget *w, Gtk::StateType state);
void popup_error (const char *text); void popup_error (const std::string& text);
void flush_pending (); void flush_pending ();
void toggle_errors (); void toggle_errors ();
void touch_display (Touchable *); void touch_display (Touchable *);

View file

@ -81,7 +81,7 @@ std::string Keyboard::user_keybindings_path;
bool Keyboard::can_save_keybindings = false; bool Keyboard::can_save_keybindings = false;
bool Keyboard::bindings_changed_after_save_became_legal = false; bool Keyboard::bindings_changed_after_save_became_legal = false;
map<string,string> Keyboard::binding_files; map<string,string> Keyboard::binding_files;
string Keyboard::_current_binding_name = _("Unknown"); string Keyboard::_current_binding_name;
map<AccelKey,pair<string,string>,Keyboard::AccelKeyLess> Keyboard::release_keys; map<AccelKey,pair<string,string>,Keyboard::AccelKeyLess> Keyboard::release_keys;
/* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */ /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
@ -110,6 +110,7 @@ Keyboard::Keyboard ()
{ {
if (_the_keyboard == 0) { if (_the_keyboard == 0) {
_the_keyboard = this; _the_keyboard = this;
_current_binding_name = _("Unknown");
} }
RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask (); RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask ();