2
# Project: gespeaker - A GTK frontend for espeak
3
# Author: Fabio Castelli <muflone@vbsimple.net>
4
# Copyright: 2009 Fabio Castelli
6
# This program is free software; you can redistribute it and/or modify it
7
# under the terms of the GNU General Public License as published by the Free
8
# Software Foundation; either version 2 of the License, or (at your option)
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16
# On Debian GNU/Linux systems, the full text of the GNU General Public License
17
# can be found in the file /usr/share/common-licenses/GPL-2.
22
import SubprocessWrapper
25
from gettext import gettext as _
26
from DialogSimpleMessages import ShowDialogError
27
from pygtkutils import *
29
def showPreferencesWindow(gladeFile, espeak):
30
prefsWindow = PreferencesWindow(gladeFile, espeak)
32
class PreferencesWindow(object):
33
def __init__(self, gladeFile, espeak):
34
self.gladeFile = gladeFile
37
self.dlgPrefs.set_icon_from_file(handlepaths.get_app_logo())
39
'on_cboPlayer_changed': self.on_cboPlayer_changed,
40
'on_btnPlayerTest_clicked': self.on_btnPlayerTest_clicked,
41
'on_chkCustomWelcome_toggled': self.on_chkCustomWelcome_toggled,
42
'on_btnRefresh_clicked': self.on_btnRefresh_clicked,
43
'on_btnOk_clicked': self.on_btnOk_clicked
45
self.gladeFile.signal_autoconnect(signals)
47
self.cboPlayer.set_active(Settings.get('PlayMethod'))
48
self.txtPlayerCommand.set_text(Settings.get('PlayCommand'))
49
self.chkPlayWelcome.set_active(Settings.get('PlayWelcomeText') == True)
50
self.chkCustomWelcome.set_active(Settings.get('UseCustomWelcome') == True)
51
self.txtWelcomeText.set_text(Settings.get('WelcomeText'))
52
self.chkSaveVoice.set_active(Settings.get('SaveVoiceSettings') == True)
53
self.chkSaveSize.set_active(Settings.get('SaveWindowSize') == True)
54
self.chkSingleRecord.set_active(Settings.get('SingleRecord') == True)
55
self.chkWordWrap.set_active(Settings.get('WordWrap') == True)
56
self.chkLoadVariants.set_active(Settings.get('LoadVariants') == True)
57
self.chooserLanguagePath.set_current_folder(Settings.get('VoicesmbPath'))
58
# Before to use the window property the realize method must be called
59
self.dlgPrefs.realize()
60
# Change WM buttons making the window only movable with the closing button
61
self.dlgPrefs.window.set_functions(gtk.gdk.FUNC_CLOSE | gtk.gdk.FUNC_MOVE)
62
# Reload mbrola languages list
63
self.btnRefresh.clicked()
65
self.dlgPrefs.destroy()
67
def loadControls(self):
68
def separator_filter(model, iter, data=None):
69
return model.get_value(iter, 2)
70
gw = self.gladeFile.get_widget
71
self.dlgPrefs = gw('dlgPreferences')
72
self.cboPlayer = gw('cboPlayer')
73
self.lblPlayerCommand = gw('lblPlayerCommand')
74
self.txtPlayerCommand = gw('txtPlayerCommand')
75
self.btnPlayerTest = gw('btnPlayerTest')
76
self.chkPlayWelcome = gw('chkPlayWelcome')
77
self.chkCustomWelcome = gw('chkCustomWelcome')
78
self.lblCustomWelcome = gw('lblCustomWelcome')
79
self.txtWelcomeText = gw('txtWelcomeText')
80
self.chkSaveVoice = gw('chkSaveVoice')
81
self.chkSaveSize = gw('chkSaveSize')
82
self.chkSingleRecord = gw('chkRecordSingleTrack')
83
self.chkWordWrap = gw('chkWordWrap')
84
self.chkLoadVariants = gw('chkLoadVariants')
85
self.tvwLanguages = gw('tvwLanguages')
86
self.chooserLanguagePath = gw('chooserLanguagePath')
87
self.btnRefresh = gw('btnRefresh')
88
self.btnOk = gw('btnOk')
89
self.imgExecutableMbrola = gw('imgExecutableMbrola')
90
self.lblExecutableMbrolaStatus = gw('lblExecutableMbrolaStatus')
91
self.lblLanguagesDetected = gw('lblLanguagesDetected')
92
# Prepare model for players combo
93
listStore = gtk.ListStore(gtk.gdk.Pixbuf, str, bool)
94
self.cboPlayer.set_model(listStore)
96
cell = gtk.CellRendererPixbuf()
97
self.cboPlayer.pack_start(cell, False)
98
self.cboPlayer.add_attribute(cell, 'pixbuf', 0)
100
cell = gtk.CellRendererText()
101
self.cboPlayer.pack_start(cell, False)
102
self.cboPlayer.add_attribute(cell, 'text', 1)
103
self.cboPlayer.set_row_separator_func(separator_filter)
104
# Load icons and text for methods
105
listStore.append([Pixbuf_load_file(
106
handlepaths.getPath('icons', 'alsalogo.png'), (24, 24)),
107
_('ALSA - Advanced Linux Sound Architecture'), False])
108
listStore.append([Pixbuf_load_file(
109
handlepaths.getPath('icons', 'palogo.png'), (24, 24)),
110
_('PulseAudio sound server'), False])
111
listStore.append([None, '_', True])
112
listStore.append([None, _('Custom sound application'), False])
113
# Change testing button caption
114
Button_change_stock_description(self.btnPlayerTest, _('_Test'), True)
115
# Create model and sorted model for mbrola languages
116
self.treeModel = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str)
117
#self.tvwLanguages.set_model(self.treeModel)
118
sortedModel = gtk.TreeModelSort(self.treeModel)
119
sortedModel.set_sort_column_id(1, gtk.SORT_ASCENDING)
120
self.tvwLanguages.set_model(sortedModel)
121
# Create columns for tvwLanguages
122
COL_IMG, COL_LANG, COL_RES, COL_STATUS = range(4)
123
cell = gtk.CellRendererPixbuf()
124
column = gtk.TreeViewColumn('')
125
column.pack_start(cell)
126
column.set_attributes(cell, pixbuf=COL_IMG)
127
self.tvwLanguages.append_column(column)
129
cell = gtk.CellRendererText()
130
column = gtk.TreeViewColumn(_('Language'), cell, text=COL_LANG)
131
column.set_sort_column_id(COL_LANG)
132
column.set_resizable(True)
133
self.tvwLanguages.append_column(column)
135
cell = gtk.CellRendererText()
136
column = gtk.TreeViewColumn(_('Resource'), cell, text=COL_RES)
137
column.set_sort_column_id(COL_RES)
138
column.set_resizable(True)
139
self.tvwLanguages.append_column(column)
141
cell = gtk.CellRendererText()
142
column = gtk.TreeViewColumn(_('Status'), cell, text=COL_STATUS)
143
column.set_sort_column_id(COL_STATUS)
144
column.set_resizable(True)
145
self.tvwLanguages.append_column(column)
146
# Order by Language column
147
#column = self.tvwLanguages.get_column(COL_LANG)
148
#column.set_sort_column_id(COL_LANG)
149
#column.set_sort_order(gtk.SORT_ASCENDING)
150
#column.set_sort_indicator(True)
152
def on_chkCustomWelcome_toggled(self, widget, data=None):
153
self.lblCustomWelcome.set_sensitive(self.chkCustomWelcome.get_active())
154
self.txtWelcomeText.set_sensitive(self.chkCustomWelcome.get_active())
156
def on_btnOk_clicked(self, widget, data=None):
158
Settings.set('PlayMethod', self.cboPlayer.get_active())
159
Settings.set('PlayCommand', self.txtPlayerCommand.get_text())
160
Settings.set('PlayWelcomeText', self.chkPlayWelcome.get_active())
161
Settings.set('UseCustomWelcome', self.chkCustomWelcome.get_active())
162
Settings.set('WelcomeText', self.txtWelcomeText.get_text())
163
Settings.set('SaveVoiceSettings', self.chkSaveVoice.get_active())
164
Settings.set('SaveWindowSize', self.chkSaveSize.get_active())
165
Settings.set('SingleRecord', self.chkSingleRecord.get_active())
166
Settings.set('WordWrap', self.chkWordWrap.get_active())
167
Settings.set('LoadVariants', self.chkLoadVariants.get_active())
168
Settings.set('VoicesmbPath', self.chooserLanguagePath.get_filename())
170
def on_cboPlayer_changed(self, widget, data=None):
171
"Enable and disable controls if custom command is not set"
172
active = self.cboPlayer.get_active()
173
text = self.txtPlayerCommand.get_text()
174
self.lblPlayerCommand.set_sensitive(active == 3)
175
self.txtPlayerCommand.set_sensitive(active == 3)
176
self.btnOk.set_sensitive((active != 3) or bool(text))
177
self.btnPlayerTest.set_sensitive((active != 3) or bool(text))
179
def on_btnPlayerTest_clicked(self, widget, data=None):
180
"Test selected player with testing.wav"
182
Window_change_cursor(self.dlgPrefs.window, gtk.gdk.WATCH, True)
183
players = ('aplay', 'paplay', '', self.txtPlayerCommand.get_text())
184
filename = handlepaths.getPath('data', 'testing.wav')
185
test = SubprocessWrapper.Popen(['cat', filename],
186
stdout=SubprocessWrapper.PIPE)
189
# Try to play with pipe
190
play = SubprocessWrapper.Popen(players[self.cboPlayer.get_active()],
192
stdout=SubprocessWrapper.PIPE,
193
stderr=SubprocessWrapper.PIPE)
195
except OSError, (errno, strerror):
196
# Error during communicate"
198
title=_('Audio testing'),
200
text=_('There was an error during the test for the audio player.\n\n'
201
'Error %s: %s') % (errno, strerror),
202
icon=handlepaths.get_app_logo()
204
# Terminate test if it's still running, follows a broken pipe error
205
if test.poll() is None:
207
# Restore default cursor
208
Window_change_cursor(self.dlgPrefs.window, None, False)
210
def on_btnRefresh_clicked(self, widget, data=None):
211
"Reload mbrola languages from the selected folder"
212
self.treeModel.clear()
213
selectedFolder = self.chooserLanguagePath.get_filename()
214
if not selectedFolder:
215
# Calling before the dialog is shown results in None path
216
selectedFolder = Settings.get('VoicesmbPath')
217
mbrolaVoices = self.espeak.loadMbrolaVoices(selectedFolder)
219
for voice in mbrolaVoices:
222
self.treeModel.append((
223
widget.render_icon(voice[2] and gtk.STOCK_YES or gtk.STOCK_NO,
224
gtk.ICON_SIZE_BUTTON), voice[0], voice[1],
225
voice[2] and _('Installed') or _('Not installed')))
226
# lblLanguagesDetected
227
self.lblLanguagesDetected.set_text(_("%d languages of %d detected") % (
228
voicesFound, len(mbrolaVoices)))
229
# Check if mbrola exists
230
status = self.espeak.mbrolaExists(Settings.cmdMbrola)
231
self.imgExecutableMbrola.set_from_stock(size=gtk.ICON_SIZE_BUTTON,
232
stock_id=status and gtk.STOCK_YES or gtk.STOCK_NO)
233
self.lblExecutableMbrolaStatus.set_label('<b>%s</b>' % (status and
234
_('Package mbrola installed') or _('Package mbrola not installed')))