#include "gtkmm2ext/rgb_macros.h"
#include "ardour/profile.h"
+#include "ardour/lmath.h"
#include "ardour/session.h"
#include "ardour/slave.h"
#include "ardour/tempo.h"
#include "i18n.h"
using namespace ARDOUR;
+using namespace ARDOUR_UI_UTILS;
using namespace PBD;
using namespace Gtk;
using namespace std;
sigc::signal<void> AudioClock::ModeChanged;
vector<AudioClock*> AudioClock::clocks;
-const double AudioClock::info_font_scale_factor = 0.50;
+const double AudioClock::info_font_scale_factor = 0.68;
const double AudioClock::separator_height = 0.0;
const double AudioClock::x_leading_padding = 6.0;
#define TXTSPAN "<span font-family=\"Sans\" foreground=\"white\">"
AudioClock::AudioClock (const string& clock_name, bool transient, const string& widget_name,
- bool allow_edit, bool follows_playhead, bool duration, bool with_info)
+ bool allow_edit, bool follows_playhead, bool duration, bool with_info,
+ bool accept_on_focus_out)
: ops_menu (0)
, _name (clock_name)
, is_transient (transient)
, is_duration (duration)
, editable (allow_edit)
, _follows_playhead (follows_playhead)
+ , _accept_on_focus_out (accept_on_focus_out)
, _off (false)
, em_width (0)
, _edit_by_click_field (false)
, last_sdelta (0)
, dragging (false)
, drag_field (Field (0))
+ , xscale (1.0)
+ , yscale (1.0)
{
set_flags (CAN_FOCUS);
first_width = req.width;
first_height = req.height;
- set_font ();
+ // XXX FIX ME: define font based on ... ???
+ // set_font ();
set_colors ();
}
void
-AudioClock::set_font ()
+AudioClock::set_font (Pango::FontDescription font)
{
Glib::RefPtr<Gtk::Style> style = get_style ();
- Pango::FontDescription font;
Pango::AttrFontDesc* font_attr;
- if (!is_realized()) {
- font = get_font_for_style (get_name());
- } else {
- font = style->get_font();
- }
-
font_size = font.get_size();
-
font_attr = new Pango::AttrFontDesc (Pango::Attribute::create_attr_font_desc (font));
normal_attributes.change (*font_attr);
uint32_t cursor_color;
if (active_state()) {
- bg_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 active: background", get_name()));
- text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 active: text", get_name()));
- editing_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 active: edited text", get_name()));
- cursor_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1 active: cursor", get_name()));
+ bg_color = ARDOUR_UI::config()->color (string_compose ("%1 active: background", get_name()));
+ text_color = ARDOUR_UI::config()->color (string_compose ("%1 active: text", get_name()));
+ editing_color = ARDOUR_UI::config()->color (string_compose ("%1 active: edited text", get_name()));
+ cursor_color = ARDOUR_UI::config()->color (string_compose ("%1 active: cursor", get_name()));
} else {
- bg_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: background", get_name()));
- text_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text", get_name()));
- editing_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: edited text", get_name()));
- cursor_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: cursor", get_name()));
+ bg_color = ARDOUR_UI::config()->color (string_compose ("%1: background", get_name()));
+ text_color = ARDOUR_UI::config()->color (string_compose ("%1: text", get_name()));
+ editing_color = ARDOUR_UI::config()->color (string_compose ("%1: edited text", get_name()));
+ cursor_color = ARDOUR_UI::config()->color (string_compose ("%1: cursor", get_name()));
}
/* store for bg and cursor in render() */
r = lrint ((r/255.0) * 65535.0);
g = lrint ((g/255.0) * 65535.0);
b = lrint ((b/255.0) * 65535.0);
+ delete foreground_attr;
foreground_attr = new Pango::AttrColor (Pango::Attribute::create_attr_foreground (r, g, b));
UINT_TO_RGBA (editing_color, &r, &g, &b, &a);
r = lrint ((r/255.0) * 65535.0);
g = lrint ((g/255.0) * 65535.0);
b = lrint ((b/255.0) * 65535.0);
+ delete editing_attr;
editing_attr = new Pango::AttrColor (Pango::Attribute::create_attr_foreground (r, g, b));
normal_attributes.change (*foreground_attr);
}
void
-AudioClock::render (cairo_t* cr)
+AudioClock::set_scale (double x, double y)
+{
+ xscale = x;
+ yscale = y;
+
+ queue_draw ();
+}
+
+void
+AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
{
/* main layout: rounded rect, plus the text */
cairo_fill (cr);
}
- cairo_move_to (cr, (get_width() - layout_width) / 2.0, (upper_height - layout_height) / 2.0);
+ double lw = layout_width * xscale;
+ double lh = layout_height * yscale;
+
+ cairo_move_to (cr, (get_width() - lw) / 2.0, (upper_height - lh) / 2.0);
+ if (xscale != 1.0 || yscale != 1.0) {
+ cairo_save (cr);
+ cairo_scale (cr, xscale, yscale);
+ }
+
pango_cairo_show_layout (cr, _layout->gobj());
+ if (xscale != 1.0 || yscale != 1.0) {
+ cairo_restore (cr);
+ }
+
if (_left_layout) {
double h = get_height() - upper_height - separator_height;
if (mode_based_info_ratio != 1.0) {
- double left_rect_width = round (((get_width() - separator_height) * mode_based_info_ratio) + 0.5);
+ double left_rect_width = get_left_rect_width();
if (_need_bg) {
if (corner_radius) {
tmp->set_font_description (font);
/* this string is the longest thing we will ever display */
- tmp->set_text (" 88:88:88,888");
+ if (_mode == MinSec)
+ tmp->set_text (" 88:88:88,888 ");
+ else
+ tmp->set_text (" 88:88:88,88 ");
tmp->get_pixel_size (req.width, req.height);
layout_height = req.height;
case 1:
case 2:
sscanf (str.c_str(), "%" PRId32, &frames);
- return lrint ((frames/(float)fps) * sr);
+ return llrint ((frames/(float)fps) * sr);
case 3:
sscanf (str.c_str(), "%1" PRId32 "%" PRId32, &secs, &frames);
- return (secs * sr) + lrint ((frames/(float)fps) * sr);
+ return (secs * sr) + llrint ((frames/(float)fps) * sr);
case 4:
sscanf (str.c_str(), "%2" PRId32 "%" PRId32, &secs, &frames);
- return (secs * sr) + lrint ((frames/(float)fps) * sr);
+ return (secs * sr) + llrint ((frames/(float)fps) * sr);
case 5:
sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &frames);
- return (mins * 60 * sr) + (secs * sr) + lrint ((frames/(float)fps) * sr);
+ return (mins * 60 * sr) + (secs * sr) + llrint ((frames/(float)fps) * sr);
case 6:
sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &frames);
- return (mins * 60 * sr) + (secs * sr) + lrint ((frames/(float)fps) * sr);
+ return (mins * 60 * sr) + (secs * sr) + llrint ((frames/(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) + lrint ((frames/(float)fps) * sr);
+ return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + llrint ((frames/(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) + lrint ((frames/(float)fps) * sr);
+ return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + llrint ((frames/(float)fps) * sr);
default:
break;
}
if (when == last_when && !force) {
+#if 0 // XXX return if no change and no change forced. verify Aug/2014
if (_mode != Timecode && _mode != MinSec) {
/* may need to force display of TC source
* time, so don't return early.
*/
+ /* ^^ Why was that?, delta times?
+ * Timecode FPS, pull-up/down, etc changes
+ * trigger a 'session_property_changed' which
+ * eventually calls set(last_when, true)
+ *
+ * re-rendering the clock every 40ms or so just
+ * because we can is not ideal.
+ */
return;
}
+#else
+ return;
+#endif
}
if (!editing) {
}
void
-AudioClock::set_minsec (framepos_t when, bool /*force*/)
+AudioClock::print_minsec (framepos_t when, char* buf, size_t bufsize, float frame_rate)
{
- char buf[32];
framecnt_t left;
int hrs;
int mins;
int secs;
int millisecs;
- bool negative = false;
+ bool negative;
+
+ if (when < 0) {
+ when = -when;
+ negative = true;
+ } else {
+ negative = false;
+ }
+
+ 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);
+
+ if (negative) {
+ snprintf (buf, bufsize, "-%02" PRId32 ":%02" PRId32 ":%02" PRId32 ".%03" PRId32, hrs, mins, secs, millisecs);
+ } else {
+ snprintf (buf, bufsize, " %02" PRId32 ":%02" PRId32 ":%02" PRId32 ".%03" PRId32, hrs, mins, secs, millisecs);
+ }
+
+}
+
+void
+AudioClock::set_minsec (framepos_t when, bool /*force*/)
+{
+ char buf[32];
if (_off) {
_layout->set_text (" --:--:--.---");
return;
}
- if (when < 0) {
- when = -when;
- negative = true;
- }
-
- 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);
- mins = (int) floor (left / (_session->frame_rate() * 60.0f));
- left -= (framecnt_t) floor (mins * _session->frame_rate() * 60.0f);
- secs = (int) floor (left / (float) _session->frame_rate());
- left -= (framecnt_t) floor (secs * _session->frame_rate());
- millisecs = floor (left * 1000.0 / (float) _session->frame_rate());
-
- if (negative) {
- snprintf (buf, sizeof (buf), "-%02" PRId32 ":%02" PRId32 ":%02" PRId32 ".%03" PRId32, hrs, mins, secs, millisecs);
- } else {
- snprintf (buf, sizeof (buf), " %02" PRId32 ":%02" PRId32 ":%02" PRId32 ".%03" PRId32, hrs, mins, secs, millisecs);
- }
+ print_minsec (when, buf, sizeof (buf), _session->frame_rate());
_layout->set_text (buf);
set_slave_info();
bool ret = CairoWidget::on_focus_out_event (ev);
if (editing) {
- end_edit (false);
+ end_edit (_accept_on_focus_out);
}
return ret;
drag_y = ev->y;
- if (trunc (drag_accum) != 0) {
+ if (floor (drag_accum) != 0) {
framepos_t frames;
framepos_t pos;
return f;
}
+void
+AudioClock::copy_text_to_clipboard () const
+{
+ string val;
+ if (editing) {
+ val = pre_edit_string;
+ } else {
+ val = _layout->get_text ();
+ }
+ const size_t trim = val.find_first_not_of(" ");
+ if (trim == string::npos) {
+ assert(0); // empty clock, can't be right.
+ return;
+ }
+ Glib::RefPtr<Clipboard> cl = Gtk::Clipboard::get();
+ cl->set_text (val.substr(trim));
+}
+
void
AudioClock::build_ops_menu ()
{
ops_items.push_back (MenuElem (_("Set From Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead)));
ops_items.push_back (MenuElem (_("Locate to This Time"), sigc::mem_fun(*this, &AudioClock::locate)));
}
+ ops_items.push_back (SeparatorElem());
+ ops_items.push_back (MenuElem (_("Copy to clipboard"), sigc::mem_fun(*this, &AudioClock::copy_text_to_clipboard)));
}
void
_layout->set_text ("");
+ Gtk::Requisition req;
+ set_clock_dimensions (req);
+
if (_left_layout) {
_left_layout->set_attributes (info_attributes);
Gtk::Requisition req;
set_clock_dimensions (req);
- set_font ();
+ /* XXXX fix me ... we shouldn't be using GTK styles anyway */
+ // set_font ();
set_colors ();
}