1 /* 2 * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com> 3 * Copyright (C) 2005-2018 Paul Davis <paul@linuxaudiosystems.com> 4 * Copyright (C) 2007 Doug McLain <doug@nostar.net> 5 * Copyright (C) 2008-2011 David Robillard <d@drobilla.net> 6 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net> 7 * Copyright (C) 2012-2017 Robin Gareus <robin@gareus.org> 8 * Copyright (C) 2015 Colin Fletcher <colin.m.fletcher@googlemail.com> 9 * Copyright (C) 2016-2017 Nick Mainsbridge <mainsbridge@gmail.com> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License along 22 * with this program; if not, write to the Free Software Foundation, Inc., 23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 */ 25 26 #ifndef __audio_clock_h__ 27 #define __audio_clock_h__ 28 29 #include <map> 30 #include <vector> 31 32 #include <pangomm.h> 33 34 #include <gtkmm/alignment.h> 35 #include <gtkmm/box.h> 36 #include <gtkmm/menu.h> 37 #include <gtkmm/label.h> 38 39 #include "ardour/ardour.h" 40 #include "ardour/session_handle.h" 41 42 #include "gtkmm2ext/cairo_widget.h" 43 #include "widgets/ardour_button.h" 44 45 namespace ARDOUR { 46 class Session; 47 } 48 49 class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr 50 { 51 public: 52 enum Mode { 53 Timecode, 54 BBT, 55 MinSec, 56 Seconds, 57 Samples 58 }; 59 60 AudioClock (const std::string& clock_name, bool is_transient, const std::string& widget_name, 61 bool editable, bool follows_playhead, bool duration = false, bool with_info = false, 62 bool accept_on_focus_out = false); 63 ~AudioClock (); 64 mode()65 Mode mode() const { return _mode; } 66 void set_off (bool yn); off()67 bool off() const { return _off; } on()68 bool on() const { return !_off; } 69 void set_widget_name (const std::string& name); 70 void set_active_state (Gtkmm2ext::ActiveState s); 71 void set_editable (bool yn); 72 void set_corner_radius (double); 73 74 void focus (); 75 76 virtual void set (samplepos_t, bool force = false, ARDOUR::samplecnt_t offset = 0); 77 void set_from_playhead (); 78 void locate (); 79 void set_mode (Mode, bool noemit = false); 80 void set_bbt_reference (samplepos_t); 81 void set_is_duration (bool); 82 83 void copy_text_to_clipboard () const; 84 name()85 std::string name() const { return _name; } 86 87 samplepos_t current_time (samplepos_t position = 0) const; 88 samplepos_t current_duration (samplepos_t position = 0) const; 89 void set_session (ARDOUR::Session *s); 90 void set_negative_allowed (bool yn); 91 left_btn()92 ArdourWidgets::ArdourButton* left_btn () { return &_left_btn; } right_btn()93 ArdourWidgets::ArdourButton* right_btn () { return &_right_btn; } 94 95 /** Alter cairo scaling during rendering. 96 * 97 * Used by clocks that resize themselves 98 * to fit any given space. Can lead 99 * to font distortion. 100 */ 101 void set_scale (double x, double y); 102 103 static void print_minsec (samplepos_t, char* buf, size_t bufsize, float sample_rate, int decimals = 3); 104 105 sigc::signal<void> ValueChanged; 106 sigc::signal<void> mode_changed; 107 sigc::signal<void> ChangeAborted; 108 109 static sigc::signal<void> ModeChanged; 110 static std::vector<AudioClock*> clocks; 111 112 protected: 113 void render (Cairo::RefPtr<Cairo::Context> const&, cairo_rectangle_t*); get_is_duration()114 bool get_is_duration () const { return is_duration; } offset()115 ARDOUR::samplecnt_t offset () const { return _offset; } 116 117 virtual void build_ops_menu (); 118 Gtk::Menu *ops_menu; 119 120 bool on_button_press_event (GdkEventButton *ev); 121 bool on_button_release_event(GdkEventButton *ev); 122 123 ArdourWidgets::ArdourButton _left_btn; 124 ArdourWidgets::ArdourButton _right_btn; 125 126 private: 127 Mode _mode; 128 std::string _name; 129 bool is_transient; 130 bool is_duration; 131 bool editable; 132 /** true if this clock follows the playhead, meaning that certain operations are redundant */ 133 bool _follows_playhead; 134 bool _accept_on_focus_out; 135 bool _off; 136 int em_width; 137 bool _edit_by_click_field; 138 bool _negative_allowed; 139 bool edit_is_negative; 140 141 samplepos_t _limit_pos; 142 143 ARDOUR::samplecnt_t _offset; 144 145 Glib::RefPtr<Pango::Layout> _layout; 146 147 bool _with_info; 148 149 Pango::AttrColor* editing_attr; 150 Pango::AttrColor* foreground_attr; 151 152 Pango::AttrList normal_attributes; 153 Pango::AttrList editing_attributes; 154 155 int first_height; 156 int first_width; 157 bool style_resets_first; 158 int layout_height; 159 int layout_width; 160 double corner_radius; 161 uint32_t font_size; 162 163 static const double info_font_scale_factor; 164 static const double separator_height; 165 static const double x_leading_padding; 166 167 enum Field { 168 Timecode_Hours = 1, 169 Timecode_Minutes, 170 Timecode_Seconds, 171 Timecode_frames, 172 MS_Hours, 173 MS_Minutes, 174 MS_Seconds, 175 MS_Milliseconds, 176 Bars, 177 Beats, 178 Ticks, 179 SS_Seconds, 180 SS_Deciseconds, 181 S_Samples, 182 }; 183 184 Field index_to_field (int index) const; 185 186 /* this maps the number of input characters/digits when editing 187 to a cursor position. insert_map[N] = index of character/digit 188 where the cursor should be after N chars/digits. it is 189 mode specific and so it is filled during set_mode(). 190 */ 191 192 std::vector<int> insert_map; 193 194 bool editing; 195 std::string edit_string; 196 std::string pre_edit_string; 197 std::string input_string; 198 199 samplepos_t bbt_reference_time; 200 samplepos_t last_when; 201 bool last_pdelta; 202 bool last_sdelta; 203 204 bool dragging; 205 double drag_start_y; 206 double drag_y; 207 double drag_accum; 208 Field drag_field; 209 210 void on_realize (); 211 bool on_key_press_event (GdkEventKey *); 212 bool on_key_release_event (GdkEventKey *); 213 bool on_scroll_event (GdkEventScroll *ev); 214 void on_style_changed (const Glib::RefPtr<Gtk::Style>&); 215 void on_size_request (Gtk::Requisition* req); 216 bool on_motion_notify_event (GdkEventMotion *ev); 217 bool on_focus_out_event (GdkEventFocus*); 218 219 void set_slave_info (); 220 void set_timecode (samplepos_t, bool); 221 void set_bbt (samplepos_t, ARDOUR::samplecnt_t, bool); 222 void set_minsec (samplepos_t, bool); 223 void set_seconds (samplepos_t, bool); 224 void set_samples (samplepos_t, bool); 225 void set_out_of_bounds (bool negative); 226 227 void set_clock_dimensions (Gtk::Requisition&); 228 229 samplepos_t get_sample_step (Field, samplepos_t pos = 0, int dir = 1); 230 231 bool timecode_validate_edit (const std::string&); 232 bool bbt_validate_edit (std::string&); 233 bool minsec_validate_edit (const std::string&); 234 235 samplepos_t samples_from_timecode_string (const std::string&) const; 236 samplepos_t samples_from_bbt_string (samplepos_t, const std::string&) const; 237 samplepos_t sample_duration_from_bbt_string (samplepos_t, const std::string&) const; 238 samplepos_t samples_from_minsec_string (const std::string&) const; 239 samplepos_t samples_from_seconds_string (const std::string&) const; 240 samplepos_t samples_from_audiosamples_string (const std::string&) const; 241 242 void session_configuration_changed (std::string); 243 void session_property_changed (const PBD::PropertyChange&); 244 245 Field index_to_field () const; 246 247 void start_edit (Field f = Field (0)); 248 void end_edit (bool); 249 void end_edit_relative (bool); 250 void edit_next_field (); 251 ARDOUR::samplecnt_t parse_as_distance (const std::string&); 252 253 ARDOUR::samplecnt_t parse_as_timecode_distance (const std::string&); 254 ARDOUR::samplecnt_t parse_as_minsec_distance (const std::string&); 255 ARDOUR::samplecnt_t parse_as_bbt_distance (const std::string&); 256 ARDOUR::samplecnt_t parse_as_seconds_distance (const std::string&); 257 ARDOUR::samplecnt_t parse_as_samples_distance (const std::string&); 258 259 void set_colors (); 260 void show_edit_status (int length); 261 int merge_input_and_edit_string (); 262 std::string get_field (Field); 263 264 void drop_focus (); 265 void dpi_reset (); 266 267 double bg_r, bg_g, bg_b, bg_a; 268 double cursor_r, cursor_g, cursor_b, cursor_a; 269 270 double xscale; 271 double yscale; 272 }; 273 274 #endif /* __audio_clock_h__ */ 275