Adapted buttons and scaled fonts and buttons
[sgc2.git] / sgc2.praat
blobec2b118812a0dfcbff4ee4359fc6fab44fe6f786
2 # SpeakGoodChinese 2.0
3
4 # Master Praat script
6 #     SpeakGoodChinese: sgc2.praat is the master GUI of SpeakGoodChinese
7 #     It is written in Praat script for the Demo window 
8 #     
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
13
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.
18
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.
23
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
27
28 include ToneProt/ToneRecognition.praat
30 demo Select outer viewport... 0 100 0 100
31 demo Axes... 0 100 0 100
33 # Initialize parameters
34 currentWord = 1
35 pinyin$ = ""
36 character$ = ""
37 sampleSound$ = ""
38 buttons$ = ""
39 config$ = ""
40 wordlistNum = 1
41 wordlistName$ = ""
42 wordlist$ = ""
43 wordlistDir$ = "wordlists"
44 displayPinyin = 1
45 displayChar = 1
46 useSoundExample = 1
48 language$ = "EN"
49 register = 180
50 precision = 3
51 logPerformance = 0
52 logDir$ = "'preferencesDirectory$'/log"
53 sgc2wordlists$ = "'preferencesDirectory$'/sgc2/wordlists"
54 shuffleLists = 1
55 defaultFontSize = 10
56 defaultFont$ = "Helvetica"
57 defaultLineWidth = 1
59 call set_up_directories
60 call read_preferences ""
62 # Set inital language
63 call set_language 'language$'
64 # Get the word-list
65 call load_word_list "'preferencesDirectory$'/sgc2/wordlists" "'wordlistDir$'" 0
66 # Draw inital window
67 call init_window
69 while demoWaitForInput()
70         .label$ = ""
71         if demoClicked()
72                 .clickX = demoX()
73                 .clickY = demoY()
74                 call buttonClicked 'buttons$' '.clickX' '.clickY'
75                 .label$ = buttonClicked.label$
76         elsif demoKeyPressed()
77                 .pressed$ = demoKey$()
78                 call keyPressed 'buttons$' '.pressed$'
79                 .label$ = keyPressed.label$
80         endif
81         
82         # Do things
83         if .label$ != ""
84                 # Push button down
85                 call Draw_button 'buttons$' '.label$' 1
86                 call process_label '.label$'
87                 # push button up
88                 call Draw_button 'buttons$' '.label$' 0
89         endif
90 endwhile
92 call end_program
95 ########################################################
96
97 # Definitions of procedures
98
99 ########################################################
101 # Do what is asked
102 procedure process_label .label$
103         if .label$ = "Quit"
104                 call end_program
105         elsif .label$ = "Config"
106                 call config_page
107         elsif .label$ = "Refresh"
108                 call init_window
109         elsif .label$ = "Record"
110         call record_sound
111         call recognizeTone
112         call write_feedback Feedback
113         elsif .label$ = "Play"
114         call play_sound 'sampleSound$'
115         elsif .label$ = "Example"
116                 call generate_example
117         elsif .label$ = "Previous"
118                 call display_text Grey
119                 currentWord -= 1
120                 call display_text Black
121                 # Draw the contour
122                 call draw_tone_contour
123         elsif .label$ = "Next"
124                 call display_text Grey
125                 currentWord += 1
126                 call display_text Black
127                 # Draw the contour
128                 call draw_tone_contour
129         elsif .label$ = "Wordlist"
130         call load_word_list "'preferencesDirectory$'/sgc2/wordlists" "'wordlistDir$'" 1
131                 call write_word_list
132         endif
133 endproc
137 # Initialize Demo Window
138 procedure init_window
139     demo Erase all
140     demoWindowTitle("Speak Good Chinese: Practice your tones")
141         demo Line width... 'defaultLineWidth'
142         demo 'defaultFont$'
143         demo 'defaultFontSize'
144         demo Black
145     demo Select outer viewport... 0 100 0 100
146     demo Axes... 0 100 0 100
147     # Define buttons in a table
148     call init_buttons
149         # Display the word-list
150         call write_word_list
151 endproc
153 # Intialize buttons
154 procedure init_buttons
155         call Draw_all_buttons 'buttons$'
156 endproc
158 # Draw all buttons
159 procedure Draw_all_buttons .table$
160         select Table '.table$'
161         .numRows = Get number of rows
162         
163         for .row to .numRows
164                 .label$ = Get value... '.row' Label
165                 call Draw_button '.table$' '.label$' 0
166         endfor
167 endproc
169 # Draw a button from a predefined button table
170 procedure Draw_button .table$ .label$ .push
171     select Table '.table$'
172     .row = Search column... Label '.label$'
173         if .row < 1
174                 exit Button Table '.table$' does not have a row with label '.label$'
175         endif
176         
177         # Set drawing parameters
178         .topBackGroundColorUp$ = "{0.97,0.97,0.97}"
179         .topLineColorUp$ = "Black"
180         .topLineWidthUp = 1.5
181         .topBackGroundColorDown$ = "{0.92,0.92,0.92}"
182         .topLineColorDown$ = "Grey"
183         .topLineWidthDown = 1.5
184         .flankBackGroundColorUp$ = "Silver"
185         .flankLineColorUp$ = "Black"
186         .flankLineWidthUp = 1.5
187         .flankBackGroundColorDown$ = "White"
188         .flankLineColorDown$ = "Black"
189         .flankLineWidthDown = 1.5
190         .buttonFontSize = defaultFontSize
191         
192         # Get button values
193     .leftX = Get value... '.row' LeftX
194     .rightX = Get value... '.row' RightX
195     .lowY = Get value... '.row' LowY
196     .highY = Get value... '.row' HighY
197     .buttonText$ = Get value... '.row' Text
198     .buttonColor$ = Get value... '.row' Color
199     .buttonDraw$ = Get value... '.row' Draw
200     .buttonKey$ = Get value... '.row' Key
201         
202         # Adapt size of button to length of text
203         demo Font size... '.buttonFontSize'
204         .buttonTextWidth = demo Text width (wc)... '.buttonText$'
205         .count = 0
206         while (.rightX - .leftX) < .buttonTextWidth + 2
207                 if .buttonFontSize > 6
208                         .buttonFontSize -= 1
209                         demo Font size... '.buttonFontSize'
210                 else
211                         .diff = (.buttonTextWidth + 2 - (.rightX - .leftX))/2
212                         .rightX += .diff
213                         .leftX -= .diff
214                         goto BUTTONADAPTED
215                 endif
216                 .buttonTextWidth = demo Text width (wc)... '.buttonText$'
217                 .count += 1
218                 if .count > 30
219                         goto BUTTONADAPTED
220                 endif
221         endwhile
222         label BUTTONADAPTED
223         .rightX = round(.rightX)
224         .leftX = round(.leftX)
225         
226         # Reset and erase button area
227     demo Select outer viewport... 0 100 0 100
228     demo Axes... 0 100 0 100
229     demo Line width... 'defaultLineWidth'
230         demo Paint rectangle... White .leftX .rightX .lowY .highY
231         
232     # Give some depth to button: Draw flank outline
233     .shiftX = -0.10
234     .shiftY = -0.30
235     .shiftLeftX = .leftX + .shiftX
236     .shiftRightX = .rightX + .shiftX
237     .shiftLowY = .lowY + .shiftY
238     .shiftHighY = .highY + .shiftY
239         if .push <= 0
240         demo Paint rounded rectangle... '.flankBackGroundColorUp$' .shiftLeftX .shiftRightX .shiftLowY .shiftHighY 3
241                 demo Colour... '.flankLineColorUp$'
242         demo Line width... '.flankLineWidthUp'
243         else
244         demo Paint rounded rectangle... '.flankBackGroundColorDown$' .shiftLeftX .shiftRightX .shiftLowY .shiftHighY 3
245                 demo Colour... '.flankLineColorDown$'
246         demo Line width... '.flankLineWidthDown'
247         endif
248     demo Draw rounded rectangle... .shiftLeftX .shiftRightX .shiftLowY .shiftHighY 3
249         
250     # Draw the button top
251         if .push <= 0
252         demo Paint rounded rectangle... '.topBackGroundColorUp$' .leftX .rightX .lowY .highY 3
253                 demo Colour... '.topLineColorUp$'
254         demo Line width... '.topLineWidthUp'
255         else
256         demo Paint rounded rectangle... '.topBackGroundColorDown$' .leftX .rightX .lowY .highY 3
257                 demo Colour... '.topLineColorDown$'
258         demo Line width... '.topLineWidthDown'
259         endif
260     demo Draw rounded rectangle... .leftX .rightX .lowY .highY 3
261    
262     # The button text and symbol
263     .centerX = (.leftX + .rightX)/2
264     .centerY = (.lowY + .highY)/2
265     .radius = (.highY - .lowY )/4
266         .newText$ = replace_regex$(.buttonText$, "['.buttonKey$']", "#%&", 1)
267         if .newText$ = ""
268                 .newText$ = .buttonText$
269         endif
270         if .push = 1
271                 demo Grey
272                 if .buttonColor$ = "Red"
273                         .buttonColor$ = "Pink"
274                 else
275                         .buttonColor$ = "Grey"
276                 endif
277     elsif .push = 2
278         .buttonColor$ = "Maroon"
279         else
280         demo Colour... Black
281         endif
282     
283     demo Colour... '.buttonColor$'
284         demo Font size... '.buttonFontSize'
285     demo Text... '.centerX' Centre '.lowY' Bottom '.newText$'
286         demo Font size... 'defaultFontSize'
287     .centerY += 1
288     call '.buttonDraw$' '.buttonColor$' '.centerX' '.centerY' '.radius' 
289         
290         # Reset
291     demo Black
292     demo Line width... 'defaultLineWidth'
293         demoShow()
294 endproc
296 # Text display
297 procedure display_text .color$
298         select Table 'wordlist$'
299         if currentWord < 0 or currentWord > numberOfWords+1
300         if shuffleLists
301                     Randomize rows
302         endif
303                 if currentWord < 0
304                         currentWord = numberOfWords
305                 else
306                         currentWord = 1
307                 endif
308         endif
309         
310         if currentWord > 0 and currentWord <= numberOfWords
311                 .displayText$ = ""
312                 .displayPinyin$ = Get value... 'currentWord' Pinyin
313                 .displayChar$ = Get value... 'currentWord' Character
314                 if .displayPinyin$ <> "-" and displayPinyin
315                         .displayText$ = .displayText$ + .displayPinyin$
316                 endif
317                 if .displayChar$ <> "-" and displayChar
318                         .displayText$ = .displayText$ + " "+ .displayChar$
319                 endif
320         elsif currentWord = 0 or currentWord = numberOfWords+1
321                 .displayText$ = "---"
322         endif
323         demo Paint rectangle... White 20 80 25 40
324     demo Paint rectangle... White 10 90 19 30
325         demo '.color$'
326         demo Font size... 24
327         demo Text... 50 Centre 25 Bottom '.displayText$'
328         demo Black
329         demo 'defaultFont$'
330         demo 'defaultFontSize'
331         demoShow()
332 endproc
334 # The example
335 procedure generate_example
336         select Table 'wordlist$'
337         if currentWord > 0 and currentWord <= numberOfWords
338                 select Table 'wordlist$'
339                 .sound$ = Get value... 'currentWord' Sound
340                 .pinyin$ = Get value... 'currentWord' Pinyin
341                 .soundFilePath$ = wordlistDir$+"/"+wordlistName$+"/"+.sound$
342                 if fileReadable("'sgc2wordlists$'/'wordlistName$'/'.sound$'")
343                         .soundFilePath$ = "'sgc2wordlists$'/'wordlistName$'/'.sound$'"
344                 endif
345                 if fileReadable(.soundFilePath$) and useSoundExample
346                         Read from file... '.soundFilePath$'
347                         Play
348                         Remove
349                 else
350                         execute "ToneProt/HumToneContour.praat" '.pinyin$' 'register'
351                 endif
352         endif
353         demoShow()
354 endproc
357 ###############################################################
359 # Button Drawing Routines
361 ###############################################################
363 # A stub for buttons that do not have a drawing routine (yet)
364 procedure DrawNull .color$ .x .y .size
365 endproc
367 procedure DrawRecord .color$ .x .y .size
368         .size /= 2
369     demo Paint circle... '.color$' '.x' '.y' '.size'
370 endproc
372 procedure DrawPlay .color$ .x .y .size
373         demo '.color$'
374         call drawTriangle 1 .x .y .size
375 endproc
377 procedure DrawPrevious .color$ .x .y .size
378         demo '.color$'
379         .size *= 2/3
380         call drawTriangle -1 .x .y .size
381         .currentX = drawTriangle.currentX
382         .endX = .currentX - 0.5
383         .lowY = .y - .size
384         .highY = .y + .size
385         demo Paint rectangle... '.color$' '.currentX' '.endX' '.lowY' '.highY'
386 endproc
388 procedure DrawNext .color$ .x .y .size
389         demo '.color$'
390         .size *= 2/3
391         call drawTriangle 1 .x .y .size
392         .currentX = drawTriangle.currentX
393         .endX = .currentX + 0.5
394         .lowY = .y - .size
395         .highY = .y + .size
396         demo Paint rectangle... '.color$' '.currentX' '.endX' '.lowY' '.highY'
397 endproc
399 procedure DrawQuit .color$ .x .y .size
400         demo Line width... 4.0
401         .xstart = .x - .size
402         .ystart = .y + .size
403         .xend = .x + .size
404         .yend = .y - .size
405         demo Draw line... .xstart .ystart .xend .yend
406         .xstart = .x - .size
407         .ystart = .y - .size
408         .xend = .x + .size
409         .yend = .y + .size
410         demo Draw line... .xstart .ystart .xend .yend
411         demo Line width... 'defaultLineWidth'
412 endproc
414 procedure DrawConfig .color$ .x .y .size
415         .size *= 1
416         demo Line width... 3.0
417         .xstart = .x - .size
418         .xend = .x + .size
419         demo Draw arrow... .xstart .y .xend .y
420         demo Line width... 'defaultLineWidth'
421 endproc
423 procedure DrawRefresh .color$ .x .y .size
424         .size /= 2
425         demo Line width... 4.0
426         demo Draw arc... '.x' '.y' '.size' 0 270
427         demo Line width... 'defaultLineWidth'
428 endproc
430 procedure DrawWordList .color$ .x .y .size
431     .xleft = .x - .size
432     .xright = .x + .size
433     .xmidleft = .x + 0.1
434     .xmidright = .x - 0.1
435     .yhigh = .y + .size
436     .yhigh = .y + .size
437         demo '.color$'
438         demo Line width... 3
439         demo Draw line... .xleft .yhigh .xmidleft .y
440         demo Draw line... .xright .yhigh .xmidright .y
441         demo Line width... 'defaultLineWidth'
442         demo Black
443 endproc
445 procedure drawTriangle .direction .x .y .size
446         # Make sure direction = +/- 1
447         if .direction = 0
448                 .direction = 1 
449         endif
450         .direction /= abs(.direction)
451         
452         .offset = 0.01
453         .currentHeight = .size
454         .currentX = .x - .direction*.size
455         
456         demo Line width... 2.0
458         while .currentHeight> 0
459                 .ystart = .y + .currentHeight
460                 .yend = .y - .currentHeight
461                 demo Draw line... .currentX .ystart .currentX .yend
462                 .currentHeight -= .offset *3/4
463                 .currentX += .direction*.offset * 1.5
464         endwhile
465         demo Line width... 'defaultLineWidth'
466 endproc
468 ###############################################################
470 # Button Processing Routines
472 ###############################################################
474 # Search row in table on label
475 procedure findLabel .table$ .label$
476         .row = 0
477         select Table '.table$'
478         .to$ = selected$("Table")
479         .to$ = "Table_"+.to$
480         .numRows = Get number of rows
481         for .i to .numRows
482                 .currentKey$ = '.to$'$[.i, "Key"]
483                 if .label$ = .currentKey$
484                         .row = .i
485                         goto FOUND
486                 endif
487         endfor
488         label FOUND
489 endproc
491 # Get the label
492 procedure buttonClicked table$ .x .y
493         .label$ = ""
494         select Table 'table$'
495         .bo$ = selected$("Table")
496         .bo$ = "Table_"+.bo$
497         .numRows = Get number of rows
498         for .i to .numRows
499                 if .label$ = ""
500                         .leftX = '.bo$'[.i, "LeftX"]
501                         .rightX = '.bo$'[.i, "RightX"]
502                         .lowY = '.bo$'[.i, "LowY"]
503                         .highY = '.bo$'[.i, "HighY"]
504                         if .x > .leftX and .x < .rightX and .y > .lowY and .y < .highY
505                                 .label$ = '.bo$'$[.i, "Label"]
506                         endif
507                 endif
508         endfor
509 endproc
511 procedure keyPressed table$ .pressed$
512         .label$ = ""
513         .lowerPressed$ = replace_regex$(.pressed$, ".", "\L&", 0)
514         .upperPressed$ = replace_regex$(.pressed$, ".", "\U&", 0)
515         select Table 'table$'
516         .bo$ = selected$("Table")
517         .bo$ = "Table_"+.bo$
518         .numRows = Get number of rows
519         for .i to .numRows
520                 if .label$ = ""
521                         .key$ = '.bo$'$[.i, "Key"]
522                         if .key$ = .lowerPressed$ or .key$ = .upperPressed$
523                                 .label$ = '.bo$'$[.i, "Label"]
524                         endif
525                 endif
526         endfor
527 endproc
529 procedure record_sound
530     if sampleSound$ != ""
531         select Sound 'sampleSound$'
532         Remove
533         sampleSound$ = ""
534     endif
535         # Recording light
536     demo Paint rectangle... White 10 90 15 25
537     demo Paint circle... Red 5 85 2.5
538     demoShow()
539     nowarn Record Sound (fixed time)... Microphone 0.99 1 44100 4
540     demo Paint circle... White 5 85 3
541     demoShow()
542     Rename... Tmp
543     Resample... 10000 50
544     Rename... Source
545     sampleSound$ = selected$("Sound")
546     select Sound Tmp
547     Remove
548     select Sound 'sampleSound$'
549 endproc
551 # Draw a tone contour
552 procedure draw_tone_contour
553     # Wipe screen
554     demo Select inner viewport... 0 100 0 100
555     demo Paint rectangle... White 20 80 40 100
556     demo Select outer viewport... 0 100 0 100
557     demo Paint rectangle... White 20 80 40 100
558     demo Paint rectangle... White 0 100 16 26
559         select Table 'wordlist$'
560         if currentWord > 0 and currentWord <= numberOfWords
561                 .sound$ = Get value... 'currentWord' Sound
562                 .pinyin$ = Get value... 'currentWord' Pinyin
563                 execute "ToneProt/DrawToneContour.praat" '.pinyin$' 'register'
564         endif   
565 endproc
567 procedure recognizeTone
568         select Table 'wordlist$'
569         if currentWord > 0 and currentWord <= numberOfWords
570                 .sound$ = Get value... 'currentWord' Sound
571                 .pinyin$ = Get value... 'currentWord' Pinyin
572         execute "ToneProt/SGC_ToneProt.praat" 'sampleSound$' '.pinyin$' 'register' 'precision' Pictures 'language$'
573         endif
574 endproc
576 procedure write_feedback .table$
577     select Table '.table$'
578     .line1$ = Get value... 1 Text
579     .line2$ = Get value... 2 Text
580     .label$ = Get value... 3 Text
582     .color$ = "Red"
583     if index(.line1$, "???") > 0
584         .color$ = "Black"
585     elsif .label$ = "Correct"
586         .color$ = "Green"
587     endif
589     demo 14
590     demo '.color$'
591     demo Paint rectangle... White 0 100 16 26
592     demo Text... 50 Centre 21 Bottom '.line1$'
593     demo Text... 50 Centre 17 Bottom '.line2$'
594         demo 'defaultFont$'
595     demo 'defaultFontSize'
596         demoShow()
597     
598         # Log performance
599         .splitIndex = index(.line1$, ": ")
600         .pinyin$ = left$(.line1$, (.splitIndex - 1))
601         .choice$ = right$(.line1$, (length(.line1$) - .splitIndex - 1))
602         call log_performance 'sampleSound$' 'register' 'precision' '.pinyin$' '.choice$'
603 endproc
605 procedure play_sound .sound$
606     if .sound$ <> ""
607         select Sound '.sound$'
608         Play
609     endif
610 endproc
612 procedure end_program
613         call write_preferences "" 
614         demo Erase all
615         select all
616         Remove
617         exit
618 endproc
620 ######################################################
622 # Configuration Page
624 ######################################################
625 procedure config_page
626     demo Erase all
627     demoWindowTitle("Speak Good Chinese: Change settings")
628     .label$ = ""
629     call Draw_config_page
630     
631     while (.label$ <> "Return") and demoWaitForInput() 
632             .label$ = ""
633             if demoClicked()
634                     .clickX = demoX()
635                     .clickY = demoY()
636                     call buttonClicked 'config$' '.clickX' '.clickY'
637                     .label$ = buttonClicked.label$
638             elsif demoKeyPressed()
639                     .pressed$ = demoKey$()
640                     call keyPressed 'config$' '.pressed$'
641                     .label$ = keyPressed.label$
642             endif
644             # Do things
645             if .label$ != ""
646                     # Handle push button in process_config
647                     call process_config '.label$'
648             endif
649         
650         if .label$ = "Return"
651             goto GOBACK
652         endif
653     endwhile
655     # Go back
656     label GOBACK
657     call init_window
658 endproc
660 procedure Draw_config_page
661     call Draw_all_buttons 'config$'
662     # Set correct buttons (alert)
663     call Draw_button 'config$' Lang'language$' 2
664     call Draw_button 'config$' Register_'register' 2
665         if displayPinyin
666         call Draw_button 'config$' DisplayPinyin 2
667         endif
668         if displayChar
669         call Draw_button 'config$' DisplayChar 2
670         endif
671         if shuffleLists
672         call Draw_button 'config$' Shuffle 2
673         endif
674         if useSoundExample
675         call Draw_button 'config$' SndExample 2
676         endif
677 endproc
679 # Draw symbols
680 procedure DrawReturn .color$ .x .y .size
681     .xleft = .x - .size
682     .xright = .x + .size
683         demo Line width... 4.0
684         demo Draw arrow... '.xleft' '.y' '.xright' '.y'
685         demo Line width... 'defaultLineWidth'
686         demoShow()
687 endproc
690 # Do what is asked
691 procedure process_config .label$
692         if .label$ = "Return"
693         call Draw_button 'config$' '.label$' 1
694                 call write_preferences ""
695         elsif .label$ = "Shuffle"
696                 shuffleLists = not shuffleLists
697                 .displayButton = 2*shuffleLists
698         call Draw_button 'config$' '.label$' '.displayButton'
699         elsif .label$ = "SndExample"
700                 useSoundExample = not useSoundExample
701                 .displayButton = 2*useSoundExample
702         call Draw_button 'config$' '.label$' '.displayButton'
703         elsif startsWith(.label$, "Lang")
704         call Draw_button 'config$' Lang'language$' 0
705         call Draw_button 'config$' '.label$' 2
706         # Someone might have to use more than 2 chars for the language code
707         .numChars = length(.label$) - length("Lang")
708                 .lang$ = right$(.label$, .numChars)
709         # Load new tables
710         call set_language '.lang$'
711         elsif startsWith(.label$, "Register_")
712         call Draw_button 'config$' Register_'register' 0
713         call Draw_button 'config$' '.label$' 2
714         # Someone might have to use more than 3 chars for the register code
715         .numChars = length(.label$) - length("Register_")
716                 .registerText$ = right$(.label$, .numChars)
717                 register = '.registerText$'
718         elsif startsWith(.label$, "Display")
719                 .displayButton = 0
720                 if .label$ = "DisplayPinyin"
721                         displayPinyin = not displayPinyin
722                         .displayButton = 2*displayPinyin
723                 endif
724                 if .label$ = "DisplayChar"
725                         displayChar = not displayChar
726                         .displayButton = 2*displayChar
727                 endif
728         call Draw_button 'config$' '.label$' '.displayButton'
729         endif
730 endproc
732 procedure set_language .lang$
733         .redraw_config = 0
734     # Remove old tables
735     if buttons$ <> ""
736         select Table 'buttons$'
737         Remove
738                 .redraw_config = 1
739     endif
740     if config$ <> ""
741         select Table 'config$'
742         Remove
743                 .redraw_config = 1
744     endif
745     
746     # Set languege
747     language$ = .lang$
748     
749     # Load buttons tables
750     Read from file... Data/Buttons.Table
751     buttons$ = selected$("Table")
752     Append column... Text
753     Append column... Key
754     .numLabels = Get number of rows
755     Read from file... Data/Buttons_'language$'.Table
756     .buttonsLang$ = selected$("Table")
757     for .row to .numLabels
758         select Table '.buttonsLang$'
759         .valueText$ = Get value... '.row' Text
760         .valueKey$ = Get value... '.row' Key
761         select Table 'buttons$'
762         Set string value... '.row' Text '.valueText$'
763         Set string value... '.row' Key '.valueKey$'
764     endfor
765     select Table '.buttonsLang$'
766     Remove
767     
768     # Load configuration table
769     Read from file... Data/Config.Table
770     config$ = selected$("Table")
771     Append column... Text
772     Append column... Key
773     .numLabels = Get number of rows
774     Read from file... Data/Config_'language$'.Table
775     .configLang$ = selected$("Table")
776     for .row to .numLabels
777         select Table '.configLang$'
778         .valueText$ = Get value... '.row' Text
779         .valueKey$ = Get value... '.row' Key
780         select Table 'config$'
781         Set string value... '.row' Text '.valueText$'
782         Set string value... '.row' Key '.valueKey$'
783     endfor
784     select Table '.configLang$'
785     Remove
787         # Make language change visible
788         if .redraw_config
789                 call Draw_config_page
790         endif
792 endproc
794 procedure load_word_list .dir1$ .dir2$ .relnumber
795     # Remove old word list
796     if wordlist$ <> ""
797         select Table 'wordlist$'
798         Remove
799     endif
800     
801     Create Strings as directory list... WordList1 '.dir1$'
802         Copy... DirWordList1
803     .numLists = Get number of strings
804     for .i to .numLists
805         select Strings WordList1
806         .currentName$ = Get string... '.i'
807                 .currentName$ = .dir1$+"/"+.currentName$
808                 select Strings DirWordList1
809                 Set string... '.i' '.currentName$'
810     endfor
812     Create Strings as directory list... WordList2 '.dir2$'
813     .numLists = Get number of strings
814         if .numLists > 0
815                 Copy... DirWordList2
816         for .i to .numLists
817                 select Strings WordList2
818                 .currentName$ = Get string... '.i'
819                         .currentName$ = .dir2$+"/"+.currentName$
820                         select Strings DirWordList2
821                         Set string... '.i' '.currentName$'
822         endfor
824                 select Strings WordList1
825                 plus Strings WordList2
826                 Append
827                 Rename... WordList
828                 select Strings WordList1
829                 plus Strings WordList2
830                 Remove
832                 select Strings DirWordList1
833                 plus Strings DirWordList2
834                 Append
835                 Rename... DirWordList
836                 select Strings DirWordList1
837                 plus Strings DirWordList2
838                 Remove
839         else
840                 select Strings WordList2
841                 Remove
842                 select Strings WordList1
843                 Rename... WordList
844                 select Strings DirWordList1
845                 Rename... DirWordList
846         endif
847         
848         # Get the position of the current word list
849         select Strings WordList
850         .currentNumber = 1
851     .numLists = Get number of strings
852         if wordlistName$ <> ""
853                 for .i to .numLists
854                 select Strings WordList
855                 .currentName$ = Get string... '.i'
856                         if .currentName$ = wordlistName$
857                                 .currentNumber = .i
858                         endif
859                 endfor
860         endif
861     wordlistNum = .currentNumber + .relnumber
862     if wordlistNum > .numLists
863         wordlistNum = 1
864     endif
865     select Strings WordList
866     wordlistName$ = Get string... 'wordlistNum'
867     select Strings DirWordList
868         .dirWordlistName$ = Get string... 'wordlistNum'
869     .dirString$ = replace_regex$(.dirWordlistName$, "[ ]", "&", 0)
870         
871         # Read in full tables
872         if fileReadable("'.dirString$'/wordlist.Table")
873         Read from file... '.dirString$'/wordlist.Table
874         Rename... 'wordlistName$'
875         # Praat wil change the name if it feels like it
876         wordlist$ = selected$("Table")
877         # Handle (legacy) simple word lists
878         elsif fileReadable("'.dirString$'/wordlist.txt")
879                 Create Table with column names... 'wordlistName$' 0 Pinyin Character Sound
880         wordlist$ = selected$("Table")
881                 Read Strings from raw text file... '.dirString$'/wordlist.txt
882                 Rename... RawWordList
883                 .numWordStrings = Get number of strings
884                 for .i to .numWordStrings
885                         select Strings RawWordList
886                         .currentLine$ = Get string... '.i'
887                         .currentPinyin$ = extractWord$(.currentLine$, "")
888                         if length(.currentLine$) > length(.currentPinyin$)+1
889                                 .currentFile$ = right$(.currentLine$, length(.currentPinyin$)+1)
890                         elsif fileReadable("'.dirString$'/'.currentPinyin$'.spx")
891                                 .currentFile$ = .currentPinyin$+".spx"
892                         elsif fileReadable("'.dirString$'/'.currentPinyin$'.flac")
893                                 .currentFile$ = .currentPinyin$+".flac"
894                         elsif fileReadable("'.dirString$'/'.currentPinyin$'.wav")
895                                 .currentFile$ = .currentPinyin$+".wav"
896                         elsif fileReadable("'.dirString$'/'.currentPinyin$'.mp3")
897                                 .currentFile$ = .currentPinyin$+".mp3"
898                         else
899                                 .currentFile$ = "-"
900                         endif
901                         select Table 'wordlist$'
902                         Append row
903                         Set string value... '.i' Pinyin '.currentPinyin$'
904                         Set string value... '.i' Character -
905                         Set string value... '.i' Sound '.currentFile$'
906                 endfor
907                 select Strings RawWordList
908                 Remove
909                 
910                 select Table 'wordlistName$'
911         else
912                 Create Table with column names... 'wordlistName$' 0 Pinyin Character Sound
913         wordlist$ = selected$("Table")
914                 Create Strings as file list... RawWordList '.dirString$'/*
915                 .numWordStrings = Get number of strings
916                 .i = 0
917                 for .j to .numWordStrings
918                         select Strings RawWordList
919                         .currentLine$ = Get string... '.j'
920                         .currentFile$ = extractWord$(.currentLine$, "")
921                         if index_regex(.currentFile$, "\.(spx|flac|wav|mp3)")
922                                 .currentPinyin$ = left$(.currentFile$, index(.currentFile$, ".")-1)
923                                 select Table 'wordlist$'
924                                 Append row
925                                 .i += 1
926                                 Set string value... '.i' Pinyin '.currentPinyin$'
927                                 Set string value... '.i' Character -
928                                 Set string value... '.i' Sound '.currentFile$'
929                         endif
930                 endfor
931                 select Strings RawWordList
932                 Remove
933                 
934                 select Table 'wordlistName$'
935         endif
936     numberOfWords = Get number of rows
937     if shuffleLists
938         Randomize rows
939     endif
940         
941         # Clean up
942     select Strings WordList
943         plus Strings DirWordList
944     Remove
945 endproc
947 procedure write_word_list
948     .xtext = 50
949     .ytext = 12
950     .ytextTop = .ytext + 5
951     .displayWordList$ = replace_regex$(wordlistName$, "[_]", " ", 0)
952     demo Blue
953     demo Paint rectangle... White 20 80 '.ytext' '.ytextTop'
954     demo Blue
955     demo Text... '.xtext' Centre '.ytext' Bottom '.displayWordList$'
956     demo Black
957         demoShow()
959         # Write current Pinyin text
960         call display_text Black
962         # Draw the contour
963         call draw_tone_contour
965 endproc
967 procedure log_performance .sampleSound$ .register .precision .pinyin$ .choice$
968         if not logPerformance
969                 logPerformance = fileReadable(logDir$+"/logPerformance.txt")
970         endif
971         # Log files
972         .currentDate$ = date$()
973         .timeStamp$ = replace_regex$(.currentDate$, "[^a-zA-Z0-9\-_]", "-", 0)
974         .choiceText$ = replace_regex$(.choice$, "[^a-zA-Z0-9\-_]", "-", 0)
976         if logPerformance
977            .outfilename$ = .pinyin$+"_"+.choice$+"_'.register'_"+.timeStamp$+".wav"
978            .logtext$ = .pinyin$+tab$+.choice$+tab$+"'.register'Hz"+tab$+.currentDate$+tab$+.outfilename$+newline$
979            fileappend 'logDir$'/logFile.txt '.logtext$'
980            select Sound 'sampleSound$'
981            Write to WAV file... 'logDir$'/'.outfilename$'
982         endif
983 endproc
985 # Make sure all Preferences directories are available
986 procedure set_up_directories
987         .dirPath$ = replace_regex$("'preferencesDirectory$'/sgc2", "[ ]", "\\&", 0);
988         if macintosh or unix
989                 system mkdir -p '.dirPath$'/wordlists
990                 system mkdir -p '.dirPath$'/log
991         elsif windows
992         endif
993 endproc
996 # Retrieve and store setting between sessions
998 procedure read_preferences .preferencesFile$
999         if not fileReadable(.preferencesFile$)
1000                 .preferencesFile$ = preferencesDirectory$+"/sgc2/sgc2rc.txt"
1001         endif
1002         if fileReadable(.preferencesFile$)
1003                 Read from file... 'preferencesDirectory$'/sgc2/sgc2rc.txt
1004                 .preferenceTable$ = selected$("Table")
1005                 .numPefKeys = Get number of rows
1007                 call findLabel '.preferenceTable$' language
1008                 if findLabel.row > 0
1009                         select Table '.preferenceTable$'
1010                         language$ = Get value... 'findLabel.row' Value
1011                 endif
1013                 call findLabel '.preferenceTable$' register
1014                 if findLabel.row > 0
1015                         select Table '.preferenceTable$'
1016                         register = Get value... 'findLabel.row' Value
1017                 endif
1019                 call findLabel '.preferenceTable$' precision
1020                 if findLabel.row > 0
1021                         select Table '.preferenceTable$'
1022                         precision = Get value... 'findLabel.row' Value
1023                 endif
1025                 call findLabel '.preferenceTable$' shuffleLists
1026                 if findLabel.row > 0
1027                         select Table '.preferenceTable$'
1028                         shuffleLists = Get value... 'findLabel.row' Value
1029                 endif
1031                 call findLabel '.preferenceTable$' useSoundExample
1032                 if findLabel.row > 0
1033                         select Table '.preferenceTable$'
1034                         useSoundExample = Get value... 'findLabel.row' Value
1035                 endif
1037                 call findLabel '.preferenceTable$' displayPinyin
1038                 if findLabel.row > 0
1039                         select Table '.preferenceTable$'
1040                         displayPinyin = Get value... 'findLabel.row' Value
1041                 endif
1043                 call findLabel '.preferenceTable$' displayChar
1044                 if findLabel.row > 0
1045                         select Table '.preferenceTable$'
1046                         displayChar = Get value... 'findLabel.row' Value
1047                 endif
1049                 call findLabel '.preferenceTable$' wordlistDir
1050                 if findLabel.row > 0
1051                         select Table '.preferenceTable$'
1052                         wordlistDir$ = Get value... 'findLabel.row' Value
1053                 endif
1055                 call findLabel '.preferenceTable$' wordlistName
1056                 if findLabel.row > 0
1057                         select Table '.preferenceTable$'
1058                         wordlistName$ = Get value... 'findLabel.row' Value
1059                 endif
1061                 call findLabel '.preferenceTable$' logdir
1062                 if findLabel.row > 0
1063                         select Table '.preferenceTable$'
1064                         logDir$ = Get value... 'findLabel.row' Value
1065                 endif
1066                 
1067                 select Table '.preferenceTable$'
1068                 Remove
1069         endif
1070 endproc
1072 procedure write_preferences .preferencesFile$
1073         Create Table with column names... Preferences 0 Key Value
1074         if index_regex(.preferencesFile$, "[a-zA-Z0-9]") <= 0
1075                 .preferencesFile$ = preferencesDirectory$ + "/sgc2/sgc2rc.txt"
1076         endif
1077         .row = 0
1078         select Table Preferences
1079         Append row
1080         .row += 1
1081         Set string value... '.row' Key language
1082         Set string value... '.row' Value 'language$'
1083         
1085         select Table Preferences
1086         Append row
1087         .row += 1
1088         Set string value... '.row' Key register
1089         Set numeric value... '.row' Value 'register'
1092         select Table Preferences
1093         Append row
1094         .row += 1
1095         Set string value... '.row' Key precision
1096         Set numeric value... '.row' Value 'precision'
1098         select Table Preferences
1099         Append row
1100         .row += 1
1101         Set string value... '.row' Key shuffleLists
1102         Set numeric value... '.row' Value 'shuffleLists'
1104         select Table Preferences
1105         Append row
1106         .row += 1
1107         Set string value... '.row' Key useSoundExample
1108         Set numeric value... '.row' Value 'useSoundExample'
1110         select Table Preferences
1111         Append row
1112         .row += 1
1113         Set string value... '.row' Key displayPinyin
1114         Set numeric value... '.row' Value 'displayPinyin'
1116         select Table Preferences
1117         Append row
1118         .row += 1
1119         Set string value... '.row' Key displayChar
1120         Set numeric value... '.row' Value 'displayChar'
1122         select Table Preferences
1123         Append row
1124         .row += 1
1125         Set string value... '.row' Key wordlistDir
1126         Set string value... '.row' Value 'wordlistDir$'
1128         select Table Preferences
1129         Append row
1130         .row += 1
1131         Set string value... '.row' Key wordlistName
1132         Set string value... '.row' Value 'wordlistName$'
1134         select Table Preferences
1135         Append row
1136         .row += 1
1137         Set string value... '.row' Key logdir
1138         Set string value... '.row' Value 'logDir$'
1139         
1140         select Table Preferences
1141         Write to table file... '.preferencesFile$'
1142         Remove
1144 endproc