mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-08 15:54:57 +01:00
(merge from 2.0-ongoing -r1911:1912) fix audio clock handling of key press; fix crash bug caused by mapping over a region list selection that includes rows without regions; also merge sampo's redirect undo/state fixes from 2.0-ongoing
git-svn-id: svn://localhost/ardour2/trunk@1913 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
dc348fb613
commit
376c5381ed
8 changed files with 241 additions and 62 deletions
|
|
@ -337,6 +337,18 @@ AudioClock::setup_events ()
|
||||||
ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
|
ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
|
||||||
ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
|
ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
|
||||||
|
|
||||||
|
hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Hours));
|
||||||
|
minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Minutes));
|
||||||
|
seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Seconds));
|
||||||
|
frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Frames));
|
||||||
|
audio_frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), AudioFrames));
|
||||||
|
bars_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Bars));
|
||||||
|
beats_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Beats));
|
||||||
|
ticks_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Ticks));
|
||||||
|
ms_hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Hours));
|
||||||
|
ms_minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Minutes));
|
||||||
|
ms_seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Seconds));
|
||||||
|
|
||||||
hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
|
hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
|
||||||
minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
|
minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
|
||||||
seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
|
seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
|
||||||
|
|
@ -372,6 +384,15 @@ AudioClock::setup_events ()
|
||||||
ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
|
ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
|
||||||
ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
|
ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
|
||||||
ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
|
ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
|
||||||
|
|
||||||
|
clock_base.signal_focus_in_event().connect (mem_fun (*this, &AudioClock::drop_focus_handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioClock::drop_focus_handler (GdkEventFocus* ignored)
|
||||||
|
{
|
||||||
|
Keyboard::magic_widget_drop_focus ();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -633,6 +654,13 @@ AudioClock::set_session (Session *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
|
||||||
|
{
|
||||||
|
/* all key activity is handled on key release */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
|
AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
|
||||||
{
|
{
|
||||||
|
|
@ -679,7 +707,7 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
|
||||||
label = &ticks_label;
|
label = &ticks_label;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ev->keyval) {
|
switch (ev->keyval) {
|
||||||
|
|
@ -729,22 +757,22 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
|
||||||
if (_mode == MinSec && field == MS_Seconds) {
|
if (_mode == MinSec && field == MS_Seconds) {
|
||||||
new_char = '.';
|
new_char = '.';
|
||||||
} else {
|
} else {
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_Return:
|
|
||||||
case GDK_KP_Enter:
|
|
||||||
case GDK_Tab:
|
case GDK_Tab:
|
||||||
move_on = true;
|
move_on = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_Escape:
|
case GDK_Escape:
|
||||||
|
case GDK_Return:
|
||||||
|
case GDK_KP_Enter:
|
||||||
clock_base.grab_focus ();
|
clock_base.grab_focus ();
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!move_on) {
|
if (!move_on) {
|
||||||
|
|
@ -865,7 +893,7 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -873,6 +901,8 @@ AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
|
||||||
{
|
{
|
||||||
key_entry_state = 0;
|
key_entry_state = 0;
|
||||||
|
|
||||||
|
Keyboard::magic_widget_grab_focus ();
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case SMPTE_Hours:
|
case SMPTE_Hours:
|
||||||
hours_ebox.set_flags (Gtk::HAS_FOCUS);
|
hours_ebox.set_flags (Gtk::HAS_FOCUS);
|
||||||
|
|
@ -922,7 +952,7 @@ AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -979,21 +1009,20 @@ AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
Keyboard::magic_widget_drop_focus ();
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
|
AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
gdk_pointer_ungrab (GDK_CURRENT_TIME);
|
||||||
dragging = false;
|
dragging = false;
|
||||||
if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
|
if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
|
||||||
// we actually dragged so return without setting editing focus, or we shift clicked
|
// we actually dragged so return without setting editing focus, or we shift clicked
|
||||||
|
return true;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1002,7 +1031,7 @@ AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
|
||||||
build_ops_menu ();
|
build_ops_menu ();
|
||||||
}
|
}
|
||||||
ops_menu->popup (1, ev->time);
|
ops_menu->popup (1, ev->time);
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Keyboard::is_context_menu_event (ev)) {
|
if (Keyboard::is_context_menu_event (ev)) {
|
||||||
|
|
@ -1010,7 +1039,7 @@ AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
|
||||||
build_ops_menu ();
|
build_ops_menu ();
|
||||||
}
|
}
|
||||||
ops_menu->popup (1, ev->time);
|
ops_menu->popup (1, ev->time);
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ev->button) {
|
switch (ev->button) {
|
||||||
|
|
@ -1059,13 +1088,13 @@ AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
|
AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
|
||||||
{
|
{
|
||||||
if (session == 0) return FALSE;
|
if (session == 0) return false;
|
||||||
|
|
||||||
nframes_t frames = 0;
|
nframes_t frames = 0;
|
||||||
|
|
||||||
|
|
@ -1077,7 +1106,7 @@ AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make absolutely sure that the pointer is grabbed */
|
/* make absolutely sure that the pointer is grabbed */
|
||||||
gdk_pointer_grab(ev->window,FALSE ,
|
gdk_pointer_grab(ev->window,false ,
|
||||||
GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
|
GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
|
||||||
NULL,NULL,ev->time);
|
NULL,NULL,ev->time);
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
|
@ -1095,21 +1124,23 @@ AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
/* used for context sensitive menu */
|
/* used for context sensitive menu */
|
||||||
return FALSE;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
|
AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
|
||||||
{
|
{
|
||||||
if (session == 0) return FALSE;
|
if (session == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
nframes_t frames = 0;
|
nframes_t frames = 0;
|
||||||
|
|
||||||
|
|
@ -1144,18 +1175,18 @@ AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
|
AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
|
||||||
{
|
{
|
||||||
if (session == 0 || !dragging) {
|
if (session == 0 || !dragging) {
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float pixel_frame_scale_factor = 0.2f;
|
float pixel_frame_scale_factor = 0.2f;
|
||||||
|
|
@ -1202,7 +1233,7 @@ AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ class AudioClock : public Gtk::HBox
|
||||||
static sigc::signal<void> ModeChanged;
|
static sigc::signal<void> ModeChanged;
|
||||||
static std::vector<AudioClock*> clocks;
|
static std::vector<AudioClock*> clocks;
|
||||||
|
|
||||||
|
static bool has_focus() { return _has_focus; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ARDOUR::Session *session;
|
ARDOUR::Session *session;
|
||||||
Mode _mode;
|
Mode _mode;
|
||||||
|
|
@ -173,9 +175,11 @@ class AudioClock : public Gtk::HBox
|
||||||
bool field_button_press_event (GdkEventButton *ev, Field);
|
bool field_button_press_event (GdkEventButton *ev, Field);
|
||||||
bool field_button_release_event (GdkEventButton *ev, Field);
|
bool field_button_release_event (GdkEventButton *ev, Field);
|
||||||
bool field_button_scroll_event (GdkEventScroll *ev, Field);
|
bool field_button_scroll_event (GdkEventScroll *ev, Field);
|
||||||
|
bool field_key_press_event (GdkEventKey *, Field);
|
||||||
bool field_key_release_event (GdkEventKey *, Field);
|
bool field_key_release_event (GdkEventKey *, Field);
|
||||||
bool field_focus_in_event (GdkEventFocus *, Field);
|
bool field_focus_in_event (GdkEventFocus *, Field);
|
||||||
bool field_focus_out_event (GdkEventFocus *, Field);
|
bool field_focus_out_event (GdkEventFocus *, Field);
|
||||||
|
bool drop_focus_handler (GdkEventFocus*);
|
||||||
|
|
||||||
void set_smpte (nframes_t, bool);
|
void set_smpte (nframes_t, bool);
|
||||||
void set_bbt (nframes_t, bool);
|
void set_bbt (nframes_t, bool);
|
||||||
|
|
@ -198,6 +202,8 @@ class AudioClock : public Gtk::HBox
|
||||||
void set_size_requests ();
|
void set_size_requests ();
|
||||||
|
|
||||||
static const uint32_t field_length[(int)AudioFrames+1];
|
static const uint32_t field_length[(int)AudioFrames+1];
|
||||||
|
static bool _has_focus;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __audio_clock_h__ */
|
#endif /* __audio_clock_h__ */
|
||||||
|
|
|
||||||
|
|
@ -231,12 +231,19 @@ Editor::region_list_selection_changed()
|
||||||
TreeView::Selection::ListHandle_Path::iterator i = rows.begin();
|
TreeView::Selection::ListHandle_Path::iterator i = rows.begin();
|
||||||
TreeIter iter;
|
TreeIter iter;
|
||||||
|
|
||||||
/* just set the first selected region (in fact, the selection model might be SINGLE, which
|
|
||||||
means there can only be one.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((iter = region_list_model->get_iter (*i))) {
|
if ((iter = region_list_model->get_iter (*i))) {
|
||||||
set_selected_regionview_from_region_list (((*iter)[region_list_columns.region]), Selection::Set);
|
boost::shared_ptr<Region> r = (*iter)[region_list_columns.region];
|
||||||
|
|
||||||
|
/* they could have clicked on a row that is just a placeholder, like "Hidden" */
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
|
||||||
|
/* just set the first selected region (in fact, the selection model might be SINGLE, which
|
||||||
|
means there can only be one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
set_selected_regionview_from_region_list (r, Selection::Set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -564,7 +571,16 @@ Editor::region_list_selection_mapover (slot<void,boost::shared_ptr<Region> > sl)
|
||||||
TreeIter iter;
|
TreeIter iter;
|
||||||
|
|
||||||
if ((iter = region_list_model->get_iter (*i))) {
|
if ((iter = region_list_model->get_iter (*i))) {
|
||||||
sl (((*iter)[region_list_columns.region]));
|
|
||||||
|
/* some rows don't have a region associated with them, but can still be
|
||||||
|
selected (XXX maybe prevent them from being selected)
|
||||||
|
*/
|
||||||
|
|
||||||
|
boost::shared_ptr<Region> r = (*iter)[region_list_columns.region];
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
sl (r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,25 @@ Keyboard* Keyboard::_the_keyboard = 0;
|
||||||
|
|
||||||
GdkModifierType Keyboard::RelevantModifierKeyMask;
|
GdkModifierType Keyboard::RelevantModifierKeyMask;
|
||||||
|
|
||||||
|
bool Keyboard::_some_magic_widget_has_focus = false;
|
||||||
|
|
||||||
|
void
|
||||||
|
Keyboard::magic_widget_grab_focus ()
|
||||||
|
{
|
||||||
|
_some_magic_widget_has_focus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Keyboard::magic_widget_drop_focus ()
|
||||||
|
{
|
||||||
|
_some_magic_widget_has_focus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Keyboard::some_magic_widget_has_focus ()
|
||||||
|
{
|
||||||
|
return _some_magic_widget_has_focus;
|
||||||
|
}
|
||||||
|
|
||||||
Keyboard::Keyboard ()
|
Keyboard::Keyboard ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,10 @@ class Keyboard : public sigc::trackable, Stateful
|
||||||
|
|
||||||
static Keyboard& the_keyboard() { return *_the_keyboard; }
|
static Keyboard& the_keyboard() { return *_the_keyboard; }
|
||||||
|
|
||||||
|
static bool some_magic_widget_has_focus ();
|
||||||
|
static void magic_widget_grab_focus ();
|
||||||
|
static void magic_widget_drop_focus ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Keyboard* _the_keyboard;
|
static Keyboard* _the_keyboard;
|
||||||
|
|
||||||
|
|
@ -104,6 +108,8 @@ class Keyboard : public sigc::trackable, Stateful
|
||||||
|
|
||||||
static gint _snooper (GtkWidget*, GdkEventKey*, gpointer);
|
static gint _snooper (GtkWidget*, GdkEventKey*, gpointer);
|
||||||
gint snooper (GtkWidget*, GdkEventKey*);
|
gint snooper (GtkWidget*, GdkEventKey*);
|
||||||
|
|
||||||
|
static bool _some_magic_widget_has_focus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ardour_keyboard_h__ */
|
#endif /* __ardour_keyboard_h__ */
|
||||||
|
|
|
||||||
|
|
@ -347,14 +347,14 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (focus) {
|
if (focus) {
|
||||||
if (GTK_IS_ENTRY(focus)) {
|
if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
|
||||||
special_handling_of_unmodified_accelerators = true;
|
special_handling_of_unmodified_accelerators = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ACCELERATOR_HANDLING
|
#ifdef DEBUG_ACCELERATOR_HANDLING
|
||||||
if (debug) {
|
if (debug) {
|
||||||
cerr << "Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " focus is an entry ? "
|
cerr << "Win = " << win << " Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " special handling ? "
|
||||||
<< special_handling_of_unmodified_accelerators
|
<< special_handling_of_unmodified_accelerators
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
@ -456,15 +456,26 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
|
||||||
/* no modifiers, propagate first */
|
/* no modifiers, propagate first */
|
||||||
|
|
||||||
#ifdef DEBUG_ACCELERATOR_HANDLING
|
#ifdef DEBUG_ACCELERATOR_HANDLING
|
||||||
if (debug) {
|
if (debug) {
|
||||||
cerr << "\tactivate, then propagate\n";
|
cerr << "\tpropagate, then activate\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!gtk_window_propagate_key_event (win, ev)) {
|
if (!gtk_window_propagate_key_event (win, ev)) {
|
||||||
|
#ifdef DEBUG_ACCELERATOR_HANDLING
|
||||||
|
if (debug) {
|
||||||
|
cerr << "\tpropagation didn't handle, so activate\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return gtk_window_activate_key (win, ev);
|
return gtk_window_activate_key (win, ev);
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG_ACCELERATOR_HANDLING
|
||||||
|
if (debug) {
|
||||||
|
cerr << "\thandled by propagate\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_ACCELERATOR_HANDLING
|
#ifdef DEBUG_ACCELERATOR_HANDLING
|
||||||
if (debug) {
|
if (debug) {
|
||||||
cerr << "\tnot handled\n";
|
cerr << "\tnot handled\n";
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,8 @@ class Route : public IO
|
||||||
uint32_t pans_required() const;
|
uint32_t pans_required() const;
|
||||||
ChanCount n_process_buffers ();
|
ChanCount n_process_buffers ();
|
||||||
|
|
||||||
virtual int _set_state (const XMLNode&, bool call_base);
|
virtual int _set_state (const XMLNode&, bool call_base);
|
||||||
|
virtual void _set_redirect_states (const XMLNodeList&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init ();
|
void init ();
|
||||||
|
|
|
||||||
|
|
@ -1805,33 +1805,26 @@ Route::_set_state (const XMLNode& node, bool call_base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XMLNodeList redirect_nodes;
|
||||||
|
|
||||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
|
||||||
|
|
||||||
child = *niter;
|
child = *niter;
|
||||||
|
|
||||||
if (child->name() == X_("Send")) {
|
if (child->name() == X_("Send") || child->name() == X_("Insert")) {
|
||||||
|
redirect_nodes.push_back(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_set_redirect_states(redirect_nodes);
|
||||||
|
|
||||||
|
|
||||||
if (!IO::ports_legal) {
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
|
||||||
|
child = *niter;
|
||||||
|
// All redirects (sends and inserts) have been applied already
|
||||||
|
|
||||||
deferred_state->add_child_copy (*child);
|
if (child->name() == X_("Automation")) {
|
||||||
|
|
||||||
} else {
|
|
||||||
add_redirect_from_xml (*child);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (child->name() == X_("Insert")) {
|
|
||||||
|
|
||||||
if (!IO::ports_legal) {
|
|
||||||
|
|
||||||
deferred_state->add_child_copy (*child);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
add_redirect_from_xml (*child);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (child->name() == X_("Automation")) {
|
|
||||||
|
|
||||||
if ((prop = child->property (X_("path"))) != 0) {
|
if ((prop = child->property (X_("path"))) != 0) {
|
||||||
load_automation (prop->value());
|
load_automation (prop->value());
|
||||||
|
|
@ -1888,6 +1881,102 @@ Route::_set_state (const XMLNode& node, bool call_base)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Route::_set_redirect_states(const XMLNodeList &nlist)
|
||||||
|
{
|
||||||
|
XMLNodeConstIterator niter;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
RedirectList::iterator i, o;
|
||||||
|
|
||||||
|
// Iterate through existing redirects, remove those which are not in the state list
|
||||||
|
for (i = _redirects.begin(); i != _redirects.end(); ) {
|
||||||
|
RedirectList::iterator tmp = i;
|
||||||
|
++tmp;
|
||||||
|
|
||||||
|
bool redirectInStateList = false;
|
||||||
|
|
||||||
|
(*i)->id().print (buf, sizeof (buf));
|
||||||
|
|
||||||
|
|
||||||
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||||
|
|
||||||
|
if (strncmp(buf,(*niter)->child(X_("Redirect"))->child(X_("IO"))->property(X_("id"))->value().c_str(), sizeof(buf)) == 0) {
|
||||||
|
redirectInStateList = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!redirectInStateList) {
|
||||||
|
remove_redirect ( *i, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Iterate through state list and make sure all redirects are on the track and in the correct order,
|
||||||
|
// set the state of existing redirects according to the new state on the same go
|
||||||
|
i = _redirects.begin();
|
||||||
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter, ++i) {
|
||||||
|
|
||||||
|
// Check whether the next redirect in the list
|
||||||
|
o = i;
|
||||||
|
|
||||||
|
while (o != _redirects.end()) {
|
||||||
|
(*o)->id().print (buf, sizeof (buf));
|
||||||
|
if ( strncmp(buf, (*niter)->child(X_("Redirect"))->child(X_("IO"))->property(X_("id"))->value().c_str(), sizeof(buf)) == 0)
|
||||||
|
break;
|
||||||
|
++o;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o == _redirects.end()) {
|
||||||
|
// If the redirect (*niter) is not on the route, we need to create it
|
||||||
|
// and move it to the correct location
|
||||||
|
|
||||||
|
RedirectList::iterator prev_last = _redirects.end();
|
||||||
|
--prev_last; // We need this to check whether adding succeeded
|
||||||
|
|
||||||
|
add_redirect_from_xml (**niter);
|
||||||
|
|
||||||
|
RedirectList::iterator last = _redirects.end();
|
||||||
|
--last;
|
||||||
|
|
||||||
|
if (prev_last == last) {
|
||||||
|
cerr << "Could not fully restore state as some redirects were not possible to create" << endl;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<Redirect> tmp = (*last);
|
||||||
|
// remove the redirect from the wrong location
|
||||||
|
_redirects.erase(last);
|
||||||
|
// insert the new redirect at the current location
|
||||||
|
_redirects.insert(i, tmp);
|
||||||
|
|
||||||
|
--i; // move pointer to the newly inserted redirect
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We found the redirect (*niter) on the route, first we must make sure the redirect
|
||||||
|
// is at the location provided in the XML state
|
||||||
|
if (i != o) {
|
||||||
|
boost::shared_ptr<Redirect> tmp = (*o);
|
||||||
|
// remove the old copy
|
||||||
|
_redirects.erase(o);
|
||||||
|
// insert the redirect at the correct location
|
||||||
|
_redirects.insert(i, tmp);
|
||||||
|
|
||||||
|
--i; // move pointer so it points to the right redirect
|
||||||
|
}
|
||||||
|
|
||||||
|
(*i)->set_state( (**niter) );
|
||||||
|
}
|
||||||
|
|
||||||
|
redirects_changed(this);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Route::curve_reallocate ()
|
Route::curve_reallocate ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue