X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Faudio_clock.cc;h=2dfdf77272e3bf254cc3b2dc7ffd53f28340c894;hb=e80ccbfc8b3a572e517cd9932e5f260e41a5dff7;hp=bb1b9f4c4370ccc962e23f00c731fa42ce090b69;hpb=1f149870448010210c6da4d0b1d58a751dc478f9;p=ardour.git diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index bb1b9f4c43..2dfdf77272 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -74,6 +74,8 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string& , layout_x_offset (0) , em_width (0) , _edit_by_click_field (false) + , _negative_allowed (false) + , edit_is_negative (false) , editing_attr (0) , foreground_attr (0) , first_height (0) @@ -190,6 +192,9 @@ AudioClock::set_font () tmp->set_text ("8"); tmp->get_pixel_size (em_width, ignore_height); + + /* force redraw of markup with new font-size */ + set (last_when, true); } void @@ -266,11 +271,6 @@ AudioClock::set_colors () _layout->set_attributes (editing_attributes); } - if (_left_layout) { - _left_layout->set_attributes (info_attributes); - _right_layout->set_attributes (info_attributes); - } - queue_draw (); } @@ -283,7 +283,7 @@ AudioClock::render (cairo_t* cr) cairo_set_source_rgba (cr, bg_r, bg_g, bg_b, bg_a); if (corner_radius) { if (_left_layout) { - Gtkmm2ext::rounded_top_half_rectangle (cr, 0, 0, get_width() - corner_radius/2.0, upper_height, corner_radius); + Gtkmm2ext::rounded_top_half_rectangle (cr, 0, 0, get_width(), upper_height, corner_radius); } else { Gtkmm2ext::rounded_rectangle (cr, 0, 0, get_width(), upper_height, corner_radius); } @@ -296,7 +296,7 @@ AudioClock::render (cairo_t* cr) if (!_fixed_width) { cairo_move_to (cr, layout_x_offset, 0); } else { - int xcenter = layout_x_offset != 0 ? 0 : (get_width() - _mode_width[_mode]) /2; + int xcenter = layout_x_offset > 0 ? 0 : (get_width() - _mode_width[_mode]) /2; cairo_move_to (cr, layout_x_offset + xcenter, (upper_height - layout_height) / 2.0); } @@ -318,7 +318,7 @@ AudioClock::render (cairo_t* cr) if (corner_radius) { Gtkmm2ext::rounded_bottom_half_rectangle (cr, 0, upper_height + separator_height, left_rect_width + (separator_height == 0 ? corner_radius : 0), - h - corner_radius/2.0, corner_radius); + h, corner_radius); } else { cairo_rectangle (cr, 0, upper_height + separator_height, left_rect_width, h); } @@ -332,8 +332,8 @@ AudioClock::render (cairo_t* cr) if (corner_radius) { Gtkmm2ext::rounded_bottom_half_rectangle (cr, left_rect_width + separator_height, upper_height + separator_height, - get_width() - separator_height - left_rect_width - corner_radius/2.0, - h - corner_radius/2.0, corner_radius); + get_width() - separator_height - left_rect_width, + h, corner_radius); } else { cairo_rectangle (cr, left_rect_width + separator_height, upper_height + separator_height, get_width() - separator_height - left_rect_width, h); @@ -352,8 +352,9 @@ AudioClock::render (cairo_t* cr) */ int x, rw, rh; _right_layout->get_pixel_size(rw, rh); - x = get_width() - rw- separator_height - x_leading_padding; + x = get_width() - rw - separator_height - x_leading_padding; if (x < x_leading_padding + left_rect_width + separator_height) { + /* rather cut off the right end than overlap with the text on the left */ x = x_leading_padding + left_rect_width + separator_height; } cairo_move_to (cr, x, upper_height + separator_height + ((h - info_height)/2.0)); @@ -379,7 +380,7 @@ AudioClock::render (cairo_t* cr) if (editing) { if (!insert_map.empty()) { - int xcenter = layout_x_offset != 0 ? 0 : (get_width() - _mode_width[_mode]) /2; + int xcenter = layout_x_offset > 0 ? 0 : (get_width() - _mode_width[_mode]) /2; if (input_string.length() < insert_map.size()) { Pango::Rectangle cursor; @@ -486,7 +487,7 @@ AudioClock::on_size_request (Gtk::Requisition* req) int ignored; tmp->set_text ("-88:88:88:88"); tmp->get_pixel_size (_mode_width[Timecode], ignored); - tmp->set_text (" 8888|88|8888"); + tmp->set_text (" 88888|88|8888"); tmp->get_pixel_size (_mode_width[BBT], ignored); tmp->set_text (" 88:88:88,888"); tmp->get_pixel_size (_mode_width[MinSec], ignored); @@ -500,14 +501,14 @@ AudioClock::on_size_request (Gtk::Requisition* req) not be sufficient for 24h worth of BBT */ - tmp->set_text (" 8888888888::,"); + tmp->set_text (" 88888888888::,"); } else { switch (_mode) { case Timecode: tmp->set_text ("-88:88:88:88"); break; case BBT: - tmp->set_text (" 8888|88|8888"); + tmp->set_text (" 88888|88|8888"); break; case MinSec: tmp->set_text (" 88:88:88,888"); @@ -550,9 +551,6 @@ AudioClock::on_size_request (Gtk::Requisition* req) req->height += separator_height; } - req->height += corner_radius/2.0; - req->width += corner_radius/2.0; - first_height = req->height; first_width = req->width; } @@ -579,8 +577,10 @@ AudioClock::start_edit (Field f) edit_string.clear (); _layout->set_text (""); } + input_string.clear (); editing = true; + edit_is_negative = false; if (f) { input_string = get_field (f); @@ -703,6 +703,7 @@ AudioClock::end_edit (bool modify) } else { editing = false; + edit_is_negative = false; _layout->set_attributes (normal_attributes); _layout->set_text (pre_edit_string); } @@ -914,7 +915,7 @@ AudioClock::end_edit_relative (bool add) } else { framepos_t c = current_time(); - if (c > frames) { + if (c > frames || _negative_allowed) { set (c - frames, true); } else { set (0, true); @@ -928,9 +929,20 @@ AudioClock::end_edit_relative (bool add) drop_focus (); } +void +AudioClock::session_property_changed (const PropertyChange& p) +{ + set (last_when, true); +} + void AudioClock::session_configuration_changed (std::string p) { + if (_negative_allowed) { + /* session option editor clock */ + return; + } + if (p == "sync-source" || p == "external-sync") { set (current_time(), true); return; @@ -968,8 +980,8 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset) } if (when == last_when && !force) { - if (_mode != Timecode) { - /* timecode may need to force display of TC source + if (_mode != Timecode && _mode != MinSec) { + /* may need to force display of TC source * time, so don't return early. */ return; @@ -994,6 +1006,9 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset) break; case MinSec: + if (_right_layout) { + _right_layout->set_alignment(Pango::ALIGN_RIGHT); + } set_minsec (when, force); break; @@ -1007,6 +1022,63 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset) last_when = when; } +void +AudioClock::set_slave_info () +{ + if (!_left_layout || !_right_layout) { + return; + } + + SyncSource sync_src = Config->get_sync_source(); + + if (_session->config.get_external_sync()) { + Slave* slave = _session->slave(); + + switch (sync_src) { + case JACK: + _left_layout->set_markup (string_compose ("%2", + INFO_FONT_SIZE, sync_source_to_string(sync_src, true))); + _right_layout->set_text (""); + break; + case MIDIClock: + if (slave) { + _left_layout->set_markup (string_compose ("%2", + INFO_FONT_SIZE, sync_source_to_string(sync_src, true))); + _right_layout->set_markup (string_compose ("%2", + INFO_FONT_SIZE, slave->approximate_current_delta())); + } else { + _left_layout->set_markup (string_compose ("%2", + INFO_FONT_SIZE, _("--pending--"))); + _right_layout->set_text (""); + } + break; + case LTC: + case MTC: + if (slave) { + bool matching; + TimecodeSlave* tcslave; + if ((tcslave = dynamic_cast(_session->slave())) != 0) { + matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format()); + _left_layout->set_markup (string_compose ("%2%4", + INFO_FONT_SIZE, sync_source_to_string(sync_src, true)[0], (matching?"green":"red"), + dynamic_cast(slave)->approximate_current_position())); + _right_layout->set_markup (string_compose ("%2", + INFO_FONT_SIZE, slave->approximate_current_delta())); + } + } else { + _left_layout->set_markup (string_compose ("%2", + INFO_FONT_SIZE, _("--pending--"))); + _right_layout->set_text (""); + } + break; + } + } else { + _left_layout->set_markup (string_compose ("INT/%2", + INFO_FONT_SIZE, sync_source_to_string(sync_src, true))); + _right_layout->set_text (""); + } +} + void AudioClock::set_frames (framepos_t when, bool /*force*/) { @@ -1052,12 +1124,12 @@ AudioClock::set_frames (framepos_t when, bool /*force*/) float vid_pullup = _session->config.get_video_pullup(); if (vid_pullup == 0.0) { - _right_layout->set_markup (string_compose ("%2", - INFO_FONT_SIZE, _("pullup: \u2012"))); + _right_layout->set_markup (string_compose ("%2 off", + INFO_FONT_SIZE, _("Pull"))); } else { - sprintf (buf, _("%+-6.4f%%"), vid_pullup); - _right_layout->set_markup (string_compose ("%2", - INFO_FONT_SIZE, buf)); + sprintf (buf, _("%+.4f%%"), vid_pullup); + _right_layout->set_markup (string_compose ("%2 %3", + INFO_FONT_SIZE, _("Pull"), buf)); } } } @@ -1105,6 +1177,7 @@ AudioClock::set_minsec (framepos_t when, bool /*force*/) } _layout->set_text (buf); + set_slave_info(); } void @@ -1138,40 +1211,7 @@ AudioClock::set_timecode (framepos_t when, bool /*force*/) _layout->set_text (Timecode::timecode_format_time(TC)); - if (_left_layout && _right_layout) { - - SyncSource sync_src = Config->get_sync_source(); - - if (_session->config.get_external_sync()) { - Slave* slave = _session->slave(); - - switch (sync_src) { - case JACK: - _left_layout->set_markup (string_compose ("%2", - INFO_FONT_SIZE, sync_source_to_string(sync_src, true))); - _right_layout->set_text (""); - break; - case LTC: - case MTC: - case MIDIClock: - if (slave) { - _left_layout->set_markup (string_compose ("%2", - INFO_FONT_SIZE, dynamic_cast(slave)->approximate_current_position())); - _right_layout->set_markup (string_compose ("%2", - INFO_FONT_SIZE, slave->approximate_current_delta())); - } else { - _left_layout->set_markup (string_compose ("%2", - INFO_FONT_SIZE, _("--pending--"))); - _right_layout->set_text (""); - } - break; - } - } else { - _left_layout->set_markup (string_compose ("INT/%2", - INFO_FONT_SIZE, sync_source_to_string(sync_src, true))); - _right_layout->set_text (""); - } - } + set_slave_info(); } void @@ -1232,11 +1272,11 @@ AudioClock::set_bbt (framepos_t when, bool /*force*/) TempoMetric m (_session->tempo_map().metric_at (pos)); sprintf (buf, "%-5.2f", m.tempo().beats_per_minute()); - _left_layout->set_markup (string_compose ("%2", + _left_layout->set_markup (string_compose ("Tempo %2", INFO_FONT_SIZE, buf)); sprintf (buf, "%g/%g", m.meter().divisions_per_bar(), m.meter().note_divisor()); - _right_layout->set_markup (string_compose ("%2", + _right_layout->set_markup (string_compose ("Meter %2", INFO_FONT_SIZE, buf)); } } @@ -1249,6 +1289,7 @@ AudioClock::set_session (Session *s) if (_session) { _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_configuration_changed, this, _1), gui_context()); + _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_property_changed, this, _1), gui_context()); const XMLProperty* prop; XMLNode* node = _session->extra_xml (X_("ClockModes")); @@ -1330,12 +1371,18 @@ AudioClock::on_key_press_event (GdkEventKey* ev) case GDK_minus: case GDK_KP_Subtract: - end_edit_relative (false); + if (_negative_allowed && input_string.empty()) { + edit_is_negative = true; + edit_string.replace(0,1,"-"); + _layout->set_text (edit_string); + queue_draw (); + } else { + end_edit_relative (false); + } return true; break; case GDK_plus: - case GDK_KP_Add: end_edit_relative (true); return true; break; @@ -1396,6 +1443,16 @@ AudioClock::on_key_press_event (GdkEventKey* ev) highlight_length = merge_input_and_edit_string (); } + if (edit_is_negative) { + edit_string.replace(0,1,"-"); + } else { + if (pre_edit_string.at(0) == '-') { + edit_string.replace(0,1,"_"); + } else { + edit_string.replace(0,1," "); + } + } + show_edit_status (highlight_length); _layout->set_text (edit_string); queue_draw (); @@ -1529,9 +1586,10 @@ AudioClock::on_button_press_event (GdkEventButton *ev) /* the text has been centered vertically, so adjust * x and y. */ + int xcenter = !_fixed_width || layout_x_offset > 0 ? 0 : (get_width() - _mode_width[_mode]) /2; y = ev->y - ((upper_height - layout_height)/2); - x = ev->x - layout_x_offset; + x = ev->x - layout_x_offset - xcenter; if (!_layout->xy_to_index (x * PANGO_SCALE, y * PANGO_SCALE, index, trailing)) { /* pretend it is a character on the far right */ @@ -1573,10 +1631,11 @@ AudioClock::on_button_release_event (GdkEventButton *ev) if (_edit_by_click_field) { + int xcenter = !_fixed_width || layout_x_offset > 0 ? 0 : (get_width() - _mode_width[_mode]) /2; int index = 0; int trailing; int y = ev->y - ((upper_height - layout_height)/2); - int x = ev->x - layout_x_offset; + int x = ev->x - layout_x_offset - xcenter; Field f; if (!_layout->xy_to_index (x * PANGO_SCALE, y * PANGO_SCALE, index, trailing)) { @@ -1643,8 +1702,9 @@ AudioClock::on_scroll_event (GdkEventScroll *ev) * x and y. */ + int xcenter = !_fixed_width || layout_x_offset > 0 ? 0 : (get_width() - _mode_width[_mode]) /2; y = ev->y - ((upper_height - layout_height)/2); - x = ev->x - layout_x_offset; + x = ev->x - layout_x_offset - xcenter; if (!_layout->xy_to_index (x * PANGO_SCALE, y * PANGO_SCALE, index, trailing)) { /* not in the main layout */ @@ -1674,7 +1734,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev) frames *= 10; } - if ((double)current_time() - (double)frames < 0.0) { + if (!_negative_allowed && (double)current_time() - (double)frames < 0.0) { set (0, true); } else { set (current_time() - frames, true); @@ -1862,9 +1922,23 @@ bool AudioClock::timecode_validate_edit (const string&) { Timecode::Time TC; + int hours; + char ignored[2]; + + if (sscanf (_layout->get_text().c_str(), "%" PRId32 ":%" PRId32 ":%" PRId32 "%[:;]%" PRId32, + &hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 5) { + return false; + } + + if (hours < 0) { + TC.hours = hours * -1; + TC.negative = true; + } else { + TC.hours = hours; + TC.negative = false; + } - if (sscanf (_layout->get_text().c_str(), "%" PRId32 ":%" PRId32 ":%" PRId32 ":%" PRId32, - &TC.hours, &TC.minutes, &TC.seconds, &TC.frames) != 4) { + if (TC.negative && !_negative_allowed) { return false; } @@ -1910,18 +1984,23 @@ AudioClock::frames_from_timecode_string (const string& str) const Timecode::Time TC; framepos_t sample; + char ignored[2]; + int hours; - if (sscanf (str.c_str(), "%d:%d:%d:%d", &TC.hours, &TC.minutes, &TC.seconds, &TC.frames) != 4) { + if (sscanf (str.c_str(), "%d:%d:%d%[:;]%d", &hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 5) { error << string_compose (_("programming error: %1 %2"), "badly formatted timecode clock string", str) << endmsg; return 0; } - + TC.hours = abs(hours); TC.rate = _session->timecode_frames_per_second(); TC.drop= _session->timecode_drop_frames(); _session->timecode_to_sample (TC, sample, false /* use_offset */, false /* use_subframes */ ); // timecode_tester (); + if (edit_is_negative) { + sample = - sample; + } return sample; } @@ -2058,7 +2137,6 @@ AudioClock::set_mode (Mode m) int ignored; _left_layout->set_text (" 1234567890"); _left_layout->get_pixel_size (ignored, info_height); - info_height += 4; _left_layout->set_text (""); _right_layout->set_text (""); @@ -2091,7 +2169,7 @@ AudioClock::set_mode (Mode m) break; case MinSec: - mode_based_info_ratio = 1.0; + mode_based_info_ratio = 0.5; insert_map.push_back (12); insert_map.push_back (11); insert_map.push_back (10); @@ -2203,3 +2281,9 @@ AudioClock::dpi_reset () first_height = 0; queue_resize (); } + +void +AudioClock::set_negative_allowed (bool yn) +{ + _negative_allowed = yn; +}