vector<AudioClock*> AudioClock::clocks;
uint32_t AudioClock::field_length[] = {
+ 1, /* Timecode_Sign */
2, /* Timecode_Hours */
2, /* Timecode_Minutes */
2, /* Timecode_Seconds */
, is_duration (duration)
, editable (allow_edit)
, _follows_playhead (follows_playhead)
+ , _off (false)
, supplemental_left (0)
, supplemental_right (0)
, last_when(0)
_fixed_cells[Bar1] = new CairoCharCell (Bar1, '|');
_fixed_cells[Bar2] = new CairoCharCell (Bar2, '|');
- // add an extra character for the negative sign
- _text_cells[Timecode_Hours] = new CairoTextCell (Timecode_Hours, field_length[Timecode_Hours] + 1);
+ _text_cells[Timecode_Sign] = new CairoTextCell (Timecode_Sign, field_length[Timecode_Sign]);
+ _text_cells[Timecode_Hours] = new CairoTextCell (Timecode_Hours, field_length[Timecode_Hours]);
_text_cells[Timecode_Minutes] = new CairoTextCell (Timecode_Minutes, field_length[Timecode_Minutes]);
_text_cells[Timecode_Seconds] = new CairoTextCell (Timecode_Seconds, field_length[Timecode_Seconds]);
_text_cells[Timecode_Frames] = new CairoTextCell (Timecode_Frames, field_length[Timecode_Frames]);
set_mode (Timecode);
set (last_when, true);
+ connect_signals ();
+
if (!is_transient) {
clocks.push_back (this);
}
/* these are not manage()'d, so that we can add/remove
them from containers as necessary.
*/
+
delete display;
delete supplemental_left;
delete supplemental_right;
- /* XXX need to delete all cells too */
+
+ for (std::map<Field,CairoCell*>::iterator i = _fixed_cells.begin(); i != _fixed_cells.end(); ++i) {
+ delete i->second;
+ }
+
+ for (std::map<Field,CairoTextCell*>::iterator i = _text_cells.begin(); i != _text_cells.end(); ++i) {
+ delete i->second;
+ }
}
void
display->set_font (font);
- /* propagate font style,but smaller, into supplemental text */
+
if (supplemental_left) {
+ /* propagate font style, sort of, into supplemental text */
boost::shared_ptr<CairoFontDescription> smaller_font (new CairoFontDescription (*display->font().get()));
smaller_font->set_size (12);
+ smaller_font->set_weight (Cairo::FONT_WEIGHT_NORMAL);
supplemental_right->set_font (smaller_font);
supplemental_left->set_font (smaller_font);
}
case Frames:
set_frames (when, force);
break;
-
- case Off:
- break;
}
last_when = when;
{
char buf[32];
snprintf (buf, sizeof (buf), "%" PRId64, when);
+
+ if (_off) {
+ display->set_text (_text_cells[AudioFrames], "-----------");
+
+ if (supplemental_left) {
+ supplemental_left->set_text (_text_cells[LowerLeft2], "");
+ supplemental_right->set_text (_text_cells[LowerRight2], "");
+ }
+
+ return;
+ }
+
display->set_text (_text_cells[AudioFrames], buf);
int secs;
int millisecs;
+ if (_off) {
+ display->set_text (_text_cells[MS_Hours], "--");
+ display->set_text (_text_cells[MS_Minutes], "--");
+ display->set_text (_text_cells[MS_Seconds], "--");
+ display->set_text (_text_cells[MS_Milliseconds], "--");
+
+ if (supplemental_left) {
+ supplemental_left->set_text (_text_cells[LowerLeft2], "");
+ supplemental_right->set_text (_text_cells[LowerRight2], "");
+ }
+
+ return;
+ }
+
left = when;
hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f));
left -= (framecnt_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f);
char buf[32];
Timecode::Time TC;
+ if (_off) {
+ display->set_text (_text_cells[Timecode_Sign], "");
+ display->set_text (_text_cells[Timecode_Hours], "--");
+ display->set_text (_text_cells[Timecode_Minutes], "--");
+ display->set_text (_text_cells[Timecode_Seconds], "--");
+ display->set_text (_text_cells[Timecode_Frames], "--");
+
+ if (supplemental_left) {
+ supplemental_left->set_text (_text_cells[LowerLeft2], "");
+ supplemental_right->set_text (_text_cells[LowerRight2], "");
+ }
+
+ return;
+ }
+
if (is_duration) {
_session->timecode_duration (when, TC);
} else {
if (force || TC.hours != last_hrs || TC.negative != last_negative) {
if (TC.negative) {
- sprintf (buf, "-%0*" PRIu32, field_length[Timecode_Hours], TC.hours);
+ display->set_text (_text_cells[Timecode_Sign], "-");
+ sprintf (buf, "%0*" PRIu32, field_length[Timecode_Hours], TC.hours);
} else {
- sprintf (buf, " %0*" PRIu32, field_length[Timecode_Hours], TC.hours);
+ display->set_text (_text_cells[Timecode_Sign], " ");
+ sprintf (buf, "%0*" PRIu32, field_length[Timecode_Hours], TC.hours);
}
display->set_text (_text_cells[Timecode_Hours], buf);
last_hrs = TC.hours;
char buf[16];
Timecode::BBT_Time BBT;
+ if (_off) {
+ display->set_text (_text_cells[Bars], "--");
+ display->set_text (_text_cells[Beats], "--");
+ display->set_text (_text_cells[Ticks], "--");
+
+ if (supplemental_left) {
+ supplemental_left->set_text (_text_cells[LowerLeft2], "");
+ supplemental_right->set_text (_text_cells[LowerRight2], "");
+ }
+
+ return;
+ }
+
/* handle a common case */
if (is_duration) {
if (when == 0) {
_session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_configuration_changed, this, _1), gui_context());
- XMLProperty* prop;
+ const 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);
+ for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
+ if ((prop = (*i)->property (X_("name"))) && prop->value() == _name) {
+
+ if ((prop = (*i)->property (X_("mode"))) != 0) {
+ amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
+ set_mode (amode);
+ }
+ if ((prop = (*i)->property (X_("on"))) != 0) {
+ set_off (!string_is_affirmative (prop->value()));
+ }
+ break;
+ }
}
}
{
switch (ev->button) {
case 1:
- if (cell) {
- editing_field = (Field) cell->id ();
- display->start_editing (cell);
+ if (editable) {
+ if (cell) {
+ Field f = (Field) cell->id ();
+ switch (f) {
+ case Timecode_Hours:
+ case Timecode_Minutes:
+ case Timecode_Seconds:
+ case Timecode_Frames:
+ case MS_Hours:
+ case MS_Minutes:
+ case MS_Seconds:
+ case MS_Milliseconds:
+ case Bars:
+ case Beats:
+ case Ticks:
+ case AudioFrames:
+ editing_field = f;
+ display->start_editing (cell);
+ break;
+ default:
+ return false;
+ }
+ }
+
+ Keyboard::magic_widget_grab_focus ();
+
+ /* 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);
+ dragging = true;
+ drag_accum = 0;
+ drag_start_y = ev->y;
+ drag_y = ev->y;
}
-
- Keyboard::magic_widget_grab_focus ();
-
- /* 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);
- dragging = true;
- drag_accum = 0;
- drag_start_y = ev->y;
- drag_y = ev->y;
break;
default:
}
bool
-AudioClock::button_release (GdkEventButton *ev, CairoCell*)
+AudioClock::button_release (GdkEventButton *ev, CairoCell* cell)
{
- if (dragging) {
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
- dragging = false;
- if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
- // we actually dragged so return without setting editing focus, or we shift clicked
- return true;
- }
- }
-
- if (!editable) {
- if (ops_menu == 0) {
- build_ops_menu ();
+ if (editable) {
+ if (dragging) {
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ dragging = false;
+ if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
+ // we actually dragged so return without setting editing focus, or we shift clicked
+ return true;
+ }
}
- ops_menu->popup (1, ev->time);
- return true;
}
if (Keyboard::is_context_menu_event (ev)) {
return true;
}
- return true;
+ return false;
}
bool
AudioClock::scroll (GdkEventScroll *ev, CairoCell* cell)
{
- if (_session == 0) {
+ if (_session == 0 || !editable) {
return false;
}
+ if (cell) {
+ Field f = (Field) cell->id ();
+ switch (f) {
+ case Timecode_Hours:
+ case Timecode_Minutes:
+ case Timecode_Seconds:
+ case Timecode_Frames:
+ case MS_Hours:
+ case MS_Minutes:
+ case MS_Seconds:
+ case MS_Milliseconds:
+ case Bars:
+ case Beats:
+ case Ticks:
+ case AudioFrames:
+ break;
+ default:
+ return false;
+ }
+ }
+
framepos_t frames = 0;
switch (ev->direction) {
case Frames:
ret = audio_frame_from_display ();
break;
-
- case Off:
- break;
}
return ret;
case Frames:
ret = audio_frame_from_display ();
break;
-
- case Off:
- break;
}
return ret;
Timecode::Time TC;
framepos_t sample;
- TC.hours = atoi (label (Timecode_Hours)->get_text());
+ if (!label (Timecode_Sign)->get_text().empty()) {
+ TC.hours = atoi (label (Timecode_Hours)->get_text());
+ } else {
+ TC.hours = -atoi (label (Timecode_Hours)->get_text());
+ }
+
TC.minutes = atoi (label (Timecode_Minutes)->get_text());
TC.seconds = atoi (label (Timecode_Seconds)->get_text());
TC.frames = atoi (label (Timecode_Frames)->get_text());
ops_items.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), BBT)));
ops_items.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), MinSec)));
ops_items.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Frames)));
- ops_items.push_back (MenuElem (_("Off"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Off)));
if (editable && !is_duration && !_follows_playhead) {
ops_items.push_back (SeparatorElem());
_session->request_locate (current_time(), _session->transport_rolling ());
}
-void
-AudioClock::disconnect_signals ()
-{
- scroll_connection.disconnect ();
- button_press_connection.disconnect ();
- button_release_connection.disconnect ();
-}
-
void
AudioClock::connect_signals ()
{
- disconnect_signals ();
-
- if (editable) {
- scroll_connection = display->scroll.connect (sigc::mem_fun (*this, &AudioClock::scroll));
- button_press_connection = display->button_press.connect (sigc::mem_fun (*this, &AudioClock::button_press));
- button_release_connection = display->button_release.connect (sigc::mem_fun (*this, &AudioClock::button_release));
- }
+ scroll_connection = display->scroll.connect (sigc::mem_fun (*this, &AudioClock::scroll));
+ button_press_connection = display->button_press.connect (sigc::mem_fun (*this, &AudioClock::button_press));
+ button_release_connection = display->button_release.connect (sigc::mem_fun (*this, &AudioClock::button_release));
}
void
switch (_mode) {
case Timecode:
+ display->add_cell (_text_cells[Timecode_Sign]);
display->add_cell (_text_cells[Timecode_Hours]);
display->add_cell (_fixed_cells[Colon1]);
display->add_cell (_text_cells[Timecode_Minutes]);
supplemental_right->add_cell (_text_cells[LowerRight1]);
supplemental_right->add_cell (_text_cells[LowerRight2]);
- supplemental_left->set_width_chars (_text_cells[LowerLeft1], 1);
+ supplemental_left->set_width_chars (_text_cells[LowerLeft1], 1);
supplemental_left->set_width_chars (_text_cells[LowerLeft2], 5.25);
- supplemental_right->set_width_chars (_text_cells[LowerRight1], 1);
+ supplemental_right->set_width_chars (_text_cells[LowerRight1], 2); // why not 1? M is too wide
supplemental_right->set_width_chars (_text_cells[LowerRight2], 5);
- supplemental_left->set_text (_text_cells[LowerLeft1], _("M"));
- supplemental_right->set_text (_text_cells[LowerRight1], _("T"));
+ supplemental_left->set_text (_text_cells[LowerLeft1], _("T"));
+ supplemental_right->set_text (_text_cells[LowerRight1], _("M"));
}
break;
display->add_cell (_text_cells[MS_Seconds]);
display->add_cell (_fixed_cells[Colon3]);
display->add_cell (_text_cells[MS_Milliseconds]);
+ if (supplemental_left) {
+ supplemental_left->add_cell (_text_cells[LowerLeft1]);
+ supplemental_left->add_cell (_text_cells[LowerLeft2]);
+ supplemental_right->add_cell (_text_cells[LowerRight1]);
+ supplemental_right->add_cell (_text_cells[LowerRight2]);
+
+ /* These are going to remain empty */
+
+ supplemental_left->set_width_chars (_text_cells[LowerLeft1], 1);
+ supplemental_left->set_width_chars (_text_cells[LowerLeft2], 5);
+
+ supplemental_right->set_width_chars (_text_cells[LowerRight1], 1);
+ supplemental_right->set_width_chars (_text_cells[LowerRight2], 1);
+
+ supplemental_left->set_text (_text_cells[LowerLeft1], _(" "));
+ supplemental_right->set_text (_text_cells[LowerRight1], _(" "));
+ }
break;
case Frames:
supplemental_right->set_text (_text_cells[LowerRight1], _("Pull"));
}
break;
-
- case Off:
- break;
}
if (supplemental_left) {
/* clear information cells */
supplemental_left->set_text (_text_cells[LowerLeft2], _(""));
supplemental_right->set_text (_text_cells[LowerRight2], _(""));
-
- /* propagate font style,but smaller, into cells */
- boost::shared_ptr<CairoFontDescription> smaller_font (new CairoFontDescription (*display->font().get()));
- smaller_font->set_size (12);
- supplemental_right->set_font (smaller_font);
- supplemental_left->set_font (smaller_font);
- }
-
- if (_mode != Off) {
- connect_signals ();
- } else {
- disconnect_signals ();
}
set (last_when, true);
set (last_when, true, 0, 's');
}
+void
+AudioClock::set_off (bool yn)
+{
+ if (_off == yn) {
+ return;
+ }
+
+ _off = yn;
+
+ if (_off) {
+ _canonical_time = current_time ();
+ _canonical_time_is_displayed = false;
+ } else {
+ _canonical_time_is_displayed = true;
+ }
+
+ /* force a possible redraw */
+
+ set (_canonical_time, true);
+}
+