[med-svn] [Git][med-team/praat][master] 4 commits: New upstream version 6.3.02

Rafael Laboissière (@rafael) gitlab at salsa.debian.org
Sun Dec 4 15:12:33 GMT 2022



Rafael Laboissière pushed to branch master at Debian Med / praat


Commits:
e07a24a3 by Rafael Laboissière at 2022-12-03T21:24:58-03:00
New upstream version 6.3.02
- - - - -
8a905ec9 by Rafael Laboissière at 2022-12-03T21:27:54-03:00
Merge tag 'upstream/6.3.02'

Upstream version 6.3.02

- - - - -
03a872d5 by Rafael Laboissière at 2022-12-03T21:28:49-03:00
d/What_s_new_.html: Update upstream changelog

Gbp-Dch: Ignore

- - - - -
34088963 by Rafael Laboissière at 2022-12-03T21:31:12-03:00
d/changelog: Add entry for release 6.3.02-1

Gbp-Dch: Ignore

- - - - -


18 changed files:

- LPC/FormantPathEditor.cpp
- LPC/manual_LPC.cpp
- debian/What_s_new_.html
- debian/changelog
- dwtest/test_Sound_voiceActivity.praat
- fon/manual_tutorials.cpp
- foned/FunctionArea.cpp
- foned/FunctionEditor_prefs.h
- sys/EditorM.h
- sys/GuiFileSelect.cpp
- sys/GuiMenuItem.cpp
- sys/ScriptEditor.cpp
- sys/TextEditor.cpp
- sys/Ui.h
- sys/UiFile.cpp
- sys/praat.cpp
- sys/praatM.h
- + test/fon/closeEditor_GUI.praat


Changes:

=====================================
LPC/FormantPathEditor.cpp
=====================================
@@ -24,6 +24,7 @@
 #include "EditorM.h"
 #include "Formant_extensions.h"
 #include "LPC_and_Formant.h"
+#include "NUM2.h"
 #include "PitchTier.h"
 #include "PitchTier_to_PointProcess.h"
 #include "Sound_and_LPC.h"
@@ -54,14 +55,14 @@ MelderColour markedCandidatesColour =  MelderColour (0.984,0.984, 0.7);
 
 #define MAX_T  0.02000000001   /* Maximum interval between two voice pulses (otherwise voiceless). */
 
