~ubuntu-branches/ubuntu/precise/gst0.10-python/precise

« back to all changes in this revision

Viewing changes to examples/fvumeter.py

  • Committer: Bazaar Package Importer
  • Author(s): Loic Minier
  • Date: 2006-06-25 19:37:45 UTC
  • Revision ID: james.westby@ubuntu.com-20060625193745-9yeg0wq56r24n57x
Tags: upstream-0.10.4
ImportĀ upstreamĀ versionĀ 0.10.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- Mode: Python -*-
 
2
# vi:si:et:sw=4:sts=4:ts=4
 
3
 
 
4
# gst-python
 
5
# Copyright (C) 2005 Fluendo S.L.
 
6
# Originally from the Flumotion streaming server.
 
7
#
 
8
# This library is free software; you can redistribute it and/or
 
9
# modify it under the terms of the GNU Library General Public
 
10
# License as published by the Free Software Foundation; either
 
11
# version 2 of the License, or (at your option) any later version.
 
12
#
 
13
# This library is distributed in the hope that it will be useful,
 
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
# Library General Public License for more details.
 
17
#
 
18
# You should have received a copy of the GNU Library General Public
 
19
# License along with this library; if not, write to the
 
20
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
21
# Boston, MA 02111-1307, USA.
 
22
#
 
23
# Author: Zaheer Merali <zaheermerali at gmail dot com>
 
24
 
 
25
import gtk
 
26
from gtk import gdk
 
27
import gobject
 
28
 
 
29
 
 
30
# this VUMeter respects IEC standard
 
31
# BS 6840-18:1996/IEC-268-18
 
32
# and is inspired by JACK's meterbridge dpm_meters.c
 
33
 
 
34
class FVUMeter(gtk.DrawingArea):
 
35
    __gsignals__ = { 'expose-event' : 'override',
 
36
                     'size-allocate': 'override',
 
37
                     'size-request': 'override',
 
38
                     'realize' : 'override'
 
39
             }
 
40
    __gproperties__ = {
 
41
        'peak' : (gobject.TYPE_FLOAT,
 
42
                  'peak volume level',
 
43
                  'peak volume level in dB',
 
44
                  -90.0,
 
45
                  0,
 
46
                  -90.0,
 
47
                  gobject.PARAM_READWRITE),
 
48
        'decay' : (gobject.TYPE_FLOAT,
 
49
                   'decay volume level',
 
50
                   'decay volume level in dB',
 
51
                   -90.0,
 
52
                   0,
 
53
                   -90.0,
 
54
                   gobject.PARAM_READWRITE),
 
55
        'orange-threshold': (gobject.TYPE_FLOAT,
 
56
                            'threshold for orange',
 
57
                            'threshold for orange use in dB',
 
58
                            -90.0,
 
59
                            0,
 
60
                            -10.0,
 
61
                            gobject.PARAM_READWRITE),
 
62
        'red-threshold': (gobject.TYPE_FLOAT,
 
63
                         'threshold for red',
 
64
                         'threshold for red use in dB',
 
65
                         -90.0,
 
66
                         0,
 
67
                         -1.0,
 
68
                         gobject.PARAM_READWRITE)
 
69
                            
 
70
    }
 
71
    green_gc = None
 
72
    orange_gc = None
 
73
    red_gc = None
 
74
    yellow_gc = None
 
75
    
 
76
    topborder = 7
 
77
    peaklevel = -90.0
 
78
    decaylevel = -90.0
 
79
    orange_threshold = -10.0
 
80
    red_threshold = -1.0
 
81
    bottomborder = 25
 
82
    leftborder = 15 
 
83
    rightborder = 65 
 
84
 
 
85
    # Returns the meter deflection percentage given a db value
 
86
    def iec_scale(self, db):
 
87
        pct = 0.0
 
88
 
 
89
        if db < -70.0:
 
90
            pct = 0.0
 
91
        elif db < -60.0:
 
92
            pct = (db + 70.0) * 0.25
 
93
        elif db < -50.0:
 
94
            pct = (db + 60.0) * 0.5 + 2.5
 
95
        elif db < -40.0:
 
96
            pct = (db + 50.0) * 0.75 + 7.5
 
97
        elif db < -30.0:
 
98
            pct = (db + 40.0) * 1.5 + 15.0
 
99
        elif db < -20.0:
 
100
            pct = (db + 30.0) * 2.0 + 30.0
 
101
        elif db < 0.0:
 
102
            pct = (db + 20.0) * 2.5 + 50.0
 
103
        else:
 
104
            pct = 100.0
 
105
 
 
106
        return pct
 
107
 
 
108
    def do_get_property(self, property):
 
109
        if property.name == 'peak':
 
110
            return self.peaklevel
 
111
        elif property.name == 'decay':
 
112
            return self.decaylevel
 
113
        elif property.name == 'orange-threshold':
 
114
            return self.orange_threshold
 
115
        elif property.name == 'red-threshold':
 
116
            return self.red_threshold
 
117
        else:
 
118
            raise AttributeError, 'unknown property %s' % property.name
 
119
 
 
120
    def do_set_property(self, property, value):
 
121
        if property.name == 'peak':
 
122
            self.peaklevel = value
 
123
        elif property.name == 'decay':
 
124
            self.decaylevel = value
 
125
        elif property.name == 'orange-threshold':
 
126
            self.orange_threshold = value
 
127
        elif property.name == 'red-threshold':
 
128
            self.red_threshold = value
 
129
        else:
 
