Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/speak
diff options
context:
space:
mode:
authorAriel Calzada <ariel@activitycentral.com>2012-06-12 01:50:43 (GMT)
committer Ariel Calzada <ariel@activitycentral.com>2012-06-12 01:50:43 (GMT)
commit45cee85ba7175ed92dd19a3e40bf9c40d029e01a (patch)
tree87132e5b6eff5dd0b823a3c165d8909a2c101259 /speak
parentc725f091fd988944611acb1f092592644815c2be (diff)
Updated codeHEADmaster
Diffstat (limited to 'speak')
-rw-r--r--speak/espeak.py3
-rw-r--r--speak/espeak_cmd.py6
-rw-r--r--speak/espeak_gst.py13
-rw-r--r--speak/eye.py45
-rw-r--r--speak/face.py29
-rw-r--r--speak/glasses.py47
-rw-r--r--speak/mouth.py37
-rw-r--r--speak/voice.py41
-rw-r--r--speak/widgets.py18
9 files changed, 102 insertions, 137 deletions
diff --git a/speak/espeak.py b/speak/espeak.py
index 1a88af3..389045d 100644
--- a/speak/espeak.py
+++ b/speak/espeak.py
@@ -1,5 +1,3 @@
-# Copyright (C) 2009, Aleksey Lim
-#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -23,7 +21,6 @@ logger = logging.getLogger('speak')
supported = True
-
class BaseAudioGrab(gobject.GObject):
__gsignals__ = {
'new-buffer': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT])
diff --git a/speak/espeak_cmd.py b/speak/espeak_cmd.py
index 1e03797..682bfcd 100644
--- a/speak/espeak_cmd.py
+++ b/speak/espeak_cmd.py
@@ -1,5 +1,3 @@
-# Copyright (C) 2009, Aleksey Lim
-#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -57,7 +55,9 @@ def voices():
if not m:
continue
language, gender, name, stuff = m.groups()
- if stuff.startswith('mb/'):
+ if stuff.startswith('mb/') or \
+ name in ('en-rhotic','english_rp','english_wmids'):
+ # these voices don't produce sound
continue
out.append((language, name))
diff --git a/speak/espeak_gst.py b/speak/espeak_gst.py
index 9cbe187..85cfa26 100644
--- a/speak/espeak_gst.py
+++ b/speak/espeak_gst.py
@@ -1,5 +1,3 @@
-# Copyright (C) 2009, Aleksey Lim
-#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -27,15 +25,11 @@ RATE_DEFAULT = RATE_MAX/2
class AudioGrabGst(espeak.BaseAudioGrab):
def speak(self, status, text):
- # XXX workaround for http://bugs.sugarlabs.org/ticket/1801
- if not [i for i in text if i.isalnum()]:
- return
-
self.make_pipeline('espeak name=espeak ! wavenc')
src = self.pipeline.get_by_name('espeak')
- pitch = int(status.pitch) - 120
- rate = int(status.rate) - 120
+ pitch = int(status.pitch) - 100
+ rate = int(status.rate) - 100
logger.debug('pitch=%d rate=%d voice=%s text=%s' % (pitch, rate,
status.voice.name, text))
@@ -52,6 +46,9 @@ def voices():
for i in gst.element_factory_make('espeak').props.voices:
name, language, dialect = i
+ if name in ('en-rhotic','english_rp','english_wmids'):
+ # these voices don't produce sound
+ continue
out.append((language, name))
return out
diff --git a/speak/eye.py b/speak/eye.py
index 7996d9d..1fe23f5 100644
--- a/speak/eye.py
+++ b/speak/eye.py
@@ -7,8 +7,8 @@
#
# Parts of Speak.activity are based on code from Measure.activity
# Copyright (C) 2007 Arjun Sarwal - arjun@laptop.org
-#
-# Speak.activity is free software: you can redistribute it and/or modify
+#
+# Speak.activity is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
@@ -28,14 +28,13 @@ import gobject
import cairo
import math
-
class Eye(gtk.DrawingArea):
def __init__(self, fill_color):
gtk.DrawingArea.__init__(self)
self.connect("expose_event", self.expose)
self.frame = 0
self.blink = False
- self.x, self.y = 0, 0
+ self.x, self.y = 0,0
self.fill_color = fill_color
# listen for clicks
@@ -79,17 +78,17 @@ class Eye(gtk.DrawingArea):
if self.x is None or self.y is None:
# look ahead, but not *directly* in the middle
- if a.x + a.width / 2 < self.parent.get_allocation().width / 2:
+ if a.x + a.width/2 < self.parent.get_allocation().width/2:
cx = a.width * 0.6
else:
cx = a.width * 0.4
return cx, a.height * 0.6
EYE_X, EYE_Y = self.translate_coordinates(
- self.get_toplevel(), a.width / 2, a.height / 2)
+ self.get_toplevel(), a.width/2, a.height/2)
EYE_HWIDTH = a.width
EYE_HHEIGHT = a.height
- BALL_DIST = EYE_HWIDTH / 4
+ BALL_DIST = EYE_HWIDTH/4
dx = self.x - EYE_X
dy = self.y - EYE_Y
@@ -107,23 +106,23 @@ class Eye(gtk.DrawingArea):
dx = dist * cosa
dy = dist * sina
- return a.width / 2 + dx, a.height / 2 + dy
+ return a.width/2 + dx, a.height/2 + dy
def expose(self, widget, event):
self.frame += 1
bounds = self.get_allocation()
eyeSize = min(bounds.width, bounds.height)
- outlineWidth = eyeSize / 20.0
- pupilSize = eyeSize / 10.0
+ outlineWidth = eyeSize/20.0
+ pupilSize = eyeSize/10.0
pupilX, pupilY = self.computePupil()
- dX = pupilX - bounds.width / 2.
- dY = pupilY - bounds.height / 2.
- distance = math.sqrt(dX * dX + dY * dY)
- limit = eyeSize / 2 - outlineWidth * 2 - pupilSize
+ dX = pupilX - bounds.width/2.
+ dY = pupilY - bounds.height/2.
+ distance = math.sqrt(dX*dX + dY*dY)
+ limit = eyeSize/2 - outlineWidth*2 - pupilSize
if distance > limit:
- pupilX = bounds.width / 2 + dX * limit / distance
- pupilY = bounds.height / 2 + dY * limit / distance
+ pupilX = bounds.width/2 + dX*limit/distance
+ pupilY = bounds.height/2 + dY*limit/distance
self.context = widget.window.cairo_create()
#self.context.set_antialias(cairo.ANTIALIAS_NONE)
@@ -134,23 +133,23 @@ class Eye(gtk.DrawingArea):
# background
self.context.set_source_rgba(*self.fill_color.get_rgba())
- self.context.rectangle(0, 0, bounds.width, bounds.height)
+ self.context.rectangle(0,0,bounds.width,bounds.height)
self.context.fill()
# eye ball
- self.context.arc(bounds.width / 2, bounds.height / 2, eyeSize / 2 - outlineWidth / 2, 0, 360)
- self.context.set_source_rgb(1, 1, 1)
+ self.context.arc(bounds.width/2,bounds.height/2, eyeSize/2-outlineWidth/2, 0,360)
+ self.context.set_source_rgb(1,1,1)
self.context.fill()
# outline
self.context.set_line_width(outlineWidth)
- self.context.arc(bounds.width / 2, bounds.height / 2, eyeSize / 2 - outlineWidth / 2, 0, 360)
- self.context.set_source_rgb(0, 0, 0)
+ self.context.arc(bounds.width/2,bounds.height/2, eyeSize/2-outlineWidth/2, 0,360)
+ self.context.set_source_rgb(0,0,0)
self.context.stroke()
# pupil
- self.context.arc(pupilX, pupilY, pupilSize, 0, 360)
- self.context.set_source_rgb(0, 0, 0)
+ self.context.arc(pupilX,pupilY,pupilSize,0,360)
+ self.context.set_source_rgb(0,0,0)
self.context.fill()
self.blink = False
diff --git a/speak/face.py b/speak/face.py
index ffbe556..5ad632c 100644
--- a/speak/face.py
+++ b/speak/face.py
@@ -44,9 +44,8 @@ FACE_PAD = 2
class Status:
def __init__(self):
self.voice = voice.defaultVoice()
- self.pitch = espeak.PITCH_MAX / 2
- self.rate = espeak.RATE_MAX / 2
-
+ self.pitch = espeak.PITCH_DEFAULT
+ self.rate = espeak.RATE_DEFAULT
self.eyes = [eye.Eye] * 2
self.mouth = mouth.Mouth
@@ -111,7 +110,7 @@ class View(gtk.EventBox):
self._mouth = None
self._mouthbox = gtk.HBox()
self._mouthbox.show()
-
+
# layout the screen
box = gtk.VBox(homogeneous=False)
box.pack_start(self._eyebox)
@@ -122,11 +121,12 @@ class View(gtk.EventBox):
self._mapped = False
self._peding = None
- self.connect('map', self.__map_cb)
+ self.connect("map_event",self._map_event)
self.update()
-
- def __map_cb(self, widget):
+
+ def _map_event(self, widget, event):
+ self._mapped = True
if self._peding:
self.update(self._peding)
self._peding = None
@@ -135,20 +135,15 @@ class View(gtk.EventBox):
if self._eyes:
map(lambda e: e.look_ahead(), self._eyes)
- def look_at(self, pos=None):
+ def look_at(self, x, y):
if self._eyes:
- if pos is None:
- display = gtk.gdk.display_get_default()
- screen_, x, y, modifiers_ = display.get_pointer()
- else:
- x, y = pos
- map(lambda e, x=x, y=y: e.look_at(x, y), self._eyes)
+ map(lambda e, x=x, y=y: e.look_at(x,y), self._eyes)
def update(self, status = None):
if not status:
status = self.status
else:
- if not self.flags() & gtk.MAPPED:
+ if not self._mapped:
self._peding = status
return
self.status = status
@@ -174,10 +169,6 @@ class View(gtk.EventBox):
# enable mouse move events so we can track the eyes while the mouse is over the mouth
#self._mouth.add_events(gtk.gdk.POINTER_MOTION_MASK)
- def set_voice(self, voice):
- self.status.voice = voice
- self.say_notification(voice.friendlyname)
-
def say(self, something):
self._audio.speak(self._peding or self.status, something)
diff --git a/speak/glasses.py b/speak/glasses.py
index 399c01a..fb64bbd 100644
--- a/speak/glasses.py
+++ b/speak/glasses.py
@@ -23,25 +23,24 @@
from eye import *
-
class Glasses(Eye):
def __init__(self, fill_color):
Eye.__init__(self, fill_color)
def expose(self, widget, event):
bounds = self.get_allocation()
-
+
eyeSize = min(bounds.width, bounds.height)
- outlineWidth = eyeSize / 20.0
- pupilSize = eyeSize / 10.0
- pupilX, pupilY = self.computePupil()
- dX = pupilX - bounds.width / 2.
- dY = pupilY - bounds.height / 2.
- distance = math.sqrt(dX * dX + dY * dY)
- limit = eyeSize / 2 - outlineWidth * 2 - pupilSize
+ outlineWidth = eyeSize/20.0
+ pupilSize = eyeSize/10.0
+ pupilX, pupilY = self.pupil_position()
+ dX = pupilX - bounds.width/2.
+ dY = pupilY - bounds.height/2.
+ distance = math.sqrt(dX*dX + dY*dY)
+ limit = eyeSize/2 - outlineWidth*2 - pupilSize
if distance > limit:
- pupilX = bounds.width / 2 + dX * limit / distance
- pupilY = bounds.height / 2 + dY * limit / distance
+ pupilX = bounds.width/2 + dX*limit/distance
+ pupilY = bounds.height/2 + dY*limit/distance
self.context = widget.window.cairo_create()
#self.context.set_antialias(cairo.ANTIALIAS_NONE)
@@ -52,31 +51,31 @@ class Glasses(Eye):
# background
self.context.set_source_rgba(*self.fill_color.get_rgba())
- self.context.rectangle(0, 0, bounds.width, bounds.height)
+ self.context.rectangle(0,0,bounds.width,bounds.height)
self.context.fill()
- def roundrect(x1, y1, x2, y2):
- self.context.move_to(x1, (y1 + y2) / 2.)
- self.context.curve_to(x1, y1, x1, y1, (x1 + x2) / 2., y1)
- self.context.curve_to(x2, y1, x2, y1, x2, (y1 + y2) / 2.)
- self.context.curve_to(x2, y2, x2, y2, (x1 + x2) / 2., y2)
- self.context.curve_to(x1, y2, x1, y2, x1, (y1 + y2) / 2.)
+ def roundrect(x1,y1, x2,y2):
+ self.context.move_to(x1, (y1+y2)/2.)
+ self.context.curve_to(x1,y1, x1,y1, (x1+x2)/2.,y1)
+ self.context.curve_to(x2,y1, x2,y1, x2,(y1+y2)/2.)
+ self.context.curve_to(x2,y2, x2,y2, (x1+x2)/2.,y2)
+ self.context.curve_to(x1,y2, x1,y2, x1,(y1+y2)/2.)
# eye ball
- roundrect(outlineWidth, outlineWidth, bounds.width - outlineWidth, bounds.height - outlineWidth)
- self.context.set_source_rgb(1, 1, 1)
+ roundrect(outlineWidth,outlineWidth, bounds.width-outlineWidth,bounds.height-outlineWidth)
+ self.context.set_source_rgb(1,1,1)
self.context.fill()
# outline
self.context.set_line_width(outlineWidth)
- roundrect(outlineWidth, outlineWidth, bounds.width - outlineWidth, bounds.height - outlineWidth)
+ roundrect(outlineWidth,outlineWidth, bounds.width-outlineWidth,bounds.height-outlineWidth)
#roundrect(0,0, bounds.width,bounds.height)
- self.context.set_source_rgb(0, 0, 0)
+ self.context.set_source_rgb(0,0,0)
self.context.stroke()
# pupil
- self.context.arc(pupilX, pupilY, pupilSize, 0, 360)
- self.context.set_source_rgb(0, 0, 0)
+ self.context.arc(pupilX,pupilY,pupilSize,0,360)
+ self.context.set_source_rgb(0,0,0)
self.context.fill()
return True
diff --git a/speak/mouth.py b/speak/mouth.py
index a72312a..b01155a 100644
--- a/speak/mouth.py
+++ b/speak/mouth.py
@@ -28,12 +28,11 @@ import cairo
from struct import unpack
import numpy.core
-
class Mouth(gtk.DrawingArea):
def __init__(self, audioSource, fill_color):
gtk.DrawingArea.__init__(self)
- self.connect("expose_event", self.expose)
+ self.connect("expose_event",self.expose)
self.buffers = []
self.buffer_size = 256
self.main_buffers = []
@@ -46,10 +45,10 @@ class Mouth(gtk.DrawingArea):
if len(buf) < 28:
self.newest_buffer = []
else:
- self.newest_buffer = list(unpack(str(int(len(buf)) / 2) + 'h', buf))
+ self.newest_buffer = list(unpack( str(int(len(buf))/2)+'h' , buf))
self.main_buffers += self.newest_buffer
- if(len(self.main_buffers) > self.buffer_size):
- del self.main_buffers[0:(len(self.main_buffers) - \
+ if(len(self.main_buffers)>self.buffer_size):
+ del self.main_buffers[0:(len(self.main_buffers)- \
self.buffer_size)]
self.queue_draw()
@@ -59,7 +58,7 @@ class Mouth(gtk.DrawingArea):
if len(self.main_buffers) == 0 or len(self.newest_buffer) == 0:
self.volume = 0
else:
- self.volume = numpy.core.max(self.main_buffers) # - numpy.core.min(self.main_buffers)
+ self.volume = numpy.core.max(self.main_buffers)# - numpy.core.min(self.main_buffers)
def expose(self, widget, event):
"""This function is the "expose" event handler and does all the drawing."""
@@ -72,30 +71,30 @@ class Mouth(gtk.DrawingArea):
self.context.set_antialias(cairo.ANTIALIAS_NONE)
#set a clip region for the expose event. This reduces redrawing work (and time)
- self.context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
+ self.context.rectangle(event.area.x, event.area.y,event.area.width, event.area.height)
self.context.clip()
# background
self.context.set_source_rgba(*self.fill_color.get_rgba())
- self.context.rectangle(0, 0, bounds.width, bounds.height)
+ self.context.rectangle(0,0, bounds.width,bounds.height)
self.context.fill()
# Draw the mouth
- volume = self.volume / 30000.
+ volume = self.volume / 65535.
mouthH = volume * bounds.height
- mouthW = volume**2 * (bounds.width / 2.) + bounds.width / 2.
+ mouthW = volume**2 * (bounds.width/2.) + bounds.width/2.
# T
# L R
# B
- Lx, Ly = bounds.width / 2 - mouthW / 2, bounds.height / 2
- Tx, Ty = bounds.width / 2, bounds.height / 2 - mouthH / 2
- Rx, Ry = bounds.width / 2 + mouthW / 2, bounds.height / 2
- Bx, By = bounds.width / 2, bounds.height / 2 + mouthH / 2
- self.context.set_line_width(min(bounds.height / 10.0, 10))
- self.context.move_to(Lx, Ly)
- self.context.curve_to(Tx, Ty, Tx, Ty, Rx, Ry)
- self.context.curve_to(Bx, By, Bx, By, Lx, Ly)
- self.context.set_source_rgb(0, 0, 0)
+ Lx,Ly = bounds.width/2 - mouthW/2, bounds.height/2
+ Tx,Ty = bounds.width/2, bounds.height/2 - mouthH/2
+ Rx,Ry = bounds.width/2 + mouthW/2, bounds.height/2
+ Bx,By = bounds.width/2, bounds.height/2 + mouthH/2
+ self.context.set_line_width(min(bounds.height/10.0, 10))
+ self.context.move_to(Lx,Ly)
+ self.context.curve_to(Tx,Ty, Tx,Ty, Rx,Ry)
+ self.context.curve_to(Bx,By, Bx,By, Lx,Ly)
+ self.context.set_source_rgb(0,0,0)
self.context.close_path()
self.context.stroke()
diff --git a/speak/voice.py b/speak/voice.py
index 7dbeb5e..5fc732e 100644
--- a/speak/voice.py
+++ b/speak/voice.py
@@ -21,8 +21,7 @@
# You should have received a copy of the GNU General Public License
# along with Speak.activity. If not, see <http://www.gnu.org/licenses/>.
-import re
-import os
+import re, os
from gettext import gettext as _
import logging
@@ -82,38 +81,8 @@ class Voice:
friendlyname = friendlyname.replace('_test','')
friendlyname = friendlyname.replace('en-','')
friendlyname = friendlyname.replace('english-wisper','whisper')
- friendlyname = friendlyname.replace('english-us', 'us')
-
-
- friendlynameRP = name # friendlyname for RP
- friendlynameRP = friendlynameRP.replace('english_rp', 'rp')
- friendlynameRP = friendlynameRP.replace('english_wmids', 'wmids')
-
- parts = re.split('[ _-]', friendlyname)
- partsRP = re.split('[ _]', friendlynameRP) #RE for english_RP
- self.short_name = _(parts[0].capitalize())
- self.friendlyname = ' '.join([self.short_name] + parts[1:])
-
- friendlynameRP1 = None
- if friendlynameRP == 'rp':
-
- friendlynameRP1 = 'English (Required Pronunciation)'
- self.friendlyname = 'English (Required Pronunciation)'
-
- friendlynameUS = None
- if friendlyname == 'us':
- friendlynameUS = 'English (USA)'
- self.friendlyname = 'English (USA)'
-
- friendlynameWMIDS = None
- if friendlynameRP == 'wmids':
- friendlynameWMIDS = 'English (West Midlands)'
- self.friendlyname = 'English (West Midlands)'
-
-
- def __cmp__(self, other):
- return cmp(self.friendlyname, other.friendlyname if other else '')
-
+ friendlyname = friendlyname.capitalize()
+ self.friendlyname = _(friendlyname)
def allVoices():
if _allVoices:
@@ -122,14 +91,12 @@ def allVoices():
for language, name in espeak.voices():
voice = Voice(language, name)
_allVoices[voice.friendlyname] = voice
-
- return _allVoices
+ return _allVoices
def by_name(name):
return allVoices().get(name, defaultVoice())
-
def defaultVoice():
"""Try to figure out the default voice, from the current locale ($LANG).
Fall back to espeak's voice called Default."""
diff --git a/speak/widgets.py b/speak/widgets.py
index e20ae35..e3fffde 100644
--- a/speak/widgets.py
+++ b/speak/widgets.py
@@ -14,7 +14,7 @@
import logging
-from port.widgets import ComboBox
+from sugar.graphics.combobox import ComboBox
import voice
@@ -46,3 +46,19 @@ class Voices(ComboBox):
self.face.status.voice = self.props.value
finally:
self.handler_unblock_by_func(self._changed_cb)
+
+ def select(self, id=None, name=None):
+ if id is not None:
+ column = 0
+ value = id
+ elif name is not None:
+ column = 1
+ value = name
+ else:
+ return
+
+ for i, item in enumerate(self.get_model()):
+ if item[column] != value:
+ continue
+ self.set_active(i)
+ break