4 # Praat script handling configuration page
6 # SpeakGoodChinese: Config.praat loads the code needed for the
7 # settings and the Settings page of SpeakGoodChinese.
9 # Copyright (C) 2007-2010 R.J.J.H. van Son
10 # The SpeakGoodChinese team are:
11 # Guangqin Chen, Zhonyan Chen, Stefan de Koning, Eveline van Hagen,
12 # Rob van Son, Dennis Vierkant, David Weenink
14 # This program is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29 ###############################################################
31 # Button Drawing Routines
33 ###############################################################
35 procedure DrawCredits .color$ .x .y .size
38 call adjustFontSizeOnHeight 24 '.lineheight'
39 .currentFontSize = adjustFontSizeOnHeight.newFontSize
40 demo Paint circle... {0.2,0.2,0.8} '.x' '.y' '.size'
42 demo Text special... '.x' centre '.y' half Times '.currentFontSize' 0 i
45 call set_font_size 'defaultFontSize'
48 procedure DrawDeleteList .color$ .x .y .size
54 demo Paint rectangle... White '.leftX' '.rightX' '.botY' '.topY'
57 .displayWordList$ = replace_regex$(wordlistName$, "[_]", " ", 0)
60 .maxWidth = (.rightX - .leftX)
61 .currentFontSize = defaultFontSize
62 call adjustFontSizeOnWidth '.currentFontSize' '.maxWidth' '.displayWordList$'
63 .currentFontSize = adjustFontSizeOnWidth.newFontSize
64 call set_font_size '.currentFontSize'
66 demo Text... '.x' Centre '.botY' Bottom '.displayWordList$'
69 call set_font_size 'defaultFontSize'
72 procedure DrawLogging .color$ .x .y .size
76 .color$ = "{0.5,0.5,1}"
80 demo Paint circle... '.color$' '.x' '.y' '.size'
83 ###############################################################
85 # Obligatory button Drawing Routines
87 # These MUST be defined
89 ###############################################################
91 procedure DrawReturn .color$ .x .y .size
92 call DrawConfig '.color$' '.x' '.y' '.size'
95 # Set the correct button states after redrawing hte window
96 procedure setConfigButtons
97 call Draw_button 'config$' Lang_'language$' 2
98 call Draw_button 'config$' Register_'register' 2
100 call Draw_button 'config$' DisplayNumbers 2
103 call Draw_button 'config$' DisplayPinyin 2
106 call Draw_button 'config$' DisplayChar 2
109 call Draw_button 'config$' Shuffle 2
112 call Draw_button 'config$' SndExample 2
115 call Draw_button 'config$' Precision 2
117 call Draw_button 'config$' Input'soundInput$' 2
118 # Handle logging buttons with forced button draw
119 if fileReadable("'preferencesLogDir$'/logPerformance.txt")
120 call Draw_button 'config$' +!Logging 'logPerformance'
124 ###############################################################
126 # Button Processing Routines
128 ###############################################################
130 procedure processConfigShuffle .clickX .clickY .pressed$
133 shuffleLists = not shuffleLists
134 .displayButton = 2*shuffleLists
135 call Draw_button '.table$' '.label$' '.displayButton'
138 procedure processConfigSndExample .clickX .clickY .pressed$
140 .label$ = "SndExample"
141 useSoundExample = not useSoundExample
142 .displayButton = 2*useSoundExample
143 call Draw_button '.table$' '.label$' '.displayButton'
146 procedure processConfigPrecision .clickX .clickY .pressed$
148 .label$ = "Precision"
156 call Draw_button '.table$' '.label$' '.displayButton'
159 procedure processConfigDisplayPinyin .clickX .clickY .pressed$
161 .label$ = "DisplayPinyin"
162 displayPinyin = not displayPinyin
163 .displayButton = 2*displayPinyin
164 call Draw_button '.table$' '.label$' '.displayButton'
167 procedure processConfigDisplayChar .clickX .clickY .pressed$
169 .label$ = "DisplayChar"
170 displayChar = not displayChar
171 .displayButton = 2*displayChar
172 call Draw_button 'table$' '.label$' '.displayButton'
175 procedure processConfigDisplayNumbers .clickX .clickY .pressed$
177 .label$ = "DisplayNumbers"
178 displayNumbers = not displayNumbers
179 .displayButton = 2*displayNumbers
180 call Draw_button 'table$' '.label$' '.displayButton'
183 procedure processConfigLang .language$ .clickX .clickY .pressed$
185 .label$ = "Lang_'.language$'"
186 call processLanguageCodes '.table$' '.label$'
189 procedure processConfigLang_EN .clickX .clickY .pressed$
192 call processLanguageCodes '.table$' '.label$'
195 procedure processConfigLang_NL .clickX .clickY .pressed$
198 call processLanguageCodes '.table$' '.label$'
201 procedure processConfigInputMicrophone .clickX .clickY .pressed$
203 .label$ = "InputMicrophone"
204 call Draw_button '.table$' Input'soundInput$' 0
205 call Draw_button '.table$' '.label$' 2
206 .numChars = length(.label$) - length("Input")
207 soundInput$ = right$(.label$, .numChars)
210 procedure processConfigInputLine .clickX .clickY .pressed$
212 .label$ = "InputLine"
213 call Draw_button '.table$' Input'soundInput$' 0
214 call Draw_button '.table$' '.label$' 2
215 .numChars = length(.label$) - length("Input")
216 soundInput$ = right$(.label$, .numChars)
219 procedure processConfigRegister .register .clickX .clickY .pressed$
221 .label$ = "Register_'.register'"
222 call setRegisterFromLabel '.table$' '.label$'
225 procedure processConfigRegister_350 .clickX .clickY .pressed$
227 .label$ = "Register_350"
228 call setRegisterFromLabel '.table$' '.label$'
231 procedure processConfigRegister_300 .clickX .clickY .pressed$
233 .label$ = "Register_300"
234 call setRegisterFromLabel '.table$' '.label$'
237 procedure processConfigRegister_250 .clickX .clickY .pressed$
239 .label$ = "Register_250"
240 call setRegisterFromLabel '.table$' '.label$'
243 procedure processConfigRegister_249 .clickX .clickY .pressed$
245 .label$ = "Register_249"
246 call setRegisterFromLabel '.table$' '.label$'
249 procedure processConfigRegister_180 .clickX .clickY .pressed$
251 .label$ = "Register_180"
252 call setRegisterFromLabel '.table$' '.label$'
255 procedure processConfigRegister_150 .clickX .clickY .pressed$
257 .label$ = "Register_150"
258 call setRegisterFromLabel '.table$' '.label$'
261 procedure setRegisterFromLabel .table$ .label$
262 call Draw_button '.table$' Register_'register' 0
263 call Draw_button '.table$' '.label$' 2
264 # Someone might have to use more than 3 chars for the register code
265 .numChars = length(.label$) - length("Register_")
266 .registerText$ = right$(.label$, .numChars)
267 register = '.registerText$'
270 procedure processConfigDeleteWordlist .clickX .clickY .pressed$
272 .label$ = "DeleteWordlist"
273 call findLabel '.table$' !'.label$'
275 select Table '.table$'
276 .alertText$ = Get value... 'findLabel.row' Text
277 .confirmKey$ = Get value... 'findLabel.row' Key
279 exit Cannot find delete directive: '.table$' !'.label$'
281 call Draw_button '.table$' '.label$' 2
282 alertText$ = .alertText$
283 call Draw_button '.table$' '.label$' 3
285 # Wait for confirmation
287 if demoInput(.confirmKey$)
288 .deleteWordListDir$ = wordlistName$
289 call load_word_list "'localWordlistDir$'" 1
290 call removeWordlist '.deleteWordListDir$'
292 call Draw_button '.table$' '.label$' 0
295 procedure processConfigInstallWordlist .clickX .clickY .pressed$
297 .label$ = "InstallWordlist"
298 call Draw_button '.table$' '.label$' 1
299 call sgc2wordlist 'homeDirectory$'
300 call sgc2wordlist 'homeDirectory$'/Downloads
301 call sgc2wordlist 'homeDirectory$'/Desktop
302 call sgc2wordlist 'preferencesDirectory$'/sgc2
303 call Draw_button '.table$' '.label$' 0
306 ###############################################################
308 # Obligatory button Processing Routines
310 # These MUST be defined
312 ###############################################################
314 procedure processConfigReturn .clickX .clickY .pressed$
317 call Draw_button '.table$' '.label$' 1
318 call write_preferences ""
321 procedure processConfigRefresh .clickX .clickY .pressed$
324 call Draw_config_page
327 procedure processConfigCredits .clickX .clickY .pressed$
330 call Draw_button '.table$' '.label$' 1
331 call write_text_table Credits_EN
333 call Draw_button '.table$' '.label$' 0
335 call Draw_config_page
338 procedure processConfigHelp .clickX .clickY .pressed$
341 call help_loop '.table$' Draw_config_page
344 ###############################################################
346 # Miscelaneous supporting code
348 ###############################################################
349 # Word lists: It is a VERY good idea to make sure that word-lists
351 procedure load_word_list .localdir$ .relnumber
352 # Remove old word list
354 select Table 'wordlist$'
356 call wipeArea 'wipeWordlistArea$'
360 # Create Table that will recieve the wordlists and directories
361 Create Table with column names... AllWordLists 0 Name Directory
362 .currentWordlistRow = 0
364 # Start with the word lists in the distribution, unless the local directory exists!
365 if not fileReadable(.localdir$)
366 call CreateCreateWordlists
367 select Table CreateWordlists
368 .numLists = Get number of rows
370 select Table CreateWordlists
371 .currentName$ = Get value... '.i' Name
372 .currentDirectory$ = "*call Create'.currentName$'"
373 select Table AllWordLists
375 .currentWordlistRow = Get number of rows
376 Set string value... '.currentWordlistRow' Name '.currentName$'
377 .currentDirectory$ = "*call Create'.currentName$'"
378 Set string value... '.currentWordlistRow' Directory '.currentDirectory$'
380 select Table CreateWordlists
384 # First the clobal word lists
385 if fileReadable(globalwordlists$)
386 Create Strings as directory list... WordList 'globalwordlists$'
387 .numLists = Get number of strings
389 select Strings WordList
390 .currentName$ = Get string... '.i'
391 select Table AllWordLists
393 .currentWordlistRow = Get number of rows
394 Set string value... '.currentWordlistRow' Name '.currentName$'
395 .currentDirectory$ = globalwordlists$+"/"+.currentName$
396 Set string value... '.currentWordlistRow' Directory '.currentDirectory$'
398 select Strings WordList
402 # Now the preferences word lists
403 if fileReadable(sgc2wordlists$)
404 Create Strings as directory list... WordList 'sgc2wordlists$'
405 .numLists = Get number of strings
407 select Strings WordList
408 .currentName$ = Get string... '.i'
409 select Table AllWordLists
411 .currentWordlistRow = Get number of rows
412 Set string value... '.currentWordlistRow' Name '.currentName$'
413 .currentDirectory$ = sgc2wordlists$+"/"+.currentName$
414 Set string value... '.currentWordlistRow' Directory '.currentDirectory$'
416 select Strings WordList
420 # Finally, the local word lists
421 if fileReadable(.localdir$)
422 Create Strings as directory list... WordList '.localdir$'
423 .numLists = Get number of strings
425 select Strings WordList
426 .currentName$ = Get string... '.i'
427 select Table AllWordLists
429 .currentWordlistRow = Get number of rows
430 Set string value... '.currentWordlistRow' Name '.currentName$'
431 .currentDirectory$ = .localdir$+"/"+.currentName$
432 Set string value... '.currentWordlistRow' Directory '.currentDirectory$'
434 select Strings WordList
438 # Get the position of the current word list
439 select Table AllWordLists
441 .numLists = Get number of rows
442 if wordlistName$ <> ""
443 select Table AllWordLists
444 .currentNumber = Search column... Name 'wordlistName$'
446 wordlistNum = .currentNumber + .relnumber
447 if wordlistNum > .numLists
449 elsif wordlistNum < 1
450 wordlistNum = .numLists
452 select Table AllWordLists
453 wordlistName$ = Get value... 'wordlistNum' Name
454 .dirWordlistName$ = Get value... 'wordlistNum' Directory
455 .dirString$ = replace_regex$(.dirWordlistName$, "[ ]", "&", 0)
457 # Read in full tables
458 if fileReadable("'.dirString$'/wordlist.Table")
459 Read from file... '.dirString$'/wordlist.Table
460 Rename... 'wordlistName$'
461 # Praat wil change the name if it feels like it
462 wordlist$ = selected$("Table")
463 # Handle (legacy) simple word lists
464 elsif fileReadable("'.dirString$'/wordlist.txt")
465 Create Table with column names... "'wordlistName$'" 0 Pinyin Character Sound
466 wordlist$ = selected$("Table")
467 Read Strings from raw text file... '.dirString$'/wordlist.txt
468 Rename... RawWordList
469 .numWordStrings = Get number of strings
470 for .i to .numWordStrings
471 select Strings RawWordList
472 .currentLine$ = Get string... '.i'
473 .currentPinyin$ = extractWord$(.currentLine$, "")
474 if length(.currentLine$) > length(.currentPinyin$)+1
475 .currentFile$ = right$(.currentLine$, length(.currentPinyin$)+1)
476 elsif fileReadable("'.dirString$'/'.currentPinyin$'.spx")
477 .currentFile$ = .currentPinyin$+".spx"
478 elsif fileReadable("'.dirString$'/'.currentPinyin$'.flac")
479 .currentFile$ = .currentPinyin$+".flac"
480 elsif fileReadable("'.dirString$'/'.currentPinyin$'.wav")
481 .currentFile$ = .currentPinyin$+".wav"
482 elsif fileReadable("'.dirString$'/'.currentPinyin$'.mp3")
483 .currentFile$ = .currentPinyin$+".mp3"
487 select Table 'wordlist$'
489 Set string value... '.i' Pinyin '.currentPinyin$'
490 Set string value... '.i' Character -
491 Set string value... '.i' Sound '.currentFile$'
493 select Strings RawWordList
496 select Table 'wordlist$'
497 elsif fileReadable(.dirString$)
498 Create Table with column names... "'wordlistName$'" 0 Pinyin Character Sound
499 wordlist$ = selected$("Table")
500 Create Strings as file list... RawWordList '.dirString$'/*
501 .numWordStrings = Get number of strings
503 for .j to .numWordStrings
504 select Strings RawWordList
505 .currentLine$ = Get string... '.j'
506 .currentFile$ = extractWord$(.currentLine$, "")
507 if index_regex(.currentFile$, "\.(spx|flac|wav|mp3)")
508 .currentPinyin$ = left$(.currentFile$, index(.currentFile$, ".")-1)
509 select Table 'wordlist$'
512 Set string value... '.i' Pinyin '.currentPinyin$'
513 Set string value... '.i' Character -
514 Set string value... '.i' Sound '.currentFile$'
517 select Strings RawWordList
520 select Table 'wordlist$'
521 elsif startsWith(.dirString$, "*call ")
522 .callProcedure$ = right$(.dirString$, length(.dirString$)-1)
524 wordlist$ = selected$("Table")
527 numberOfWords = Get number of rows
533 select Table AllWordLists
536 # There were no Word Lists
539 wordlistName$ = "No Word Lists available"
541 Create Table with column names... "'wordlistName$'" 0 Pinyin Character Sound
542 wordlist$ = selected$("Table")
546 Set string value... '.i' Pinyin ni3hao3
547 Set string value... '.i' Character -
548 Set string value... '.i' Sound -
551 Set string value... '.i' Pinyin xie4xie0
552 Set string value... '.i' Character -
553 Set string value... '.i' Sound -
556 Set string value... '.i' Pinyin zai4jian4
557 Set string value... '.i' Character -
558 Set string value... '.i' Sound -
559 numberOfWords = Get number of rows
562 call set_window_title 'buttons$' 'wordlistName$'
565 procedure display_word_list_name
569 .displayWordList$ = replace_regex$(wordlistName$, "[_]", " ", 0)
570 call wipeArea 'wipeWordlistArea$'
571 call adjustFontSizeOnHeight 'defaultFontSize' 5
572 .currentFontSize = adjustFontSizeOnHeight.newFontSize
575 demo Text special... '.xtext' Centre '.ytext' Bottom Helvetica '.currentFontSize' 0 '.displayWordList$'
578 call set_font_size 'defaultFontSize'
581 procedure write_word_list
583 call draw_tone_contour
585 # Write current Pinyin text
586 call display_text Black
588 # Write the current word list name
589 call display_word_list_name
592 procedure start_logging
593 if fileReadable("'preferencesLogDir$'/logPerformance.txt")
594 .logDirectory$ < 'preferencesLogDir$'/logPerformance.txt
595 .logDirectory$ = extractWord$(.logDirectory$, "")
596 if .logDirectory$ = "" or not fileReadable(.logDirectory$)
597 .logDirectory$ = "'preferencesDirectory$'/sgc2/log"
599 createDirectory("'.logDirectory$'/sgc2log")
600 currentLogDirectory$ = "'.logDirectory$'/sgc2log/log'logtimeStamp$'"
601 createDirectory(currentLogDirectory$)
602 if not fileReadable("'currentLogDirectory$'/wordlist.Table")
603 .headerLine$ = "Pinyin'tab$'Character'tab$'Sound'newline$'"
604 .headerLine$ > 'currentLogDirectory$'/wordlist.Table
611 procedure log_performance .recordedSound$ .register .precision .pinyin$ .choice$
613 .currentDate$ = date$()
614 .timeStamp$ = replace_regex$(.currentDate$, "[^a-zA-Z0-9\-_]", "-", 0)
615 .choiceText$ = replace_regex$(.choice$, "[^a-zA-Z0-9\-_]", "-", 0)
617 if logPerformance and fileReadable("'preferencesLogDir$'/logPerformance.txt")
618 .outfilename$ = .pinyin$+"_"+.choice$+"_'.register'_"+.timeStamp$+".wav"
619 .logtext$ = .pinyin$+tab$+.choice$+tab$+"'.register'Hz"+tab$+.currentDate$+tab$+.outfilename$+newline$
621 fileappend 'currentLogDirectory$'/logFile.txt '.logtext$'
623 fileappend 'currentLogDirectory$'/wordlist.Table '.pinyin$''tab$''.choice$''tab$''.outfilename$''newline$'
625 select Sound 'recordedSound$'
626 Write to WAV file... 'currentLogDirectory$'/'.outfilename$'
630 procedure paint_logging_light
632 .row = Search column... Label !Logging
634 exit Button Table Config does not have a row with label !Logging
637 .leftX = Get value... '.row' LeftX
638 .rightX = Get value... '.row' RightX
639 .lowY = Get value... '.row' LowY
640 .highY = Get value... '.row' HighY
641 .buttonColor$ = Get value... '.row' Color
642 .centerX = (.leftX + .rightX)/2
643 .centerY = (.lowY + .highY)/2
644 .radius = (.highY - .lowY )/(4*2)
645 .wipeRadius = 1.1*.radius
646 if logPerformance and fileReadable("'preferencesLogDir$'/logPerformance.txt")
647 demo Paint circle... White '.centerX' '.centerY' '.wipeRadius'
648 demo Paint circle... '.buttonColor$' '.centerX' '.centerY' '.radius'
651 demo Paint circle... White '.centerX' '.centerY' '.wipeRadius'
656 # Uninstall word lists
657 procedure removeWordlist .deletedWordlistName$
659 if fileReadable("'preferencesDirectory$'/sgc2/wordlists/'.deletedWordlistName$'")
660 .targetDir$ = "'preferencesDirectory$'/sgc2/wordlists/'.deletedWordlistName$'"
661 elsif fileReadable("'localWordlistDir$'/'.deletedWordlistName$'")
662 .targetDir$ = "'localWordlistDir$'/'.deletedWordlistName$'"
664 Create Strings as file list... DeleteList '.targetDir$'/*
665 .numdeleteFiles = Get number of strings
666 for .i to .numdeleteFiles
667 .file$ = Get string... '.i'
668 deleteFile("'.targetDir$'/'.file$'")
670 deleteFile("'.targetDir$'")
674 procedure sgc2wordlist .sourceDir$
675 if startsWith(.sourceDir$, "preferencesDirectory$")
676 .sourceDir$ = replace$(.sourceDir$, "preferencesDirectory$", preferencesDirectory$)
679 .targetDirectory$ = "'preferencesDirectory$'/sgc2/wordlists"
680 if fileReadable(.sourceDir$)
681 Create Strings as file list... PackageList '.sourceDir$'/*.sgc
682 .numFiles = Get number of strings
684 select Strings PackageList
685 .file$ = Get string... '.i'
686 .dirname$ = left$(.file$, index(.file$, ".sgc")-1)
687 .wordlistDirectory$ = .targetDirectory$+"/"+.dirname$
688 if not (fileReadable(.dirname$) or fileReadable(.wordlistDirectory$))
689 createDirectory(.wordlistDirectory$)
691 system cp ''.sourceDir$'/'.file$'' ''.wordlistDirectory$'/'
692 system cd ''.wordlistDirectory$'';unzip ''.file$'';rm ''.file$''
696 # printline '.dirname$' already exists
700 select Strings PackageList