~ubuntu-branches/ubuntu/trusty/gespeaker/trusty-proposed

« back to all changes in this revision

Viewing changes to src/PreferencesWindow.py

  • Committer: Bazaar Package Importer
  • Author(s): Fabio Castelli
  • Date: 2009-12-12 19:59:25 UTC
  • Revision ID: james.westby@ubuntu.com-20091212195925-4ze3lc6pfredpwf1
Tags: upstream-0.7
ImportĀ upstreamĀ versionĀ 0.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##
 
2
#   Project: gespeaker - A GTK frontend for espeak  
 
3
#    Author: Fabio Castelli <muflone@vbsimple.net>
 
4
# Copyright: 2009 Fabio Castelli
 
5
#   License: GPL-2+
 
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)
 
9
#  any later version.
 
10
 
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
 
14
#  more details.
 
15
 
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.
 
18
##
 
19
 
 
20
import gtk
 
21
import Settings
 
22
import SubprocessWrapper
 
23
import os.path
 
24
import handlepaths
 
25
from gettext import gettext as _
 
26
from DialogSimpleMessages import ShowDialogError
 
27
from pygtkutils import *
 
28
 
 
29
def showPreferencesWindow(gladeFile, espeak):
 
30
  prefsWindow = PreferencesWindow(gladeFile, espeak)
 
31
 
 
32
class PreferencesWindow(object):
 
33
  def __init__(self, gladeFile, espeak):
 
34
    self.gladeFile = gladeFile
 
35
    self.espeak = espeak
 
36
    self.loadControls()
 
37
    self.dlgPrefs.set_icon_from_file(handlepaths.get_app_logo())
 
38
    signals = {
 
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
 
44
    }
 
45
    self.gladeFile.signal_autoconnect(signals)
 
46
    # Load settings
 
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()
 
64
    self.dlgPrefs.run()
 
65
    self.dlgPrefs.destroy()
 
66
 
 
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)
 
95
    # First is image
 
96
    cell = gtk.CellRendererPixbuf()
 
97
    self.cboPlayer.pack_start(cell, False)
 
98
    self.cboPlayer.add_attribute(cell, 'pixbuf', 0)
 
99
    # Second is text
 
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)
 
128
    
 
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)
 
134
 
 
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)
 
140
 
 
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)
 
151
 
 
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())
 
155
 
 
156
  def on_btnOk_clicked(self, widget, data=None):
 
157
    "Apply settings"
 
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())
 
169
 
 
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))
 
178
 
 
179
  def on_btnPlayerTest_clicked(self, widget, data=None):
 
180
    "Test selected player with testing.wav"
 
181
    # Set waiting cursor
 
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)
 
187
    play = None
 
188
    try:
 
189
      # Try to play with pipe
 
190
      play = SubprocessWrapper.Popen(players[self.cboPlayer.get_active()], 
 
191
        stdin=test.stdout,
 
192
        stdout=SubprocessWrapper.PIPE,
 
193
        stderr=SubprocessWrapper.PIPE)
 
194
      play.communicate()
 
195
    except OSError, (errno, strerror):
 
196
      # Error during communicate"
 
197
      ShowDialogError(
 
198
        title=_('Audio testing'),
 
199
        showOk=True,
 
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()
 
203
      )
 
204
    # Terminate test if it's still running, follows a broken pipe error
 
205
    if test.poll() is None:
 
206
      test.terminate()
 
207
    # Restore default cursor
 
208
    Window_change_cursor(self.dlgPrefs.window, None, False)
 
209
 
 
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)
 
218
    voicesFound = 0
 
219
    for voice in mbrolaVoices:
 
220
      if voice[2]:
 
221
        voicesFound += 1
 
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')))