7 public class Display
: DisplayBase
{
19 private string _time_alt
;
20 public string time_alt
{
21 get { return _time_alt
; }
23 if (_time_alt
!= value
) {
30 public bool realtime
{ get; set; }
32 public uint32 samplerate
{ get; set; }
34 public uint32 buffer_size
{ get; set; }
36 private uint32 _xruns
;
42 if (_xruns
!= value
) {
54 set_size_request (width
, height
);
58 protected override bool draw_contents (Cairo
.Context cr
, Gdk
.EventExpose event
) {
60 double font_size
= 16;
61 double smaller_font_size
= font_size
- 4;
64 Color popup_arrow_color
= color_from_string ("#ffffff");
66 ///////////////////////////// ABOVE
68 text (cr
, time
, padding
+ x
, y
, font_size
);
70 Cairo
.TextExtents ext
= Cairo
.TextExtents();
71 cr
.text_extents (time_alt
, ref ext
);
73 // show alt text right justified
74 text (cr
, time_alt
, inner_width
- ext
.x_advance
- ext
.x_bearing
- padding
, y
, font_size
);
76 ////////////////////////////// LINES
79 Color
.parse (text_color_default
, out line_color
);
80 set_source_from_color (cr
, line_color
, 0.5);
82 /* shows text boundaries for visual debugging: left bound
83 cr.move_to (x, y + ext.y_bearing);
84 cr.rel_line_to (0, ext.height);
88 cr
.text_extents (time
, ref ext
);
89 // clock time separator line
90 var vline_x
= padding
+ x
+ ext
.x_advance
+ ext
.x_bearing
+ padding
+ 1;
92 cr
.move_to (vline_x
, padding
);
93 cr
.rel_line_to (0, inner_height
- 2 * padding
+ 1);
96 var hline_y
= padding
+ ext
.height
+ padding
+ 2;
98 // vertical separator line
99 cr
.move_to (padding
, hline_y
);
100 cr
.rel_line_to (width
- 20, 0);
103 ////////////////////////////// BELOW
104 var y_text_below
= 0.5 + hline_y
+ smaller_font_size
;
108 cr
.text_extents (rt
, ref ext
);
110 text (cr
, rt
, padding
, y_text_below
, smaller_font_size
);
113 var x_after_rt
= padding
+ ext
.x_advance
;
116 string xruns_str
= "X: %u".printf (xruns
);
119 text (cr
, xruns_str
, x_after_rt
, y_text_below
, smaller_font_size
);
121 text (cr
, xruns_str
, x_after_rt
, y_text_below
, smaller_font_size
, "#ff0000");
125 text (cr
, "%u".printf (buffer_size
), vline_x
+ padding
, y_text_below
, smaller_font_size
);
128 string samplerate_str
= "%u".printf (samplerate
);
129 cr
.text_extents (samplerate_str
, ref ext
);
130 text (cr
, samplerate_str
, inner_width
- ext
.x_advance
- ext
.x_bearing
- padding
- 1, y_text_below
, smaller_font_size
);
136 public static uint32 no_xruns
;
138 static int jackpanel_xrun_callback (void *panel
) {
143 public class Jackpanel
: Alignment
{
145 jack_client_t
* client
;
146 jack_status_t status
;
147 string time_in_frames
;
149 string time_h_min_sec
;
153 TransportButton to_start
;
154 TransportButton fast_backward
;
155 TransportButton play
;
156 TransportButton stop
;
157 TransportButton fast_forward
;
159 float acceleration
= 1.0f
;
161 private void initialize_jack (string client_name
) {
162 client
= jack_client_open (client_name
, jack_options_t
.JackNullOption
, ref status
);
163 if (client
== null) {
164 stderr
.printf ("jack_client_open() failed, status = 0x%2.0x\n", status
);
165 if ((status
& jack_status_t
.JackServerFailed
) != 0) {
166 stderr
.printf ("Unable to connect to JACK server\n");
170 if ((status
& jack_status_t
.JackServerStarted
) != 0) {
171 stderr
.printf ("JACK server started\n");
173 if ((status
& jack_status_t
.JackNameNotUnique
) != 0) {
174 client_name
= jack_get_client_name(client
);
175 stderr
.printf ("unique name `%s' assigned\n", client_name
);
178 jack_set_xrun_callback (client
, jackpanel_xrun_callback
, (void *)this
);
180 if (jack_activate (client
) != 0) {
181 stderr
.printf ("cannot activate client");
185 private void show_time () {
186 jack_position_t current
= jack_position_t ();
187 jack_transport_state_t transport_state
;
190 transport_state
= jack_transport_query (client
, ref current
);
191 frame_time
= jack_frame_time (client
);
193 var time_seconds
= (int)current
.frame
/ (int)current
.frame_rate
;
194 time_h_min_sec
= "%02d:%02d:%02d".printf (time_seconds
/ 3600, (time_seconds
% 3600) / 60, time_seconds
% 60);
195 time_in_frames
= "%u".printf ((uint32)current
.frame
);
197 switch (transport_state
) {
198 case jack_transport_state_t
.JackTransportStopped
:
199 play
.set_active_no_signals (false);
201 case jack_transport_state_t
.JackTransportRolling
:
202 play
.set_active_no_signals (true);
204 case jack_transport_state_t
.JackTransportStarting
:
205 //stdout.printf ("state: Starting");
208 stderr
.printf ("jack transport state: [unknown]");
212 if ((current
.valid
& jack_position_bits_t
.JackPositionBBT
) != 0) {
213 time_in_bbt
= "%3u|%u|%04u".printf (current
.bar
, current
.beat
, current
.tick
);
214 display
.time_alt
= time_in_bbt
;
216 display
.time_alt
= time_in_frames
;
219 display
.time
= time_h_min_sec
;
222 private bool show_state () {
223 display
.realtime
= jack_is_realtime (client
) != 0;
225 display
.samplerate
= jack_get_sample_rate (client
);
227 display
.buffer_size
= jack_get_buffer_size (client
);
229 display
.xruns
= no_xruns
;
231 // this one redraws the panel
237 Jackpanel (string client_name
) {
238 var table
= new
Table (5, 2, false);
239 display
= new
Display ();
240 to_start
= new
TransportButton (TransportButton
.IconType
.TO_START
);
241 to_start
.height
= 20;
243 to_start
.pressed
+= () => {
244 jack_transport_locate(client
, 0);
247 fast_backward
= new
TransportButton (TransportButton
.IconType
.FAST_BACKWARD
);
248 fast_backward
.height
= 20;
249 fast_backward
.width
= 31;
250 fast_backward
.pressed
+= () => {
251 wind_transport (-1.0f
);
253 Timeout
.add (200, () => {
254 accelerate_transport (fast_backward
, -1.0f
);
258 fast_backward
.released
+= () => {
262 play
= new
TransportButton (TransportButton
.IconType
.PLAY
);
265 play
.toggled
+= (button
, active
) => {
267 jack_transport_start (client
);
269 jack_transport_stop (client
);
273 stop
= new
TransportButton (TransportButton
.IconType
.STOP
);
276 stop
.pressed
+= () => {
277 jack_transport_stop (client
);
281 fast_forward
= new
TransportButton (TransportButton
.IconType
.FAST_FORWARD
);
282 fast_forward
.height
= 20;
283 fast_forward
.width
= 31;
284 fast_forward
.pressed
+= () => {
285 wind_transport (1.0f
);
287 Timeout
.add (200, () => {
288 accelerate_transport (fast_forward
, 1.0f
);
292 fast_forward
.released
+= () => {
297 table
.attach_defaults (display
, 0, 5, 0, 1);
299 table
.attach_defaults (to_start
, 0, 1, 1, 2);
300 table
.attach_defaults (fast_backward
, 1, 2, 1, 2);
301 table
.attach_defaults (fast_forward
, 2, 3, 1, 2);
302 table
.attach_defaults (stop
, 3, 4, 1, 2);
303 table
.attach_defaults (play
, 4, 5, 1, 2);
305 table
.set_col_spacing (0, 4);
306 table
.set_col_spacing (1, 4);
307 table
.set_col_spacing (2, 10);
308 table
.set_col_spacing (3, 4);
311 initialize_jack (client_name
);
312 Timeout
.add (200, show_state
);
315 private void wind_transport (float direction
) {
316 jack_position_t pos
= jack_position_t ();
317 jack_transport_query(client
, ref pos
);
320 float location
= (((float) pos
.frame
/ pos
.frame_rate
) + direction
* acceleration
) * pos
.frame_rate
;
322 if (location
< 0.0f
) {
326 jack_transport_locate(client
, (uint32)location
);
329 private bool accelerate_transport (TransportButton button
, float direction
) {
331 if (acceleration
< 120.0f
) {
332 acceleration
*= 1.11f
;
335 wind_transport (direction
);
341 static int main (string[] args
) {
343 var window
= new Gtk
.Window (Gtk
.WindowType
.TOPLEVEL
);
344 var panel
= new
Jackpanel (Path
.get_basename(args
[0]));
346 window
.destroy
+= Gtk
.main_quit
;
353 } //namespace Jackpanel