Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xSpeak.activity/activity.py61
-rw-r--r--Speak.activity/chat.py228
-rw-r--r--Speak.activity/chatbox.py93
-rw-r--r--Speak.activity/eye.py5
-rw-r--r--Speak.activity/face.py72
-rw-r--r--Speak.activity/fft_mouth.py8
-rw-r--r--Speak.activity/glasses.py6
-rw-r--r--Speak.activity/mouth.py7
-rw-r--r--Speak.activity/toolbars.py28
-rw-r--r--Speak.activity/waveform_mouth.py8
10 files changed, 395 insertions, 121 deletions
diff --git a/Speak.activity/activity.py b/Speak.activity/activity.py
index 94b94e6..ddfcfd5 100755
--- a/Speak.activity/activity.py
+++ b/Speak.activity/activity.py
@@ -57,6 +57,10 @@ import fft_mouth
import waveform_mouth
import voice
import face
+from toolbars import ChatToolbar
+from chat import Chat
+
+CHAT_TOOLBAR = 3
class SpeakActivity(activity.Activity):
def __init__(self, handle):
@@ -87,20 +91,32 @@ class SpeakActivity(activity.Activity):
box = gtk.VBox(homogeneous=False)
box.pack_start(self.face)
box.pack_start(self.entrycombo, expand=False)
-
- self.set_canvas(box)
- box.show_all()
box.add_events(gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.POINTER_MOTION_MASK)
box.connect("motion_notify_event", self._mouse_moved_cb)
box.connect("button_press_event", self._mouse_clicked_cb)
+ # desktop
+ self.notebook = gtk.Notebook()
+ self.notebook.show()
+ self.notebook.props.show_border = False
+ self.notebook.props.show_tabs = False
+ self.set_canvas(self.notebook)
+
+ box.show_all()
+ self.notebook.append_page(box)
+
+ self.chat = Chat()
+ self.chat.show_all()
+ self.notebook.append_page(self.chat)
+
# make some toolbars
toolbox = activity.ActivityToolbox(self)
self.set_toolbox(toolbox)
toolbox.show()
#activitybar = toolbox.get_activity_toolbar()
+ toolbox.connect('current-toolbar-changed', self._toolbar_changed_cb)
voicebar = self.make_voice_bar()
toolbox.add_toolbar("Voice", voicebar)
@@ -110,6 +126,10 @@ class SpeakActivity(activity.Activity):
toolbox.add_toolbar("Face", facebar)
facebar.show()
+ chatbar = ChatToolbar()
+ toolbox.add_toolbar(_('Chat'), chatbar)
+ chatbar.show()
+
# make the text box active right away
self.entry.grab_focus()
@@ -164,7 +184,7 @@ class SpeakActivity(activity.Activity):
def write_file(self, file_path):
f = open(file_path, "w")
f.write("speak file format v1\n")
- f.write("voice=%s\n" % quote(self.face.voice.friendlyname))
+ f.write("voice=%s\n" % quote(self.face.status.voice.friendlyname))
f.write("text=%s\n" % quote(self.entry.props.text))
history = map(lambda i: i[0], self.entrycombo.get_model())
f.write("history=[%s]\n" % ",".join(map(quote, history)))
@@ -271,13 +291,13 @@ class SpeakActivity(activity.Activity):
for name in voicenames:
self.voice_combo.append_item(self.voices[name], name)
self.voice_combo.set_active(voicenames.index(
- self.face.voice.friendlyname))
+ self.face.status.voice.friendlyname))
combotool = ToolComboBox(self.voice_combo)
voicebar.insert(combotool, -1)
combotool.show()
- self.pitchadj = gtk.Adjustment(self.face.pitch, 0, face.PITCH_MAX, 1,
- face.PITCH_MAX/10, 0)
+ self.pitchadj = gtk.Adjustment(self.face.status.pitch, 0,
+ face.PITCH_MAX, 1, face.PITCH_MAX/10, 0)
pitchbar = gtk.HScale(self.pitchadj)
pitchbar.set_draw_value(False)
#pitchbar.set_inverted(True)
@@ -289,8 +309,8 @@ class SpeakActivity(activity.Activity):
voicebar.insert(pitchtool, -1)
pitchbar.show()
- self.rateadj = gtk.Adjustment(self.face.rate, 0, face.RATE_MAX, 1,
- face.RATE_MAX/10, 0)
+ self.rateadj = gtk.Adjustment(self.face.status.rate, 0, face.RATE_MAX,
+ 1, face.RATE_MAX/10, 0)
ratebar = gtk.HScale(self.rateadj)
ratebar.set_draw_value(False)
#ratebar.set_inverted(True)
@@ -305,15 +325,15 @@ class SpeakActivity(activity.Activity):
return voicebar
def voice_changed_cb(self, combo):
- self.face.voice = combo.props.value
- self.face.say(self.face.voice.friendlyname)
+ self.face.status.voice = combo.props.value
+ self.face.say(self.face.status.voice.friendlyname)
def pitch_adjusted_cb(self, get, data=None):
- self.face.pitch = get.value
+ self.face.status.pitch = get.value
self.face.say(_("pitch adjusted"))
def rate_adjusted_cb(self, get, data=None):
- self.face.rate = get.value
+ self.face.status.rate = get.value
self.face.say(_("rate adjusted"))
def make_face_bar(self):
@@ -353,7 +373,8 @@ class SpeakActivity(activity.Activity):
return facebar
def mouth_changed_cb(self, combo, quiet):
- self.face.implant_mouth(combo.props.value)
+ self.face.status.mouth = combo.props.value
+ self.face.update()
# this SegFaults: self.face.say(combo.get_active_text())
if not quiet:
@@ -363,8 +384,9 @@ class SpeakActivity(activity.Activity):
if self.numeyesadj is None:
return
- self.face.implant_eyes(self.eye_shape_combo.props.value,
- self.numeyesadj.value)
+ self.face.status.eyes = [self.eye_shape_combo.props.value] \
+ * int(self.numeyesadj.value)
+ self.face.update()
# this SegFaults: self.face.say(self.eye_shape_combo.get_active_text())
if not quiet:
@@ -426,6 +448,13 @@ class SpeakActivity(activity.Activity):
else:
self.face.verbose()
+ def _toolbar_changed_cb(self, widget, index):
+ if index == CHAT_TOOLBAR:
+ self.chat.update(self.face.status)
+ self.notebook.set_current_page(1)
+ else:
+ self.notebook.set_current_page(0)
+
#def on_quit(self, data=None):
# self.audio.on_quit()
diff --git a/Speak.activity/chat.py b/Speak.activity/chat.py
new file mode 100644
index 0000000..9dae48b
--- /dev/null
+++ b/Speak.activity/chat.py
@@ -0,0 +1,228 @@
+# 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
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import gtk
+import pango
+import hippo
+import logging
+
+import sugar.graphics.style as style
+from sugar.graphics.roundbox import CanvasRoundBox
+
+import eye
+import glasses
+import mouth
+import face
+from chatbox import ChatBox
+
+BUDDY_SIZE = min(100, min(gtk.gdk.screen_width(),
+ gtk.gdk.screen_height() - style.LARGE_ICON_SIZE) / 5)
+BUDDY_XPAD = 0
+BUDDY_YPAD = 5
+
+BUDDIES_WIDTH = int(BUDDY_SIZE * 2.5)
+BUDDIES_COLOR = style.COLOR_SELECTION_GREY
+#COLOR_BUTTON_GREY
+
+ENTRY_COLOR = style.COLOR_PANEL_GREY
+ENTRY_XPAD = 0
+ENTRY_YPAD = 7
+
+class Chat(hippo.Canvas):
+ def __init__(self):
+ hippo.Canvas.__init__(self)
+ self._buddies = {}
+
+ self.connect('motion_notify_event', self._motion_notify_cb)
+
+ # buddies box
+
+ self._buddies_list = hippo.CanvasBox(
+ background_color = BUDDIES_COLOR.get_int(),
+ box_width = BUDDIES_WIDTH,
+ padding = ENTRY_YPAD,
+ spacing = ENTRY_YPAD
+ )
+
+ self._buddies_box = hippo.CanvasScrollbars()
+ self._buddies_box.set_policy(hippo.ORIENTATION_HORIZONTAL,
+ hippo.SCROLLBAR_NEVER)
+ self._buddies_box.set_root(self._buddies_list)
+
+ # chat entry
+
+ self.chat = ChatBox()
+ self.me = self.chat.owner
+
+ self.my_face, self_face = self._new_face(self.chat.owner, ENTRY_COLOR)
+
+ chat_post = gtk.TextView()
+ chat_post.modify_bg(gtk.STATE_INSENSITIVE,
+ style.COLOR_WHITE.get_gdk_color())
+ chat_post.modify_base(gtk.STATE_INSENSITIVE,
+ style.COLOR_WHITE.get_gdk_color())
+ chat_post.connect('key-press-event', self._key_press_cb)
+
+ chat_post_box = CanvasRoundBox(
+ background_color = style.COLOR_WHITE.get_int(),
+ padding_left = ENTRY_XPAD,
+ padding_right = ENTRY_XPAD,
+ padding_top = ENTRY_YPAD,
+ padding_bottom = ENTRY_YPAD
+ )
+ chat_post_box.props.border_color = ENTRY_COLOR.get_int()
+ chat_post_box.append(hippo.CanvasWidget(widget=chat_post),
+ hippo.PACK_EXPAND)
+
+ chat_entry = CanvasRoundBox(
+ background_color = ENTRY_COLOR.get_int(),
+ padding_left = ENTRY_XPAD,
+ padding_right = ENTRY_XPAD,
+ padding_top = ENTRY_YPAD,
+ padding_bottom = ENTRY_YPAD,
+ spacing = ENTRY_YPAD
+ )
+ chat_entry.props.orientation = hippo.ORIENTATION_HORIZONTAL
+ chat_entry.props.border_color = style.COLOR_WHITE.get_int()
+ chat_entry.append(self_face)
+ chat_entry.append(chat_post_box, hippo.PACK_EXPAND)
+
+ chat_box = hippo.CanvasBox(
+ orientation = hippo.ORIENTATION_VERTICAL,
+ background_color = style.COLOR_WHITE.get_int(),
+ )
+ chat_box.append(self.chat, hippo.PACK_EXPAND)
+ chat_box.append(chat_entry)
+
+ # desk
+
+ self._desk = hippo.CanvasBox()
+ self._desk.props.orientation=hippo.ORIENTATION_HORIZONTAL
+ self._desk.append(chat_box, hippo.PACK_EXPAND)
+
+ self.set_root(self._desk)
+
+ self._add_buddy(self.chat.owner)
+
+ def update(self, status, buddy = None, text = None):
+ if not buddy or buddy == self.me:
+ face = self.my_face
+ else:
+ i = self._buddies.get(buddy)
+ if i:
+ face = i['face']
+ else:
+ self._add_buddy(boddy)
+ face = self._buddies[buddy]['face']
+
+ if status:
+ face.update(status)
+ if text:
+ face.say(text)
+
+ def farewell(self, buddy):
+ i = self._buddies.get(buddy)
+ if not i:
+ logging.debug('farewell: cannot find boddy %s' % buddy.props.nick)
+ return
+
+ self._buddies_list.remove(i['box'])
+ del self._buddies[buddy]
+
+ if len(self._buddies) == 0:
+ self._desk.remove(self._buddies_box)
+
+ def _add_buddy(self, buddy):
+ box = hippo.CanvasBox(
+ orientation = hippo.ORIENTATION_HORIZONTAL,
+ background_color = BUDDIES_COLOR.get_int(),
+ spacing = ENTRY_YPAD
+ )
+
+ buddy_face, buddy_widget = self._new_face(buddy, BUDDIES_COLOR)
+
+ nick = hippo.CanvasText(
+ text = buddy.props.nick,
+ xalign = hippo.ALIGNMENT_START,
+ yalign = hippo.ALIGNMENT_START
+ )
+
+ box.append(buddy_widget)
+ box.append(nick, hippo.PACK_EXPAND)
+
+ self._buddies[buddy] = {
+ 'box' : box,
+ 'face' : buddy_face }
+ self._buddies_list.append(box)
+
+ if len(self._buddies) == 1:
+ self._desk.append(self._buddies_box)
+
+ def _key_press_cb(self, widget, event):
+ if event.keyval == gtk.keysyms.Return:
+ if not (event.state & gtk.gdk.CONTROL_MASK):
+ text = widget.get_buffer().props.text
+ self.chat.add_text(None, text)
+ widget.get_buffer().props.text = ''
+
+ #if len(self._buddies) == 1:
+ # self._del_buddy(self.chat.owner)
+ #else:
+ # self._add_buddy(self.chat.owner)
+
+ self.update(None, None, text)
+ return True
+ return False
+
+ def _new_face(self, buddy, color):
+ stroke_color, fill_color = buddy.props.color.split(',')
+ stroke_color = style.Color(stroke_color)
+ fill_color = style.Color(fill_color)
+
+ buddy_face = face.View(fill_color)
+ buddy_face.show_all()
+
+ inner = CanvasRoundBox(
+ background_color = fill_color.get_int(),
+ padding_top = BUDDY_YPAD,
+ padding_bottom = BUDDY_YPAD,
+ padding_left = BUDDY_XPAD,
+ padding_right = BUDDY_XPAD,
+ )
+ inner.props.border_color = fill_color.get_int()
+ inner.append(hippo.CanvasWidget(widget=buddy_face), hippo.PACK_EXPAND)
+
+ outer = CanvasRoundBox(
+ background_color = stroke_color.get_int(),
+ box_width = BUDDY_SIZE,
+ box_height = BUDDY_SIZE,
+ padding_top = BUDDY_YPAD,
+ padding_bottom = BUDDY_YPAD,
+ padding_left = BUDDY_XPAD,
+ padding_right = BUDDY_XPAD
+ )
+ outer.props.border_color = stroke_color.get_int()
+ outer.append(inner, hippo.PACK_EXPAND)
+
+ return (buddy_face, outer)
+
+ def _look_at(self, x, y):
+ self.my_face.look_at(x, y)
+ for i in self._buddies.values():
+ i['face'].look_at(x, y)
+
+ def _motion_notify_cb(self, widget, event):
+ display = gtk.gdk.display_get_default()
+ screen, x, y, modifiers = display.get_pointer()
+ self._look_at(x,y)
diff --git a/Speak.activity/chatbox.py b/Speak.activity/chatbox.py
index 31b3120..d098ca5 100644
--- a/Speak.activity/chatbox.py
+++ b/Speak.activity/chatbox.py
@@ -35,12 +35,9 @@ URL_REGEXP = re.compile('((http|ftp)s?://)?'
'(([-a-zA-Z0-9]+[.])+[-a-zA-Z0-9]{2,}|([0-9]{1,3}[.]){3}[0-9]{1,3})'
'(:[1-9][0-9]{0,4})?(/[-a-zA-Z0-9/%~@&_+=;:,.?#]*[a-zA-Z0-9/])?')
-class ChatBox(gtk.VBox):
- __gsignals__ = {
- 'send_message': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]) }
-
+class ChatBox(hippo.CanvasScrollbars):
def __init__(self):
- gtk.VBox.__init__(self, homogeneous=False)
+ hippo.CanvasScrollbars.__init__(self)
self.owner = presenceservice.get_instance().get_owner()
@@ -56,32 +53,14 @@ class ChatBox(gtk.VBox):
spacing=0,
background_color=COLOR_WHITE.get_int())
- self._scrolled = hippo.CanvasScrollbars()
- self._scrolled.set_policy(hippo.ORIENTATION_HORIZONTAL,
+ self.set_policy(hippo.ORIENTATION_HORIZONTAL,
hippo.SCROLLBAR_NEVER)
- self._scrolled.set_root(self._conversation)
+ self.set_root(self._conversation)
- vadj = self._scrolled.props.widget.get_vadjustment()
+ vadj = self.props.widget.get_vadjustment()
vadj.connect('changed', self._scroll_changed_cb)
vadj.connect('value-changed', self._scroll_value_changed_cb)
- self._entry = gtk.Entry()
- self._entry.modify_bg(gtk.STATE_INSENSITIVE,
- COLOR_WHITE.get_gdk_color())
- self._entry.modify_base(gtk.STATE_INSENSITIVE,
- COLOR_WHITE.get_gdk_color())
- #self._entry.set_sensitive(False)
- self._entry.connect('activate', self._entry_activate_cb)
-
- hbox = gtk.HBox()
- hbox.add(self._entry)
-
- canvas = hippo.Canvas()
- canvas.set_root(self._scrolled)
-
- self.pack_start(canvas)
- self.pack_start(hbox, expand=False)
-
def get_log(self):
return self._chat_log
@@ -110,36 +89,32 @@ class ChatBox(gtk.VBox):
| +----------------+ |
`--------------------------------'
"""
- if buddy:
- if type(buddy) is dict:
- # dict required for loading chat log from journal
- nick = buddy['nick']
- color = buddy['color']
- else:
- nick = buddy.props.nick
- color = buddy.props.color
- try:
- color_stroke_html, color_fill_html = color.split(',')
- except ValueError:
- color_stroke_html, color_fill_html = ('#000000', '#888888')
-
- # Select text color based on fill color:
- color_fill_rgba = Color(color_fill_html).get_rgba()
- color_fill_gray = (color_fill_rgba[0] + color_fill_rgba[1] +
- color_fill_rgba[2])/3
- color_stroke = Color(color_stroke_html).get_int()
- color_fill = Color(color_fill_html).get_int()
-
- if color_fill_gray < 0.5:
- text_color = COLOR_WHITE.get_int()
- else:
- text_color = COLOR_BLACK.get_int()
+ if not buddy:
+ buddy = self.owner
+
+ if type(buddy) is dict:
+ # dict required for loading chat log from journal
+ nick = buddy['nick']
+ color = buddy['color']
+ else:
+ nick = buddy.props.nick
+ color = buddy.props.color
+ try:
+ color_stroke_html, color_fill_html = color.split(',')
+ except ValueError:
+ color_stroke_html, color_fill_html = ('#000000', '#888888')
+
+ # Select text color based on fill color:
+ color_fill_rgba = Color(color_fill_html).get_rgba()
+ color_fill_gray = (color_fill_rgba[0] + color_fill_rgba[1] +
+ color_fill_rgba[2])/3
+ color_stroke = Color(color_stroke_html).get_int()
+ color_fill = Color(color_fill_html).get_int()
+
+ if color_fill_gray < 0.5:
+ text_color = COLOR_WHITE.get_int()
else:
- nick = '???' # XXX: should be '' but leave for debugging
- color_stroke = COLOR_BLACK.get_int()
- color_fill = COLOR_WHITE.get_int()
text_color = COLOR_BLACK.get_int()
- color = '#000000,#FFFFFF'
self._add_log(nick, color, text, status_message)
@@ -252,16 +227,6 @@ class ChatBox(gtk.VBox):
adj.set_value(adj.upper-adj.page_size)
self._scroll_value = adj.get_value()
- def _entry_activate_cb(self, entry):
- text = entry.props.text
- logging.debug('Entry: %s' % text)
- if not text: return
-
- self.add_text(self.owner, text)
- entry.props.text = ''
- self.emit('send_message', text)
-
-
def _link_activated_cb(self, link):
url = url_check_protocol(link.props.text)
self._show_via_journal(url)
diff --git a/Speak.activity/eye.py b/Speak.activity/eye.py
index fb67f6b..b368b41 100644
--- a/Speak.activity/eye.py
+++ b/Speak.activity/eye.py
@@ -29,12 +29,13 @@ import cairo
import math
class Eye(gtk.DrawingArea):
- def __init__(self):
+ 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.fill_color = fill_color
# listen for clicks
self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
@@ -111,7 +112,7 @@ class Eye(gtk.DrawingArea):
self.context.clip()
# background
- self.context.set_source_rgb(.5,.5,.5)
+ self.context.set_source_rgba(*self.fill_color.get_rgba())
self.context.rectangle(0,0,bounds.width,bounds.height)
self.context.fill()
diff --git a/Speak.activity/face.py b/Speak.activity/face.py
index bf4a02e..7dbaa77 100644
--- a/Speak.activity/face.py
+++ b/Speak.activity/face.py
@@ -45,6 +45,7 @@ from gettext import gettext as _
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.toolcombobox import ToolComboBox
from sugar.graphics.combobox import ComboBox
+import sugar.graphics.style as style
import pygst
pygst.require("0.10")
@@ -60,15 +61,24 @@ import waveform_mouth
PITCH_MAX = 100
RATE_MAX = 100
+FACE_PAD = 2
-class View(gtk.VBox):
+class Status:
def __init__(self):
- gtk.VBox.__init__(self, homogeneous=False)
-
- #self.voice = random.choice(self.voices.values())
self.voice = voice.defaultVoice()
self.pitch = PITCH_MAX/2
self.rate = RATE_MAX/2
+ self.eyes = [eye.Eye] * 2
+ self.mouth = mouth.Mouth
+
+class View(gtk.EventBox):
+ def __init__(self, fill_color=style.COLOR_BUTTON_GREY):
+ gtk.EventBox.__init__(self)
+
+ self.status = Status()
+ self.fill_color = fill_color
+
+ self.connect('size-allocate', self._size_allocate_cb)
self._audio = audio.AudioGrab()
self._synth = None
@@ -95,34 +105,45 @@ class View(gtk.VBox):
self._mouthbox.show()
# layout the screen
- self.pack_start(self._eyebox, expand=False)
- self.pack_start(self._mouthbox)
+ box = gtk.VBox(homogeneous=False)
+ box.pack_start(self._eyebox)
+ box.pack_start(self._mouthbox, False)
+ box.set_border_width(FACE_PAD)
+ self.modify_bg(gtk.STATE_NORMAL, self.fill_color.get_gdk_color())
+ self.add(box)
+
+ self.update()
def look_ahead(self):
- map(lambda e: e.look_ahead(), self._eyes)
+ if self._eyes:
+ map(lambda e: e.look_ahead(), self._eyes)
def look_at(self, x, y):
- map(lambda e, x=x, y=y: e.look_at(x,y), self._eyes)
+ if 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:
+ self.status = status
- def implant_eyes(self, klass, number):
if self._eyes:
for eye in self._eyes:
self._eyebox.remove(eye)
+ if self._mouth:
+ self._mouthbox.remove(self._mouth)
self._eyes = []
- for i in range(int(number)):
- eye = klass()
+ for i in status.eyes:
+ eye = i(self.fill_color)
self._eyes.append(eye)
- self._eyebox.pack_start(eye)
- eye.set_size_request(300,300)
+ self._eyebox.pack_start(eye, padding=FACE_PAD)
+ #eye.set_size_request(300,300)
eye.show()
- def implant_mouth(self, klass):
- if self._mouth:
- self._mouthbox.remove(self._mouth)
-
- self._mouth = klass(self._audio)
+ self._mouth = status.mouth(self._audio, self.fill_color)
self._mouth.show()
self._mouthbox.add(self._mouth)
@@ -133,9 +154,9 @@ class View(gtk.VBox):
if self._audio is None:
return
- logging.debug('%s: %s' % (self.voice.name, something))
- pitch = int(self.pitch)
- rate = int(self.rate)
+ logging.debug('%s: %s' % (self.status.voice.name, something))
+ pitch = int(self.status.pitch)
+ rate = int(self.status.rate)
if self._synth is not None:
# speechd uses -100 to 100
@@ -145,7 +166,7 @@ class View(gtk.VBox):
self._synth.set_rate(rate)
self._synth.set_pitch(pitch)
- self._synth.set_language(self.voice.language)
+ self._synth.set_language(self.status.voice.language)
self._synth.speak(something) #, callback=self._synth_cb)
else:
# espeak uses 0 to 99
@@ -153,11 +174,9 @@ class View(gtk.VBox):
# espeak uses 80 to 370
rate = 80 + (370-80) * rate / 100
- logging.error(">> %d:%d" %(pitch, rate))
-
# ideally we would stream the audio instead of writing to disk each time...
wavpath = "/tmp/speak.wav"
- subprocess.call(["espeak", "-w", wavpath, "-p", str(pitch), "-s", str(rate), "-v", self.voice.name, something], stdout=subprocess.PIPE)
+ subprocess.call(["espeak", "-w", wavpath, "-p", str(pitch), "-s", str(rate), "-v", self.status.voice.name, something], stdout=subprocess.PIPE)
self._audio.playfile(wavpath)
def quiet(self):
@@ -165,3 +184,6 @@ class View(gtk.VBox):
def verbose(self):
self._audio.restart_sound_device()
+
+ def _size_allocate_cb(self, widget, allocation):
+ self._mouthbox.set_size_request(-1, int(allocation.height/2.5))
diff --git a/Speak.activity/fft_mouth.py b/Speak.activity/fft_mouth.py
index 08564d8..53bcadf 100644
--- a/Speak.activity/fft_mouth.py
+++ b/Speak.activity/fft_mouth.py
@@ -34,9 +34,9 @@ except:
from FFT import *
class FFTMouth(Mouth):
- def __init__(self, audioSource):
+ def __init__(self, audioSource, fill_color):
- Mouth.__init__(self, audioSource)
+ Mouth.__init__(self, audioSource, fill_color)
self.peaks = []
@@ -107,12 +107,12 @@ class FFTMouth(Mouth):
self.context.clip()
# background
- self.context.set_source_rgb(.5,.5,.5)
+ self.context.set_source_rgba(*self.fill_color.get_rgba())
self.context.rectangle(0,0, bounds.width,bounds.height)
self.context.fill()
# Draw the waveform
- self.context.set_line_width(10.0)
+ self.context.set_line_width(min(bounds.height/10.0, 10))
self.context.set_source_rgb(0,0,0)
count = 0
for peak in self.peaks:
diff --git a/Speak.activity/glasses.py b/Speak.activity/glasses.py
index 864ebae..fb64bbd 100644
--- a/Speak.activity/glasses.py
+++ b/Speak.activity/glasses.py
@@ -24,8 +24,8 @@
from eye import *
class Glasses(Eye):
- def __init__(self):
- Eye.__init__(self)
+ def __init__(self, fill_color):
+ Eye.__init__(self, fill_color)
def expose(self, widget, event):
bounds = self.get_allocation()
@@ -50,7 +50,7 @@ class Glasses(Eye):
self.context.clip()
# background
- self.context.set_source_rgb(.5,.5,.5)
+ self.context.set_source_rgba(*self.fill_color.get_rgba())
self.context.rectangle(0,0,bounds.width,bounds.height)
self.context.fill()
diff --git a/Speak.activity/mouth.py b/Speak.activity/mouth.py
index d725cf6..404eb3d 100644
--- a/Speak.activity/mouth.py
+++ b/Speak.activity/mouth.py
@@ -29,7 +29,7 @@ from struct import unpack
import numpy.core
class Mouth(gtk.DrawingArea):
- def __init__(self, audioSource):
+ def __init__(self, audioSource, fill_color):
gtk.DrawingArea.__init__(self)
self.connect("expose_event",self.expose)
@@ -37,6 +37,7 @@ class Mouth(gtk.DrawingArea):
self.buffer_size = 256
self.main_buffers = []
self.newest_buffer = []
+ self.fill_color = fill_color
audioSource.connect("new-buffer", self._new_buffer)
@@ -69,7 +70,7 @@ class Mouth(gtk.DrawingArea):
self.context.clip()
# background
- self.context.set_source_rgb(.5,.5,.5)
+ self.context.set_source_rgba(*self.fill_color.get_rgba())
self.context.rectangle(0,0, bounds.width,bounds.height)
self.context.fill()
@@ -84,7 +85,7 @@ class Mouth(gtk.DrawingArea):
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(10.0)
+ 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)
diff --git a/Speak.activity/toolbars.py b/Speak.activity/toolbars.py
new file mode 100644
index 0000000..9aa5567
--- /dev/null
+++ b/Speak.activity/toolbars.py
@@ -0,0 +1,28 @@
+# Speak.activity
+# A simple front end to the espeak text-to-speech engine on the XO laptop
+# http://wiki.laptop.org/go/Speak
+#
+# Copyright (C) 2008 Joshua Minor
+# This file is part of Speak.activity
+#
+# 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
+# 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.
+#
+# Speak.activity is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 gtk
+
+class ChatToolbar(gtk.Toolbar):
+ def __init__(self):
+ gtk.Toolbar.__init__(self)
diff --git a/Speak.activity/waveform_mouth.py b/Speak.activity/waveform_mouth.py
index 05d7249..71a10ea 100644
--- a/Speak.activity/waveform_mouth.py
+++ b/Speak.activity/waveform_mouth.py
@@ -26,9 +26,9 @@
from mouth import *
class WaveformMouth(Mouth):
- def __init__(self, audioSource):
+ def __init__(self, audioSource, fill_color):
- Mouth.__init__(self, audioSource)
+ Mouth.__init__(self, audioSource, fill_color)
self.buffer_size = 100
self.peaks = []
@@ -54,12 +54,12 @@ class WaveformMouth(Mouth):
self.context.clip()
# background
- self.context.set_source_rgb(.5,.5,.5)
+ self.context.set_source_rgba(*self.fill_color.get_rgba())
self.context.rectangle(0,0, bounds.width,bounds.height)
self.context.fill()
# Draw the waveform
- self.context.set_line_width(10.0)
+ self.context.set_line_width(min(bounds.height/10.0, 10))
count = 0
buflen = float(len(self.main_buffers))
for value in self.main_buffers: