diff options
-rw-r--r-- | activity.py | 40 | ||||
-rw-r--r-- | brain.py | 46 | ||||
-rw-r--r-- | chat.py | 83 | ||||
-rw-r--r-- | espeak_cmd.py | 4 | ||||
-rw-r--r-- | espeak_gst.py | 2 | ||||
-rw-r--r-- | eye.py | 24 | ||||
-rw-r--r-- | face.py | 50 | ||||
-rw-r--r-- | fft_mouth.py | 71 | ||||
-rw-r--r-- | glasses.py | 24 | ||||
-rw-r--r-- | messenger.py | 20 | ||||
-rw-r--r-- | mouth.py | 25 | ||||
-rwxr-xr-x | setup.py | 6 | ||||
-rw-r--r-- | voice.py | 63 | ||||
-rw-r--r-- | waveform_mouth.py | 43 |
14 files changed, 277 insertions, 224 deletions
diff --git a/activity.py b/activity.py index b973ca9..a044423 100644 --- a/activity.py +++ b/activity.py @@ -99,8 +99,8 @@ class SpeakActivity(SharedActivity): # desktop self.notebook.show() - self.notebook.props.show_border=False - self.notebook.props.show_tabs=False + self.notebook.props.show_border = False + self.notebook.props.show_tabs = False box.show_all() self.notebook.append_page(box) @@ -123,7 +123,7 @@ class SpeakActivity(SharedActivity): self.voices = ComboBox() for name in sorted(voice.allVoices().keys()): vn = voice.allVoices()[name] - n = name [ : 26 ] + ".." + n = name[:26] + ".." self.voices.append_item(vn, n) self.voices.select(voice.defaultVoice()) @@ -178,8 +178,10 @@ class SpeakActivity(SharedActivity): def new_instance(self): self.voices.connect('changed', self.__changed_voices_cb) - self.pitchadj.connect("value_changed", self.pitch_adjusted_cb, self.pitchadj) - self.rateadj.connect("value_changed", self.rate_adjusted_cb, self.rateadj) + self.pitchadj.connect("value_changed", self.pitch_adjusted_cb, + self.pitchadj) + self.rateadj.connect("value_changed", self.rate_adjusted_cb, + self.rateadj) self.mouth_shape_combo.connect('changed', self.mouth_changed_cb, False) self.mouth_changed_cb(self.mouth_shape_combo, True) self.numeyesadj.connect("value_changed", self.eyes_changed_cb, False) @@ -248,7 +250,7 @@ class SpeakActivity(SharedActivity): voicebar = gtk.Toolbar() self.pitchadj = gtk.Adjustment(self.face.status.pitch, 0, - espeak.PITCH_MAX, 1, espeak.PITCH_MAX/10, 0) + espeak.PITCH_MAX, 1, espeak.PITCH_MAX / 10, 0) pitchbar = gtk.HScale(self.pitchadj) pitchbar.set_draw_value(False) # pitchbar.set_inverted(True) @@ -260,8 +262,8 @@ class SpeakActivity(SharedActivity): label_text=_('Pitch:')) voicebar.insert(pitchbar_toolitem, -1) - self.rateadj = gtk.Adjustment(self.face.status.rate, 0, espeak.RATE_MAX, - 1, espeak.RATE_MAX / 10, 0) + self.rateadj = gtk.Adjustment(self.face.status.rate, 0, + espeak.RATE_MAX, 1, espeak.RATE_MAX / 10, 0) ratebar = gtk.HScale(self.rateadj) ratebar.set_draw_value(False) # ratebar.set_inverted(True) @@ -289,7 +291,8 @@ class SpeakActivity(SharedActivity): self.mouth_shape_combo = ComboBox() self.mouth_shape_combo.append_item(mouth.Mouth, _("Simple")) - self.mouth_shape_combo.append_item(waveform_mouth.WaveformMouth, _("Waveform")) + self.mouth_shape_combo.append_item(waveform_mouth.WaveformMouth, + _("Waveform")) self.mouth_shape_combo.append_item(fft_mouth.FFTMouth, _("Frequency")) self.mouth_shape_combo.set_active(0) @@ -357,15 +360,15 @@ class SpeakActivity(SharedActivity): keyname = gtk.gdk.keyval_name(event.keyval) if keyname == "Up": index = self.entrycombo.get_active() - if index>0: - index-=1 + if index > 0: + index -= 1 self.entrycombo.set_active(index) - self.entry.select_region(0,-1) + self.entry.select_region(0, -1) return True elif keyname == "Down": index = self.entrycombo.get_active() - if index<len(self.entrycombo.get_model())-1: - index+=1 + if index < len(self.entrycombo.get_model()) - 1: + index += 1 self.entrycombo.set_active(index) self.entry.select_region(0, -1) return True @@ -384,15 +387,16 @@ class SpeakActivity(SharedActivity): else: self.face.say(text) - # add this text to our history unless it is the same as the last item + # add this text to our history unless + # it is the same as the last item history = self.entrycombo.get_model() - if len(history)==0 or history[-1][0] != text: + if len(history) == 0 or history[-1][0] != text: self.entrycombo.append_text(text) # don't let the history get too big - while len(history)>20: + while len(history) > 20: self.entrycombo.remove_text(0) # select the new item - self.entrycombo.set_active(len(history)-1) + self.entrycombo.set_active(len(history) - 1) # select the whole text entry.select_region(0, -1) @@ -1,21 +1,23 @@ # HablarConSara.activity # A simple hack to attach a chatterbot to speak activity -# Copyright (C) 2008 Sebastian Silva Fundacion FuenteLibre sebastian@fuentelibre.org +# Copyright (C) 2008 +# Sebastian Silva Fundacion FuenteLibre sebastian@fuentelibre.org # # Style and structure taken from Speak.activity Copyright (C) Joshua Minor # -# HablarConSara.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. +# HablarConSara.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. # -# HablarConSara.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. +# HablarConSara.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 HablarConSara.activity. If not, see <http://www.gnu.org/licenses/>. +# You should have received a copy of the GNU General Public License +# along with HablarConSara.activity. +# If not, see <http://www.gnu.org/licenses/>. import gtk import gobject @@ -29,15 +31,14 @@ from toolkit.combobox import ComboBox import aiml import voice -BOTS = { - _('Spanish'): { 'name': 'Sara', - 'brain': 'bot/sara.brn', - 'predicates': { 'nombre_bot': 'Sara', - 'botmaster': 'La comunidad Azucar' } }, - _('English'): { 'name': 'Alice', - 'brain': 'bot/alice.brn', - 'predicates': { 'name': 'Alice', - 'master': 'The Sugar Community' } } } +BOTS = {_('Spanish'): {'name': 'Sara', + 'brain': 'bot/sara.brn', + 'predicates': {'nombre_bot': 'Sara', + 'botmaster': 'La comunidad Azucar'}}, + _('English'): {'name': 'Alice', + 'brain': 'bot/alice.brn', + 'predicates': {'name': 'Alice', + 'master': 'The Sugar Community'}}} def get_mem_info(tag): @@ -122,8 +123,9 @@ def load(activity, voice, sorry=None): activity.set_cursor(old_cursor) if is_first_session: - hello = _("Hello, I'm a robot \"%s\". Please ask me any question.") \ - % BOTS[voice.friendlyname]['name'] + hello = _("Hello, I'm a robot \"%s\". " +\ + "Please ask me any question.") %\ + BOTS[voice.friendlyname]['name'] if sorry: hello += ' ' + sorry activity.face.say_notification(hello) @@ -58,11 +58,10 @@ class View(hippo.Canvas): # buddies box self._buddies_list = hippo.CanvasBox( - background_color = BUDDIES_COLOR.get_int(), - box_width = BUDDIES_WIDTH, - padding = ENTRY_YPAD, - spacing = ENTRY_YPAD - ) + 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, @@ -84,33 +83,29 @@ class View(hippo.Canvas): chat_post.props.wrap_mode = gtk.WRAP_WORD_CHAR chat_post.set_size_request(-1, BUDDY_SIZE - ENTRY_YPAD * 2) 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 + 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 = 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(my_face_widget) 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 = 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) @@ -161,31 +156,23 @@ class View(hippo.Canvas): def shut_up(self): for i in self._buddies.values(): - i['face'].shut_up(); - self.me.shut_up(); + i['face'].shut_up() + self.me.shut_up() def _add_buddy(self, buddy): - box = hippo.CanvasBox( - orientation = hippo.ORIENTATION_HORIZONTAL, - background_color = BUDDIES_COLOR.get_int(), - spacing = ENTRY_YPAD - ) + 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) - char_box = hippo.CanvasBox( - orientation = hippo.ORIENTATION_VERTICAL, - ) - nick = hippo.CanvasText( - text = buddy.props.nick, - xalign = hippo.ALIGNMENT_START, - yalign = hippo.ALIGNMENT_START - ) - lang = hippo.CanvasText( - text = '', - xalign = hippo.ALIGNMENT_START, - yalign = hippo.ALIGNMENT_START - ) + char_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL) + nick = hippo.CanvasText(text=buddy.props.nick, + xalign=hippo.ALIGNMENT_START, + yalign=hippo.ALIGNMENT_START) + lang = hippo.CanvasText(text='', + xalign=hippo.ALIGNMENT_START, + yalign=hippo.ALIGNMENT_START) char_box.append(nick) char_box.append(lang) @@ -226,18 +213,14 @@ class View(hippo.Canvas): buddy_face = face.View(fill_color) buddy_face.show_all() - inner = CanvasRoundBox( - background_color = fill_color.get_int(), - ) + inner = CanvasRoundBox(background_color=fill_color.get_int()) inner.props.border_color = fill_color.get_int() inner.append(hippo.CanvasWidget(widget=buddy_face), hippo.PACK_EXPAND) inner.props.border = BUDDY_PAD - outer = CanvasRoundBox( - background_color = stroke_color.get_int(), - box_width = BUDDY_SIZE, - box_height = BUDDY_SIZE, - ) + outer = CanvasRoundBox(background_color=stroke_color.get_int(), + box_width=BUDDY_SIZE, + box_height=BUDDY_SIZE) outer.props.border_color = stroke_color.get_int() outer.append(inner, hippo.PACK_EXPAND) outer.props.border = BUDDY_PAD diff --git a/espeak_cmd.py b/espeak_cmd.py index 1f50bbf..f074207 100644 --- a/espeak_cmd.py +++ b/espeak_cmd.py @@ -25,6 +25,7 @@ import espeak PITCH_MAX = 99 RATE_MAX = 99 + class AudioGrabCmd(espeak.BaseAudioGrab): def speak(self, status, text): self.make_pipeline('filesrc name=file-source') @@ -45,6 +46,7 @@ class AudioGrabCmd(espeak.BaseAudioGrab): # play self.restart_sound_device() + def voices(): out = [] result = subprocess.Popen(["espeak", "--voices"], stdout=subprocess.PIPE) \ @@ -55,7 +57,7 @@ def voices(): if not m: continue language, gender, name, stuff = m.groups() - if stuff.startswith('mb/'): #or \ + if stuff.startswith('mb/'): # or \ #name in ('en-rhotic','english_rp','english_wmids'): # these voices don't produce sound continue diff --git a/espeak_gst.py b/espeak_gst.py index a492cf6..4da4f9d 100644 --- a/espeak_gst.py +++ b/espeak_gst.py @@ -23,6 +23,7 @@ import espeak PITCH_MAX = 200 RATE_MAX = 200 + class AudioGrabGst(espeak.BaseAudioGrab): def speak(self, status, text): # XXX workaround for http://bugs.sugarlabs.org/ticket/1801 @@ -46,6 +47,7 @@ class AudioGrabGst(espeak.BaseAudioGrab): self.restart_sound_device() + def voices(): out = [] @@ -12,12 +12,12 @@ # 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/>. @@ -115,8 +115,12 @@ class Eye(gtk.DrawingArea): self.context = widget.window.cairo_create() #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) + #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.clip() # background @@ -125,13 +129,21 @@ class Eye(gtk.DrawingArea): self.context.fill() # eye ball - self.context.arc(bounds.width / 2, bounds.height / 2, eyeSize / 2 - outlineWidth / 2, 0, 360) + 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.arc(bounds.width / 2, + bounds.height / 2, + eyeSize / 2 - outlineWidth / 2, + 0, + 360) self.context.set_source_rgb(0, 0, 0) self.context.stroke() @@ -7,22 +7,22 @@ # # 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 logging +import logging import gtk import cjson @@ -40,6 +40,7 @@ logger = logging.getLogger('speak') FACE_PAD = 2 + class Status: def __init__(self): self.voice = voice.defaultVoice() @@ -50,26 +51,26 @@ class Status: self.mouth = mouth.Mouth def serialize(self): - eyes = { eye.Eye : 1, - glasses.Glasses : 2 } - mouths = { mouth.Mouth : 1, - fft_mouth.FFTMouth : 2, - waveform_mouth.WaveformMouth : 3 } + eyes = {eye.Eye: 1, + glasses.Glasses: 2} + mouths = {mouth.Mouth: 1, + fft_mouth.FFTMouth: 2, + waveform_mouth.WaveformMouth: 3} return cjson.encode({ - 'voice' : { 'language' : self.voice.language, - 'name' : self.voice.name }, - 'pitch' : self.pitch, - 'rate' : self.rate, - 'eyes' : [eyes[i] for i in self.eyes], - 'mouth' : mouths[self.mouth] }) + 'voice': {'language': self.voice.language, + 'name': self.voice.name}, + 'pitch': self.pitch, + 'rate': self.rate, + 'eyes': [eyes[i] for i in self.eyes], + 'mouth': mouths[self.mouth]}) def deserialize(self, buf): - eyes = { 1: eye.Eye, - 2: glasses.Glasses } - mouths = { 1: mouth.Mouth, - 2: fft_mouth.FFTMouth, - 3: waveform_mouth.WaveformMouth } + eyes = {1: eye.Eye, + 2: glasses.Glasses} + mouths = {1: mouth.Mouth, + 2: fft_mouth.FFTMouth, + 3: waveform_mouth.WaveformMouth} data = cjson.decode(buf) self.voice = voice.Voice(data['voice']['language'], @@ -90,6 +91,7 @@ class Status: new.mouth = self.mouth return new + class View(gtk.EventBox): def __init__(self, fill_color=style.COLOR_BUTTON_GREY): gtk.EventBox.__init__(self) @@ -142,7 +144,7 @@ class View(gtk.EventBox): x, y = pos map(lambda e, x=x, y=y: e.look_at(x, y), self._eyes) - def update(self, status = None): + def update(self, status=None): if not status: status = self.status else: @@ -169,7 +171,8 @@ class View(gtk.EventBox): self._mouth.show() self._mouthbox.add(self._mouth) - # enable mouse move events so we can track the eyes while the mouse is over the mouth + # 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): @@ -188,4 +191,5 @@ class View(gtk.EventBox): self._audio.stop_sound_device() def _size_allocate_cb(self, widget, allocation): - self._mouthbox.set_size_request(-1, int(allocation.height/2.5)) + self._mouthbox.set_size_request(-1, + int(allocation.height / 2.5)) diff --git a/fft_mouth.py b/fft_mouth.py index 53bcadf..8200ef6 100644 --- a/fft_mouth.py +++ b/fft_mouth.py @@ -7,17 +7,17 @@ # # 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/>. @@ -33,66 +33,69 @@ except: from Numeric import ceil from FFT import * + class FFTMouth(Mouth): def __init__(self, audioSource, fill_color): Mouth.__init__(self, audioSource, fill_color) - + self.peaks = [] self.y_mag = 1.7 - self.freq_range=70 + self.freq_range = 70 self.draw_interval = 1 self.num_of_points = 105 - self.stop=False + self.stop = False - self.y_mag_bias_multiplier = 1 #constant to multiply with self.param2 while scaling values + #constant to multiply with self.param2 while scaling values + self.y_mag_bias_multiplier = 1 self.fftx = [] self.scaleX = "10" self.scaleY = "10" - def processBuffer(self, bounds): - self.param1 = bounds.height/65536.0 - self.param2 = bounds.height/2.0 + self.param1 = bounds.height / 65536.0 + self.param2 = bounds.height / 2.0 - if(self.stop==False): + if(self.stop == False): Fs = 48000 - nfft= 65536 - self.newest_buffer=self.newest_buffer[0:256] - self.fftx = fft(self.newest_buffer, 256,-1) + nfft = 65536 + self.newest_buffer = self.newest_buffer[0:256] + self.fftx = fft(self.newest_buffer, 256, -1) - self.fftx=self.fftx[0:self.freq_range*2] - self.draw_interval=bounds.width/(self.freq_range*2.) + self.fftx = self.fftx[0:self.freq_range * 2] + self.draw_interval = bounds.width / (self.freq_range * 2.) - NumUniquePts = ceil((nfft+1)/2) - self.buffers=abs(self.fftx)*0.02 - self.y_mag_bias_multiplier=0.1 + NumUniquePts = ceil((nfft + 1) / 2) + self.buffers = abs(self.fftx) * 0.02 + self.y_mag_bias_multiplier = 0.1 self.scaleX = "hz" self.scaleY = "" - if(len(self.buffers)==0): + if(len(self.buffers) == 0): return False # Scaling the values val = [] for i in self.buffers: - temp_val_float = float(self.param1*i*self.y_mag) + self.y_mag_bias_multiplier * self.param2 + temp_val_float = float(self.param1 * i * self.y_mag) +\ + self.y_mag_bias_multiplier * self.param2 if(temp_val_float >= bounds.height): - temp_val_float = bounds.height-25 + temp_val_float = bounds.height - 25 if(temp_val_float <= 0): temp_val_float = 25 - val.append( temp_val_float ) + val.append(temp_val_float) self.peaks = val def expose(self, widget, event): - """This function is the "expose" event handler and does all the drawing.""" + """This function is the "expose" event + handler and does all the drawing.""" bounds = self.get_allocation() @@ -102,26 +105,32 @@ class FFTMouth(Mouth): self.context = widget.window.cairo_create() 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) + #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.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 waveform - self.context.set_line_width(min(bounds.height/10.0, 10)) - self.context.set_source_rgb(0,0,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: - self.context.line_to(bounds.width/2 + count,bounds.height/2 - peak) + self.context.line_to(bounds.width / 2 + count, + bounds.height / 2 - peak) count += self.draw_interval self.context.stroke() count = 0 for peak in self.peaks: - self.context.line_to(bounds.width/2 - count,bounds.height/2 - peak) + self.context.line_to(bounds.width / 2 - count, + bounds.height / 2 - peak) count += self.draw_interval self.context.stroke() @@ -7,17 +7,17 @@ # # 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/>. @@ -46,8 +46,12 @@ class Glasses(Eye): self.context = widget.window.cairo_create() #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) + #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.clip() # background @@ -63,13 +67,19 @@ class Glasses(Eye): self.context.curve_to(x1, y2, x1, y2, x1, (y1 + y2) / 2.) # eye ball - roundrect(outlineWidth, outlineWidth, bounds.width - outlineWidth, bounds.height - outlineWidth) + 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.stroke() diff --git a/messenger.py b/messenger.py index 14151e5..eb03bda 100644 --- a/messenger.py +++ b/messenger.py @@ -28,6 +28,7 @@ SERVICE = 'org.sugarlabs.Speak' IFACE = SERVICE PATH = '/org/sugarlabs/Speak' + class Messenger(ExportedGObject): def __init__(self, tube, is_initiator, chat): ExportedGObject.__init__(self, tube, PATH) @@ -61,10 +62,16 @@ class Messenger(ExportedGObject): if not self._entered: self.me = self._tube.get_unique_name() - self._tube.add_signal_receiver(self._ping_cb, '_ping', IFACE, path=PATH, - sender_keyword='sender') - self._tube.add_signal_receiver(self._post_cb, '_post', IFACE, path=PATH, - sender_keyword='sender') + self._tube.add_signal_receiver(self._ping_cb, + '_ping', + IFACE, + path=PATH, + sender_keyword='sender') + self._tube.add_signal_receiver(self._post_cb, + '_post', + IFACE, + path=PATH, + sender_keyword='sender') if not self.is_initiator: self._ping(self.chat.me.status.serialize()) @@ -97,7 +104,8 @@ class Messenger(ExportedGObject): tp_handle = self._tube.bus_name_to_handle[sender] buddy = self._tube.get_buddy(tp_handle) - if not buddy: return + if not buddy: + return self._buddies[tp_handle] = buddy logger.debug('ping received from %s(%s) status=%s' \ @@ -116,7 +124,7 @@ class Messenger(ExportedGObject): tp_handle = self._tube.bus_name_to_handle[sender] buddy = self._buddies[tp_handle] - logger.debug('message received from %s(%s): %s' + logger.debug('message received from %s(%s): %s' % (sender, buddy.props.nick, text)) self.chat.post(buddy, face.Status().deserialize(sender_status), text) @@ -7,17 +7,17 @@ # # 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/>. @@ -46,7 +46,8 @@ 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) - \ @@ -59,10 +60,12 @@ 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.""" + """This function is the "expose" event + handler and does all the drawing.""" bounds = self.get_allocation() self.processBuffer(bounds) @@ -71,8 +74,12 @@ class Mouth(gtk.DrawingArea): self.context = widget.window.cairo_create() 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) + # 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.clip() # background @@ -83,7 +90,7 @@ class Mouth(gtk.DrawingArea): # Draw the mouth volume = self.volume / 30000. 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 @@ -9,17 +9,17 @@ # # 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/>. @@ -7,12 +7,12 @@ # # 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 @@ -21,7 +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 re import os from gettext import gettext as _ @@ -30,8 +30,10 @@ logger = logging.getLogger('speak') import espeak -# Lets trick gettext into generating entries for the voice names we expect espeak to have -# If espeak actually has new or different names then they won't get translated, but they +# Lets trick gettext into generating entries +# for the voice names we expect espeak to have +# If espeak actually has new or different names +# then they won't get translated, but they # should still show up in the interface. expectedVoiceNames = [ _("Brazil"), @@ -72,43 +74,42 @@ expectedVoiceNames = [ _allVoices = {} _defaultVoice = None + class Voice: def __init__(self, language, name): self.language = language self.name = name friendlyname = name - friendlyname = friendlyname.replace('-test','') - friendlyname = friendlyname.replace('_test','') - friendlyname = friendlyname.replace('en-','') - friendlyname = friendlyname.replace('english-wisper','whisper') + friendlyname = friendlyname.replace('-test', '') + 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 = 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 + partsRP = re.split('[ _]', friendlynameRP) # RE for english_RP self.short_name = _(parts[0].capitalize()) self.friendlyname = ' '.join([self.short_name] + parts[1:]) - - friendlynameRP1 = None + + friendlynameRP1 = None if friendlynameRP == 'rp': - + friendlynameRP1 = 'English (Received Pronunciation)' self.friendlyname = 'English (Received 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)' - + self.friendlyname = 'English (West Midlands)' def __cmp__(self, other): return cmp(self.friendlyname, other.friendlyname if other else '') @@ -121,14 +122,14 @@ def allVoices(): for language, name in espeak.voices(): voice = Voice(language, name) _allVoices[voice.friendlyname] = voice - + 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.""" @@ -140,11 +141,11 @@ def defaultVoice(): voices = allVoices() - def fit(a,b): + def fit(a, b): "Compare two language ids to see if they are similar." - as_ = re.split(r'[^a-z]+', a.lower()) - bs = re.split(r'[^a-z]+', b.lower()) - for count in range(0, min(len(as_),len(bs))): + as_ = re.split(r'[^a-z]+', a.lower()) + bs = re.split(r'[^a-z]+', b.lower()) + for count in range(0, min(len(as_), len(bs))): if as_[count] != bs[count]: count -= 1 break @@ -157,14 +158,16 @@ def defaultVoice(): best = voices[_("Default")] for voice in voices.values(): voiceMetric = fit(voice.language, lang) - bestMetric = fit(best.language, lang) - if lang=='en_AU.UTF-8': - if voice.friendlyname=='English (Received Pronunciation)': + bestMetric = fit(best.language, lang) + if lang == 'en_AU.UTF-8': + if voice.friendlyname == 'English (Received Pronunciation)': best = voice break if voiceMetric > bestMetric: best = voice - print "Best voice for LANG %s seems to be %s %s" % (lang, best.language, best.friendlyname) - _defaultVoice = best + print "Best voice for LANG %s seems to be %s %s" % (lang, + best.language, + best.friendlyname) + _defaultVoice = best return best diff --git a/waveform_mouth.py b/waveform_mouth.py index 71a10ea..b9c4238 100644 --- a/waveform_mouth.py +++ b/waveform_mouth.py @@ -7,17 +7,17 @@ # # 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/>. @@ -25,56 +25,63 @@ from mouth import * + class WaveformMouth(Mouth): def __init__(self, audioSource, fill_color): Mouth.__init__(self, audioSource, fill_color) - + self.buffer_size = 100 self.peaks = [] - self.stop=False + self.stop = False self.y_mag_bias_multiplier = 1 self.y_mag = 0.7 def expose(self, widget, event): - """This function is the "expose" event handler and does all the drawing.""" + """This function is the "expose" + event handler and does all the drawing.""" bounds = self.get_allocation() - self.param1 = bounds.height/65536.0 - self.param2 = bounds.height/2.0 + self.param1 = bounds.height / 65536.0 + self.param2 = bounds.height / 2.0 #Create context, disable antialiasing self.context = widget.window.cairo_create() 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) + #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.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 waveform - self.context.set_line_width(min(bounds.height/10.0, 10)) + 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: - peak = float(self.param1*value*self.y_mag) + self.y_mag_bias_multiplier * self.param2 + peak = float(self.param1 * value * self.y_mag) +\ + self.y_mag_bias_multiplier * self.param2 if peak >= bounds.height: peak = bounds.height if peak <= 0: peak = 0 - - x = count / buflen * bounds.width - self.context.line_to(x,bounds.height - peak) - + + x = count / buflen * bounds.width + self.context.line_to(x, bounds. height - peak) + count += 1 - self.context.set_source_rgb(0,0,0) + self.context.set_source_rgb(0, 0, 0) self.context.stroke() return True |