X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Faudio_clock.cc;h=28505ab46d6f06baa9770c43f37c12b7644a6549;hb=185be4e841e182bbe7cb7820f9cb6371ebebe15d;hp=860e80af5d72d0ba3de49a20ed7e789daa31499f;hpb=209d967b1bb80a9735d690d8f4f0455ecb9970ca;p=ardour.git diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index 860e80af5d..28505ab46d 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -15,16 +15,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ #include // for sprintf #include -#include + +#include +#include + +#include #include #include #include +#include #include "ardour_ui.h" #include "audio_clock.h" @@ -33,8 +37,16 @@ #include "i18n.h" using namespace ARDOUR; -using namespace SigC; +using namespace PBD; +using namespace sigc; using namespace Gtk; +using namespace std; + +using PBD::atoi; +using PBD::atof; + +sigc::signal AudioClock::ModeChanged; +vector AudioClock::clocks; const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = { 2, /* SMPTE_Hours */ @@ -50,8 +62,10 @@ const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = { 10 /* Audio Frame */ }; -AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool with_tempo_and_meter) - : is_duration (duration), +AudioClock::AudioClock (std::string clock_name, bool transient, std::string widget_name, bool allow_edit, bool duration, bool with_info) + : _name (clock_name), + is_transient (transient), + is_duration (duration), editable (allow_edit), colon1 (":"), colon2 (":"), @@ -67,9 +81,51 @@ AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool ops_menu = 0; dragging = false; + if (with_info) { + frames_upper_info_label = manage (new Label); + frames_lower_info_label = manage (new Label); + smpte_upper_info_label = manage (new Label); + smpte_lower_info_label = manage (new Label); + bbt_upper_info_label = manage (new Label); + bbt_lower_info_label = manage (new Label); + + frames_upper_info_label->set_name ("AudioClockFramesUpperInfo"); + frames_lower_info_label->set_name ("AudioClockFramesLowerInfo"); + smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo"); + smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo"); + bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo"); + bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo"); + + Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0); + Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0); + + frames_info_box.pack_start (*frames_upper_info_label, true, true); + frames_info_box.pack_start (*frames_lower_info_label, true, true); + smpte_info_box.pack_start (*smpte_upper_info_label, true, true); + smpte_info_box.pack_start (*smpte_lower_info_label, true, true); + bbt_info_box.pack_start (*bbt_upper_info_label, true, true); + bbt_info_box.pack_start (*bbt_lower_info_label, true, true); + + } else { + frames_upper_info_label = 0; + frames_lower_info_label = 0; + smpte_upper_info_label = 0; + smpte_lower_info_label = 0; + bbt_upper_info_label = 0; + bbt_lower_info_label = 0; + } + audio_frames_ebox.add (audio_frames_label); - frames_packer_hbox.set_border_width (2); - frames_packer_hbox.pack_start (audio_frames_ebox, false, false); + + frames_packer.set_homogeneous (false); + frames_packer.set_border_width (2); + frames_packer.pack_start (audio_frames_ebox, false, false); + + if (with_info) { + frames_packer.pack_start (frames_info_box, false, false, 5); + } + + frames_packer_hbox.pack_start (frames_packer, true, false); hours_ebox.add (hours_label); minutes_ebox.add (minutes_label); @@ -92,6 +148,10 @@ AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool smpte_packer.pack_start (colon3, false, false); smpte_packer.pack_start (frames_ebox, false, false); + if (with_info) { + smpte_packer.pack_start (smpte_info_box, false, false, 5); + } + smpte_packer_hbox.pack_start (smpte_packer, true, false); bbt_packer.set_homogeneous (false); @@ -102,20 +162,8 @@ AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool bbt_packer.pack_start (b2, false, false); bbt_packer.pack_start (ticks_ebox, false, false); - if (with_tempo_and_meter) { - meter_label = manage (new Label); - tempo_label = manage (new Label); - - meter_label->set_name ("BBTMeterLabel"); - tempo_label->set_name ("BBTTempoLabel"); - - tempo_meter_box.pack_start (*meter_label, false, false); - tempo_meter_box.pack_start (*tempo_label, false, false); - - bbt_packer.pack_start (tempo_meter_box, false, false, 5); - } else { - meter_label = 0; - tempo_label = 0; + if (with_info) { + bbt_packer.pack_start (bbt_info_box, false, false, 5); } bbt_packer_hbox.pack_start (bbt_packer, true, false); @@ -130,7 +178,50 @@ AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool minsec_packer_hbox.pack_start (minsec_packer, true, false); - set_name (name); + clock_frame.set_shadow_type (Gtk::SHADOW_IN); + clock_frame.set_name ("BaseFrame"); + + clock_frame.add (clock_base); + + set_widget_name (widget_name); + + _mode = BBT; /* lie to force mode switch */ + set_mode (SMPTE); + + pack_start (clock_frame, true, true); + + /* the clock base handles button releases for menu popup regardless of + editable status. if the clock is editable, the clock base is where + we pass focus to after leaving the last editable "field", which + will then shutdown editing till the user starts it up again. + + it does this because the focus out event on the field disables + keyboard event handling, and we don't connect anything up to + notice focus in on the clock base. hence, keyboard event handling + stays disabled. + */ + + clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK); + clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours)); + + Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed)); + + if (editable) { + setup_events (); + } + + set (last_when, true); + + if (!is_transient) { + clocks.push_back (this); + } +} + +void +AudioClock::set_widget_name (string name) +{ + Widget::set_name (name); + clock_base.set_name (name); audio_frames_label.set_name (name); @@ -164,158 +255,135 @@ AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool b1.set_name (name); b2.set_name (name); - clock_frame.set_shadow_type (GTK_SHADOW_IN); - clock_frame.set_name ("BaseFrame"); - - clock_frame.add (clock_base); - - _mode = BBT; /* lie to force mode switch */ - set_mode (SMPTE); - - pack_start (clock_frame, true, true); - - /* the clock base handles button releases for menu popup regardless of - editable status. if the clock is editable, the clock base is where - we pass focus to after leaving the last editable "field", which - will then shutdown editing till the user starts it up again. - - it does this because the focus out event on the field disables - keyboard event handling, and we don't connect anything up to - notice focus in on the clock base. hence, keyboard event handling - stays disabled. - */ - - clock_base.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); - clock_base.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Hours)); - - if (editable) { - setup_events (); - } - - set (last_when, true); + queue_draw (); } void AudioClock::setup_events () { - clock_base.set_flags (GTK_CAN_FOCUS); - - hours_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - minutes_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - seconds_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - frames_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - bars_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - beats_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - ticks_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - ms_hours_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - ms_minutes_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - ms_seconds_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - audio_frames_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); - - hours_ebox.set_flags (GTK_CAN_FOCUS); - minutes_ebox.set_flags (GTK_CAN_FOCUS); - seconds_ebox.set_flags (GTK_CAN_FOCUS); - frames_ebox.set_flags (GTK_CAN_FOCUS); - audio_frames_ebox.set_flags (GTK_CAN_FOCUS); - bars_ebox.set_flags (GTK_CAN_FOCUS); - beats_ebox.set_flags (GTK_CAN_FOCUS); - ticks_ebox.set_flags (GTK_CAN_FOCUS); - ms_hours_ebox.set_flags (GTK_CAN_FOCUS); - ms_minutes_ebox.set_flags (GTK_CAN_FOCUS); - ms_seconds_ebox.set_flags (GTK_CAN_FOCUS); - - hours_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Hours)); - minutes_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes)); - seconds_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds)); - frames_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Frames)); - audio_frames_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), AudioFrames)); - bars_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Bars)); - beats_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Beats)); - ticks_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Ticks)); - ms_hours_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Hours)); - ms_minutes_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Minutes)); - ms_seconds_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Seconds)); - - hours_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Hours)); - minutes_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Minutes)); - seconds_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Seconds)); - frames_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Frames)); - audio_frames_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), AudioFrames)); - bars_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Bars)); - beats_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Beats)); - ticks_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Ticks)); - ms_hours_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Hours)); - ms_minutes_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Minutes)); - ms_seconds_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Seconds)); - - hours_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Hours)); - minutes_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Minutes)); - seconds_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Seconds)); - frames_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Frames)); - audio_frames_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), AudioFrames)); - bars_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Bars)); - beats_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Beats)); - ticks_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Ticks)); - ms_hours_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Hours)); - ms_minutes_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Minutes)); - ms_seconds_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Seconds)); - - hours_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Hours)); - minutes_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Minutes)); - seconds_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Seconds)); - frames_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Frames)); - audio_frames_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), AudioFrames)); - bars_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Bars)); - beats_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Beats)); - ticks_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Ticks)); - ms_hours_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Hours)); - ms_minutes_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Minutes)); - ms_seconds_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Seconds)); - - hours_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Hours)); - minutes_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Minutes)); - seconds_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Seconds)); - frames_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Frames)); - audio_frames_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), AudioFrames)); - bars_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Bars)); - beats_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Beats)); - ticks_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Ticks)); - ms_hours_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Hours)); - ms_minutes_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Minutes)); - ms_seconds_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Seconds)); - - hours_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Hours)); - minutes_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Minutes)); - seconds_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Seconds)); - frames_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Frames)); - audio_frames_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), AudioFrames)); - bars_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Bars)); - beats_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Beats)); - ticks_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Ticks)); - ms_hours_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Hours)); - ms_minutes_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Minutes)); - ms_seconds_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Seconds)); - - Gtkmmext::set_usize_to_display_given_text (hours_label, "-88", 0, 2); - Gtkmmext::set_usize_to_display_given_text (minutes_label, "88", 0, 2); - Gtkmmext::set_usize_to_display_given_text (seconds_label, "88", 0, 2); - Gtkmmext::set_usize_to_display_given_text (frames_label, "88", 0, 2); - - Gtkmmext::set_usize_to_display_given_text (bars_label, "-888", 0, 2); - Gtkmmext::set_usize_to_display_given_text (beats_label, "88", 0, 2); - Gtkmmext::set_usize_to_display_given_text (ticks_label, "8888", 0, 2); - - Gtkmmext::set_usize_to_display_given_text (audio_frames_label, "4294967296", 0, 2); + clock_base.set_flags (Gtk::CAN_FOCUS); + + hours_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + minutes_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + seconds_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + frames_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + bars_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + beats_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + ticks_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + ms_hours_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + ms_minutes_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + ms_seconds_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + audio_frames_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK); + + hours_ebox.set_flags (Gtk::CAN_FOCUS); + minutes_ebox.set_flags (Gtk::CAN_FOCUS); + seconds_ebox.set_flags (Gtk::CAN_FOCUS); + frames_ebox.set_flags (Gtk::CAN_FOCUS); + audio_frames_ebox.set_flags (Gtk::CAN_FOCUS); + bars_ebox.set_flags (Gtk::CAN_FOCUS); + beats_ebox.set_flags (Gtk::CAN_FOCUS); + ticks_ebox.set_flags (Gtk::CAN_FOCUS); + ms_hours_ebox.set_flags (Gtk::CAN_FOCUS); + ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS); + ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS); + + hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours)); + minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes)); + seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds)); + frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames)); + audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames)); + bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars)); + beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats)); + ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks)); + ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours)); + ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes)); + ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds)); + + hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours)); + minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes)); + seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds)); + frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames)); + audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames)); + bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars)); + beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats)); + ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks)); + ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours)); + ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes)); + ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds)); + + hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours)); + minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes)); + seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds)); + frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames)); + audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames)); + bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars)); + beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats)); + ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks)); + ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours)); + ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes)); + ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds)); + + hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours)); + minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes)); + seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds)); + frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames)); + audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames)); + bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars)); + beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats)); + ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks)); + ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours)); + 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)); + + 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)); + seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds)); + frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames)); + audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames)); + bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars)); + beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats)); + ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks)); + ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours)); + ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes)); + ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds)); + + hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours)); + minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes)); + seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds)); + frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames)); + audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames)); + bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars)); + beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats)); + ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks)); + ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours)); + ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes)); + ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds)); + + hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours)); + minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes)); + seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds)); + frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames)); + audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames)); + bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars)); + beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats)); + ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks)); + 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_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds)); } void -AudioClock::realize_impl () +AudioClock::on_realize () { - HBox::realize_impl (); + HBox::on_realize (); + + /* styles are not available until the widgets are bound to a window */ + + set_size_requests (); } void -AudioClock::set (jack_nframes_t when, bool force) +AudioClock::set (nframes_t when, bool force) { if ((!force && !is_visible()) || session == 0) { @@ -351,37 +419,77 @@ AudioClock::set (jack_nframes_t when, bool force) } void -AudioClock::set_frames (jack_nframes_t when, bool force) +AudioClock::smpte_offset_changed () +{ + nframes_t current; + + switch (_mode) { + case SMPTE: + if (is_duration) { + current = current_duration(); + } else { + current = current_time (); + } + set (current, true); + break; + default: + break; + } +} + +void +AudioClock::set_frames (nframes_t when, bool force) { char buf[32]; snprintf (buf, sizeof (buf), "%u", when); audio_frames_label.set_text (buf); + + if (frames_upper_info_label) { + nframes_t rate = session->frame_rate(); + + if (fmod (rate, 1000.0) == 0.000) { + sprintf (buf, "%uK", rate/1000); + } else { + sprintf (buf, "%.3fK", rate/1000.0f); + } + + frames_upper_info_label->set_text (buf); + + float vid_pullup = Config->get_video_pullup(); + + if (vid_pullup == 0.0) { + frames_lower_info_label->set_text(_("none")); + } else { + sprintf (buf, "%-6.4f", vid_pullup); + frames_lower_info_label->set_text (buf); + } + } } void -AudioClock::set_minsec (jack_nframes_t when, bool force) +AudioClock::set_minsec (nframes_t when, bool force) { char buf[32]; - jack_nframes_t left; + nframes_t left; int hrs; int mins; float secs; left = when; hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); - left -= (jack_nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (jack_nframes_t) floor (mins * session->frame_rate() * 60.0f); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); secs = left / (float) session->frame_rate(); if (force || hrs != ms_last_hrs) { - sprintf (buf, "%d", hrs); + sprintf (buf, "%02d", hrs); ms_hours_label.set_text (buf); ms_last_hrs = hrs; } if (force || mins != ms_last_mins) { - sprintf (buf, "%d", mins); + sprintf (buf, "%02d", mins); ms_minutes_label.set_text (buf); ms_last_mins = mins; } @@ -394,10 +502,10 @@ AudioClock::set_minsec (jack_nframes_t when, bool force) } void -AudioClock::set_smpte (jack_nframes_t when, bool force) +AudioClock::set_smpte (nframes_t when, bool force) { char buf[32]; - SMPTE_Time smpte; + SMPTE::Time smpte; if (is_duration) { session->smpte_duration (when, smpte); @@ -407,9 +515,9 @@ AudioClock::set_smpte (jack_nframes_t when, bool force) if (force || smpte.hours != last_hrs || smpte.negative != last_negative) { if (smpte.negative) { - sprintf (buf, "-%02ld", smpte.hours); + sprintf (buf, "-%02" PRIu32, smpte.hours); } else { - sprintf (buf, " %02ld", smpte.hours); + sprintf (buf, " %02" PRIu32, smpte.hours); } hours_label.set_text (buf); last_hrs = smpte.hours; @@ -417,26 +525,46 @@ AudioClock::set_smpte (jack_nframes_t when, bool force) } if (force || smpte.minutes != last_mins) { - sprintf (buf, "%02ld", smpte.minutes); + sprintf (buf, "%02" PRIu32, smpte.minutes); minutes_label.set_text (buf); last_mins = smpte.minutes; } if (force || smpte.seconds != last_secs) { - sprintf (buf, "%02ld", smpte.seconds); + sprintf (buf, "%02" PRIu32, smpte.seconds); seconds_label.set_text (buf); last_secs = smpte.seconds; } if (force || smpte.frames != last_frames) { - sprintf (buf, "%02ld", smpte.frames); + sprintf (buf, "%02" PRIu32, smpte.frames); frames_label.set_text (buf); last_frames = smpte.frames; } + + if (smpte_upper_info_label) { + double smpte_frames = session->smpte_frames_per_second(); + + if ( fmod(smpte_frames, 1.0) == 0.0) { + sprintf (buf, "%u", int (smpte_frames)); + } else { + sprintf (buf, "%.2f", smpte_frames); + } + + smpte_upper_info_label->set_text (buf); + + if (session->smpte_drop_frames()) { + sprintf (buf, "DF"); + } else { + sprintf (buf, "NDF"); + } + + smpte_lower_info_label->set_text (buf); + } } void -AudioClock::set_bbt (jack_nframes_t when, bool force) +AudioClock::set_bbt (nframes_t when, bool force) { char buf[16]; BBT_Time bbt; @@ -449,12 +577,12 @@ AudioClock::set_bbt (jack_nframes_t when, bool force) sprintf (buf, "%04" PRIu32, bbt.ticks); ticks_label.set_text (buf); - if (meter_label) { + if (bbt_upper_info_label) { TempoMap::Metric m (session->tempo_map().metric_at (when)); sprintf (buf, "%-5.2f", m.tempo().beats_per_minute()); - tempo_label->set_text (buf); + bbt_lower_info_label->set_text (buf); sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor()); - meter_label->set_text (buf); + bbt_upper_info_label->set_text (buf); } } @@ -464,11 +592,23 @@ AudioClock::set_session (Session *s) session = s; if (s) { + + XMLProperty* prop; + XMLNode* node = session->extra_xml (X_("ClockModes")); + AudioClock::Mode amode; + + if (node) { + if ((prop = node->property (_name)) != 0) { + amode = AudioClock::Mode (string_2_enum (prop->value(), amode)); + set_mode (amode); + } + } + set (last_when, true); } } -gint +bool AudioClock::field_key_release_event (GdkEventKey *ev, Field field) { Label *label = 0; @@ -627,6 +767,17 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field) // Check SMPTE fields for sanity (may also adjust fields) smpte_sanitize_display(); break; + case Bars: + case Beats: + case Ticks: + // Bars or beats should never be 0 + if (atoi(bars_label.get_text()) == 0) { + bars_label.set_text("001"); + } + if (atoi(beats_label.get_text()) == 0) { + beats_label.set_text("01"); + } + break; default: break; } @@ -692,125 +843,121 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field) return TRUE; } -gint +bool AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field) { - ARDOUR_UI::instance()->allow_focus (true); - key_entry_state = 0; switch (field) { case SMPTE_Hours: - hours_ebox.set_flags (GTK_HAS_FOCUS); - hours_ebox.set_state (GTK_STATE_ACTIVE); + hours_ebox.set_flags (Gtk::HAS_FOCUS); + hours_ebox.set_state (Gtk::STATE_ACTIVE); break; case SMPTE_Minutes: - minutes_ebox.set_flags (GTK_HAS_FOCUS); - minutes_ebox.set_state (GTK_STATE_ACTIVE); + minutes_ebox.set_flags (Gtk::HAS_FOCUS); + minutes_ebox.set_state (Gtk::STATE_ACTIVE); break; case SMPTE_Seconds: - seconds_ebox.set_flags (GTK_HAS_FOCUS); - seconds_ebox.set_state (GTK_STATE_ACTIVE); + seconds_ebox.set_flags (Gtk::HAS_FOCUS); + seconds_ebox.set_state (Gtk::STATE_ACTIVE); break; case SMPTE_Frames: - frames_ebox.set_flags (GTK_HAS_FOCUS); - frames_ebox.set_state (GTK_STATE_ACTIVE); + frames_ebox.set_flags (Gtk::HAS_FOCUS); + frames_ebox.set_state (Gtk::STATE_ACTIVE); break; case AudioFrames: - audio_frames_ebox.set_flags (GTK_HAS_FOCUS); - audio_frames_ebox.set_state (GTK_STATE_ACTIVE); + audio_frames_ebox.set_flags (Gtk::HAS_FOCUS); + audio_frames_ebox.set_state (Gtk::STATE_ACTIVE); break; case MS_Hours: - ms_hours_ebox.set_flags (GTK_HAS_FOCUS); - ms_hours_ebox.set_state (GTK_STATE_ACTIVE); + ms_hours_ebox.set_flags (Gtk::HAS_FOCUS); + ms_hours_ebox.set_state (Gtk::STATE_ACTIVE); break; case MS_Minutes: - ms_minutes_ebox.set_flags (GTK_HAS_FOCUS); - ms_minutes_ebox.set_state (GTK_STATE_ACTIVE); + ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS); + ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE); break; case MS_Seconds: - ms_seconds_ebox.set_flags (GTK_HAS_FOCUS); - ms_seconds_ebox.set_state (GTK_STATE_ACTIVE); + ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS); + ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE); break; case Bars: - bars_ebox.set_flags (GTK_HAS_FOCUS); - bars_ebox.set_state (GTK_STATE_ACTIVE); + bars_ebox.set_flags (Gtk::HAS_FOCUS); + bars_ebox.set_state (Gtk::STATE_ACTIVE); break; case Beats: - beats_ebox.set_flags (GTK_HAS_FOCUS); - beats_ebox.set_state (GTK_STATE_ACTIVE); + beats_ebox.set_flags (Gtk::HAS_FOCUS); + beats_ebox.set_state (Gtk::STATE_ACTIVE); break; case Ticks: - ticks_ebox.set_flags (GTK_HAS_FOCUS); - ticks_ebox.set_state (GTK_STATE_ACTIVE); + ticks_ebox.set_flags (Gtk::HAS_FOCUS); + ticks_ebox.set_state (Gtk::STATE_ACTIVE); break; } return FALSE; } -gint +bool AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field) { - ARDOUR_UI::instance()->allow_focus (false); - switch (field) { case SMPTE_Hours: - hours_ebox.unset_flags (GTK_HAS_FOCUS); - hours_ebox.set_state (GTK_STATE_NORMAL); + hours_ebox.unset_flags (Gtk::HAS_FOCUS); + hours_ebox.set_state (Gtk::STATE_NORMAL); break; case SMPTE_Minutes: - minutes_ebox.unset_flags (GTK_HAS_FOCUS); - minutes_ebox.set_state (GTK_STATE_NORMAL); + minutes_ebox.unset_flags (Gtk::HAS_FOCUS); + minutes_ebox.set_state (Gtk::STATE_NORMAL); break; case SMPTE_Seconds: - seconds_ebox.unset_flags (GTK_HAS_FOCUS); - seconds_ebox.set_state (GTK_STATE_NORMAL); + seconds_ebox.unset_flags (Gtk::HAS_FOCUS); + seconds_ebox.set_state (Gtk::STATE_NORMAL); break; case SMPTE_Frames: - frames_ebox.unset_flags (GTK_HAS_FOCUS); - frames_ebox.set_state (GTK_STATE_NORMAL); + frames_ebox.unset_flags (Gtk::HAS_FOCUS); + frames_ebox.set_state (Gtk::STATE_NORMAL); break; case AudioFrames: - audio_frames_ebox.unset_flags (GTK_HAS_FOCUS); - audio_frames_ebox.set_state (GTK_STATE_NORMAL); + audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS); + audio_frames_ebox.set_state (Gtk::STATE_NORMAL); break; case MS_Hours: - ms_hours_ebox.unset_flags (GTK_HAS_FOCUS); - ms_hours_ebox.set_state (GTK_STATE_NORMAL); + ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS); + ms_hours_ebox.set_state (Gtk::STATE_NORMAL); break; case MS_Minutes: - ms_minutes_ebox.unset_flags (GTK_HAS_FOCUS); - ms_minutes_ebox.set_state (GTK_STATE_NORMAL); + ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS); + ms_minutes_ebox.set_state (Gtk::STATE_NORMAL); break; case MS_Seconds: - ms_seconds_ebox.unset_flags (GTK_HAS_FOCUS); - ms_seconds_ebox.set_state (GTK_STATE_NORMAL); + ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS); + ms_seconds_ebox.set_state (Gtk::STATE_NORMAL); break; case Bars: - bars_ebox.unset_flags (GTK_HAS_FOCUS); - bars_ebox.set_state (GTK_STATE_NORMAL); + bars_ebox.unset_flags (Gtk::HAS_FOCUS); + bars_ebox.set_state (Gtk::STATE_NORMAL); break; case Beats: - beats_ebox.unset_flags (GTK_HAS_FOCUS); - beats_ebox.set_state (GTK_STATE_NORMAL); + beats_ebox.unset_flags (Gtk::HAS_FOCUS); + beats_ebox.set_state (Gtk::STATE_NORMAL); break; case Ticks: - ticks_ebox.unset_flags (GTK_HAS_FOCUS); - ticks_ebox.set_state (GTK_STATE_NORMAL); + ticks_ebox.unset_flags (Gtk::HAS_FOCUS); + ticks_ebox.set_state (Gtk::STATE_NORMAL); break; } return FALSE; } -gint +bool AudioClock::field_button_release_event (GdkEventButton *ev, Field field) { @@ -890,12 +1037,12 @@ AudioClock::field_button_release_event (GdkEventButton *ev, Field field) return TRUE; } -gint +bool AudioClock::field_button_press_event (GdkEventButton *ev, Field field) { if (session == 0) return FALSE; - jack_nframes_t frames = 0; + nframes_t frames = 0; switch (ev->button) { case 1: @@ -906,7 +1053,7 @@ AudioClock::field_button_press_event (GdkEventButton *ev, Field field) /* make absolutely sure that the pointer is grabbed */ 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); dragging = true; drag_accum = 0; @@ -926,38 +1073,50 @@ AudioClock::field_button_press_event (GdkEventButton *ev, Field field) return FALSE; break; - case 4: - if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { - frames = get_frames (field); - if (frames != 0) { - if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { - frames *= 10; - } - set (current_time() + frames, true); - ValueChanged (); /* EMIT_SIGNAL */ - } - } + default: + return FALSE; break; + } + + return TRUE; +} - case 5: - if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { - frames = get_frames (field); - if (frames != 0) { - if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { - frames *= 10; - } +bool +AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field) +{ + if (session == 0) return FALSE; - if ((double)current_time() - (double)frames < 0.0) { - set (0, true); - } - else { - set (current_time() - frames, true); - } - - ValueChanged (); /* EMIT_SIGNAL */ - } - } - break; + nframes_t frames = 0; + + switch (ev->direction) { + + case GDK_SCROLL_UP: + frames = get_frames (field); + if (frames != 0) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + frames *= 10; + } + set (current_time() + frames, true); + ValueChanged (); /* EMIT_SIGNAL */ + } + break; + + case GDK_SCROLL_DOWN: + frames = get_frames (field); + if (frames != 0) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + frames *= 10; + } + + if ((double)current_time() - (double)frames < 0.0) { + set (0, true); + } else { + set (current_time() - frames, true); + } + + ValueChanged (); /* EMIT_SIGNAL */ + } + break; default: return FALSE; @@ -967,7 +1126,7 @@ AudioClock::field_button_press_event (GdkEventButton *ev, Field field) return TRUE; } -gint +bool AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field) { if (session == 0 || !dragging) { @@ -996,8 +1155,8 @@ AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field) if (trunc(drag_accum) != 0) { - jack_nframes_t frames; - jack_nframes_t pos ; + nframes_t frames; + nframes_t pos ; int dir; dir = (drag_accum < 0 ? 1:-1); pos = current_time(); @@ -1005,7 +1164,7 @@ AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field) if (frames != 0 && frames * drag_accum < current_time()) { - set ((jack_nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land + set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land } else { set (0 , false); @@ -1021,24 +1180,24 @@ AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field) return TRUE; } -jack_nframes_t -AudioClock::get_frames (Field field,jack_nframes_t pos,int dir) +nframes_t +AudioClock::get_frames (Field field,nframes_t pos,int dir) { - jack_nframes_t frames = 0; + nframes_t frames = 0; BBT_Time bbt; switch (field) { case SMPTE_Hours: - frames = (jack_nframes_t) floor (3600.0 * session->frame_rate()); + frames = (nframes_t) floor (3600.0 * session->frame_rate()); break; case SMPTE_Minutes: - frames = (jack_nframes_t) floor (60.0 * session->frame_rate()); + frames = (nframes_t) floor (60.0 * session->frame_rate()); break; case SMPTE_Seconds: frames = session->frame_rate(); break; case SMPTE_Frames: - frames = (jack_nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second); + frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second()); break; case AudioFrames: @@ -1046,10 +1205,10 @@ AudioClock::get_frames (Field field,jack_nframes_t pos,int dir) break; case MS_Hours: - frames = (jack_nframes_t) floor (3600.0 * session->frame_rate()); + frames = (nframes_t) floor (3600.0 * session->frame_rate()); break; case MS_Minutes: - frames = (jack_nframes_t) floor (60.0 * session->frame_rate()); + frames = (nframes_t) floor (60.0 * session->frame_rate()); break; case MS_Seconds: frames = session->frame_rate(); @@ -1078,10 +1237,10 @@ AudioClock::get_frames (Field field,jack_nframes_t pos,int dir) return frames; } -jack_nframes_t -AudioClock::current_time (jack_nframes_t pos) const +nframes_t +AudioClock::current_time (nframes_t pos) const { - jack_nframes_t ret = 0; + nframes_t ret = 0; switch (_mode) { case SMPTE: @@ -1106,10 +1265,10 @@ AudioClock::current_time (jack_nframes_t pos) const return ret; } -jack_nframes_t -AudioClock::current_duration (jack_nframes_t pos) const +nframes_t +AudioClock::current_duration (nframes_t pos) const { - jack_nframes_t ret = 0; + nframes_t ret = 0; switch (_mode) { case SMPTE: @@ -1146,7 +1305,7 @@ AudioClock::smpte_sanitize_display() seconds_label.set_text("59"); } - switch ((long)rint(session->smpte_frames_per_second)) { + switch ((long)rint(session->smpte_frames_per_second())) { case 24: if (atoi(frames_label.get_text()) > 23) { frames_label.set_text("23"); @@ -1166,28 +1325,30 @@ AudioClock::smpte_sanitize_display() break; } - if (session->smpte_drop_frames) { + if (session->smpte_drop_frames()) { if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) { frames_label.set_text("02"); } } } -jack_nframes_t +nframes_t AudioClock::smpte_frame_from_display () const { if (session == 0) { return 0; } - SMPTE_Time smpte; - jack_nframes_t sample; + SMPTE::Time smpte; + nframes_t sample; smpte.hours = atoi (hours_label.get_text()); smpte.minutes = atoi (minutes_label.get_text()); smpte.seconds = atoi (seconds_label.get_text()); smpte.frames = atoi (frames_label.get_text()); - + smpte.rate = session->smpte_frames_per_second(); + smpte.drop= session->smpte_drop_frames(); + session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ ); @@ -1201,11 +1362,11 @@ AudioClock::smpte_frame_from_display () const #define SMPTE_SAMPLE_TEST_7 // Testcode for smpte<->sample conversions (P.S.) - SMPTE_Time smpte1; - jack_nframes_t sample1; - jack_nframes_t oldsample = 0; - SMPTE_Time smpte2; - jack_nframes_t sample_increment; + SMPTE::Time smpte1; + nframes_t sample1; + nframes_t oldsample = 0; + SMPTE::Time smpte2; + nframes_t sample_increment; sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second); @@ -1564,7 +1725,7 @@ AudioClock::smpte_frame_from_display () const return sample; } -jack_nframes_t +nframes_t AudioClock::minsec_frame_from_display () const { if (session == 0) { @@ -1575,13 +1736,13 @@ AudioClock::minsec_frame_from_display () const int mins = atoi (ms_minutes_label.get_text()); float secs = atof (ms_seconds_label.get_text()); - jack_nframes_t sr = session->frame_rate(); + nframes_t sr = session->frame_rate(); - return (jack_nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr)); + return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr)); } -jack_nframes_t -AudioClock::bbt_frame_from_display (jack_nframes_t pos) const +nframes_t +AudioClock::bbt_frame_from_display (nframes_t pos) const { if (session == 0) { error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg; @@ -1595,14 +1756,14 @@ AudioClock::bbt_frame_from_display (jack_nframes_t pos) const any.bbt.beats = atoi (beats_label.get_text()); any.bbt.ticks = atoi (ticks_label.get_text()); - jack_nframes_t ret = session->convert_to_frames_at (pos, any); + nframes_t ret = session->convert_to_frames_at (pos, any); return ret; } -jack_nframes_t -AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const +nframes_t +AudioClock::bbt_frame_duration_from_display (nframes_t pos) const { if (session == 0) { error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg; @@ -1619,10 +1780,10 @@ AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const return session->tempo_map().bbt_duration_at(pos,bbt,1); } -jack_nframes_t +nframes_t AudioClock::audio_frame_from_display () const { - return (jack_nframes_t) atoi (audio_frames_label.get_text()); + return (nframes_t) atoi (audio_frames_label.get_text()); } void @@ -1637,11 +1798,11 @@ AudioClock::build_ops_menu () MenuList& mode_items = mode_menu->items(); mode_menu->set_name ("ArdourContextMenu"); - mode_items.push_back (MenuElem (_("SMPTE"), bind (slot (*this, &AudioClock::set_mode), SMPTE))); - mode_items.push_back (MenuElem (_("Bars:Beats"), bind (slot (*this, &AudioClock::set_mode), BBT))); - mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (slot (*this, &AudioClock::set_mode), MinSec))); - mode_items.push_back (MenuElem (_("Audio Frames"), bind (slot (*this, &AudioClock::set_mode), Frames))); - mode_items.push_back (MenuElem (_("Off"), bind (slot (*this, &AudioClock::set_mode), Off))); + mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE))); + mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT))); + mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec))); + mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames))); + mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off))); ops_items.push_back (MenuElem (_("Mode"), *mode_menu)); } @@ -1656,10 +1817,8 @@ AudioClock::set_mode (Mode m) started editing the clock and then we switch clock mode. */ - if (ARDOUR_UI::instance()) { - ARDOUR_UI::instance()->allow_focus (false); - } - + clock_base.grab_focus (); + if (_mode == m) { return; } @@ -1675,24 +1834,70 @@ AudioClock::set_mode (Mode m) } _mode = m; - + switch (_mode) { case SMPTE: clock_base.add (smpte_packer_hbox); break; + case BBT: clock_base.add (bbt_packer_hbox); break; + case MinSec: clock_base.add (minsec_packer_hbox); break; + case Frames: clock_base.add (frames_packer_hbox); + break; + case Off: break; } + + set_size_requests (); set (last_when, true); clock_base.show_all (); key_entry_state = 0; + + if (!is_transient) { + ModeChanged (); /* EMIT SIGNAL */ + } +} + +void +AudioClock::set_size_requests () +{ + /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */ + + switch (_mode) { + case SMPTE: + Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5); + Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5); + Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5); + Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5); + break; + + case BBT: + Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5); + Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5); + Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5); + break; + + case MinSec: + Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5); + Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5); + Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5); + break; + + case Frames: + Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5); + break; + + case Off: + break; + + } }