1 # This file is part of jack_mixer
3 # Copyright (C) 2006 Nedko Arnaudov <nedko@arnaudov.name>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 class MeterWidget(gtk
.DrawingArea
):
22 def __init__(self
, scale
):
23 gtk
.DrawingArea
.__init
__(self
)
27 self
.connect("expose-event", self
.on_expose
)
28 self
.connect("size-request", self
.on_size_request
)
29 self
.connect("size_allocate", self
.on_size_allocate
)
31 self
.color_bg
= gtk
.gdk
.Color(0,0,0)
32 self
.color_value
= None
33 self
.color_mark
= gtk
.gdk
.Color(int(65535 * 0.2), int(65535 * 0.2), int(65535 * 0.2))
36 self
.cache_surface
= None
38 def set_color(self
, color
):
39 self
.color_value
= color
40 self
.cache_surface
= None
43 def on_expose(self
, widget
, event
):
44 cairo_ctx
= widget
.window
.cairo_create()
46 # set a clip region for the expose event
47 cairo_ctx
.rectangle(event
.area
.x
, event
.area
.y
, event
.area
.width
, event
.area
.height
)
54 def on_size_allocate(self
, widget
, allocation
):
55 #print allocation.x, allocation.y, allocation.width, allocation.height
56 self
.width
= float(allocation
.width
)
57 self
.height
= float(allocation
.height
)
59 self
.cache_surface
= None
61 def on_size_request(self
, widget
, requisition
):
62 #print "size-request, %u x %u" % (requisition.width, requisition.height)
63 requisition
.width
= 20
66 def invalidate_all(self
):
67 self
.queue_draw_area(0, 0, int(self
.width
), int(self
.height
))
69 def draw_background(self
, cairo_ctx
):
70 if not self
.cache_surface
:
71 self
.cache_surface
= cairo
.Surface
.create_similar(
72 cairo_ctx
.get_target(),
76 cache_cairo_ctx
= cairo
.Context(self
.cache_surface
)
78 cache_cairo_ctx
.set_source_rgba(0, 0, 0, 0)
79 cache_cairo_ctx
.rectangle(0, 0, self
.width
, self
.height
)
80 cache_cairo_ctx
.fill()
82 cache_cairo_ctx
.set_source_rgba(0.2, 0.2, 0.2, 1)
83 cache_cairo_ctx
.select_font_face("Fixed")
84 cache_cairo_ctx
.set_font_size(self
.font_size
)
85 glyph_width
= self
.font_size
* 3 / 5 # avarage glyph ratio
86 for mark
in self
.scale
.get_marks():
87 mark_position
= int(self
.height
* (1 - mark
.scale
))
88 cache_cairo_ctx
.move_to(0, mark_position
)
89 cache_cairo_ctx
.line_to(self
.width
, mark_position
)
90 cache_cairo_ctx
.stroke()
91 x_correction
= self
.width
/ 2 - glyph_width
* len(mark
.text
) / 2
92 cache_cairo_ctx
.move_to(x_correction
, mark_position
- 2)
93 cache_cairo_ctx
.show_text(mark
.text
)
94 cairo_ctx
.set_source_surface(self
.cache_surface
, 0, 0)
97 def draw_value(self
, cairo_ctx
, value
, x
, width
):
98 if self
.color_value
is not None:
99 cairo_ctx
.set_source_color(self
.color_value
)
101 height
= self
.allocation
.height
102 gradient
= cairo
.LinearGradient(1, 1, width
-1, height
-1)
103 gradient
.add_color_stop_rgb(0, 1, 0, 0)
104 gradient
.add_color_stop_rgb(0.2, 1, 1, 0)
105 gradient
.add_color_stop_rgb(1, 0, 1, 0)
106 cairo_ctx
.set_source(gradient
)
107 cairo_ctx
.rectangle(x
, self
.height
* (1 - value
), width
, self
.height
* value
)
110 def set_scale(self
, scale
):
112 self
.cache_surface
= None
113 self
.invalidate_all()
115 class MonoMeterWidget(MeterWidget
):
116 def __init__(self
, scale
):
117 MeterWidget
.__init
__(self
, scale
)
121 def draw(self
, cairo_ctx
):
122 self
.draw_background(cairo_ctx
)
123 self
.draw_value(cairo_ctx
, self
.value
, self
.width
/4.0, self
.width
/2.0)
125 def set_value(self
, value
):
126 if value
!= self
.raw_value
:
127 self
.raw_value
= value
128 self
.value
= self
.scale
.db_to_scale(value
)
129 self
.invalidate_all()
130 if value
== self
.raw_value
:
132 self
.raw_value
= value
133 old_value
= self
.value
134 self
.value
= self
.scale
.db_to_scale(value
)
135 if (abs(old_value
-self
.value
) * self
.height
) > 1:
136 self
.invalidate_all()
138 class StereoMeterWidget(MeterWidget
):
139 def __init__(self
, scale
):
140 MeterWidget
.__init
__(self
, scale
)
147 def draw(self
, cairo_ctx
):
148 self
.draw_background(cairo_ctx
)
149 self
.draw_value(cairo_ctx
, self
.left
, self
.width
/5.0, self
.width
/5.0)
150 self
.draw_value(cairo_ctx
, self
.right
, self
.width
/5.0 * 3.0, self
.width
/5.0)
152 def set_values(self
, left
, right
):
153 if left
== self
.raw_left
and right
== self
.raw_right
:
156 self
.raw_right
= right
158 old_right
= self
.right
159 self
.left
= self
.scale
.db_to_scale(left
)
160 self
.right
= self
.scale
.db_to_scale(right
)
161 if (abs(old_left
-self
.left
) * self
.height
) > 1 or (abs(old_right
-self
.right
) * self
.height
) > 1:
162 self
.invalidate_all()