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 from gi
.repository
import Gtk
22 from gi
.repository
import Gdk
25 log
= logging
.getLogger(__name__
)
28 class MeterWidget(Gtk
.DrawingArea
):
29 def __init__(self
, scale
):
30 log
.debug("Creating MeterWidget for scale %s", scale
)
33 self
.color_bg
= Gdk
.Color(0, 0, 0)
34 self
.color_value
= None
35 self
.color_mark
= Gdk
.Color(int(65535 * 0.2), int(65535 * 0.2), int(65535 * 0.2))
38 self
.cache_surface
= None
40 self
.preferred_width
= 25
41 self
.preferred_height
= 200
45 self
.connect("draw", self
.draw
)
46 self
.connect("size-allocate", self
.on_size_allocate
)
49 return self
.widen(False)
51 def widen(self
, flag
=True):
52 self
.set_size_request(
53 self
.preferred_width
if flag
else self
.min_width
, self
.preferred_height
56 def set_color(self
, color
):
57 self
.color_value
= color
58 self
.cache_surface
= None
61 def on_expose(self
, widget
, event
):
62 cairo_ctx
= widget
.window
.cairo_create()
63 # set a clip region for the expose event
64 cairo_ctx
.rectangle(event
.area
.x
, event
.area
.y
, event
.area
.width
, event
.area
.height
)
71 def on_size_allocate(self
, widget
, allocation
):
72 self
.width
= float(allocation
.width
)
73 self
.height
= float(allocation
.height
)
75 self
.cache_surface
= None
77 def invalidate_all(self
):
78 self
.queue_draw_area(0, 0, int(self
.width
), int(self
.height
))
80 def draw_background(self
, cairo_ctx
):
81 if not self
.cache_surface
:
82 self
.cache_surface
= cairo
.Surface
.create_similar(
83 cairo_ctx
.get_target(), cairo
.CONTENT_COLOR
, int(self
.width
), int(self
.height
)
85 cache_cairo_ctx
= cairo
.Context(self
.cache_surface
)
87 cache_cairo_ctx
.set_source_rgba(0, 0, 0, 0)
88 cache_cairo_ctx
.rectangle(0, 0, self
.width
, self
.height
)
89 cache_cairo_ctx
.fill()
91 cache_cairo_ctx
.set_source_rgba(0.2, 0.2, 0.2, 1)
92 cache_cairo_ctx
.select_font_face("Fixed")
93 cache_cairo_ctx
.set_font_size(self
.font_size
)
94 glyph_width
= self
.font_size
* 3 / 5 # avarage glyph ratio
96 for mark
in self
.scale
.get_marks():
97 mark_position
= int(self
.height
* (1 - mark
.scale
))
98 cache_cairo_ctx
.move_to(0, mark_position
)
99 cache_cairo_ctx
.line_to(self
.width
, mark_position
)
100 cache_cairo_ctx
.stroke()
101 x_correction
= self
.width
/ 2 - glyph_width
* len(mark
.text
) / 2
102 cache_cairo_ctx
.move_to(x_correction
, mark_position
- 2)
103 cache_cairo_ctx
.show_text(mark
.text
)
105 cairo_ctx
.set_source_surface(self
.cache_surface
, 0, 0)
108 def draw_value(self
, cairo_ctx
, value
, x
, width
):
109 if self
.color_value
is not None:
110 cairo_ctx
.set_source_rgb(
111 self
.color_value
.red
/ 65535.0,
112 self
.color_value
.green
/ 65535.0,
113 self
.color_value
.blue
/ 65535.0,
117 gradient
= cairo
.LinearGradient(1, 1, width
- 1, height
- 1)
119 if self
.scale
.scale_id
== "K20":
120 gradient
.add_color_stop_rgb(0, 1, 0, 0)
121 gradient
.add_color_stop_rgb(0.38, 1, 1, 0)
122 gradient
.add_color_stop_rgb(0.5, 0, 1, 0)
123 gradient
.add_color_stop_rgb(1, 0, 0, 1)
124 elif self
.scale
.scale_id
== "K14":
125 gradient
.add_color_stop_rgb(0, 1, 0, 0)
126 gradient
.add_color_stop_rgb(1 - self
.scale
.db_to_scale(-14), 1, 1, 0)
127 gradient
.add_color_stop_rgb(1 - self
.scale
.db_to_scale(-24), 0, 1, 0)
128 gradient
.add_color_stop_rgb(1, 0, 0, 1)
130 gradient
.add_color_stop_rgb(0, 1, 0, 0)
131 gradient
.add_color_stop_rgb(0.2, 1, 1, 0)
132 gradient
.add_color_stop_rgb(1, 0, 1, 0)
134 cairo_ctx
.set_source(gradient
)
136 cairo_ctx
.rectangle(x
, self
.height
* (1 - value
), width
, self
.height
* value
)
139 def draw_peak(self
, cairo_ctx
, value
, x
, width
):
140 cairo_ctx
.set_source_rgb(1, 1, 1)
141 cairo_ctx
.rectangle(x
, self
.height
* (1 - value
), width
, 2.5)
144 def set_scale(self
, scale
):
146 self
.cache_surface
= None
147 self
.invalidate_all()
150 class MonoMeterWidget(MeterWidget
):
151 def __init__(self
, scale
):
152 super().__init
__(scale
)
158 def draw(self
, widget
, cairo_ctx
):
159 self
.draw_background(cairo_ctx
)
160 self
.draw_value(cairo_ctx
, self
.value
, self
.width
/ 4.0, self
.width
/ 2.0)
161 self
.draw_peak(cairo_ctx
, self
.pk
, self
.width
/ 4.0, self
.width
/ 2.0)
163 def set_values(self
, pk
, value
):
164 if value
== self
.raw_value
and pk
== self
.raw_pk
:
167 self
.raw_value
= value
169 old_value
= self
.value
171 self
.value
= self
.scale
.db_to_scale(value
)
172 self
.pk
= self
.scale
.db_to_scale(pk
)
174 if (abs(old_value
- self
.value
) * self
.height
) > 0.01 or (
175 abs(old_pk
- self
.pk
) * self
.height
177 self
.invalidate_all()
180 class StereoMeterWidget(MeterWidget
):
181 def __init__(self
, scale
):
182 super().__init
__(scale
)
189 self
.raw_left_pk
= 0.0
190 self
.raw_right_pk
= 0.0
195 def draw(self
, widget
, cairo_ctx
):
196 self
.draw_background(cairo_ctx
)
197 self
.draw_value(cairo_ctx
, self
.left
, self
.width
/ 5.0, self
.width
/ 5.0)
198 self
.draw_value(cairo_ctx
, self
.right
, self
.width
/ 5.0 * 3.0, self
.width
/ 5.0)
199 self
.draw_peak(cairo_ctx
, self
.pk_left
, self
.width
/ 5.0, self
.width
/ 5.0)
200 self
.draw_peak(cairo_ctx
, self
.pk_right
, self
.width
/ 5.0 * 3.0, self
.width
/ 5.0)
202 def set_values(self
, pk_l
, pk_r
, left
, right
):
204 left
== self
.raw_left
205 and right
== self
.raw_right
206 and pk_l
== self
.raw_left_pk
207 and pk_r
== self
.raw_right_pk
212 self
.raw_right
= right
213 self
.raw_left_pk
= pk_l
214 self
.raw_right_pk
= pk_r
216 old_right
= self
.right
217 old_pk_left
= self
.pk_left
218 old_pk_right
= self
.pk_right
219 self
.left
= self
.scale
.db_to_scale(left
)
220 self
.right
= self
.scale
.db_to_scale(right
)
221 self
.pk_left
= self
.scale
.db_to_scale(pk_l
)
222 self
.pk_right
= self
.scale
.db_to_scale(pk_r
)
225 (abs(old_left
- self
.left
) * self
.height
) > 0.01
226 or (abs(old_right
- self
.right
) * self
.height
) > 0.01
227 or (abs(old_pk_left
- self
.pk_left
) * self
.height
) > 0.01
228 or (abs(old_pk_right
- self
.pk_right
) * self
.height
) > 0.01
230 self
.invalidate_all()