* stderr.printf -> debug etc
[jackpanel.git] / jackpanel / Display.vala
blob94e51214c508fa71bba574cf4c3579885d2ad040
1 using Gtk;
2 using Gdk;
3 using Prolooks;
5 namespace Jackpanel {
7 public class Display : PanelDisplayBase {
8 private double realtime_x;
9 private double realtime_y;
10 private double realtime_w;
11 private double realtime_h;
13 public signal void toggle_realtime_requested (bool new_state);
15 private bool _realtime;
16 public bool realtime {
17 get { return _realtime; }
18 set {
19 if (_realtime != value) {
20 _realtime = value;
21 queue_draw ();
26 static jack_nframes_t[] sample_rates = { 22050, 32000, 44100, 48000, 96000, 192000 };
27 private jack_nframes_t _sample_rate;
28 public jack_nframes_t sample_rate {
29 get {
30 return _sample_rate;
32 set {
33 if (_sample_rate != value) {
34 _sample_rate = value;
35 queue_draw ();
39 public signal void sample_rate_changed (jack_nframes_t new_sample_rate);
40 private double sample_rate_x;
41 private double sample_rate_y;
42 private double sample_rate_w;
43 private double sample_rate_h;
44 private Menu sample_rate_menu;
46 private jack_nframes_t _buffer_size;
47 public jack_nframes_t buffer_size {
48 get {
49 return _buffer_size;
51 set {
52 if (_buffer_size != value) {
53 _buffer_size = value;
54 queue_draw ();
59 static uint[] buffer_sizes = { 16, 32, 64, 128, 256, 512, 1024, 2048 };
60 public signal void buffer_size_changed (jack_nframes_t new_buffer_size);
61 private double buffer_size_x;
62 private double buffer_size_y;
63 private double buffer_size_w;
64 private double buffer_size_h;
65 private Menu buffer_size_menu;
68 public Display () {
69 base ();
70 width = 182;
71 height = 49;
72 set_size_request (width, height);
76 private double popup_triangle_width () { return 7.0; }
78 public void draw_popup_triangle (Cairo.Context cr, double x, double y) {
79 cr.save ();
80 set_source_from_color_string (cr, "#b3b6af");
81 cr.new_path ();
82 cr.move_to (x, y);
83 cr.line_to (x + popup_triangle_width (), y);
84 cr.line_to (x + popup_triangle_width () / 2.0, y + 4);
85 cr.close_path ();
86 cr.fill ();
87 cr.restore ();
90 private const double padding = 3;
91 private const double font_size = 16;
92 private double vline_x;
94 protected override void redraw_time () {
95 queue_draw_area ((int)padding + (int)inner_x, (int)padding + (int)inner_y, (int) vline_x + (int)padding - (int)inner_x, (int)font_size);
98 protected override void redraw_time_alt () {
99 queue_draw_area ((int)vline_x + 2*(int)padding, (int)inner_y + (int)padding, (int)inner_width - (int)vline_x, (int)font_size);
102 protected override bool draw_contents (Cairo.Context cr, Gdk.EventExpose event) {
103 double smaller_font_size = font_size - 4;
104 double x = 0;
105 double y = font_size;
106 ///////////////////////////// ABOVE
107 // show time text
108 text (cr, time, padding + x, y, font_size);
110 Cairo.TextExtents ext = Cairo.TextExtents();
111 cr.text_extents (time_alt, ref ext);
113 // show alt text right justified
114 text (cr, time_alt, inner_width - ext.x_advance - ext.x_bearing - padding, y, font_size);
116 ////////////////////////////// LINES
117 // draw lines
118 Color line_color;
119 Color.parse (text_color_default, out line_color);
120 set_source_from_color (cr, line_color, 0.5);
122 cr.text_extents (time, ref ext);
123 // clock time separator line
124 vline_x = padding + x + ext.x_advance + ext.x_bearing + padding + 1;
126 cr.move_to (vline_x, padding);
127 cr.rel_line_to (0, inner_height - 2 * padding + 1);
128 cr.stroke();
130 var hline_y = padding + ext.height + padding + 2;
132 // vertical separator line
133 cr.move_to (padding, hline_y);
134 cr.rel_line_to (width - 20, 0);
135 cr.stroke();
137 ////////////////////////////// BELOW
138 var y_text_below = 0.5 + hline_y + smaller_font_size;
140 // Realtime
141 string rt = "RT";
142 cr.text_extents (rt, ref ext);
143 if (realtime) {
144 text (cr, rt, padding, y_text_below, smaller_font_size);
147 realtime_x = padding;
148 realtime_y = y_text_below - ext.height;
149 realtime_w = ext.x_advance;
150 realtime_h = ext.height;
152 var x_after_rt = padding + ext.x_advance;
154 // Xruns
155 string xruns_str = "X: %u".printf (xruns);
156 cr.text_extents (xruns_str, ref ext);
157 if (xruns == 0) {
158 text (cr, xruns_str, x_after_rt, y_text_below, smaller_font_size);
159 } else {
160 text (cr, xruns_str, x_after_rt, y_text_below, smaller_font_size, "#ff0000");
163 xruns_x = x_after_rt;
164 xruns_y = y_text_below - ext.height;
165 xruns_w = vline_x - x_after_rt;
166 xruns_h = ext.height;
168 // buffer size
169 string buffer_size_str = "%2.1fms".printf (buffer_size*1000.0/(double)sample_rate);
171 cr.text_extents (buffer_size_str, ref ext);
172 var y_popup_triangle = y_text_below - ext.height + 1.0;
174 buffer_size_x = vline_x + padding;
175 buffer_size_y = y_popup_triangle;
176 buffer_size_w = ext.x_advance + ext.x_bearing + popup_triangle_width ();
177 buffer_size_h = ext.height;
178 text (cr, buffer_size_str, buffer_size_x, y_text_below, smaller_font_size);
179 draw_popup_triangle (cr, buffer_size_x + ext.x_advance + ext.x_bearing + 1.0, y_popup_triangle);
181 // sample_rate
182 string sample_rate_str = "%u".printf (sample_rate);
183 cr.text_extents (sample_rate_str, ref ext);
185 sample_rate_x = inner_width - ext.x_advance - ext.x_bearing - padding - 1 - popup_triangle_width ();
186 sample_rate_y = y_popup_triangle;
187 sample_rate_w = ext.x_advance + ext.x_bearing + popup_triangle_width ();
188 sample_rate_h = ext.height;
189 text (cr, sample_rate_str, sample_rate_x, y_text_below, smaller_font_size);
190 draw_popup_triangle (cr, inner_width - popup_triangle_width () - padding, y_popup_triangle);
192 return false;
195 public override bool button_press_event (Gdk.EventButton event) {
196 if (event.type == EventType.BUTTON_PRESS) {
197 if (is_in_rect (event.x, event.y, sample_rate_x, sample_rate_y, sample_rate_w, sample_rate_h)) {
198 sample_rate_menu = new Menu();
199 for (int i = 0; i < sample_rates.length; i++) {
200 var item = new MenuItem.with_label ("%u".printf (sample_rates[i]));
201 item.activate += (item) => {
202 string rate_str = ((Gtk.Label)((Gtk.Item)item).get_child ()).get_text();
203 var new_rate = (jack_nframes_t) rate_str.to_ulong ();
204 if (new_rate != sample_rate) {
205 sample_rate_changed (new_rate);
208 sample_rate_menu.append (item);
211 sample_rate_menu.popup (null, null, null, 3, event.time);
212 sample_rate_menu.show_all();
213 return true;
215 if (is_in_rect (event.x, event.y, buffer_size_x, buffer_size_y, buffer_size_w, buffer_size_h)) {
216 buffer_size_menu = new Menu ();
217 for (int i = 0; i < buffer_sizes.length; i++) {
218 var item = new MenuItem.with_label ("%2.1fms".printf (buffer_sizes[i]*1000.0/(double)sample_rate));
219 item.user_data = &buffer_sizes[i];
220 item.activate += (item) => {
221 buffer_size_changed (*((jack_nframes_t *)item.user_data));
223 buffer_size_menu.append (item);
226 buffer_size_menu.popup (null, null, null, 3, event.time);
227 buffer_size_menu.show_all();
228 return true;
232 if (event.type == EventType.BUTTON_PRESS && event.button == 1) {
233 if (is_in_rect (event.x, event.y, realtime_x, realtime_y, realtime_w, realtime_h)) {
234 toggle_realtime_requested (!realtime);
237 if (is_in_rect (event.x, event.y, xruns_x, xruns_y, xruns_w, xruns_h)) {
238 reset_xruns_requested ();
241 return false;
244 private bool was_in_realtime_rect;
246 public override bool motion_notify_event (Gdk.EventMotion event) {
248 var cr = Gdk.cairo_create (this.window);
250 if (is_in_rect (event.x, event.y, realtime_x, realtime_y, realtime_w, realtime_h)) {
251 was_in_realtime_rect = true;
252 set_source_from_color_string (cr, text_color_default, 0.1);
253 cr.rectangle (realtime_x, realtime_y, realtime_w, realtime_h);
254 cr.fill ();
255 } else {
256 if (was_in_realtime_rect) {
257 queue_draw ();
261 return false;
266 } //namespace Jackpanel