3 # Copyright (C) 2008,2009 Nedko Arnaudov <nedko@arnaudov.name>
4 # Copyright (C) 2006 Leonard Ritter <contact@leonard-ritter.com>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; version 2 of the License
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 import xml
.dom
.minidom
28 from math
import pi
, sin
, cos
, atan2
, log
29 from colorsys
import hls_to_rgb
, rgb_to_hls
33 def map_coords_linear(x
,y
):
36 def map_coords_spheric(x
,y
):
37 nx
= cos(x
* 2 * pi
) * y
38 ny
= -sin(x
* 2 * pi
) * y
41 def get_peaks(f
, tolerance
=0.01, maxd
=0.01, mapfunc
=map_coords_linear
):
48 for i
in xrange(int(corners
)):
54 t
= atan2((y0
- y
), (x0
- x
)) / (2*pi
)
56 if (abs(td
) >= tolerance
):
62 def make_knobshape(gaps
, gapdepth
):
63 def knobshape_func(x
):
68 if (x
>= g1
) and (x
< 0.5):
70 return 0.5 - gapdepth
* x
* 0.9
71 elif (x
>= 0.5) and (x
< g2
):
73 return 0.5 - gapdepth
* (1-x
) * 0.9
76 return get_peaks(knobshape_func
, 0.03, 0.05, map_coords_spheric
)
78 def hls_to_color(h
,l
,s
):
79 r
,g
,b
= hls_to_rgb(h
,l
,s
)
80 return gtk
.gdk
.color_parse('#%04X%04X%04X' % (int(r
*65535),int(g
*65535),int(b
*65535)))
82 def color_to_hls(color
):
83 string
= color
.to_string()
84 r
= int(string
[1:5], 16) / 65535.0
85 g
= int(string
[5:9], 16) / 65535.0
86 b
= int(string
[9:13], 16) / 65535.0
87 return rgb_to_hls(r
, g
, b
)
91 MARKER_ARROW
= 'arrow'
95 LEGEND_DOTS
= 'dots' # painted dots
96 LEGEND_LINES
= 'lines' # painted ray-like lines
97 LEGEND_RULER
= 'ruler' # painted ray-like lines + a circular one
98 LEGEND_RULER_INWARDS
= 'ruler-inwards' # same as ruler, but the circle is on the outside
99 LEGEND_LED_SCALE
= 'led-scale' # an LCD scale
100 LEGEND_LED_DOTS
= 'led-dots' # leds around the knob
104 self
.tooltip_window
= gtk
.Window(gtk
.WINDOW_POPUP
)
105 self
.tooltip
= gtk
.Label()
106 #self.tooltip.modify_fg(gtk.STATE_NORMAL, hls_to_color(0.0, 1.0, 0.0))
107 self
.tooltip_timeout
= None
110 vbox2
.add(self
.tooltip
)
111 vbox2
.set_border_width(2)
113 self
.tooltip_window
.add(vbox
)
114 vbox
.connect('expose-event', self
.on_tooltip_expose
)
116 def show_tooltip(self
, knob
):
117 text
= knob
.format_value()
118 rc
= knob
.get_allocation()
119 x
,y
= knob
.window
.get_origin()
120 self
.tooltip_window
.show_all()
121 w
,h
= self
.tooltip_window
.get_size()
122 wx
,wy
= x
+rc
.x
-w
, y
+rc
.y
+rc
.height
/2-h
/2
123 self
.tooltip_window
.move(wx
,wy
)
124 rc
= self
.tooltip_window
.get_allocation()
125 self
.tooltip_window
.window
.invalidate_rect((0,0,rc
.width
,rc
.height
), False)
126 self
.tooltip
.set_text(text
)
127 if self
.tooltip_timeout
:
128 gobject
.source_remove(self
.tooltip_timeout
)
129 self
.tooltip_timeout
= gobject
.timeout_add(500, self
.hide_tooltip
)
131 def hide_tooltip(self
):
132 self
.tooltip_window
.hide_all()
134 def on_tooltip_expose(self
, widget
, event
):
135 ctx
= widget
.window
.cairo_create()
136 rc
= widget
.get_allocation()
137 #ctx.set_source_rgb(*hls_to_rgb(0.0, 0.0, 0.5))
139 ctx
.set_source_rgb(*hls_to_rgb(0.0, 0.0, 0.5))
140 ctx
.translate(0.5, 0.5)
141 ctx
.set_line_width(1)
142 ctx
.rectangle(rc
.x
, rc
.y
,rc
.width
-1,rc
.height
-1)
149 def get_knob_tooltip():
152 knob_tooltip
= KnobTooltip()
155 class SmartAdjustment(gtk
.Adjustment
):
156 def __init__(self
, log
=False, value
=0, lower
=0, upper
=0, step_incr
=0, page_incr
=0, page_size
=0):
158 gtk
.Adjustment
.__init
__(self
, value
, lower
, upper
, step_incr
, page_incr
, page_size
)
159 self
.normalized_value
= self
.real2norm(self
.value
)
161 def real2norm(self
, value
):
163 return log(value
/ self
.lower
, self
.upper
/ self
.lower
)
165 return (value
- self
.lower
) / (self
.upper
- self
.lower
)
167 def norm2real(self
, value
):
169 return self
.lower
* pow(self
.upper
/ self
.lower
, value
)
171 return value
* (self
.upper
- self
.lower
) + self
.lower
173 def set_value(self
, value
):
174 self
.normalized_value
= self
.real2norm(value
)
175 gtk
.Adjustment
.set_value(self
, value
)
177 def get_normalized_value(self
):
178 return self
.normalized_value
180 def set_normalized_value(self
, value
):
181 self
.normalized_value
= value
183 if self
.normalized_value
< 0.0:
184 self
.normalized_value
= 0.0
185 elif self
.normalized_value
> 1.0:
186 self
.normalized_value
= 1.0
188 self
.set_value(self
.norm2real(self
.normalized_value
))
190 class Knob(gtk
.VBox
):
192 gtk
.VBox
.__init
__(self
)
197 self
.max_value
= 127.0
198 self
.fg_hls
= 0.0, 0.7, 0.0
199 self
.legend_hls
= None
200 self
.dragging
= False
205 self
.marker
= MARKER_LINE
206 self
.angle
= (3.0/4.0) * 2 * pi
207 self
.knobshape
= None
208 self
.legend
= LEGEND_DOTS
211 self
.set_double_buffered(True)
212 self
.connect('realize', self
.on_realize
)
213 self
.connect("size_allocate", self
.on_size_allocate
)
214 self
.connect('expose-event', self
.on_expose
)
215 self
.set_border_width(6)
216 self
.set_size_request(50, 50)
217 self
.tooltip_enabled
= False
220 def set_adjustment(self
, adj
):
223 self
.value
= adj
.get_normalized_value()
225 self
.adj
.disconnect(self
.adj_id
)
227 self
.adj_id
= adj
.connect("value-changed", self
.on_adj_value_changed
)
229 def is_sensitive(self
):
230 return self
.get_property("sensitive")
232 def format_value(self
):
234 value
= self
.adj
.value
237 return ("%%.%if" % self
.digits
) % value
239 def show_tooltip(self
):
240 if self
.tooltip_enabled
:
241 get_knob_tooltip().show_tooltip(self
)
243 def on_realize(self
, widget
):
244 self
.root
= self
.get_toplevel()
245 self
.root
.add_events(gtk
.gdk
.ALL_EVENTS_MASK
)
246 self
.root
.connect('scroll-event', self
.on_mousewheel
)
247 self
.root
.connect('button-press-event', self
.on_left_down
)
248 self
.root
.connect('button-release-event', self
.on_left_up
)
249 self
.root
.connect('motion-notify-event', self
.on_motion
)
250 self
.update_knobshape()
252 def update_knobshape(self
):
253 rc
= self
.get_allocation()
254 b
= self
.get_border_width()
255 size
= min(rc
.width
, rc
.height
) - 2*b
256 gd
= float(self
.gapdepth
*0.5) / size
258 self
.knobshape
= make_knobshape(self
.gaps
, gd
)
260 def set_legend_scale(self
, scale
):
264 def set_legend_line_width(self
, width
):
268 def set_segments(self
, segments
):
269 self
.segments
= segments
272 def set_marker(self
, marker
):
276 def set_range(self
, minvalue
, maxvalue
):
277 self
.min_value
= minvalue
278 self
.max_value
= maxvalue
279 self
.set_value(self
.value
)
281 def quantize_value(self
, value
):
282 scaler
= 10**self
.digits
283 value
= int((value
*scaler
)+0.5) / float(scaler
)
286 def on_adj_value_changed(self
, adj
):
287 new_value
= adj
.get_normalized_value()
288 if self
.value
!= new_value
:
289 self
.value
= new_value
292 def set_value(self
, value
):
294 self
.value
= min(max(self
.quantize_value(value
), self
.min_value
), self
.max_value
)
295 if self
.value
!= oldval
:
297 self
.adj
.set_normalized_value(value
)
303 def set_top_color(self
, h
, l
, s
):
307 def set_legend_color(self
, h
, l
, s
):
308 self
.legend_hls
= h
,l
,s
311 def get_top_color(self
):
314 def set_gaps(self
, gaps
):
316 self
.knobshape
= None
322 def set_gap_depth(self
, gapdepth
):
323 self
.gapdepth
= gapdepth
324 self
.knobshape
= None
327 def get_gap_depth(self
):
330 def set_angle(self
, angle
):
337 def set_legend(self
, legend
):
341 def get_legend(self
):
344 def on_left_down(self
, widget
, event
):
345 #print "on_left_down"
347 # dont drag insensitive widgets
348 if not self
.is_sensitive():
351 if not sum(self
.get_allocation().intersect((int(event
.x
), int(event
.y
), 1, 1))):
353 if event
.button
== 1:
354 #print "start draggin"
355 self
.startvalue
= self
.value
363 def on_left_up(self
, widget
, event
):
365 if not self
.dragging
:
367 if event
.button
== 1:
368 #print "stop draggin"
369 self
.dragging
= False
374 def on_motion(self
, widget
, event
):
377 # dont drag insensitive widgets
378 if not self
.is_sensitive():
382 x
,y
,state
= self
.window
.get_pointer()
383 rc
= self
.get_allocation()
384 range = self
.max_value
- self
.min_value
386 if event
.state
& gtk
.gdk
.SHIFT_MASK
:
388 value
= self
.startvalue
- ((y
- self
.start
)*range)/scale
390 self
.set_value(value
)
392 if oldval
!= self
.value
:
394 self
.startvalue
= self
.value
398 def on_mousewheel(self
, widget
, event
):
400 # dont move insensitive widgets
401 if not self
.is_sensitive():
404 if not sum(self
.get_allocation().intersect((int(event
.x
), int(event
.y
), 1, 1))):
406 range = self
.max_value
- self
.min_value
407 minstep
= 1.0 / (10**self
.digits
)
408 if event
.state
& (gtk
.gdk
.SHIFT_MASK | gtk
.gdk
.BUTTON1_MASK
):
411 step
= max(self
.quantize_value(range/25.0), minstep
)
413 if event
.direction
== gtk
.gdk
.SCROLL_UP
:
415 elif event
.direction
== gtk
.gdk
.SCROLL_DOWN
:
417 self
.set_value(value
)
420 def on_size_allocate(self
, widget
, allocation
):
421 #print allocation.x, allocation.y, allocation.width, allocation.height
422 self
.update_knobshape()
424 def draw_points(self
, ctx
, peaks
):
425 ctx
.move_to(*peaks
[0])
426 for peak
in peaks
[1:]:
430 if not self
.legend_hls
:
431 self
.legend_hls
= color_to_hls(self
.style
.fg
[gtk
.STATE_NORMAL
])
433 if not self
.knobshape
:
434 self
.update_knobshape()
435 startangle
= pi
*1.5 - self
.angle
*0.5
436 angle
= ((self
.value
- self
.min_value
) / (self
.max_value
- self
.min_value
)) * self
.angle
+ startangle
437 rc
= self
.get_allocation()
438 size
= min(rc
.width
, rc
.height
)
440 kh
= self
.get_border_width() # knob height
442 ps
= 1.0/size
# pixel size
443 ps2
= 1.0 / (size
-(2*kh
)-1) # pixel size inside knob
444 ss
= ps
* kh
# shadow size
445 lsize
= ps2
* self
.lsize
# legend line width
447 ctx
.translate(rc
.x
, rc
.y
)
448 ctx
.translate(0.5,0.5)
449 ctx
.translate(size
*0.5, size
*0.5)
450 ctx
.scale(size
-(2*kh
)-1, size
-(2*kh
)-1)
451 if self
.legend
== LEGEND_DOTS
:
453 ctx
.set_source_rgb(*hls_to_rgb(*self
.legend_hls
))
455 for i
in xrange(dots
):
456 s
= float(i
)/(dots
-1)
457 a
= startangle
+ self
.angle
*s
463 ctx
.arc(0.5+lsize
, 0.0, r
, 0.0, 2*pi
)
467 elif self
.legend
in (LEGEND_LINES
, LEGEND_RULER
, LEGEND_RULER_INWARDS
):
469 ctx
.set_source_rgb(*hls_to_rgb(*self
.legend_hls
))
472 for i
in xrange(dots
):
473 s
= float(i
)/(dots
-1)
474 a
= startangle
+ self
.angle
*s
480 ctx
.move_to(0.5+ps2
+n
*0.1, 0.0)
481 ctx
.line_to(0.5+ps2
+n
*0.1+r
, 0.0)
482 ctx
.set_line_width(lsize
)
486 if self
.legend
== LEGEND_RULER
:
488 ctx
.set_source_rgb(*hls_to_rgb(*self
.legend_hls
))
489 ctx
.set_line_width(lsize
)
490 ctx
.arc(0.0, 0.0, 0.5+ps2
+n
*0.1, startangle
, startangle
+self
.angle
)
493 elif self
.legend
== LEGEND_RULER_INWARDS
:
495 ctx
.set_source_rgb(*hls_to_rgb(*self
.legend_hls
))
496 ctx
.set_line_width(lsize
)
497 ctx
.arc(0.0, 0.0, 0.5+ps2
+n
, startangle
, startangle
+self
.angle
)
500 # draw shadow only for sensitive widgets that have height
501 if self
.is_sensitive() and kh
:
503 ctx
.translate(ss
, ss
)
505 self
.draw_points(ctx
, self
.knobshape
)
508 ctx
.set_source_rgba(0,0,0,0.3)
511 if self
.legend
in (LEGEND_LED_SCALE
, LEGEND_LED_DOTS
):
512 ch
,cl
,cs
= self
.legend_hls
515 ctx
.set_line_cap(cairo
.LINE_CAP_ROUND
)
516 ctx
.set_source_rgb(*hls_to_rgb(ch
,cl
*0.2,cs
))
517 ctx
.set_line_width(lsize
)
518 ctx
.arc(0.0, 0.0, 0.5+ps2
+n
*0.5, startangle
, startangle
+self
.angle
)
520 ctx
.set_source_rgb(*hls_to_rgb(ch
,cl
,cs
))
521 if self
.legend
== LEGEND_LED_SCALE
:
522 ctx
.set_line_width(lsize
-ps2
*2)
523 ctx
.arc(0.0, 0.0, 0.5+ps2
+n
*0.5, startangle
, angle
)
525 elif self
.legend
== LEGEND_LED_DOTS
:
528 seg
= self
.angle
/dots
529 endangle
= startangle
+ self
.angle
530 for i
in xrange(dots
):
531 s
= float(i
)/(dots
-1)
532 a
= startangle
+ self
.angle
*s
533 if ((a
-seg
*0.5) > angle
) or (angle
== startangle
):
540 ctx
.arc(0.5+ps2
+n
*0.5, 0.0, r
, 0.0, 2*pi
)
544 pat
= cairo
.LinearGradient(-0.5, -0.5, 0.5, 0.5)
545 pat
.add_color_stop_rgb(1.0, 0.2,0.2,0.2)
546 pat
.add_color_stop_rgb(0.0, 0.3,0.3,0.3)
549 self
.draw_points(ctx
, self
.knobshape
)
552 ctx
.set_source_rgba(0.1,0.1,0.1,1)
554 ctx
.identity_matrix()
555 ctx
.set_line_width(1.0)
559 ctx
.arc(0.0, 0.0, 0.5-self
.gd
, 0.0, pi
*2.0)
560 ctx
.set_source_rgb(*hls_to_rgb(self
.fg_hls
[0], max(self
.fg_hls
[1]*0.4,0.0), self
.fg_hls
[2]))
562 ctx
.arc(0.0, 0.0, 0.5-self
.gd
-ps
, 0.0, pi
*2.0)
563 ctx
.set_source_rgb(*hls_to_rgb(self
.fg_hls
[0], min(self
.fg_hls
[1]*1.2,1.0), self
.fg_hls
[2]))
565 ctx
.arc(0.0, 0.0, 0.5-self
.gd
-(2*ps
), 0.0, pi
*2.0)
566 ctx
.set_source_rgb(*hls_to_rgb(*self
.fg_hls
))
569 # dont draw cap for insensitive widgets
570 if not self
.is_sensitive():
573 #~ ctx.set_line_cap(cairo.LINE_CAP_ROUND)
574 #~ ctx.move_to(0.5-0.3-self.gd-ps, 0.0)
575 #~ ctx.line_to(0.5-self.gd-ps*5, 0.0)
577 if self
.marker
== MARKER_LINE
:
578 ctx
.set_line_cap(cairo
.LINE_CAP_BUTT
)
579 ctx
.move_to(0.5-0.3-self
.gd
-ps
, 0.0)
580 ctx
.line_to(0.5-self
.gd
-ps
, 0.0)
582 ctx
.identity_matrix()
583 ctx
.translate(0.5,0.5)
584 ctx
.set_line_width(5)
585 ctx
.set_source_rgb(*hls_to_rgb(self
.fg_hls
[0], min(self
.fg_hls
[1]*1.2,1.0), self
.fg_hls
[2]))
586 ctx
.stroke_preserve()
587 ctx
.set_line_width(3)
588 ctx
.set_source_rgb(*hls_to_rgb(self
.fg_hls
[0], max(self
.fg_hls
[1]*0.4,0.0), self
.fg_hls
[2]))
591 elif self
.marker
== MARKER_DOT
:
592 ctx
.arc(0.5-0.05-self
.gd
-ps
*5, 0.0, 0.05, 0.0, 2*pi
)
594 ctx
.identity_matrix()
595 ctx
.set_source_rgb(*hls_to_rgb(self
.fg_hls
[0], min(self
.fg_hls
[1]*1.2,1.0), self
.fg_hls
[2]))
596 ctx
.stroke_preserve()
597 ctx
.set_line_width(1)
598 ctx
.set_source_rgb(*hls_to_rgb(self
.fg_hls
[0], max(self
.fg_hls
[1]*0.4,0.0), self
.fg_hls
[2]))
601 elif self
.marker
== MARKER_ARROW
:
602 ctx
.set_line_cap(cairo
.LINE_CAP_BUTT
)
603 ctx
.move_to(0.5-0.3-self
.gd
-ps
, 0.1)
604 ctx
.line_to(0.5-0.1-self
.gd
-ps
, 0.0)
605 ctx
.line_to(0.5-0.3-self
.gd
-ps
, -0.1)
608 ctx
.identity_matrix()
609 #~ ctx.set_source_rgb(*hls_to_rgb(self.fg_hls[0], min(self.fg_hls[1]*1.2,1.0), self.fg_hls[2]))
610 #~ ctx.stroke_preserve()
611 ctx
.set_line_width(1)
612 ctx
.set_source_rgb(*hls_to_rgb(self
.fg_hls
[0], max(self
.fg_hls
[1]*0.4,0.0), self
.fg_hls
[2]))
617 rect
= self
.get_allocation()
619 self
.window
.invalidate_rect(rect
, False)
622 def on_expose(self
, widget
, event
):
623 self
.context
= self
.window
.cairo_create()
624 self
.draw(self
.context
)
628 def __init__(self
, argv
):
629 self
.fake
= len(argv
) == 1
632 self
.label
= self
.human_id
= "fake"
637 self
.host_osc_url
= argv
[1]
638 self
.plugin_uri
= argv
[2]
640 self
.human_id
= argv
[4]
641 if self
.human_id
== "":
642 self
.human_id
= self
.label
644 self
.server
= liblo
.Server()
645 self
.server
.add_method(None, None, self
.on_osc
)
648 def send_update(self
):
651 #print "UI -> update -> host"
652 liblo
.send(self
.host_osc_url
, "//update", self
.server
.get_url())
654 def send_port_value(self
, port_index
, value
):
657 liblo
.send(self
.host_osc_url
, "//control", int(port_index
), float(value
))
659 def send_exiting(self
):
662 liblo
.send(self
.host_osc_url
, "//exiting")
671 while self
.server
.recv(0):
674 def on_osc(self
, path
, args
, types
):
675 if path
== "/control" and types
== "if":
676 self
.on_port_value_changed(args
[0], args
[1])
677 elif path
== "/show" and types
== "":
679 elif path
== "/hide" and types
== "":
681 elif path
== "/quit" and types
== "":
684 print "Unhandled OSC message. path='%s' types='%s', args=%s" % (path
, types
, repr(args
))
686 def on_port_value_changed(self
, port_index
, port_value
):
698 class filter_ui(dssi_ui
):
699 def __init__(self
, argv
):
700 dssi_ui
.__init
__(self
, argv
)
702 if self
.plugin_uri
== "http://nedko.aranaudov.org/soft/filter/1/mono":
704 elif self
.plugin_uri
== "http://nedko.aranaudov.org/soft/filter/1/stereo":
709 self
.window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
710 #self.window.set_size_request(600, 400)
711 self
.window
.set_title("%s (4-band parametric filter)" % self
.human_id
)
712 self
.window
.set_role("plugin_ui")
714 self
.top_vbox
= gtk
.VBox()
716 align
= gtk
.Alignment(0.5, 0.5, 1.0, 1.0)
717 align
.set_padding(4, 10, 10, 10)
718 align
.add(self
.top_vbox
)
720 self
.window
.add(align
)
722 self
.param_hbox
= gtk
.HBox()
723 self
.top_vbox
.pack_start(self
.param_hbox
)
725 self
.param_hbox
.set_spacing(10)
727 self
.initator
= False
731 master_box
= gtk
.VBox()
732 master_box
.set_spacing(5)
734 port
= {'index': 0, 'name': 'Active', 'type': 'toggle'}
735 self
.ports
.append(port
)
736 self
.add_param_box(master_box
, self
.create_toggle_box(port
))
738 port
= {'index': 1, 'name': 'Gain', 'type': 'knob', 'min': -20.0, 'max': 20.0, 'unit': 'dB', 'log': False}
739 self
.ports
.append(port
)
740 self
.add_param_box(master_box
, self
.create_knob_box(port
))
742 self
.param_hbox
.pack_start(master_box
, True, True)
745 {'name': 'Active', 'type': 'toggle'},
746 {'name': 'Frequency', 'type': 'knob', 'unit': 'Hz', 'log': True},
747 {'name': 'Bandwidth', 'type': 'knob', 'min': 0.125, 'max': 8.0, 'unit': '', 'log': True},
748 {'name': 'Gain', 'type': 'knob', 'min': -20.0, 'max': 20.0, 'unit': 'dB', 'log': False}]
750 freq_min
= [ 20.0, 40.0, 100.0, 200.0]
751 freq_max
= [2000.0, 4000.0, 10000.0, 20000.0]
755 for i
in [0, 1, 2, 3]:
756 band_frame
= gtk
.Frame("Band %d" % (i
+ 1))
757 band_frame
.set_label_align(0.5, 0.5)
759 band_box
= gtk
.VBox()
760 band_box
.set_spacing(5)
762 for parameter
in band_parameters
:
764 port
= parameter
.copy()
765 port
['index'] = port_index
768 if port
['name'] == 'Frequency':
769 port
['min'] = freq_min
[i
]
770 port
['max'] = freq_max
[i
]
772 self
.ports
.append(port
)
774 #param_box.set_spacing(5)
775 if port
['type'] == 'knob':
776 self
.add_param_box(band_box
, self
.create_knob_box(port
))
777 elif port
['type'] == 'toggle':
778 self
.add_param_box(band_box
, self
.create_toggle_box(port
))
780 band_frame
.add(band_box
)
782 self
.param_hbox
.pack_start(band_frame
, True, True)
786 def create_knob_box(self
, port
):
787 param_box
= gtk
.VBox()
788 step
= (port
['max'] - port
['min']) / 100
789 adj
= SmartAdjustment(port
['log'], port
['min'], port
['min'], port
['max'], step
, step
* 20)
793 adj
.connect("value-changed", self
.on_adj_value_changed
)
796 knob
.set_adjustment(adj
)
797 align
= gtk
.Alignment(0.5, 0.5, 0, 0)
798 align
.set_padding(0, 0, 20, 20)
800 param_box
.pack_start(align
, False)
802 adj
.label
= gtk
.Label("xxx")
803 param_box
.pack_start(adj
.label
, False)
804 #spin = gtk.SpinButton(adj, 0.0, 2)
805 #param_box.pack_start(spin, False)
807 label
= gtk
.Label(port
['name'])
808 param_box
.pack_start(label
, False)
811 def create_toggle_box(self
, port
):
812 param_box
= gtk
.VBox()
813 button
= gtk
.CheckButton(port
['name'])
816 button
.connect("toggled", self
.on_button_toggled
)
818 align
= gtk
.Alignment(0.5, 0.5, 0, 0)
820 param_box
.pack_start(align
, False)
823 def add_param_box(self
, container
, param_box
):
824 align
= gtk
.Alignment(0.5, 0.5, 1.0, 1.0)
825 align
.set_padding(10, 10, 10, 10)
828 container
.pack_start(align
, True)
830 def on_adj_value_changed(self
, adj
):
831 value
= adj
.get_value()
838 text
= format
% value
839 unit
= adj
.port
['unit']
843 adj
.label
.set_text(text
)
846 #print adj.port, adj.get_value()
847 self
.send_port_value(adj
.port
['index'] + self
.port_base
, value
)
849 def on_button_toggled(self
, widget
):
851 if widget
.get_active():
855 self
.send_port_value(widget
.port
['index'] + self
.port_base
, value
)
858 self
.window
.connect("destroy", self
.on_window_closed
)
859 gobject
.timeout_add(50, self
.on_idle
)
866 def on_port_value_changed(self
, port_index
, port_value
):
867 #print "port %d set to %f" % (port_index, port_value)
868 port_index
-= self
.port_base
869 port
= self
.ports
[port_index
]
870 port_type
= port
['type']
871 if port_type
== 'knob':
872 if port
.has_key('adj'):
873 self
.initator
= False
874 port
['adj'].set_value(port_value
)
876 elif port_type
== 'toggle':
877 if port
.has_key('widget'):
883 self
.initator
= False
884 port
['widget'].set_active(toggled
)
888 self
.window
.show_all()
891 self
.window
.hide_all()
896 def on_window_closed(self
, arg
):
901 filter_ui(sys
.argv
).run()
904 if __name__
== '__main__':