X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Faudio_clock.cc;h=fd8aca8df18466016f9494a761bc093b22b59ef1;hb=611dcdd24932222d676da4d9a4dca643f79db4a4;hp=47f17e5f4e9d15a6a86d2e3990cf96ef73915c68;hpb=eba4f18a92f478df4a92ca46bac8ba44afc5ddca;p=ardour.git diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index 47f17e5f4e..fd8aca8df1 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) @@ -70,7 +70,8 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string& , _off (false) , _fixed_width (true) , layout_x_offset (0) - , ops_menu (0) + , em_width (0) + , _edit_by_click_field (false) , editing_attr (0) , foreground_attr (0) , first_height (0) @@ -171,6 +172,17 @@ AudioClock::set_font () info_attributes.change (*font_attr); delete font_attr; + + /* get the figure width for the font. This doesn't have to super + * accurate since we only use it to measure the (roughly 1 character) + * offset from the position Pango tells us for the "cursor" + */ + + Glib::RefPtr tmp = Pango::Layout::create (get_pango_context()); + int ignore_height; + + tmp->set_text ("8"); + tmp->get_pixel_size (em_width, ignore_height); } void @@ -332,8 +344,6 @@ AudioClock::render (cairo_t* cr) } if (editing) { - const double cursor_width = 12; /* need em width here, not 16 */ - if (!insert_map.empty()) { @@ -352,12 +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, - layout_x_offset + cursor.get_x()/PANGO_SCALE + cursor_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, - layout_x_offset + cursor.get_x()/PANGO_SCALE + cursor_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); } @@ -404,7 +415,6 @@ AudioClock::on_size_allocate (Gtk::Allocation& alloc) /* left justify */ layout_x_offset = 0; } - } void @@ -511,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()) { @@ -523,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) { @@ -546,6 +606,7 @@ AudioClock::end_edit (bool modify) break; case MinSec: + ok = minsec_validate_edit (edit_string); break; case Frames: @@ -734,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; } @@ -762,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; @@ -910,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; @@ -955,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; @@ -1021,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; @@ -1080,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); } } @@ -1127,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: @@ -1216,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]; @@ -1238,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 (); @@ -1265,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) @@ -1363,15 +1455,6 @@ AudioClock::on_button_press_event (GdkEventButton *ev) switch (ev->button) { case 1: if (editable && !_off) { - dragging = true; - /* 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), - NULL,NULL,ev->time); - drag_accum = 0; - drag_start_y = ev->y; - drag_y = ev->y; - int index; int trailing; int y; @@ -1384,10 +1467,16 @@ AudioClock::on_button_press_event (GdkEventButton *ev) y = ev->y - ((upper_height - layout_height)/2); x = ev->x - layout_x_offset; - if (_layout->xy_to_index (x * PANGO_SCALE, y * PANGO_SCALE, index, trailing)) { + if (_layout->xy_to_index (x * PANGO_SCALE, y * PANGO_SCALE, index, trailing)) { drag_field = index_to_field (index); - } else { - drag_field = Field (0); + dragging = true; + /* 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), + NULL,NULL,ev->time); + drag_accum = 0; + drag_start_y = ev->y; + drag_y = ev->y; } } break; @@ -1413,10 +1502,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 (); + } } } - } } @@ -1542,7 +1657,7 @@ AudioClock::on_motion_notify_event (GdkEventMotion *ev) int dir; dir = (drag_accum < 0 ? 1:-1); pos = current_time(); - frames = get_frame_step (drag_field,pos,dir); + frames = get_frame_step (drag_field, pos, dir); if (frames != 0 && frames * drag_accum < current_time()) { set ((framepos_t) floor (pos - drag_accum * frames), false); // minus because up is negative in GTK @@ -1621,7 +1736,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; } @@ -1659,7 +1774,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; } @@ -1672,7 +1791,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; @@ -1681,11 +1800,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; } @@ -1698,6 +1817,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 { @@ -1776,10 +1911,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); } @@ -1962,7 +2097,7 @@ AudioClock::set_off (bool yn) void AudioClock::focus () { - start_edit (); + start_edit (Field (0)); } void