X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Faudio_clock.cc;h=2656c2b445f128cf31d0217d09fe392f17ae7a0a;hb=57d7b5de65b399fc7d1d61a3a9212c0fa7f1e95c;hp=3053dd9a871bb9cb2b992fed79ac72b55b028bf1;hpb=a6d71df0d06c8efcf1ee306a5fbc70a4ddceb12f;p=ardour.git diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index 3053dd9a87..2656c2b445 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -26,15 +26,17 @@ #include #include -#include "gtkmm2ext/cairocell.h" #include "gtkmm2ext/utils.h" #include "gtkmm2ext/rgb_macros.h" +#include "widgets/tooltips.h" + #include "ardour/profile.h" #include "ardour/lmath.h" #include "ardour/session.h" -#include "ardour/slave.h" +#include "ardour/transport_master.h" #include "ardour/tempo.h" +#include "ardour/transport_master_manager.h" #include "ardour/types.h" #include "ardour_ui.h" @@ -42,7 +44,6 @@ #include "enums_convert.h" #include "gui_thread.h" #include "keyboard.h" -#include "tooltips.h" #include "ui_config.h" #include "utils.h" @@ -50,6 +51,7 @@ using namespace ARDOUR; using namespace ARDOUR_UI_UTILS; +using namespace ArdourWidgets; using namespace PBD; using namespace Gtk; using namespace std; @@ -77,6 +79,7 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string& , _edit_by_click_field (false) , _negative_allowed (false) , edit_is_negative (false) + , _limit_pos (INT64_MAX - 1) , _with_info (with_info) , editing_attr (0) , foreground_attr (0) @@ -106,7 +109,7 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string& _mode = BBT; /* lie to force mode switch */ set_mode (Timecode); - set (last_when, true); + AudioClock::set (last_when, true); if (!is_transient) { clocks.push_back (this); @@ -185,7 +188,7 @@ AudioClock::set_font (Pango::FontDescription font) tmp->get_pixel_size (em_width, ignore_height); /* force redraw of markup with new font-size */ - set (last_when, true); + AudioClock::set (last_when, true); } void @@ -326,10 +329,10 @@ AudioClock::render (Cairo::RefPtr const& ctx, cairo_rectangle_t* cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a); cairo_rectangle (cr, - min (get_width() - 2.0, - (double) xcenter + cursor.get_x()/PANGO_SCALE + em_width), - (get_height() - layout_height)/2.0, - 2.0, cursor.get_height()/PANGO_SCALE); + min (get_width() - 2.0, + (double) xcenter + cursor.get_x()/PANGO_SCALE + em_width), + (get_height() - layout_height)/2.0, + 2.0, cursor.get_height()/PANGO_SCALE); cairo_fill (cr); } else { /* we've entered all possible digits, no cursor */ @@ -451,7 +454,7 @@ AudioClock::get_field (Field f) case Timecode_Seconds: return edit_string.substr (7, 2); break; - case Timecode_Frames: + case Timecode_frames: return edit_string.substr (10, 2); break; case MS_Hours: @@ -475,7 +478,11 @@ AudioClock::get_field (Field f) case Ticks: return edit_string.substr (8, 4); break; - case AudioFrames: + case SS_Seconds: + return edit_string.substr (0, 8); + case SS_Deciseconds: + return edit_string.substr (9, 1); + case S_Samples: return edit_string; break; } @@ -502,7 +509,9 @@ AudioClock::end_edit (bool modify) ok = minsec_validate_edit (edit_string); break; - case Frames: + case Seconds: + /* fall through */ + case Samples: if (edit_string.length() < 1) { edit_string = pre_edit_string; } @@ -518,31 +527,35 @@ AudioClock::end_edit (bool modify) } else { editing = false; - framepos_t pos = 0; /* stupid gcc */ + samplepos_t pos = 0; /* stupid gcc */ switch (_mode) { case Timecode: - pos = frames_from_timecode_string (edit_string); + pos = samples_from_timecode_string (edit_string); break; case BBT: if (is_duration) { - pos = frame_duration_from_bbt_string (bbt_reference_time, edit_string); + pos = sample_duration_from_bbt_string (bbt_reference_time, edit_string); } else { - pos = frames_from_bbt_string (0, edit_string); + pos = samples_from_bbt_string (0, edit_string); } break; case MinSec: - pos = frames_from_minsec_string (edit_string); + pos = samples_from_minsec_string (edit_string); + break; + + case Seconds: + pos = samples_from_seconds_string (edit_string); break; - case Frames: - pos = frames_from_audioframes_string (edit_string); + case Samples: + pos = samples_from_audiosamples_string (edit_string); break; } - set (pos, true); + AudioClock::set (pos, true); _layout->set_attributes (normal_attributes); ValueChanged(); /* EMIT_SIGNAL */ } @@ -573,10 +586,22 @@ AudioClock::drop_focus () } } -framecnt_t -AudioClock::parse_as_frames_distance (const std::string& str) +samplecnt_t +AudioClock::parse_as_seconds_distance (const std::string& str) { - framecnt_t f; + float f; + + if (sscanf (str.c_str(), "%f", &f) == 1) { + return f * _session->sample_rate(); + } + + return 0; +} + +samplecnt_t +AudioClock::parse_as_samples_distance (const std::string& str) +{ + samplecnt_t f; if (sscanf (str.c_str(), "%" PRId64, &f) == 1) { return f; @@ -585,10 +610,10 @@ AudioClock::parse_as_frames_distance (const std::string& str) return 0; } -framecnt_t +samplecnt_t AudioClock::parse_as_minsec_distance (const std::string& str) { - framecnt_t sr = _session->frame_rate(); + samplecnt_t sr = _session->sample_rate(); int msecs; int secs; int mins; @@ -635,12 +660,12 @@ AudioClock::parse_as_minsec_distance (const std::string& str) return 0; } -framecnt_t +samplecnt_t AudioClock::parse_as_timecode_distance (const std::string& str) { double fps = _session->timecode_frames_per_second(); - framecnt_t sr = _session->frame_rate(); - int frames; + samplecnt_t sr = _session->sample_rate(); + int samples; int secs; int mins; int hrs; @@ -650,32 +675,32 @@ AudioClock::parse_as_timecode_distance (const std::string& str) return 0; case 1: case 2: - sscanf (str.c_str(), "%" PRId32, &frames); - return llrint ((frames/(float)fps) * sr); + sscanf (str.c_str(), "%" PRId32, &samples); + return llrint ((samples/(float)fps) * sr); case 3: - sscanf (str.c_str(), "%1" PRId32 "%" PRId32, &secs, &frames); - return (secs * sr) + llrint ((frames/(float)fps) * sr); + sscanf (str.c_str(), "%1" PRId32 "%" PRId32, &secs, &samples); + return (secs * sr) + llrint ((samples/(float)fps) * sr); case 4: - sscanf (str.c_str(), "%2" PRId32 "%" PRId32, &secs, &frames); - return (secs * sr) + llrint ((frames/(float)fps) * sr); + sscanf (str.c_str(), "%2" PRId32 "%" PRId32, &secs, &samples); + return (secs * sr) + llrint ((samples/(float)fps) * sr); case 5: - sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &frames); - return (mins * 60 * sr) + (secs * sr) + llrint ((frames/(float)fps) * sr); + sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &samples); + return (mins * 60 * sr) + (secs * sr) + llrint ((samples/(float)fps) * sr); case 6: - sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &frames); - return (mins * 60 * sr) + (secs * sr) + llrint ((frames/(float)fps) * sr); + sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &samples); + return (mins * 60 * sr) + (secs * sr) + llrint ((samples/(float)fps) * sr); case 7: - sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &frames); - return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + llrint ((frames/(float)fps) * sr); + sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &samples); + return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + llrint ((samples/(float)fps) * sr); case 8: - sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &frames); - return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + llrint ((frames/(float)fps) * sr); + sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &samples); + return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + llrint ((samples/(float)fps) * sr); default: break; @@ -684,21 +709,21 @@ AudioClock::parse_as_timecode_distance (const std::string& str) return 0; } -framecnt_t +samplecnt_t AudioClock::parse_as_bbt_distance (const std::string&) { return 0; } -framecnt_t +samplecnt_t AudioClock::parse_as_distance (const std::string& instr) { switch (_mode) { case Timecode: return parse_as_timecode_distance (instr); break; - case Frames: - return parse_as_frames_distance (instr); + case Samples: + return parse_as_samples_distance (instr); break; case BBT: return parse_as_bbt_distance (instr); @@ -706,6 +731,9 @@ AudioClock::parse_as_distance (const std::string& instr) case MinSec: return parse_as_minsec_distance (instr); break; + case Seconds: + return parse_as_seconds_distance (instr); + break; } return 0; } @@ -728,7 +756,10 @@ AudioClock::end_edit_relative (bool add) ok = minsec_validate_edit (edit_string); break; - case Frames: + case Seconds: + break; + + case Samples: break; } @@ -742,23 +773,23 @@ AudioClock::end_edit_relative (bool add) return; } - framecnt_t frames = parse_as_distance (input_string); + samplecnt_t samples = parse_as_distance (input_string); editing = false; editing = false; _layout->set_attributes (normal_attributes); - if (frames != 0) { + if (samples != 0) { if (add) { - set (current_time() + frames, true); + AudioClock::set (current_time() + samples, true); } else { - framepos_t c = current_time(); + samplepos_t c = current_time(); - if (c > frames || _negative_allowed) { - set (c - frames, true); + if (c > samples || _negative_allowed) { + AudioClock::set (c - samples, true); } else { - set (0, true); + AudioClock::set (0, true); } } ValueChanged (); /* EMIT SIGNAL */ @@ -772,7 +803,7 @@ AudioClock::end_edit_relative (bool add) void AudioClock::session_property_changed (const PropertyChange&) { - set (last_when, true); + AudioClock::set (last_when, true); } void @@ -784,7 +815,7 @@ AudioClock::session_configuration_changed (std::string p) } if (p == "sync-source" || p == "external-sync") { - set (current_time(), true); + AudioClock::set (current_time(), true); return; } @@ -792,7 +823,7 @@ AudioClock::session_configuration_changed (std::string p) return; } - framecnt_t current; + samplecnt_t current; switch (_mode) { case Timecode: @@ -801,7 +832,7 @@ AudioClock::session_configuration_changed (std::string p) } else { current = current_time (); } - set (current, true); + AudioClock::set (current, true); break; default: break; @@ -809,16 +840,23 @@ AudioClock::session_configuration_changed (std::string p) } void -AudioClock::set (framepos_t when, bool force, framecnt_t offset) +AudioClock::set (samplepos_t when, bool force, samplecnt_t offset) { - if ((!force && !is_visible()) || _session == 0) { + if ((!force && !is_visible()) || _session == 0) { return; } + _offset = offset; if (is_duration) { when = when - offset; } + if (when > _limit_pos) { + when = _limit_pos; + } else if (when < -_limit_pos) { + when = -_limit_pos; + } + if (when == last_when && !force) { #if 0 // XXX return if no change and no change forced. verify Aug/2014 if (_mode != Timecode && _mode != MinSec) { @@ -858,8 +896,12 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset) set_minsec (when, force); break; - case Frames: - set_frames (when, force); + case Seconds: + set_seconds (when, force); + break; + + case Samples: + set_samples (when, force); break; } } @@ -897,20 +939,19 @@ AudioClock::set_slave_info () return; } - SyncSource sync_src = Config->get_sync_source(); + boost::shared_ptr tm = TransportMasterManager::instance().current(); - if (_session->config.get_external_sync()) { - Slave* slave = _session->slave(); + if (_session->transport_master_is_external()) { - switch (sync_src) { + switch (tm->type()) { case Engine: - _left_btn.set_text (sync_source_to_string (sync_src, true), true); + _left_btn.set_text (tm->name(), true); _right_btn.set_text ("", true); break; case MIDIClock: - if (slave) { - _left_btn.set_text (sync_source_to_string (sync_src, true), true); - _right_btn.set_text (slave->approximate_current_delta (), true); + if (tm) { + _left_btn.set_text (tm->display_name(), true); + _right_btn.set_text (tm->delta_string (), true); } else { _left_btn.set_text (_("--pending--"), true); _right_btn.set_text ("", true); @@ -918,17 +959,17 @@ AudioClock::set_slave_info () break; case LTC: case MTC: - if (slave) { + if (tm) { bool matching; - TimecodeSlave* tcslave; - if ((tcslave = dynamic_cast(_session->slave())) != 0) { - matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format()); + boost::shared_ptr tcmaster; + if ((tcmaster = boost::dynamic_pointer_cast(tm)) != 0) { + matching = (tcmaster->apparent_timecode_format() == _session->config.get_timecode_format()); _left_btn.set_text (string_compose ("%1%2", - sync_source_to_string(sync_src, true)[0], - dynamic_cast(slave)->approximate_current_position (), - matching ? "#66ff66" : "#ff3333" + tm->display_name()[0], + tcmaster->position_string (), + matching ? "#66ff66" : "#ff3333" ), true); - _right_btn.set_text (slave->approximate_current_delta (), true); + _right_btn.set_text (tm->delta_string (), true); } } else { _left_btn.set_text (_("--pending--"), true); @@ -937,14 +978,31 @@ AudioClock::set_slave_info () break; } } else { - _left_btn.set_text (string_compose ("%1/%2", - _("INT"), sync_source_to_string(sync_src, true)), true); + _left_btn.set_text (string_compose ("%1/%2", _("INT"), tm->display_name()), true); _right_btn.set_text ("", true); } } void -AudioClock::set_frames (framepos_t when, bool /*force*/) +AudioClock::set_out_of_bounds (bool negative) +{ + if (is_duration) { + if (negative) { + _layout->set_text (" >>> -- <<< "); + } else { + _layout->set_text (" >>> ++ <<< "); + } + } else { + if (negative) { + _layout->set_text (" <<<<<<<<<< "); + } else { + _layout->set_text (" >>>>>>>>>> "); + } + } +} + +void +AudioClock::set_samples (samplepos_t when, bool /*force*/) { char buf[32]; bool negative = false; @@ -961,16 +1019,18 @@ AudioClock::set_frames (framepos_t when, bool /*force*/) negative = true; } - if (negative) { + if (when >= _limit_pos) { + set_out_of_bounds (negative); + } else if (negative) { snprintf (buf, sizeof (buf), "-%10" PRId64, when); + _layout->set_text (buf); } else { snprintf (buf, sizeof (buf), " %10" PRId64, when); + _layout->set_text (buf); } - _layout->set_text (buf); - if (_with_info) { - framecnt_t rate = _session->frame_rate(); + samplecnt_t rate = _session->sample_rate(); if (fmod (rate, 100.0) == 0.0) { sprintf (buf, "%.1fkHz", rate/1000.0); @@ -992,9 +1052,35 @@ AudioClock::set_frames (framepos_t when, bool /*force*/) } void -AudioClock::print_minsec (framepos_t when, char* buf, size_t bufsize, float frame_rate) +AudioClock::set_seconds (samplepos_t when, bool /*force*/) +{ + char buf[32]; + + if (_off) { + _layout->set_text (" ----------"); + _left_btn.set_text ("", true); + _right_btn.set_text ("", true); + return; + } + + if (when >= _limit_pos || when <= -_limit_pos) { + set_out_of_bounds (when < 0); + } else { + if (when < 0) { + snprintf (buf, sizeof (buf), "%12.1f", when / (float)_session->sample_rate()); + } else { + snprintf (buf, sizeof (buf), " %11.1f", when / (float)_session->sample_rate()); + } + _layout->set_text (buf); + } + + set_slave_info(); +} + +void +AudioClock::print_minsec (samplepos_t when, char* buf, size_t bufsize, float sample_rate) { - framecnt_t left; + samplecnt_t left; int hrs; int mins; int secs; @@ -1009,13 +1095,13 @@ AudioClock::print_minsec (framepos_t when, char* buf, size_t bufsize, float fram } left = when; - hrs = (int) floor (left / (frame_rate * 60.0f * 60.0f)); - left -= (framecnt_t) floor (hrs * frame_rate * 60.0f * 60.0f); - mins = (int) floor (left / (frame_rate * 60.0f)); - left -= (framecnt_t) floor (mins * frame_rate * 60.0f); - secs = (int) floor (left / (float) frame_rate); - left -= (framecnt_t) floor ((double)(secs * frame_rate)); - millisecs = floor (left * 1000.0 / (float) frame_rate); + hrs = (int) floor (left / (sample_rate * 60.0f * 60.0f)); + left -= (samplecnt_t) floor (hrs * sample_rate * 60.0f * 60.0f); + mins = (int) floor (left / (sample_rate * 60.0f)); + left -= (samplecnt_t) floor (mins * sample_rate * 60.0f); + secs = (int) floor (left / (float) sample_rate); + left -= (samplecnt_t) floor ((double)(secs * sample_rate)); + millisecs = floor (left * 1000.0 / (float) sample_rate); if (negative) { snprintf (buf, bufsize, "-%02" PRId32 ":%02" PRId32 ":%02" PRId32 ".%03" PRId32, hrs, mins, secs, millisecs); @@ -1026,7 +1112,7 @@ AudioClock::print_minsec (framepos_t when, char* buf, size_t bufsize, float fram } void -AudioClock::set_minsec (framepos_t when, bool /*force*/) +AudioClock::set_minsec (samplepos_t when, bool /*force*/) { char buf[32]; @@ -1038,14 +1124,18 @@ AudioClock::set_minsec (framepos_t when, bool /*force*/) return; } - print_minsec (when, buf, sizeof (buf), _session->frame_rate()); + if (when >= _limit_pos || when <= -_limit_pos) { + set_out_of_bounds (when < 0); + } else { + print_minsec (when, buf, sizeof (buf), _session->sample_rate()); + _layout->set_text (buf); + } - _layout->set_text (buf); set_slave_info(); } void -AudioClock::set_timecode (framepos_t when, bool /*force*/) +AudioClock::set_timecode (samplepos_t when, bool /*force*/) { Timecode::Time TC; bool negative = false; @@ -1061,6 +1151,11 @@ AudioClock::set_timecode (framepos_t when, bool /*force*/) when = -when; negative = true; } + if (when >= _limit_pos) { + set_out_of_bounds (negative); + set_slave_info(); + return; + } if (is_duration) { _session->timecode_duration (when, TC); @@ -1076,13 +1171,13 @@ AudioClock::set_timecode (framepos_t when, bool /*force*/) } void -AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/) +AudioClock::set_bbt (samplepos_t when, samplecnt_t offset, bool /*force*/) { char buf[64]; Timecode::BBT_Time BBT; bool negative = false; - if (_off) { + if (_off || when >= _limit_pos || when < -_limit_pos) { _layout->set_text (" ---|--|----"); _left_btn.set_text ("", true); _right_btn.set_text ("", true); @@ -1107,15 +1202,15 @@ AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/) offset = bbt_reference_time; } - const double divisions = tmap.meter_section_at_frame (offset).divisions_per_bar(); + const double divisions = tmap.meter_section_at_sample (offset).divisions_per_bar(); Timecode::BBT_Time sub_bbt; if (negative) { - BBT = tmap.bbt_at_beat (tmap.beat_at_frame (offset)); - sub_bbt = tmap.bbt_at_frame (offset - when); + BBT = tmap.bbt_at_beat (tmap.beat_at_sample (offset)); + sub_bbt = tmap.bbt_at_sample (offset - when); } else { - BBT = tmap.bbt_at_beat (tmap.beat_at_frame (when + offset)); - sub_bbt = tmap.bbt_at_frame (offset); + BBT = tmap.bbt_at_beat (tmap.beat_at_sample (when + offset)); + sub_bbt = tmap.bbt_at_sample (offset); } BBT.bars -= sub_bbt.bars; @@ -1140,7 +1235,7 @@ AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/) } } } else { - BBT = _session->tempo_map().bbt_at_frame (when); + BBT = _session->tempo_map().bbt_at_sample (when); } if (negative) { @@ -1154,7 +1249,7 @@ AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/) _layout->set_text (buf); if (_with_info) { - framepos_t pos; + samplepos_t pos; if (bbt_reference_time < 0) { pos = when; @@ -1165,13 +1260,13 @@ AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/) TempoMetric m (_session->tempo_map().metric_at (pos)); if (m.tempo().note_type() == 4) { - snprintf (buf, sizeof(buf), "\u2669 = %.3f", _session->tempo_map().tempo_at_frame (pos).note_types_per_minute()); + snprintf (buf, sizeof(buf), "\u2669 = %.3f", _session->tempo_map().tempo_at_sample (pos).note_types_per_minute()); _left_btn.set_text (string_compose ("%1", buf), true); } else if (m.tempo().note_type() == 8) { - snprintf (buf, sizeof(buf), "\u266a = %.3f", _session->tempo_map().tempo_at_frame (pos).note_types_per_minute()); + snprintf (buf, sizeof(buf), "\u266a = %.3f", _session->tempo_map().tempo_at_sample (pos).note_types_per_minute()); _left_btn.set_text (string_compose ("%1", buf), true); } else { - snprintf (buf, sizeof(buf), "%.1f = %.3f", m.tempo().note_type(), _session->tempo_map().tempo_at_frame (pos).note_types_per_minute()); + snprintf (buf, sizeof(buf), "%.1f = %.3f", m.tempo().note_type(), _session->tempo_map().tempo_at_sample (pos).note_types_per_minute()); _left_btn.set_text (string_compose ("%1: %2", S_("Tempo|T"), buf), true); } @@ -1187,6 +1282,11 @@ AudioClock::set_session (Session *s) if (_session) { + int64_t limit_sec = UIConfiguration::instance().get_clock_display_limit (); + if (limit_sec > 0) { + _limit_pos = (samplecnt_t) floor ((double)(limit_sec * _session->sample_rate())); + } + Config->ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_configuration_changed, this, _1), gui_context()); _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()); @@ -1212,7 +1312,7 @@ AudioClock::set_session (Session *s) } } - set (last_when, true); + AudioClock::set (last_when, true); } } @@ -1226,7 +1326,7 @@ AudioClock::on_key_press_event (GdkEventKey* ev) string new_text; char new_char = 0; int highlight_length; - framepos_t pos; + samplepos_t pos; switch (ev->keyval) { case GDK_0: @@ -1326,7 +1426,7 @@ AudioClock::on_key_press_event (GdkEventKey* ev) use_input_string: switch (_mode) { - case Frames: + case Samples: /* get this one in the right order, and to the right width */ if (ev->keyval == GDK_Delete || ev->keyval == GDK_BackSpace) { edit_string = edit_string.substr (0, edit_string.length() - 1); @@ -1445,7 +1545,7 @@ AudioClock::index_to_field (int index) const } else if (index < 10) { return Timecode_Seconds; } else { - return Timecode_Frames; + return Timecode_frames; } break; case BBT: @@ -1468,8 +1568,15 @@ AudioClock::index_to_field (int index) const return MS_Milliseconds; } break; - case Frames: - return AudioFrames; + case Seconds: + if (index < 10) { + return SS_Seconds; + } else { + return SS_Deciseconds; + } + break; + case Samples: + return S_Samples; break; } @@ -1479,6 +1586,11 @@ AudioClock::index_to_field (int index) const bool AudioClock::on_button_press_event (GdkEventButton *ev) { + if (!_session || _session->actively_recording()) { + /* swallow event, do nothing */ + return true; + } + switch (ev->button) { case 1: if (editable && !_off) { @@ -1522,6 +1634,11 @@ AudioClock::on_button_press_event (GdkEventButton *ev) bool AudioClock::on_button_release_event (GdkEventButton *ev) { + if (!_session || _session->actively_recording()) { + /* swallow event, do nothing */ + return true; + } + if (editable && !_off) { if (dragging) { gdk_pointer_ungrab (GDK_CURRENT_TIME); @@ -1549,9 +1666,10 @@ AudioClock::on_button_release_event (GdkEventButton *ev) f = index_to_field (index); switch (f) { - case Timecode_Frames: + case Timecode_frames: case MS_Milliseconds: case Ticks: + case SS_Deciseconds: f = Field (0); break; default: @@ -1595,7 +1713,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev) int index; int trailing; - if (editing || _session == 0 || !editable || _off) { + if (editing || _session == 0 || !editable || _off || _session->actively_recording()) { return false; } @@ -1616,32 +1734,32 @@ AudioClock::on_scroll_event (GdkEventScroll *ev) } Field f = index_to_field (index); - framepos_t frames = 0; + samplepos_t samples = 0; switch (ev->direction) { case GDK_SCROLL_UP: - frames = get_frame_step (f, current_time(), 1); - if (frames != 0) { + samples = get_sample_step (f, current_time(), 1); + if (samples != 0) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - frames *= 10; + samples *= 10; } - set (current_time() + frames, true); + AudioClock::set (current_time() + samples, true); ValueChanged (); /* EMIT_SIGNAL */ } break; case GDK_SCROLL_DOWN: - frames = get_frame_step (f, current_time(), -1); - if (frames != 0) { + samples = get_sample_step (f, current_time(), -1); + if (samples != 0) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - frames *= 10; + samples *= 10; } - if (!_negative_allowed && (double)current_time() - (double)frames < 0.0) { - set (0, true); + if (!_negative_allowed && (double)current_time() - (double)samples < 0.0) { + AudioClock::set (0, true); } else { - set (current_time() - frames, true); + AudioClock::set (current_time() - samples, true); } ValueChanged (); /* EMIT_SIGNAL */ @@ -1659,85 +1777,91 @@ AudioClock::on_scroll_event (GdkEventScroll *ev) bool AudioClock::on_motion_notify_event (GdkEventMotion *ev) { - if (editing || _session == 0 || !dragging) { + if (editing || _session == 0 || !dragging || _session->actively_recording()) { return false; } - float pixel_frame_scale_factor = 0.2f; + float pixel_sample_scale_factor = 0.2f; if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - pixel_frame_scale_factor = 0.1f; + pixel_sample_scale_factor = 0.1f; } if (Keyboard::modifier_state_contains (ev->state, - Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) { - - pixel_frame_scale_factor = 0.025f; + Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) { + pixel_sample_scale_factor = 0.025f; } double y_delta = ev->y - drag_y; - drag_accum += y_delta*pixel_frame_scale_factor; + drag_accum += y_delta*pixel_sample_scale_factor; drag_y = ev->y; if (floor (drag_accum) != 0) { - framepos_t frames; - framepos_t pos; + samplepos_t samples; + samplepos_t pos; int dir; dir = (drag_accum < 0 ? 1:-1); pos = current_time(); - frames = get_frame_step (drag_field, pos, dir); + samples = get_sample_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 + if (samples != 0 && samples * drag_accum < current_time()) { + AudioClock::set ((samplepos_t) floor (pos - drag_accum * samples), false); // minus because up is negative in GTK } else { - set (0 , false); - } + AudioClock::set (0 , false); + } - drag_accum= 0; + drag_accum= 0; ValueChanged(); /* EMIT_SIGNAL */ } return true; } -framepos_t -AudioClock::get_frame_step (Field field, framepos_t pos, int dir) +samplepos_t +AudioClock::get_sample_step (Field field, samplepos_t pos, int dir) { - framecnt_t f = 0; + samplecnt_t f = 0; Timecode::BBT_Time BBT; switch (field) { case Timecode_Hours: - f = (framecnt_t) floor (3600.0 * _session->frame_rate()); + f = (samplecnt_t) floor (3600.0 * _session->sample_rate()); break; case Timecode_Minutes: - f = (framecnt_t) floor (60.0 * _session->frame_rate()); + f = (samplecnt_t) floor (60.0 * _session->sample_rate()); break; case Timecode_Seconds: - f = _session->frame_rate(); + f = _session->sample_rate(); break; - case Timecode_Frames: - f = (framecnt_t) floor (_session->frame_rate() / _session->timecode_frames_per_second()); + case Timecode_frames: + f = (samplecnt_t) floor (_session->sample_rate() / _session->timecode_frames_per_second()); break; - case AudioFrames: + case S_Samples: f = 1; break; + case SS_Seconds: + f = (samplecnt_t) _session->sample_rate(); + break; + case SS_Deciseconds: + f = (samplecnt_t) _session->sample_rate() / 10.f; + break; + case MS_Hours: - f = (framecnt_t) floor (3600.0 * _session->frame_rate()); + f = (samplecnt_t) floor (3600.0 * _session->sample_rate()); break; case MS_Minutes: - f = (framecnt_t) floor (60.0 * _session->frame_rate()); + f = (samplecnt_t) floor (60.0 * _session->sample_rate()); break; case MS_Seconds: - f = (framecnt_t) _session->frame_rate(); + f = (samplecnt_t) _session->sample_rate(); break; case MS_Milliseconds: - f = (framecnt_t) floor (_session->frame_rate() / 1000.0); + f = (samplecnt_t) floor (_session->sample_rate() / 1000.0); break; case Bars: @@ -1759,7 +1883,7 @@ AudioClock::get_frame_step (Field field, framepos_t pos, int dir) f = _session->tempo_map().bbt_duration_at(pos,BBT,dir); break; default: - error << string_compose (_("programming error: %1"), "attempt to get frames from non-text field!") << endmsg; + error << string_compose (_("programming error: %1"), "attempt to get samples from non-text field!") << endmsg; f = 0; break; } @@ -1767,30 +1891,26 @@ AudioClock::get_frame_step (Field field, framepos_t pos, int dir) return f; } -framepos_t -AudioClock::current_time (framepos_t) const +samplepos_t +AudioClock::current_time (samplepos_t) const { return last_when; } -framepos_t -AudioClock::current_duration (framepos_t pos) const +samplepos_t +AudioClock::current_duration (samplepos_t pos) const { - framepos_t ret = 0; + samplepos_t ret = 0; switch (_mode) { - case Timecode: - ret = last_when; - break; case BBT: - ret = frame_duration_from_bbt_string (pos, _layout->get_text()); + ret = sample_duration_from_bbt_string (pos, _layout->get_text()); break; + case Timecode: case MinSec: - ret = last_when; - break; - - case Frames: + case Seconds: + case Samples: ret = last_when; break; } @@ -1799,7 +1919,7 @@ AudioClock::current_duration (framepos_t pos) const } bool -AudioClock::bbt_validate_edit (const string& str) +AudioClock::bbt_validate_edit (string & str) { AnyTime any; @@ -1816,7 +1936,14 @@ AudioClock::bbt_validate_edit (const string& str) } if (!is_duration && any.bbt.beats == 0) { - return false; + /* user could not have mean zero beats because for a + * non-duration clock that's impossible. Assume that they + * mis-entered things and meant Bar|1|ticks + */ + + char buf[128]; + snprintf (buf, sizeof (buf), "%" PRIu32 "|%" PRIu32 "|%" PRIu32, any.bbt.bars, 1, any.bbt.ticks); + str = buf; } return true; @@ -1830,7 +1957,7 @@ AudioClock::timecode_validate_edit (const string&) char ignored[2]; if (sscanf (_layout->get_text().c_str(), "%[- _]%" PRId32 ":%" PRId32 ":%" PRId32 "%[:;]%" PRId32, - ignored, &hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 6) { + ignored, &hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 6) { return false; } @@ -1879,15 +2006,15 @@ AudioClock::minsec_validate_edit (const string& str) return true; } -framepos_t -AudioClock::frames_from_timecode_string (const string& str) const +samplepos_t +AudioClock::samples_from_timecode_string (const string& str) const { if (_session == 0) { return 0; } Timecode::Time TC; - framepos_t sample; + samplepos_t sample; char ignored[2]; int hours; @@ -1909,26 +2036,26 @@ AudioClock::frames_from_timecode_string (const string& str) const return sample; } -framepos_t -AudioClock::frames_from_minsec_string (const string& str) const +samplepos_t +AudioClock::samples_from_minsec_string (const string& str) const { if (_session == 0) { return 0; } int hrs, mins, secs, millisecs; - framecnt_t sr = _session->frame_rate(); + samplecnt_t sr = _session->sample_rate(); if (sscanf (str.c_str(), "%d:%d:%d.%d", &hrs, &mins, &secs, &millisecs) != 4) { error << string_compose (_("programming error: %1 %2"), "badly formatted minsec clock string", str) << endmsg; return 0; } - return (framepos_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr) + (millisecs * sr / 1000.0)); + return (samplepos_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr) + (millisecs * sr / 1000.0)); } -framepos_t -AudioClock::frames_from_bbt_string (framepos_t pos, const string& str) const +samplepos_t +AudioClock::samples_from_bbt_string (samplepos_t pos, const string& str) const { if (_session == 0) { error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg; @@ -1945,18 +2072,18 @@ AudioClock::frames_from_bbt_string (framepos_t pos, const string& str) const if (is_duration) { any.bbt.bars++; any.bbt.beats++; - return _session->any_duration_to_frames (pos, any); + return _session->any_duration_to_samples (pos, any); } else { - return _session->convert_to_frames (any); - } + return _session->convert_to_samples (any); + } } -framepos_t -AudioClock::frame_duration_from_bbt_string (framepos_t pos, const string& str) const +samplepos_t +AudioClock::sample_duration_from_bbt_string (samplepos_t pos, const string& str) const { if (_session == 0) { - error << "AudioClock::frame_duration_from_bbt_string() called with BBT mode but without session!" << endmsg; + error << "AudioClock::sample_duration_from_bbt_string() called with BBT mode but without session!" << endmsg; return 0; } @@ -1969,10 +2096,18 @@ AudioClock::frame_duration_from_bbt_string (framepos_t pos, const string& str) c return _session->tempo_map().bbt_duration_at(pos,bbt,1); } -framepos_t -AudioClock::frames_from_audioframes_string (const string& str) const +samplepos_t +AudioClock::samples_from_seconds_string (const string& str) const +{ + float f; + sscanf (str.c_str(), "%f", &f); + return f * _session->sample_rate(); +} + +samplepos_t +AudioClock::samples_from_audiosamples_string (const string& str) const { - framepos_t f; + samplepos_t f; sscanf (str.c_str(), "%" PRId64, &f); return f; } @@ -2006,7 +2141,8 @@ AudioClock::build_ops_menu () ops_items.push_back (MenuElem (_("Timecode"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Timecode, false))); ops_items.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), BBT, false))); ops_items.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), MinSec, false))); - ops_items.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Frames, false))); + ops_items.push_back (MenuElem (_("Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Seconds, false))); + ops_items.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Samples, false))); if (editable && !_off && !is_duration && !_follows_playhead) { ops_items.push_back (SeparatorElem()); @@ -2024,7 +2160,7 @@ AudioClock::set_from_playhead () return; } - set (_session->transport_frame()); + AudioClock::set (_session->transport_sample()); ValueChanged (); } @@ -2090,11 +2226,24 @@ AudioClock::set_mode (Mode m, bool noemit) insert_map.push_back (1); break; - case Frames: + case Seconds: + insert_map.push_back (11); + insert_map.push_back (9); + insert_map.push_back (8); + insert_map.push_back (7); + insert_map.push_back (6); + insert_map.push_back (5); + insert_map.push_back (4); + insert_map.push_back (3); + insert_map.push_back (2); + insert_map.push_back (1); + break; + + case Samples: break; } - set (last_when, true); + AudioClock::set (last_when, true); if (!is_transient && !noemit) { ModeChanged (); /* EMIT SIGNAL (the static one)*/ @@ -2104,7 +2253,7 @@ AudioClock::set_mode (Mode m, bool noemit) } void -AudioClock::set_bbt_reference (framepos_t pos) +AudioClock::set_bbt_reference (samplepos_t pos) { bbt_reference_time = pos; } @@ -2136,7 +2285,7 @@ AudioClock::set_is_duration (bool yn) } is_duration = yn; - set (last_when, true); + AudioClock::set (last_when, true); } void @@ -2152,7 +2301,7 @@ AudioClock::set_off (bool yn) * change */ - set (last_when, true); + AudioClock::set (last_when, true); } void