130
            raise AttributeError, 'unknown property %s' % property.name
 
131
 
 
132
        self.queue_draw()
 
133
                
 
134
    def do_size_request(self, requisition):
 
135
        requisition.width = 250 
 
136
        requisition.height = 50
 
137
 
 
138
    def do_size_allocate(self, allocation):
 
139
        self.allocation = allocation
 
140
        if self.flags() & gtk.REALIZED:
 
141
            self.window.move_resize(*allocation)
 
142
    
 
143
    def do_realize(self):
 
144
        self.set_flags(self.flags() | gtk.REALIZED)
 
145
 
 
146
        self.window = gdk.Window(self.get_parent_window(),
 
147
                                 width=self.allocation.width,
 
148
                                 height=self.allocation.height,
 
149
                                 window_type=gdk.WINDOW_CHILD,
 
150
                                 wclass=gdk.INPUT_OUTPUT,
 
151
                                 event_mask=self.get_events() | gdk.EXPOSURE_MASK)
 
152
 
 
153
        colormap = gtk.gdk.colormap_get_system()
 
154
        green = colormap.alloc_color(0, 65535, 0)
 
155
        orange = colormap.alloc_color(65535, 32768, 0)
 
156
        red = colormap.alloc_color(65535, 0, 0)
 
157
        yellow = colormap.alloc_color(65535, 65535, 0)
 
158
        self.green_gc = gdk.GC(self.window, foreground=green)
 
159
        self.orange_gc = gdk.GC(self.window, foreground=orange)
 
160
        self.red_gc = gdk.GC(self.window, foreground=red)
 
161
        self.yellow_gc = gdk.GC(self.window, foreground=yellow)
 
162
 
 
163
        self.window.set_user_data(self)
 
164
        self.style.attach(self.window)
 
165
        self.style.set_background(self.window, gtk.STATE_NORMAL)
 
166
 
 
167
    def do_expose_event(self, event):
 
168
        self.chain(event)
 
169
       
 
170
        x, y, w, h = self.allocation
 
171
        vumeter_width = w - (self.leftborder + self.rightborder)
 
172
        vumeter_height = h - (self.topborder + self.bottomborder)
 
173
        self.window.draw_rectangle(self.style.black_gc, True,
 
174
                                   self.leftborder, self.topborder,
 
175
                                   vumeter_width, 
 
176
                                   vumeter_height)
 
177
        # draw peak level
 
178
        # 0 maps to width of 0, full scale maps to total width
 
179
        peaklevelpct = self.iec_scale(self.peaklevel)
 
180
        peakwidth = int(vumeter_width * (peaklevelpct / 100))
 
181
        draw_gc = self.green_gc
 
182
        if self.peaklevel >= self.orange_threshold:
 
183
            draw_gc = self.orange_gc
 
184
        if self.peaklevel >= self.red_threshold:
 
185
            draw_gc = self.red_gc
 
186
        if peakwidth > 0:
 
187
            self.window.draw_rectangle(draw_gc, True,
 
188
                    self.leftborder, self.topborder,
 
189
                    peakwidth, vumeter_height)
 
190
     
 
191
        # draw yellow decay level
 
192
        if self.decaylevel > -90.0:
 
193
            decaylevelpct = self.iec_scale(self.decaylevel)
 
194
            decaywidth = int(vumeter_width * (decaylevelpct / 100))
 
195
            # cheat the geometry by drawing 0% level at pixel 0,
 
196
            # which is same position as just above 0%
 
197
            if decaywidth == 0:
 
198
                decaywidth = 1
 
199
            self.window.draw_line(self.yellow_gc,
 
200
                self.leftborder + decaywidth - 1,
 
201
                self.topborder,
 
202
                self.leftborder + decaywidth - 1,
 
203
                self.topborder + vumeter_height - 1)
 
204
 
 
205
        # draw tick marks
 
206
        scalers = [
 
207
            ('-90', 0.0),
 
208
            ('-40', 0.15),
 
209
            ('-30', 0.30),
 
210
            ('-20', 0.50),
 
211
            ('-10', 0.75),
 
212
            ( '-5', 0.875),
 
213
            (  '0', 1.0),
 
214
        ]
 
215
        for level, scale in scalers:
 
216
            # tick mark, 6 pixels high
 
217
            # we cheat again here by putting the 0 at the first pixel
 
218
            self.window.draw_line(self.style.black_gc, 
 
219
                self.leftborder + int(scale * (vumeter_width - 1)),
 
220
                h - self.bottomborder,
 
221
                self.leftborder + int(scale * (vumeter_width - 1)),
 
222
                h - self.bottomborder + 5)
 
223
            # tick label
 
224
            layout = self.create_pango_layout(level)
 
225
            layout_width, layout_height = layout.get_pixel_size()
 
226
            self.window.draw_layout(self.style.black_gc,
 
227
                self.leftborder + int(scale * vumeter_width)
 
228
                    - int(layout_width / 2),
 
229
                h - self.bottomborder + 7, layout)
 
230
 
 
231
        # draw the peak level to the right
 
232
        layout = self.create_pango_layout("%.2fdB" % self.peaklevel)
 
233
        layout_width, layout_height = layout.get_pixel_size()
 
234
        self.window.draw_layout(self.style.black_gc,
 
235
            self.leftborder + vumeter_width + 5,
 
236
            self.topborder + int(vumeter_height / 2 - layout_height / 2),
 
237
            layout)
 
238
 
 
239
gobject.type_register(FVUMeter)