3 # This file is part of jack_mixer
5 # Copyright (C) 2006 Nedko Arnaudov <nedko@arnaudov.name>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; version 2 of the License
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23 class adjustment_dBFS(gtk.Adjustment):
24 def __init__(self, scale, default_db):
25 self.default_value = scale.db_to_scale(default_db)
28 gtk.Adjustment.__init__(self, self.default_value, 0.0, 1.0, 0.02)
29 self.connect("value-changed", self.on_value_changed)
30 self.disable_value_notify = False
33 self.set_value(self.get_value() + self.step_increment)
36 self.set_value(self.get_value() - self.step_increment)
39 self.set_value(self.default_value)
41 def get_value_db(self):
44 def set_value_db(self, db):
46 self.disable_value_notify = True
47 self.set_value(self.scale.db_to_scale(db))
48 self.disable_value_notify = False
49 self.emit("volume-changed")
51 def on_value_changed(self, adjustment):
52 if not self.disable_value_notify:
53 self.db = self.scale.scale_to_db(self.get_value())
54 self.emit("volume-changed")
56 def set_scale(self, scale):
58 self.disable_value_notify = True
59 self.set_value(self.scale.db_to_scale(self.db))
60 self.disable_value_notify = False
62 gobject.signal_new("volume-changed", adjustment_dBFS, gobject.SIGNAL_RUN_FIRST | gobject.SIGNAL_ACTION, gobject.TYPE_NONE, [])
65 class GtkSlider(gtk.VScale):
66 def __init__(self, adjustment):
67 gtk.VScale.__init__(self, adjustment)
68 self.set_draw_value(False)
69 self.set_inverted(True)
71 # HACK: we want the behaviour you get with the middle button, so we
72 # mangle the events. Clicking with other buttons moves the slider in
73 # step increments, clicking with the middle button moves the slider
74 # to the location of the click.
75 self.connect('button-press-event', self.button_press_event)
76 self.connect('button-release-event', self.button_release_event)
78 def button_press_event(self, widget, event):
82 def button_release_event(self, widget, event):
87 class CustomSliderWidget(gtk.DrawingArea):
88 def __init__(self, adjustment):
89 gtk.DrawingArea.__init__(self)
91 self.adjustment = adjustment
93 self.connect("expose-event", self.on_expose)
94 self.connect("size-request", self.on_size_request)
95 self.connect("size_allocate", self.on_size_allocate)
96 adjustment.connect("value-changed", self.on_value_changed)
97 self.connect("button-press-event", self.on_mouse)
98 self.connect("motion-notify-event", self.on_mouse)
99 self.set_events(gtk.gdk.BUTTON1_MOTION_MASK | gtk.gdk.BUTTON1_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK)
101 def on_mouse(self, widget, event):
102 if event.type == gtk.gdk.BUTTON_PRESS:
103 #print "mouse button %u pressed %u:%u" % (event.button, event.x, event.y)
104 if event.button == 1:
105 if event.y >= self.slider_rail_up and event.y < self.slider_rail_up + self.slider_rail_height:
106 self.adjustment.set_value(1 - float(event.y - self.slider_rail_up)/float(self.slider_rail_height))
107 elif event.button == 2:
108 self.adjustment.reset()
109 elif event.type == gtk.gdk.MOTION_NOTIFY:
110 #print "mouse motion %u:%u" % (event.x, event.y)
111 if event.y < self.slider_rail_up:
112 y = self.slider_rail_up
113 elif event.y > self.slider_rail_up + self.slider_rail_height:
114 y = self.slider_rail_up + self.slider_rail_height
117 self.adjustment.set_value(1 - float(y - self.slider_rail_up)/float(self.slider_rail_height))
121 def on_value_changed(self, adjustment):
122 self.invalidate_all()
124 def on_expose(self, widget, event):
125 cairo_ctx = widget.window.cairo_create()
127 # set a clip region for the expose event
128 cairo_ctx.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
135 def on_size_allocate(self, widget, allocation):
136 #print allocation.x, allocation.y, allocation.width, allocation.height
137 self.width = float(allocation.width)
138 self.height = float(allocation.height)
141 def on_size_request(self, widget, requisition):
142 #print "size-request, %u x %u" % (requisition.width, requisition.height)
143 requisition.width = 20
146 def invalidate_all(self):
147 self.queue_draw_area(0, 0, int(self.width), int(self.height))
149 def draw(self, cairo_ctx):
150 if self.flags() & gtk.HAS_FOCUS:
151 state = gtk.STATE_PRELIGHT
153 state = gtk.STATE_NORMAL
155 #cairo_ctx.rectangle(0, 0, self.width, self.height)
156 #cairo_ctx.set_source_color(self.style.bg[state])
157 #cairo_ctx.fill_preserve()
158 cairo_ctx.set_source_color(self.style.fg[state])
161 slider_knob_width = self.width * 3 / 4
162 slider_knob_height = self.width * 3 / 2
163 slider_knob_height -= slider_knob_height % 2
164 slider_knob_height += 1
166 slider_x = self.width/2
168 cairo_ctx.set_line_width(1)
171 cairo_ctx.set_source_color(self.style.dark[state])
172 self.slider_rail_up = slider_knob_height/2 + (self.width - slider_knob_width)/2
173 self.slider_rail_height = self.height - 2 * self.slider_rail_up
174 cairo_ctx.move_to(slider_x, self.slider_rail_up)
175 cairo_ctx.line_to(slider_x, self.slider_rail_height + self.slider_rail_up)
179 slider_y = round(self.slider_rail_up + self.slider_rail_height * (1 - self.adjustment.get_value()))
180 cairo_ctx.rectangle(slider_x - float(slider_knob_width)/2,
181 slider_y - slider_knob_height/2,
182 float(slider_knob_width),
184 cairo_ctx.set_source_color(self.style.bg[state])
185 cairo_ctx.fill_preserve()
186 cairo_ctx.set_source_color(self.style.fg[state])
189 cairo_ctx.set_source_color(self.style.fg[state])
190 for i in range(int(slider_knob_height/2))[8:]:
192 correction = 1.0 + (float(slider_knob_height)/2.0 - float(i)) / 10.0
195 w = float(slider_knob_width)/2.0 - correction
198 cairo_ctx.move_to(x1, y+0.5)
199 cairo_ctx.line_to(x2, y+0.5)
201 cairo_ctx.move_to(x1, y-0.5)
202 cairo_ctx.line_to(x2, y-0.5)
203 cairo_ctx.set_line_width(1)
205 # slider knob middle mark
206 cairo_ctx.move_to(slider_x - float(slider_knob_width)/2, slider_y)
207 cairo_ctx.line_to(slider_x + float(slider_knob_width)/2, slider_y)
208 cairo_ctx.set_line_width(2)