X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Faudio_clock.cc;h=dbe7f03a1453ecbeca417115694fb28255a75d5a;hb=c40437430acf4b65d8acb8b084eae8cd2f6f5402;hp=eb41ef319d113788e0369999b07f1f2964163890;hpb=24a919ce6d3509e777339a7da4a87ed00556a053;p=ardour.git diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index eb41ef319d..dbe7f03a14 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -24,17 +24,16 @@ #include "pbd/enumwriter.h" #include +#include #include "gtkmm2ext/cairocell.h" #include "gtkmm2ext/utils.h" #include "gtkmm2ext/rgb_macros.h" -#include "ardour/ardour.h" +#include "ardour/types.h" #include "ardour/session.h" #include "ardour/tempo.h" #include "ardour/profile.h" -#include "ardour/slave.h" -#include #include "ardour_ui.h" #include "audio_clock.h" @@ -62,7 +61,8 @@ const double AudioClock::x_leading_padding = 6.0; AudioClock::AudioClock (const string& clock_name, bool transient, const string& widget_name, bool allow_edit, bool follows_playhead, bool duration, bool with_info) - : _name (clock_name) + : ops_menu (0) + , _name (clock_name) , is_transient (transient) , is_duration (duration) , editable (allow_edit) @@ -71,7 +71,7 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string& , _fixed_width (true) , layout_x_offset (0) , em_width (0) - , ops_menu (0) + , _edit_by_click_field (false) , editing_attr (0) , foreground_attr (0) , first_height (0) @@ -362,11 +362,13 @@ AudioClock::render (cairo_t* cr) cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a); if (!_fixed_width) { cairo_rectangle (cr, - min (get_width() - 2.0, (double) cursor.get_x()/PANGO_SCALE + em_width), 0, + min (get_width() - 2.0, + (double) cursor.get_x()/PANGO_SCALE + layout_x_offset + em_width), 0, 2.0, cursor.get_height()/PANGO_SCALE); } else { cairo_rectangle (cr, - min (get_width() - 2.0, (double) layout_x_offset + cursor.get_x()/PANGO_SCALE + em_width), + min (get_width() - 2.0, + (double) layout_x_offset + cursor.get_x()/PANGO_SCALE + em_width), (upper_height - layout_height)/2.0, 2.0, cursor.get_height()/PANGO_SCALE); } @@ -519,7 +521,7 @@ AudioClock::show_edit_status (int length) } void -AudioClock::start_edit () +AudioClock::start_edit (Field f) { pre_edit_string = _layout->get_text (); if (!insert_map.empty()) { @@ -531,12 +533,62 @@ AudioClock::start_edit () input_string.clear (); editing = true; + if (f) { + input_string = get_field (f); + show_edit_status (merge_input_and_edit_string ()); + _layout->set_text (edit_string); + } + queue_draw (); Keyboard::magic_widget_grab_focus (); grab_focus (); } +string +AudioClock::get_field (Field f) +{ + switch (f) { + case Timecode_Hours: + return edit_string.substr (1, 2); + break; + case Timecode_Minutes: + return edit_string.substr (4, 2); + break; + case Timecode_Seconds: + return edit_string.substr (7, 2); + break; + case Timecode_Frames: + return edit_string.substr (10, 2); + break; + case MS_Hours: + return edit_string.substr (1, 2); + break; + case MS_Minutes: + return edit_string.substr (4, 2); + break; + case MS_Seconds: + return edit_string.substr (7, 2); + break; + case MS_Milliseconds: + return edit_string.substr (10, 3); + break; + case Bars: + return edit_string.substr (1, 3); + break; + case Beats: + return edit_string.substr (5, 2); + break; + case Ticks: + return edit_string.substr (8, 4); + break; + case AudioFrames: + return edit_string; + break; + } + return ""; +} + void AudioClock::end_edit (bool modify) { @@ -554,6 +606,7 @@ AudioClock::end_edit (bool modify) break; case MinSec: + ok = minsec_validate_edit (edit_string); break; case Frames: @@ -742,7 +795,7 @@ AudioClock::parse_as_timecode_distance (const std::string& str) } framecnt_t -AudioClock::parse_as_bbt_distance (const std::string& str) +AudioClock::parse_as_bbt_distance (const std::string&) { return 0; } @@ -770,6 +823,35 @@ AudioClock::parse_as_distance (const std::string& instr) void AudioClock::end_edit_relative (bool add) { + bool ok = true; + + switch (_mode) { + case Timecode: + ok = timecode_validate_edit (edit_string); + break; + + case BBT: + ok = bbt_validate_edit (edit_string); + break; + + case MinSec: + ok = minsec_validate_edit (edit_string); + break; + + case Frames: + break; + } + + if (!ok) { + edit_string = pre_edit_string; + input_string.clear (); + _layout->set_text (edit_string); + show_edit_status (0); + /* edit attributes remain in use */ + queue_draw (); + return; + } + framecnt_t frames = parse_as_distance (input_string); editing = false; @@ -918,7 +1000,7 @@ AudioClock::set_frames (framepos_t when, bool /*force*/) } void -AudioClock::set_minsec (framepos_t when, bool force) +AudioClock::set_minsec (framepos_t when, bool /*force*/) { char buf[32]; framecnt_t left; @@ -963,7 +1045,7 @@ AudioClock::set_minsec (framepos_t when, bool force) } void -AudioClock::set_timecode (framepos_t when, bool force) +AudioClock::set_timecode (framepos_t when, bool /*force*/) { char buf[32]; Timecode::Time TC; @@ -1029,7 +1111,7 @@ AudioClock::set_timecode (framepos_t when, bool force) } void -AudioClock::set_bbt (framepos_t when, bool force) +AudioClock::set_bbt (framepos_t when, bool /*force*/) { char buf[16]; Timecode::BBT_Time BBT; @@ -1088,7 +1170,7 @@ AudioClock::set_bbt (framepos_t when, bool force) sprintf (buf, "%-5.2f", m.tempo().beats_per_minute()); _left_layout->set_text (buf); - sprintf (buf, "%g/%g", m.meter().beats_per_bar(), m.meter().note_divisor()); + sprintf (buf, "%g/%g", m.meter().divisions_per_bar(), m.meter().note_divisor()); _right_layout->set_text (buf); } } @@ -1135,6 +1217,8 @@ AudioClock::on_key_press_event (GdkEventKey* ev) string new_text; char new_char = 0; + int highlight_length; + framepos_t pos; switch (ev->keyval) { case GDK_0: @@ -1224,18 +1308,13 @@ AudioClock::on_key_press_event (GdkEventKey* ev) use_input_string: - int highlight_length = 0; - framepos_t pos; - - /* merge with pre-edit-string into edit string */ - switch (_mode) { case Frames: /* get this one in the right order, and to the right width */ - if (ev->keyval != GDK_Delete && ev->keyval != GDK_BackSpace) { - edit_string.push_back (new_char); - } else { + if (ev->keyval == GDK_Delete || ev->keyval == GDK_BackSpace) { edit_string = edit_string.substr (0, edit_string.length() - 1); + } else { + edit_string.push_back (new_char); } if (!edit_string.empty()) { char buf[32]; @@ -1246,26 +1325,11 @@ AudioClock::on_key_press_event (GdkEventKey* ev) /* highlight the whole thing */ highlight_length = edit_string.length(); break; - - default: - edit_string = pre_edit_string; - if (input_string.empty()) { - highlight_length = 0; - } else { - // for (int i = input_string.length() - 1; i >= 0; --i) { - string::size_type target; - for (string::size_type i = 0; i < input_string.length(); ++i) { - target = insert_map[input_string.length() - 1 - i]; - edit_string[target] = input_string[i]; - } - /* highlight from end to wherever the last character was added */ - highlight_length = edit_string.length() - insert_map[input_string.length()-1]; - } - break; + default: + highlight_length = merge_input_and_edit_string (); } - - + show_edit_status (highlight_length); _layout->set_text (edit_string); queue_draw (); @@ -1273,6 +1337,26 @@ AudioClock::on_key_press_event (GdkEventKey* ev) return true; } +int +AudioClock::merge_input_and_edit_string () +{ + /* merge with pre-edit-string into edit string */ + + edit_string = pre_edit_string; + + if (input_string.empty()) { + return 0; + } + + string::size_type target; + for (string::size_type i = 0; i < input_string.length(); ++i) { + target = insert_map[input_string.length() - 1 - i]; + edit_string[target] = input_string[i]; + } + /* highlight from end to wherever the last character was added */ + return edit_string.length() - insert_map[input_string.length()-1]; +} + bool AudioClock::on_key_release_event (GdkEventKey *ev) @@ -1421,10 +1505,36 @@ AudioClock::on_button_release_event (GdkEventButton *ev) return true; } else { if (ev->button == 1) { - start_edit (); + + if (_edit_by_click_field) { + + int index = 0; + int trailing; + int y = ev->y - ((upper_height - layout_height)/2); + int x = ev->x - layout_x_offset; + Field f; + + if (!_layout->xy_to_index (x * PANGO_SCALE, y * PANGO_SCALE, index, trailing)) { + return true; + } + + f = index_to_field (index); + + switch (f) { + case Timecode_Frames: + case MS_Milliseconds: + case Ticks: + f = Field (0); + break; + default: + break; + } + start_edit (f); + } else { + start_edit (); + } } } - } } @@ -1629,7 +1739,7 @@ AudioClock::get_frame_step (Field field, framepos_t pos, int dir) } framepos_t -AudioClock::current_time (framepos_t pos) const +AudioClock::current_time (framepos_t) const { return last_when; } @@ -1667,7 +1777,11 @@ AudioClock::bbt_validate_edit (const string& str) if (sscanf (str.c_str(), BBT_SCANF_FORMAT, &any.bbt.bars, &any.bbt.beats, &any.bbt.ticks) != 3) { return false; } - + + if (any.bbt.ticks > Timecode::BBT_Time::ticks_per_beat) { + return false; + } + if (!is_duration && any.bbt.bars == 0) { return false; } @@ -1680,7 +1794,7 @@ AudioClock::bbt_validate_edit (const string& str) } bool -AudioClock::timecode_validate_edit (const string& str) +AudioClock::timecode_validate_edit (const string&) { Timecode::Time TC; @@ -1689,11 +1803,11 @@ AudioClock::timecode_validate_edit (const string& str) return false; } - if (TC.minutes > 59U || TC.seconds > 59U) { + if (TC.hours > 23U || TC.minutes > 59U || TC.seconds > 59U) { return false; } - if (TC.frames > (long)rint(_session->timecode_frames_per_second()) - 1) { + if (TC.frames > (uint32_t) rint (_session->timecode_frames_per_second()) - 1) { return false; } @@ -1706,6 +1820,22 @@ AudioClock::timecode_validate_edit (const string& str) return true; } +bool +AudioClock::minsec_validate_edit (const string& str) +{ + int hrs, mins, secs, millisecs; + + if (sscanf (str.c_str(), "%d:%d:%d.%d", &hrs, &mins, &secs, &millisecs) != 4) { + return false; + } + + if (hrs > 23 || mins > 59 || secs > 59 || millisecs > 999) { + return false; + } + + return true; +} + framepos_t AudioClock::frames_from_timecode_string (const string& str) const { @@ -1784,10 +1914,10 @@ AudioClock::frame_duration_from_bbt_string (framepos_t pos, const string& str) c Timecode::BBT_Time bbt; - if (sscanf (str.c_str(), BBT_SCANF_FORMAT, &bbt.bars, &bbt.beats, &bbt.ticks) != 0) { + if (sscanf (str.c_str(), BBT_SCANF_FORMAT, &bbt.bars, &bbt.beats, &bbt.ticks) != 3) { return 0; } - + return _session->tempo_map().bbt_duration_at(pos,bbt,1); } @@ -1970,7 +2100,7 @@ AudioClock::set_off (bool yn) void AudioClock::focus () { - start_edit (); + start_edit (Field (0)); } void