-static autoPitchTier Pitch_to_PitchTier_part (Pitch me, double tmin, double tmax) {
+static autoPitchTier Pitch_to_PitchTier_part (Pitch me, double startTime, double endTime) {
 	try {
-		autoPitchTier thee = PitchTier_create (tmin, tmax);
+		autoPitchTier thee = PitchTier_create (startTime, endTime);
 		for (integer i = 1; i <= my nx; i ++) {
 			const double time = Sampled_indexToX (me, i);
-			if (time < tmin)
+			if (time < startTime)
 				continue;
-			if (time > tmax)
+			if (time > endTime)
 				break;
 			const double frequency = my frames [i]. candidates [1]. frequency;
 			/*
@@ -77,18 +78,17 @@ static autoPitchTier Pitch_to_PitchTier_part (Pitch me, double tmin, double tmax
 	}
 }
 
-static autoPointProcess PointProcess_extractPart (PointProcess me, double tmin, double tmax) {
+static autoPointProcess PointProcess_extractPart (PointProcess me, double startTime, double endTime) {
 	try {
 		integer i1 = 1, i2 = my nt;
-		const double t = my t [i1];
-		while (my t [i1] < tmin)
+		while (i1 <= my nt && my t [i1] < startTime)
 			i1 ++;
-		while (my t [i2] > tmax)
+		while (i2 >= 1 && my t [i2] > endTime)
 			i2 --;
 		const integer nt = i2 - i1 + 1;
 		Melder_require (nt > 0,
 			U"There must be at least one point in the interval.");
-		autoPointProcess thee = PointProcess_create (tmin, tmax, nt);
+		autoPointProcess thee = PointProcess_create (startTime, endTime, nt);
 		thy nt = nt;
 		thy t.size = nt;
 		thy t.get()  <<= my t.part (i1, i2);
@@ -98,34 +98,32 @@ static autoPointProcess PointProcess_extractPart (PointProcess me, double tmin,
 	}
 }
 
-static autoSound FormantPathEditor_getResynthesis (FormantPathEditor me) {
-	Melder_require (my startSelection != my endSelection,
-		U"Please make a selection first.");
-	constexpr double fadeTime = 0.005;
-	double tmin = my startSelection - fadeTime, tmax = my endSelection + fadeTime;
-	Melder_clipLeft (my tmin, & tmin);
-	Melder_clipRight (& tmax, my tmax);
-	
-	SoundAnalysisArea_haveVisiblePitch (my formantPathArea().get());
-	Pitch pitch = my formantPathArea() -> d_pitch.get();
-	autoPitchTier pitchtierPart = Pitch_to_PitchTier_part (pitch, tmin, tmax);
-	
-	SoundAnalysisArea_haveVisiblePulses (my formantPathArea().get());
-	PointProcess pulses = my formantPathArea() -> d_pulses.get();
-	autoPointProcess pulsesPart = PointProcess_extractPart (pulses, tmin, tmax);
-	
-	autoPointProcess pulses2 = PitchTier_Point_to_PointProcess (pitchtierPart.get(), pulsesPart.get(), MAX_T);
-	const double samplingFrequency = 22050.0;
-	autoSound train = PointProcess_to_Sound_pulseTrain (pulses2.get(), samplingFrequency , 0.7, 0.05, 30);
-	
-	autoFormant formantPart = Formant_extractPart (my formantPathArea() -> d_formant.get(), tmin, tmax);
-	autoLPC lpc = Formant_to_LPC (formantPart.get(), 1.0 / samplingFrequency);
-	
-	autoSound sound = LPC_Sound_filter (lpc.get(), train.get(), false);
-	Vector_scale (sound.get(), 0.99);
-	Sound_fade (sound.get(), 0, sound -> xmin, fadeTime, false, true);
-	Sound_fade (sound.get(), 0, sound -> xmax, -fadeTime, true, true);
-	return sound;
+static autoSound FormantPathEditor_getResynthesis (FormantPathEditor me, double startTime, double endTime) {
+	try {
+		SoundAnalysisArea_haveVisiblePitch (my formantPathArea().get());
+		Pitch pitch = my formantPathArea() -> d_pitch.get();
+		autoPitchTier pitchtierPart = Pitch_to_PitchTier_part (pitch, startTime, endTime);
+		
+		SoundAnalysisArea_haveVisiblePulses (my formantPathArea().get());
+		PointProcess pulses = my formantPathArea() -> d_pulses.get();
+		autoPointProcess pulsesPart = PointProcess_extractPart (pulses, startTime, endTime);
+		
+		autoPointProcess pulses2 = PitchTier_Point_to_PointProcess (pitchtierPart.get(), pulsesPart.get(), MAX_T);
+		const double samplingFrequency = 22050.0;
+		autoSound train = PointProcess_to_Sound_pulseTrain (pulses2.get(), samplingFrequency , 0.7, 0.05, 30);
+		
+		autoFormant formantPart = Formant_extractPart (my formantPathArea() -> d_formant.get(), startTime, endTime);
+		autoLPC lpc = Formant_to_LPC (formantPart.get(), 1.0 / samplingFrequency);
+		
+		autoSound sound = LPC_Sound_filter (lpc.get(), train.get(), false);
+		Vector_scale (sound.get(), 0.99);
+		constexpr double fadeTime = 0.005;
+		Sound_fade (sound.get(), 0, sound -> xmin, fadeTime, false, true);
+		Sound_fade (sound.get(), 0, sound -> xmax, -fadeTime, true, true);
+		return sound;
+	} catch (MelderError) {
+		Melder_throw (U"Could not synthesize.");
+	}
 }
 
 static void FormantPathEditor_getDrawingData (FormantPathEditor me, double *out_startTime, double *out_endTime, double *out_xCursor, double *out_yCursor) {
@@ -151,6 +149,25 @@ static void FormantPathEditor_getDrawingData (FormantPathEditor me, double *out_
 				my formantPathArea() -> d_spectrogram_cursor < my formantPathArea() -> instancePref_spectrogram_viewTo() ? my formantPathArea() -> d_spectrogram_cursor : -1000.0 );
 }
 
+static void Formant_replaceFrames (Formant target, integer beginFrame, integer endFrame, Formant source) {
+	// Precondition target and source have exactly the same Sampled xmin, xmax, x1, nx, dx
+	if (beginFrame == endFrame && beginFrame == 0) {
+		beginFrame = 1;
+		endFrame = target -> nx;
+	}
+	Melder_require (beginFrame <= endFrame,
+		U"The start frame should not be after the end frame.");
+	Melder_require (beginFrame > 0, 
+		U"The begin frame should be larger than zero.");
+	Melder_require (endFrame <= target->nx,
+		U"The end frame sould not be larger than ", target->nx);
+	for (integer iframe = beginFrame ; iframe <= endFrame; iframe ++) {
+		Formant_Frame targetFrame = & target -> frames [iframe];
+		Formant_Frame sourceFrame = & source -> frames [iframe];
+		sourceFrame -> copy (targetFrame);
+	}
+}
+
 /********** METHODS **********/
 
 /***** TIER MENU *****/
@@ -218,6 +235,28 @@ static void menu_cb_candidates_FindPath (FormantPathEditor me, EDITOR_ARGS) {
 	EDITOR_END
 }
 
+static void menu_cb_selectCandidateWithlowestStress (FormantPathEditor me, EDITOR_ARGS) {
+	double startTime = my startSelection, endTime = my endSelection;
+	if (my startSelection == my endSelection) {
+		startTime = my startWindow;
+		endTime = my endWindow;
+	}
+	autoINTVEC parameters = splitByWhitespaceWithRanges_INTVEC (my instancePref_modeler_numberOfParametersPerTrack());
+	autoVEC stresses = FormantPath_getStressOfCandidates (my formantPath(), startTime, endTime, 0, 0, parameters.get(), 
+		my instancePref_modeler_varianceExponent());
+	const integer minPos = NUMminPos (stresses.get());
+	my selectedCandidate = minPos;
+	Editor_save (me, U"Change ceiling");
+	integer ifmin, ifmax;
+	Sampled_getWindowSamples (my formantPath(), startTime, endTime, & ifmin, & ifmax);
+	for (integer iframe = ifmin; iframe <= ifmax; iframe ++)
+		my formantPath() -> path [iframe] = my selectedCandidate;
+	Formant source = my formantPath() -> formantCandidates.at [my selectedCandidate];
+	Formant_replaceFrames (my formantPathArea() -> d_formant.get(), ifmin, ifmax, source);
+	FunctionEditor_redraw (me);
+	Editor_broadcastDataChanged (me);
+}
+
 static void menu_cb_DrawVisibleCandidates (FormantPathEditor me, EDITOR_ARGS) {
 	EDITOR_FORM (U"Draw visible candidates", nullptr)
 		my v_form_pictureWindow (cmd);
@@ -250,6 +289,25 @@ static void menu_cb_DrawVisibleCandidates (FormantPathEditor me, EDITOR_ARGS) {
 	EDITOR_END
 }
 
+static void menu_cb_play_resynthesis (FormantPathEditor me, EDITOR_ARGS) {
+	PLAY_DATA
+		MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
+		double startTime,endTime;
+		FormantPathEditor_getDrawingData (me, & startTime, & endTime, nullptr, nullptr);
+		autoSound resynthesis = FormantPathEditor_getResynthesis (me, startTime, endTime);
+		Sound_playPart (resynthesis.get(), startTime, endTime, theFunctionEditor_playCallback, me);
+	PLAY_DATA_END
+}
+
+static void menu_cb_extract_resynthesis (FormantPathEditor me, EDITOR_ARGS) {
+	CONVERT_DATA_TO_ONE
+		double startTime,endTime;
+		FormantPathEditor_getDrawingData (me, & startTime, & endTime, nullptr, nullptr);
+	
+		autoSound result = FormantPathEditor_getResynthesis (me, startTime, endTime);
+	CONVERT_DATA_TO_ONE_END (U"untitled")
+}
+
 static void INFO_DATA__stressOfFitsListing (FormantPathEditor me, EDITOR_ARGS) {
 	INFO_DATA
 		double startTime = my startSelection, endTime = my endSelection;
@@ -277,11 +335,18 @@ void structFormantPathEditor :: v_createMenus () {
 	EditorMenu menu = Editor_addMenu (this, U"Candidates", 0);
 	EditorMenu_addCommand (menu, U"Candidate modelling settings...", 0, menu_cb_candidate_modellingSettings);
 	EditorMenu_addCommand (menu, U"Advanced candidate drawing settings...", 0, menu_cb_AdvancedCandidateDrawingSettings);
-	EditorMenu_addCommand (menu, U"-- drawing --", 0, 0);
-	EditorMenu_addCommand (menu, U"Find path...", 0, menu_cb_candidates_FindPath);
-	EditorMenu_addCommand (menu, U"Draw visible candidates...", 0, menu_cb_DrawVisibleCandidates);
+	EditorMenu_addCommand (menu, U"- Draw candidates to picture window:", 0, nullptr);
+		EditorMenu_addCommand (menu, U"Draw visible candidates...", 1, menu_cb_DrawVisibleCandidates);
+	EditorMenu_addCommand (menu, U"- Select candidates:", 0, nullptr);
+		EditorMenu_addCommand (menu, U"Select candidate with lowest stress", 1, menu_cb_selectCandidateWithlowestStress);
+	EditorMenu_addCommand (menu, U"Find path...", 1, menu_cb_candidates_FindPath);
 	EditorMenu_addCommand (menu, U"-- candidate queries --", 0, 0);
 	EditorMenu_addCommand (menu, U"Stress of fits listing", 0, INFO_DATA__stressOfFitsListing);
+	if (soundArea()) {
+		EditorMenu_addCommand (menu, U"- Candidate resynthesis:", 0, nullptr);
+		EditorMenu_addCommand (menu, U"Play resynthesis", 1, menu_cb_play_resynthesis);
+		EditorMenu_addCommand (menu, U"Extract resynthesis", 1, menu_cb_extract_resynthesis);
+	}
 }
 
 void structFormantPathEditor :: v_createMenuItems_help (EditorMenu menu) {
@@ -332,25 +397,6 @@ void structFormantPathEditor :: v_drawSelectionViewer () {
 	previousEndTime = endTime;
 }
 
-static void Formant_replaceFrames (Formant target, integer beginFrame, integer endFrame, Formant source) {
-	// Precondition target and source have exactly the same Sampled xmin, xmax, x1, nx, dx
-	if (beginFrame == endFrame && beginFrame == 0) {
-		beginFrame = 1;
-		endFrame = target -> nx;
-	}
-	Melder_require (beginFrame <= endFrame,
-		U"The start frame should not be after the end frame.");
-	Melder_require (beginFrame > 0, 
-		U"The begin frame should be larger than zero.");
-	Melder_require (endFrame <= target->nx,
-		U"The end frame sould not be larger than ", target->nx);
-	for (integer iframe = beginFrame ; iframe <= endFrame; iframe ++) {
-		Formant_Frame targetFrame = & target -> frames [iframe];
-		Formant_Frame sourceFrame = & source -> frames [iframe];
-		sourceFrame -> copy (targetFrame);
-	}
-}
-
 void structFormantPathEditor :: v_clickSelectionViewer (double xWC, double yWC) {
 	/*
 		On which of the modelers was the click?
@@ -381,8 +427,9 @@ void structFormantPathEditor :: v_clickSelectionViewer (double xWC, double yWC)
 void structFormantPathEditor :: v_play (double startingTime, double endTime) {
 	if (our soundArea()) {
 		if (our clickWasModifiedByShiftKey) {
-			autoSound resynthesis = FormantPathEditor_getResynthesis (this);
+			autoSound resynthesis = FormantPathEditor_getResynthesis (this, startingTime, endTime);
 			Sound_playPart (resynthesis.get(), startingTime, endTime, theFunctionEditor_playCallback, this);
+			our clickWasModifiedByShiftKey = false;
 		} else {
 			SoundArea_play (our soundArea().get(), startingTime, endTime);
 		}


=====================================
LPC/manual_LPC.cpp
=====================================
@@ -28,12 +28,12 @@
 void manual_LPC (ManPages me);
 void manual_LPC (ManPages me)
 {
-MAN_BEGIN (U"Candidate modelling settings...", U"djmw", 20210813)
+MAN_BEGIN (U"Candidate modelling settings...", U"djmw", 20221129)
 INTRO (U"A command in the #Candidates menu of the @FormantPathEditor window.")
 TAG (U"##Coefficients by track#")
 DEFINITION (U"determines how many coefficients will be used in the modelling of a formant track. "
-	"The first number determines the number of coefficients that will be used for modeling formant 1 with a polynomial function."
-	"The second number determines the number of coefficients for the modelling of formant 2, and so on. " 
+
+"The second number determines the number of coefficients for the modelling of formant 2, and so on. " 
 	"For example, if you specify \"4 3 3\", the first three formants will be modelled. Formant 1 will be modelled with 4 "
 	"coefficients which means that a third order polynomial is used for modelling. Formant 2 and formant 3 are modelled with "
 	"3 coefficients which means that their tracks will be modelled as parabolas.")


=====================================
debian/What_s_new_.html
=====================================
@@ -7,10 +7,18 @@ What's new?
 <p>
 Latest changes in Praat.</p>
 <p>
+<b>6.3.02</b> (29 November 2022)</p>
+<ul>
+<li>
+ Linux: corrected a bug introduced in 6.2.20 by which typing Tab would not start a Sound.
+<li>
+ Sound window: corrected a bug introduced in 6.2.19 by which drawing selection hairs could not be switched off (or on) when painting a spectrogram to the Picture window.
+</ul>
+<p>
 <b>6.3.01</b> (21 November 2022)</p>
 <ul>
 <li>
- Fixed a crash when closing an editor window by choosing Close (or by typing Command-W).
+ Fixed a crash introduced in 6.3 when closing an editor window by choosing Close (or by typing Command-W).
 </ul>
 <p>
 <b>6.3</b> (15 November 2022)</p>
@@ -284,7 +292,7 @@ What used to be new?</h3>
 </ul>
 <hr>
 <address>
-	<p>© ppgb, November 21, 2022</p>
+	<p>© ppgb, November 29, 2022</p>
 </address>
 </body>
 </html>


=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+praat (6.3.02-1) unstable; urgency=medium
+
+  * New upstream version 6.3.02
+
+ -- Rafael Laboissière <rafael at debian.org>  Sat, 03 Dec 2022 21:30:36 -0300
+
 praat (6.3.01-1) unstable; urgency=medium
 
   * New upstream version 6.3.01


=====================================
dwtest/test_Sound_voiceActivity.praat
=====================================
@@ -1,7 +1,10 @@
 # test_Sound_voiceActivity.praat
 # djmw 20210317
 
+
+random_initializeWithSeedUnsafelyButPredictably (0.5)
 noise = Create Sound from formula: "noise", 1, 0, 1, 44100, ~ randomGauss(0,1)
+random_initializeSafelyAndUnpredictably ()
 textgrid = nowarn To TextGrid (voice activity): 0.0, 0.3, 0.1, 70, 6000, -10, -35, 0.1, 0.1, "silent", "sounding"
 numberOfIntervals = Get number of intervals: 1
 assert numberOfIntervals = 1


=====================================
fon/manual_tutorials.cpp
=====================================
@@ -22,10 +22,14 @@
 void manual_tutorials_init (ManPages me);
 void manual_tutorials_init (ManPages me) {
 
-MAN_BEGIN (U"What's new?", U"ppgb", 20221121)
+MAN_BEGIN (U"What's new?", U"ppgb", 20221125)
 INTRO (U"Latest changes in Praat.")
+NORMAL (U"##6.3.02# (xx November 2022)")
+LIST_ITEM (U"• Linux: corrected a bug introduced in 6.2.20 by which typing Tab would not start a Sound.")
+LIST_ITEM (U"• Sound window: corrected a bug introduced in 6.2.19 by which drawing selection hairs could not be switched off "
+	"(or on) when painting a spectrogram to the Picture window.")
 NORMAL (U"##6.3.01# (21 November 2022)")
-LIST_ITEM (U"• Fixed a crash when closing an editor window by choosing Close (or by typing Command-W).")
+LIST_ITEM (U"• Fixed a crash introduced in 6.3 when closing an editor window by choosing Close (or by typing Command-W).")
 NORMAL (U"##6.3# (15 November 2022)")
 LIST_ITEM (U"• Number-aware sorting for labels when drawing tables.")
 LIST_ITEM (U"• Scripting: sort\\$ \\# ( ), shuffle\\$ \\# ( ), sort\\_ numberAware\\$ \\# ( ).")


=====================================
foned/FunctionArea.cpp
=====================================
@@ -41,14 +41,12 @@ void structFunctionArea :: v_form_pictureSelection (EditorCommand cmd) {
 	UiForm_addBoolean (cmd -> d_uiform.get(), & v_form_pictureSelection__drawSelectionHairs, nullptr, U"Draw selection hairs", true);
 }
 void structFunctionArea :: v_ok_pictureSelection (EditorCommand cmd) {
-	FunctionEditor me = (FunctionEditor) cmd -> d_editor;
-	SET_BOOLEAN (v_form_pictureSelection__drawSelectionTimes, my classPref_picture_drawSelectionTimes())
-	SET_BOOLEAN (v_form_pictureSelection__drawSelectionHairs, my classPref_picture_drawSelectionHairs())
+	SET_BOOLEAN (v_form_pictureSelection__drawSelectionTimes, our classPref_picture_drawSelectionTimes())
+	SET_BOOLEAN (v_form_pictureSelection__drawSelectionHairs, our classPref_picture_drawSelectionHairs())
 }
-void structFunctionArea :: v_do_pictureSelection (EditorCommand cmd) {
-	FunctionEditor me = (FunctionEditor) cmd -> d_editor;
-	my setClassPref_picture_drawSelectionTimes (v_form_pictureSelection__drawSelectionTimes);
-	my setClassPref_picture_drawSelectionHairs (v_form_pictureSelection__drawSelectionHairs);
+void structFunctionArea :: v_do_pictureSelection (EditorCommand /* cmd */) {
+	our setClassPref_picture_drawSelectionTimes (v_form_pictureSelection__drawSelectionTimes);
+	our setClassPref_picture_drawSelectionHairs (v_form_pictureSelection__drawSelectionHairs);
 }
 
 void FunctionArea_drawRightMark (FunctionArea me, double yWC, conststring32 yWC_string, conststring32 units, int verticalAlignment) {


=====================================
foned/FunctionEditor_prefs.h
=====================================
@@ -23,8 +23,6 @@ Prefs_begin (FunctionEditor)
 	ClassPrefs_addBool       (FunctionEditor, synchronizedZoomAndScroll,  1, true)
 	InstancePrefs_addBool    (FunctionEditor, showSelectionViewer, 1, false)
 	InstancePrefs_addDouble  (FunctionEditor, arrowScrollStep,     1, U"0.05")
-	ClassPrefs_addBool       (FunctionEditor, picture_drawSelectionTimes, 1, true)
-	ClassPrefs_addBool       (FunctionEditor, picture_drawSelectionHairs, 1, true)
 
 Prefs_end (FunctionEditor)
 


=====================================
sys/EditorM.h
=====================================
@@ -378,7 +378,7 @@ _form_inited_: \
 		cmd -> d_uiform = UiOutfile_createE (cmd, title, cmd -> itemTitle.get(), helpTitle); \
 		} if (! _args_ && ! _sendingForm_ && ! _sendingString_) { char32 defaultName [300]; defaultName [0] = U'\0';
 #define EDITOR_DO_SAVE \
-	UiOutfile_do (cmd -> d_uiform.get(), defaultName, my boss()); } else { MelderFile file; structMelderFile _file2 { }; \
+	UiOutfile_do (cmd -> d_uiform.get(), defaultName); } else { MelderFile file; structMelderFile _file2 { }; \
 	if (_args_) { \
 		Melder_require (_narg_ == 1, \
 			U"Command requires exactly 1 argument, the name of the file to write, instead of the given ", _narg_, U" arguments."); \


=====================================
sys/GuiFileSelect.cpp
=====================================
@@ -1,6 +1,6 @@
 /* GuiFileSelect.cpp
  *
- * Copyright (C) 2010-2021 Paul Boersma, 2013 Tom Naughton
+ * Copyright (C) 2010-2022 Paul Boersma, 2013 Tom Naughton
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@ autoStringSet GuiFileSelect_getInfileNames (GuiWindow parent, conststring32 titl
 		static structMelderDir dir { };
 		GuiObject dialog = gtk_file_chooser_dialog_new (Melder_peek32to8 (title), nullptr, GTK_FILE_CHOOSER_ACTION_OPEN,
 			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, nullptr);
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent -> d_gtkWindow));
 		gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), allowMultipleFiles);
 		if (MelderDir_isNull (& dir))   // first time?
 			Melder_getDefaultDir (& dir);
@@ -128,6 +129,7 @@ autostring32 GuiFileSelect_getOutfileName (GuiWindow parent, conststring32 title
 		static structMelderFile file;
 		GuiObject dialog = gtk_file_chooser_dialog_new (Melder_peek32to8 (title), nullptr, GTK_FILE_CHOOSER_ACTION_SAVE,
 			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, nullptr);
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent -> d_gtkWindow));
 		gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), true);
 		if (file. path [0] != U'\0')
 			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), Melder_peek32to8_fileSystem (file. path));
@@ -190,6 +192,7 @@ autostring32 GuiFileSelect_getFolderName (GuiWindow parent, conststring32 title)
 		static structMelderFile file;
 		GuiObject dialog = gtk_file_chooser_dialog_new (Melder_peek32to8 (title), nullptr, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
 			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, "Choose", GTK_RESPONSE_ACCEPT, nullptr);
+		gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent -> d_gtkWindow));
 		if (file. path [0] != U'\0') {
 			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), Melder_peek32to8_fileSystem (file. path));
 		}


=====================================
sys/GuiMenuItem.cpp
=====================================
@@ -85,8 +85,10 @@ Thing_implement (GuiMenuItem, GuiThing, 0);
 	}
 	static void _guiGtkMenuItem_activateCallback (GuiObject widget, gpointer void_me) {
 		iam (GuiMenuItem);
-		if (my d_callbackBlocked) return;
-		if (G_OBJECT_TYPE (widget) == GTK_TYPE_RADIO_MENU_ITEM && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) return;
+		if (my d_callbackBlocked)
+			return;
+		if (G_OBJECT_TYPE (widget) == GTK_TYPE_RADIO_MENU_ITEM && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
+			return;
 		structGuiMenuItemEvent event { me, false, false, false };
 		if (my d_callback) {
 			try {
@@ -362,12 +364,12 @@ GuiMenuItem GuiMenu_addItem (GuiMenu menu, conststring32 title, uint32 flags,
 	my d_boss = boss;
 	#if gtk
 		if (commandCallback) {
-			if (flags == GuiMenu_TAB) {
+			if (accelerator == GuiMenu_TAB && ! (flags & GuiMenu_SHIFT)) {
 				GtkWidget *shell = gtk_widget_get_toplevel (gtk_menu_get_attach_widget (GTK_MENU (menu -> d_widget)));
 				trace (U"tab set in GTK window ", Melder_pointer (shell));
 				g_object_set_data (G_OBJECT (shell), "tabCallback", (gpointer) _guiGtkMenuItem_activateCallback);
 				g_object_set_data (G_OBJECT (shell), "tabClosure", (gpointer) me.get());
-			} else if (flags == (GuiMenu_TAB | GuiMenu_SHIFT)) {
+			} else if (accelerator == GuiMenu_TAB && (flags & GuiMenu_SHIFT)) {
 				GtkWidget *shell = gtk_widget_get_toplevel (gtk_menu_get_attach_widget (GTK_MENU (menu -> d_widget)));
 				trace (U"shift-tab set in GTK window ", Melder_pointer (shell));
 				g_object_set_data (G_OBJECT (shell), "shiftTabCallback", (gpointer) _guiGtkMenuItem_activateCallback);


=====================================
sys/ScriptEditor.cpp
=====================================
@@ -27,7 +27,7 @@ static CollectionOf <structScriptEditor> theReferencesToAllOpenScriptEditors;
 
 bool ScriptEditors_dirty () {
 	for (integer i = 1; i <= theReferencesToAllOpenScriptEditors.size; i ++) {
-		ScriptEditor me = theReferencesToAllOpenScriptEditors.at [i];
+		const ScriptEditor me = theReferencesToAllOpenScriptEditors.at [i];
 		if (my dirty)
 			return true;
 	}
@@ -41,14 +41,14 @@ void structScriptEditor :: v9_destroy () noexcept {
 }
 
 void structScriptEditor :: v_nameChanged () {
-	bool dirtinessAlreadyShown = GuiWindow_setDirty (our windowForm, dirty);
+	const bool dirtinessAlreadyShown = GuiWindow_setDirty (our windowForm, our dirty);
 	static MelderString buffer;
-	MelderString_copy (& buffer, name [0] ? U"Script" : U"untitled script");
-	if (editorClass)
+	MelderString_copy (& buffer, our name [0] != U'\0' ? U"Script" : U"untitled script");
+	if (our editorClass)
 		MelderString_append (& buffer, U" [", environmentName.get(), U"]");
-	if (name [0])
+	if (our name [0] != U'\0')
 		MelderString_append (& buffer, U" ", MelderFile_messageName (& file));
-	if (dirty && ! dirtinessAlreadyShown)
+	if (our dirty && ! dirtinessAlreadyShown)
 		MelderString_append (& buffer, U" (modified)");
 	GuiShell_setTitle (windowForm, buffer.string);
 }
@@ -67,7 +67,7 @@ static void args_ok (UiForm sendingForm, integer /* narg */, Stackel /* args */,
 	iam (ScriptEditor);
 	autostring32 text = GuiText_getString (my textWidget);
 	structMelderFile file { };
-	if (my name [0]) {
+	if (my name [0] != U'\0') {
 		Melder_pathToFile (my name.get(), & file);
 		MelderFile_setDefaultDir (& file);
 	}
@@ -76,7 +76,7 @@ static void args_ok (UiForm sendingForm, integer /* narg */, Stackel /* args */,
 	Interpreter_getArgumentsFromDialog (my interpreter.get(), sendingForm);
 
 	autoPraatBackground background;
-	if (my name [0])
+	if (my name [0] != U'\0')
 		MelderFile_setDefaultDir (& file);
 	Interpreter_run (my interpreter.get(), text.get());
 }
@@ -89,7 +89,7 @@ static void args_ok_selectionOnly (UiForm sendingForm, integer /* narg */, Stack
 	if (! text)
 		Melder_throw (U"No text is selected any longer.\nPlease reselect or click Cancel.");
 	structMelderFile file { };
-	if (my name [0]) {
+	if (my name [0] != U'\0') {
 		Melder_pathToFile (my name.get(), & file);
 		MelderFile_setDefaultDir (& file);
 	}
@@ -98,7 +98,7 @@ static void args_ok_selectionOnly (UiForm sendingForm, integer /* narg */, Stack
 	Interpreter_getArgumentsFromDialog (my interpreter.get(), sendingForm);
 
 	autoPraatBackground background;
-	if (my name [0])
+	if (my name [0] != U'\0')
 		MelderFile_setDefaultDir (& file);
 	Interpreter_run (my interpreter.get(), text.get());
 }
@@ -110,7 +110,7 @@ static void menu_cb_run (ScriptEditor me, EDITOR_ARGS) {
 	autostring32 text = GuiText_getString (my textWidget);
 	trace (U"Running the following script (1):\n", text.get());
 	structMelderFile file { };
-	if (my name [0]) {
+	if (my name [0] != U'\0') {
 		Melder_pathToFile (my name.get(), & file);
 		MelderFile_setDefaultDir (& file);
 	}
@@ -140,7 +140,7 @@ static void menu_cb_run (ScriptEditor me, EDITOR_ARGS) {
 	}
 	Melder_includeIncludeFiles (& text);
 	const integer npar = Interpreter_readParameters (my interpreter.get(), text.get());
-	if (npar) {
+	if (npar != 0) {
 		/*
 			Pop up a dialog box for querying the arguments.
 		*/
@@ -148,7 +148,7 @@ static void menu_cb_run (ScriptEditor me, EDITOR_ARGS) {
 		UiForm_do (my argsDialog.get(), false);
 	} else {
 		autoPraatBackground background;
-		if (my name [0])
+		if (my name [0] != U'\0')
 			MelderFile_setDefaultDir (& file);
 		trace (U"Running the following script (2):\n", text.get());
 		Interpreter_run (my interpreter.get(), text.get());
@@ -162,13 +162,13 @@ static void menu_cb_runSelection (ScriptEditor me, EDITOR_ARGS) {
 	if (! text)
 		Melder_throw (U"No text selected.");
 	structMelderFile file { };
-	if (my name [0]) {
+	if (my name [0] != U'\0') {
 		Melder_pathToFile (my name.get(), & file);
 		MelderFile_setDefaultDir (& file);
 	}
 	Melder_includeIncludeFiles (& text);
-	integer npar = Interpreter_readParameters (my interpreter.get(), text.get());
-	if (npar) {
+	const integer npar = Interpreter_readParameters (my interpreter.get(), text.get());
+	if (npar != 0) {
 		/*
 			Pop up a dialog box for querying the arguments.
 		*/
@@ -176,7 +176,7 @@ static void menu_cb_runSelection (ScriptEditor me, EDITOR_ARGS) {
 		UiForm_do (my argsDialog.get(), false);
 	} else {
 		autoPraatBackground background;
-		if (my name [0])
+		if (my name [0] != U'\0')
 			MelderFile_setDefaultDir (& file);
 		Interpreter_run (my interpreter.get(), text.get());
 	}
@@ -214,7 +214,7 @@ static void menu_cb_addToFixedMenu (ScriptEditor me, EDITOR_ARGS) {
 		INTEGER (depth, U"Depth", U"0")
 		INFILE (scriptFile, U"Script file", U"")
 	EDITOR_OK
-		if (my name [0])
+		if (my name [0] != U'\0')
 			SET_STRING (scriptFile, my name.get())
 		else
 			SET_STRING (scriptFile, U"(please save your script first)")
@@ -237,7 +237,7 @@ static void menu_cb_addToDynamicMenu (ScriptEditor me, EDITOR_ARGS) {
 		INTEGER (depth, U"Depth", U"0")
 		INFILE (scriptFile, U"Script file", U"")
 	EDITOR_OK
-		if (my name [0])
+		if (my name [0] != U'\0')
 			SET_STRING (scriptFile, my name.get())
 		else
 			SET_STRING (scriptFile, U"(please save your script first)")
@@ -275,7 +275,7 @@ static void menu_cb_pasteHistory (ScriptEditor me, EDITOR_ARGS) {
 static void menu_cb_expandIncludeFiles (ScriptEditor me, EDITOR_ARGS) {
 	structMelderFile file { };
 	autostring32 text = GuiText_getString (my textWidget);
-	if (my name [0]) {
+	if (my name [0] != U'\0') {
 		Melder_pathToFile (my name.get(), & file);
 		MelderFile_setDefaultDir (& file);
 	}


=====================================
sys/TextEditor.cpp
=====================================
@@ -124,7 +124,7 @@ static void cb_open_ok (UiForm sendingForm, integer /* narg */, Stackel /* args
 static void cb_showOpen (EditorCommand cmd) {
 	TextEditor me = (TextEditor) cmd -> d_editor;
 	if (! my openDialog)
-		my openDialog = UiInfile_create (my windowForm, U"Open", cb_open_ok, me, nullptr, nullptr, false);
+		my openDialog = UiInfile_create (my windowForm, nullptr, U"Open", cb_open_ok, me, nullptr, nullptr, false);
 	UiInfile_do (my openDialog.get());
 }
 
@@ -138,10 +138,10 @@ static void cb_saveAs_ok (UiForm sendingForm, integer /* narg */, Stackel /* arg
 
 static void menu_cb_saveAs (TextEditor me, EDITOR_ARGS) {
 	if (! my saveDialog)
-		my saveDialog = UiOutfile_create (my windowForm, U"Save", cb_saveAs_ok, me, nullptr, nullptr);
+		my saveDialog = UiOutfile_create (my windowForm, nullptr, U"Save", cb_saveAs_ok, me, nullptr, nullptr);
 	char32 defaultName [300];
 	Melder_sprint (defaultName,300, ! my v_fileBased () ? U"info.txt" : my name [0] ? MelderFile_name (& my file) : U"");
-	UiOutfile_do (my saveDialog.get(), defaultName, nullptr);
+	UiOutfile_do (my saveDialog.get(), defaultName);
 }
 
 static void gui_button_cb_saveAndOpen (EditorCommand cmd, GuiButtonEvent /* event */) {


=====================================
sys/Ui.h
=====================================
@@ -308,17 +308,17 @@ MelderColour UiForm_getColour_check (UiForm me, conststring32 fieldName);
 void UiForm_call (UiForm me, integer narg, Stackel args, Interpreter interpreter);
 void UiForm_parseString (UiForm me, conststring32 arguments, Interpreter interpreter);
 
-autoUiForm UiInfile_create (GuiWindow parent, conststring32 title,
+autoUiForm UiInfile_create (GuiWindow parent, Editor optionalEditor, conststring32 title,
   UiCallback okCallback, void *okClosure,
   conststring32 invokingButtonTitle, conststring32 helpTitle, bool allowMultipleFiles);
 
-autoUiForm UiOutfile_create (GuiWindow parent, conststring32 title,
+autoUiForm UiOutfile_create (GuiWindow parent, Editor optionalEditor, conststring32 title,
   UiCallback okCallback, void *okClosure,
   conststring32 invokingButtonTitle, conststring32 helpTitle);
 
 void UiInfile_do (UiForm me);
 
-void UiOutfile_do (UiForm me, conststring32 defaultName, Editor optionalEditor);
+void UiOutfile_do (UiForm me, conststring32 defaultName);
 
 MelderFile UiFile_getFile (UiForm me);
 


=====================================
sys/UiFile.cpp
=====================================
@@ -30,11 +30,12 @@ MelderFile UiFile_getFile (UiForm me) {
 
 /********** READING A FILE **********/
 
-autoUiForm UiInfile_create (GuiWindow parent, conststring32 title,
+autoUiForm UiInfile_create (GuiWindow parent, Editor optionalEditor, conststring32 title,
 	UiCallback okCallback, void *okClosure,
 	conststring32 invokingButtonTitle, conststring32 helpTitle, bool allowMultipleFiles)
 {
 	autoUiForm me = Thing_new (UiForm);
+	my optionalEditor = optionalEditor;
 	my okCallback = okCallback;
 	my buttonClosure = okClosure;
 	my invokingButtonTitle = Melder_dup (invokingButtonTitle);
@@ -58,7 +59,7 @@ void UiInfile_do (UiForm me) {
 			structMelderFile file { };
 			MelderFile_copy (& my file, & file);
 			try {
-				my okCallback (me, 0, nullptr, nullptr, nullptr, my invokingButtonTitle.get(), false, my buttonClosure, nullptr);
+				my okCallback (me, 0, nullptr, nullptr, nullptr, my invokingButtonTitle.get(), false, my buttonClosure, my optionalEditor);
 			} catch (MelderError) {
 				Melder_throw (U"File ", & file, U" not finished.");
 			}
@@ -70,10 +71,11 @@ void UiInfile_do (UiForm me) {
 
 /********** WRITING A FILE **********/
 
-autoUiForm UiOutfile_create (GuiWindow parent, conststring32 title,
+autoUiForm UiOutfile_create (GuiWindow parent, Editor optionalEditor, conststring32 title,
 	UiCallback okCallback, void *okClosure, conststring32 invokingButtonTitle, conststring32 helpTitle)
 {
 	autoUiForm me = Thing_new (UiForm);
+	my optionalEditor = optionalEditor;
 	my okCallback = okCallback;
 	my buttonClosure = okClosure;
 	my invokingButtonTitle = Melder_dup (invokingButtonTitle);
@@ -85,7 +87,7 @@ autoUiForm UiOutfile_create (GuiWindow parent, conststring32 title,
 }
 
 static void commonOutfileCallback (UiForm sendingForm, integer narg, Stackel args, conststring32 sendingString,
-	Interpreter interpreter, conststring32 /* invokingButtonTitle */, bool /* modified */, void *closure, Editor optionalEditor)
+	Interpreter interpreter, conststring32 /* invokingButtonTitle */, bool /* modified */, void *closure, Editor /* optionalEditor */)
 {
 	EditorCommand command = (EditorCommand) closure;
 	command -> commandCallback (command -> sender, command, sendingForm, narg, args, sendingString, interpreter);
@@ -93,21 +95,22 @@ static void commonOutfileCallback (UiForm sendingForm, integer narg, Stackel arg
 
 autoUiForm UiOutfile_createE (EditorCommand cmd, conststring32 title, conststring32 invokingButtonTitle, conststring32 helpTitle) {
 	Editor editor = cmd -> d_editor;
-	autoUiForm dia = UiOutfile_create (editor -> windowForm, title, commonOutfileCallback, cmd, invokingButtonTitle, helpTitle);
+	autoUiForm dia = UiOutfile_create (editor -> windowForm, editor, title, commonOutfileCallback, cmd, invokingButtonTitle, helpTitle);
 	dia -> command = cmd;
 	return dia;
 }
 
 autoUiForm UiInfile_createE (EditorCommand cmd, conststring32 title, conststring32 invokingButtonTitle, conststring32 helpTitle) {
 	Editor editor = cmd -> d_editor;
-	autoUiForm dia = UiInfile_create (editor -> windowForm, title, commonOutfileCallback, cmd, invokingButtonTitle, helpTitle, false);
+	autoUiForm dia = UiInfile_create (editor -> windowForm, editor, title, commonOutfileCallback, cmd, invokingButtonTitle, helpTitle, false);
 	dia -> command = cmd;
 	return dia;
 }
 
-void UiOutfile_do (UiForm me, conststring32 defaultName, Editor optionalEditor) {
-	autostring32 outfileName = GuiFileSelect_getOutfileName (nullptr, my name.get(), defaultName);
-	if (! outfileName) return;   // cancelled
+void UiOutfile_do (UiForm me, conststring32 defaultName) {
+	autostring32 outfileName = GuiFileSelect_getOutfileName (my d_dialogParent, my name.get(), defaultName);
+	if (! outfileName)
+		return;   // cancelled
 	if (my allowExecutionHook && ! my allowExecutionHook (my allowExecutionClosure)) {
 		Melder_flushError (U"Dialog \"", my name.get(), U"\" cancelled.");
 		return;
@@ -118,7 +121,7 @@ void UiOutfile_do (UiForm me, conststring32 defaultName, Editor optionalEditor)
 	UiHistory_write (U"\n");
 	UiHistory_write_colonize (my invokingButtonTitle.get());
 	try {
-		my okCallback (me, 0, nullptr, nullptr, nullptr, my invokingButtonTitle.get(), false, my buttonClosure, optionalEditor);
+		my okCallback (me, 0, nullptr, nullptr, nullptr, my invokingButtonTitle.get(), false, my buttonClosure, my optionalEditor);
 	} catch (MelderError) {
 		Melder_flushError (U"File ", & file, U" not finished.");
 	}


=====================================
sys/praat.cpp
=====================================
@@ -277,7 +277,7 @@ void praat_write_do (UiForm dia, conststring32 extension) {
 			MelderString_copy (& defaultFileName, U"praat.", extension);
 		}
 	}
-	UiOutfile_do (dia, defaultFileName.string, nullptr);
+	UiOutfile_do (dia, defaultFileName.string);
 }
 
 static void removeAllReferencesToMoribundEditor (Editor editor) {


=====================================
sys/praatM.h
=====================================
@@ -355,11 +355,11 @@
 	extern "C" void proc (UiForm sendingForm, integer, structStackel args [], conststring32 sendingString, \
 			Interpreter interpreter, conststring32 invokingButtonTitle, bool, void *okClosure, Editor optionalEditor); \
 	void proc (UiForm _sendingForm_, integer _narg_, structStackel _args_ [], conststring32 _sendingString_, \
-			Interpreter interpreter, conststring32 _invokingButtonTitle_, bool, void *_okClosure_, Editor) \
+			Interpreter interpreter, conststring32 _invokingButtonTitle_, bool, void *_okClosure_, Editor _optionalEditor_) \
 	{ \
 		{ static autoUiForm _dia_; \
 		if (! _dia_) \
-			_dia_ = UiInfile_create (theCurrentPraatApplication -> topShell, title, proc, _okClosure_, _invokingButtonTitle_, help, allowMult); \
+			_dia_ = UiInfile_create (theCurrentPraatApplication -> topShell, _optionalEditor_, title, proc, _okClosure_, _invokingButtonTitle_, help, allowMult); \
 		if (_narg_ < 0) UiForm_info (_dia_.get(), _narg_); else if (! _args_ && ! _sendingForm_ && ! _sendingString_) { \
 			UiInfile_do (_dia_.get()); \
 		} else { \
@@ -389,7 +389,7 @@
 	{ \
 		{ static autoUiForm _dia_; \
 		if (! _dia_) \
-			_dia_ = UiOutfile_create (theCurrentPraatApplication -> topShell, title, proc, _okClosure_, _invokingButtonTitle_, help); \
+			_dia_ = UiOutfile_create (theCurrentPraatApplication -> topShell, _optionalEditor_, title, proc, _okClosure_, _invokingButtonTitle_, help); \
 		if (_narg_ < 0) UiForm_info (_dia_.get(), _narg_); else if (! _args_ && ! _sendingForm_ && ! _sendingString_) { \
 			praat_write_do (_dia_.get(), ext); \
 		} else { \


=====================================
test/fon/closeEditor_GUI.praat
=====================================
@@ -0,0 +1,10 @@
+Create Sound from formula: "X", 1, 0, 1, 44100, "1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)"
+selectObject: "Sound X"
+View & Edit
+editor: "Sound X"
+Close
+a = 1
+a$ = "hello"
+removeObject: "Sound X"
+Create Sound from formula: "X", 1, 0, 1, 44100, "1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)"
+Remove
\ No newline at end of file



View it on GitLab: https://salsa.debian.org/med-team/praat/-/compare/b60b06eb433777dc28e9cdab68492bfbb3a6f6ca...34088963d6c15b90d3f93fd206ca825703ac7632

-- 
View it on GitLab: https://salsa.debian.org/med-team/praat/-/compare/b60b06eb433777dc28e9cdab68492bfbb3a6f6ca...34088963d6c15b90d3f93fd206ca825703ac7632
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20221204/c8a50cd4/attachment-0001.htm>


More information about the debian-med-commit mailing list