Link to home
Start Free TrialLog in
Avatar of Peter Kiers
Peter KiersFlag for Netherlands

asked on

Read the values from Inifile.

Hi,

I have made a dialogform called SettingsDlg.
On this form I have a listbox (called lbVoices) where
the speech-engines get loaded. And 2 trackbars
for the Volume and Rate(called tbVolume and tbRate).

The selections that are made in the SettingsDlg
will be saved and loaded from an INI-file. The
purpose of the SettingsDlg is to set the default
Speech-engine, rate and volume.

But on the main form (called MainForm) I have
a Combobox called (cbVoices) and 2 spinedits
for the volume and rate (VolspEdt and RateEdt) also.

What I would like is that alle the speech-engines
get loaded in the cbvoices aslo but the engine selected
that is mentioned in the ini-file. And the spinedits have
to get their value from the ini-file too.

Is that possible?
If so who can help me?

I have put the code of the SettingsDlg in the code-section.

and these are the procedures of the mainform that has to be changed:

procedure TMainForm.FormCreate(Sender: TObject);
var
  I: Integer;
  SOToken: ISpeechObjectToken;
  SOTokens: ISpeechObjectTokens;
begin
  SpVoice1.EventInterests := SVEAllEvents;
  SOTokens := SpVoice1.GetVoices('', '');
  for I := 0 to SOTokens.Count - 1 do
  begin
    SOToken := SOTokens.Item(I);
    cbVoices.Items.AddObject(SOToken.GetDescription(0), TObject(SOToken));
    SOToken._AddRef;
  end;
  if cbVoices.Items.Count > 0 then
  begin
    cbVoices.ItemIndex := 0;
    cbVoices.OnChange(cbVoices);
  end;
  RateSpEdt.Value := SpVoice1.Rate;
  VolSpEdt.Value:= SpVoice1.Volume;
end;

procedure TMainForm.RateSpEdtChange(Sender: TObject);
begin
  StopBtn.Click;
  SpVoice1.Rate :=RateSpEdt.Value;
end;

procedure TMainForm.VolSpEdtChange(Sender: TObject);
begin
  StopBtn.Click;
  SpVoice1.Volume := VolSpEdt.Value;
end;

Peter

unit Settings;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls,
  Buttons, ComCtrls, ExtCtrls, Spin, IniFiles, DBCtrls, OleServer, SpeechLib_TLB;

type
  TSettingsDlg = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    OKBtn: TButton;
    CancelBtn: TButton;
    HelpBtn: TButton;
    Label2: TLabel;
    Label7: TLabel;
    reText: TRichEdit;
    SpVoice2: TSpVoice;
    TestBtn: TButton;
    LbVoices: TListBox;
    tbRate: TTrackBar;
    tbVolume: TTrackBar;
    tbPitch: TTrackBar;
    StaticText1: TStaticText;
    StaticText2: TStaticText;
    StaticText3: TStaticText;
    lblRate: TLabel;
    lblVolume: TLabel;
    lblPitch: TLabel;
    procedure SpVoice2StartStream(ASender: TObject; StreamNumber: Integer;
      StreamPosition: OleVariant);
    procedure SpVoice2EndStream(ASender: TObject; StreamNumber: Integer;
      StreamPosition: OleVariant);
    procedure tbPitchChange(Sender: TObject);
    procedure tbRateChange(Sender: TObject);
    procedure tbVolumeChange(Sender: TObject);
    procedure TestBtnClick(Sender: TObject);
    procedure LbVoicesClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    SettingsFile: string;
    procedure LoadSettings;
    procedure SaveSettings;
  public
    { Public declarations }
  end;

var
  SettingsDlg: TSettingsDlg;

implementation

uses Main;

{$R *.dfm}

procedure TSettingsDlg.FormCreate(Sender: TObject);
var
  I: Integer;
  SOToken: ISpeechObjectToken;
  SOTokens: ISpeechObjectTokens;
begin
  SettingsFile := ChangeFileExt(Application.ExeName, '.ini');
  SpVoice2.EventInterests := SVEAllEvents;
  SOTokens := SpVoice2.GetVoices('', '');
  for I := 0 to SOTokens.Count - 1 do
  begin
    SOToken := SOTokens.Item(I);
    lbVoices.Items.AddObject(SOToken.GetDescription(0), TObject(SOToken));
    SOToken._AddRef;
  end;
  tbRate.Position := SpVoice2.Rate;
  lblRate.Caption := IntToStr(tbRate.Position);
  tbVolume.Position := SpVoice2.Volume;
  lblVolume.Caption := IntToStr(tbVolume.Position);
  LoadSettings;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.FormDestroy(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to lbVoices.Items.Count - 1 do
  ISpeechObjectToken(Pointer(lbVoices.Items.Objects[I]))._Release;
  SaveSettings;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.LbVoicesClick(Sender: TObject);
var
  SOToken: ISpeechObjectToken; 
begin 
 SOToken := ISpeechObjectToken(Pointer( lbVoices.Items.Objects[lbVoices.ItemIndex])); 
 SpVoice2.Voice := SOToken; 
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.LoadSettings;
var
 ini: TIniFile;
 defVoice: string;
begin
 ini := TIniFile.Create(SettingsFile);
 try
  if lbVoices.Items.Count > 0
   then defVoice := lbVoices.Items[0]
   Else defVoice := '';
  lbVoices.ItemIndex := lbVoices.Items.IndexOf(ini.ReadString('Voice','Voice', defVoice));
  tbVolume.Position := ini.ReadInteger('Voice', 'Volume', SpVoice2.Volume);
  tbRate.Position := ini.ReadInteger('Voice', 'Rate', SpVoice2.Rate);
 finally
  FreeAndNil(ini);
 end;
 LbVoicesClick(lbVoices);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.SaveSettings;
var ini: TIniFile;
    defVoice: string;
begin
  ini := TIniFile.Create(SettingsFile);
  try
  defVoice := '';
  if lbVoices.ItemIndex >= 0 then
  defVoice := lbVoices.Items[lbVoices.ItemIndex];
    ini.WriteString('Voice', 'Voice', defVoice);
    ini.WriteInteger('Voice', 'Volume', SpVoice2.Volume);
    ini.WriteInteger('Voice', 'Rate', SpVoice2.Rate);
  finally
    FreeAndNil(ini)
  end;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.SpVoice2EndStream(ASender: TObject;
  StreamNumber: Integer; StreamPosition: OleVariant);
begin
  TestBtn.Caption := 'Test';
  tbPitch.Enabled := true;
  tbVolume.Enabled := true;
  tbRate.Enabled := true;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.SpVoice2StartStream(ASender: TObject;
  StreamNumber: Integer; StreamPosition: OleVariant);
begin
  TestBtn.Caption := 'Stop';
  tbPitch.Enabled := false;
  tbVolume.Enabled := false;
  tbRate.Enabled := false;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.tbPitchChange(Sender: TObject);
begin
  lblPitch.Caption := IntToStr(tbPitch.Position);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.tbRateChange(Sender: TObject);
begin
  SpVoice2.Rate := tbRate.Position;
  lblRate.Caption := IntToStr(tbRate.Position);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.tbVolumeChange(Sender: TObject);
begin
  SpVoice2.Volume := tbVolume.Position;
  lblVolume.Caption := IntToStr(tbVolume.Position);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.TestBtnClick(Sender: TObject);
begin
 If TestBtn.Caption = 'Test' then
 begin
   TestBtn.Caption := 'Stop';
   SpVoice2.Speak(reText.Text, SVSFlagsAsync);
 end else begin
   TestBtn.Caption := 'Test';
   SpVoice2.Skip('Sentence', MaxInt);
 end;
end;
(*---------------------------------------------------*)
end.

Open in new window

Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

you mean you have 2 interfaces to select the settings ? one in your main form and one in your SettingsDlg ?
that's a bit strange.

Can you tell us what is the purpose of this dual config ?
The fact that you use also 2 TSpVoice objects, one in your settings and one in your main form is a bit confusing as well.

What I would do, if I where you, would be to keep the TSettingsDlg as it is because it's cleaner (just rename SpVoice2 as SpVoice), and remove the SpVoice in main form.

You would then in all your application use ONLY the spVoice in your dlg form, for all purpose. And no config in the main form, just a button to access the SettingsDlg
Avatar of Peter Kiers

ASKER

I want to give the user the ability to set default settings of the speech-engine, volume
and rate in the SettingsDlg. When these values are chosen they will be save to ini-file.
And the mainform has a combobox and 2 spinedits for the speechegine and volume
and rate and these components have to get their value from the inifile. Or is theire a better way?
Yes, I use 2 spvoice-components, and I know 1 is better, but I though to ask that in another question.
P.
> And the mainform has a combobox and 2 spinedits for the speechegine and volume
> and rate and these components have to get their value from the inifile.
So, in this case, what is the purpose of the SettingsDlg ? Just to set the Default values in case there is nothing in the ini file for the main form components settings ?

> Yes, I use 2 spvoice-components, and I know 1 is better, but I though to ask that in another question
Then probably it's time to rethink your application with ONE spVoice, and only ONE settings interface

I think the only thing you have to do is to remove in your main form all the components to set the voice parameters, replace with a Settings button that calls your dlg, and replace all SpVoice with SettingsDlg.SpVoice when you start reading something
"What I would do, if I where you, would be to keep the TSettingsDlg as it is because it's cleaner (just rename SpVoice2 as SpVoice), and remove the SpVoice in main form."

I did that.

P.
Another application has that too.
example1: the dialog where the user can select the speechengine and volume and rate
example2: the mainform that get the values that are set from the settingsdlg after pressing ok.

p.
EX1.jpg
forgot the other pic.
ex2.jpg
If you want to use these settings in multiple applications, you should design a frame containing only the voice config (and the voice component). That is just another problem.
for the moment, I think having 2 interfaces for settings is confusing. If you want to keep it that way, the main one (settingsDlg) should be the only one save in ini, and the other one is just for temporary adjustements. The initial value of these at application startup should be the same as the SettingsDlg (and initialized as well when you reopen/close the settingsDlg)
IN STEPS:

1. At the start of the application the combobox and the 2 spinedits have to get the values out of the inifile.
2. When the user open SettingsDlg he can then select his volume/rate settings and speechengine.
3. After pressing OK the values are stored back to the inifile and passed on to the combobox and spinedits.

P.
Better explained:

1. At the start of the application the combobox and the 2 spinedits on the mainform have to get the values out of the inifile.
2. When the user open SettingsDlg he can then select his volume/rate settings and speechengine.
3. After pressing OK of the SettingsDlg the values are stored back to the inifile and passed on to the combobox and spinedits on the main form

P.
ASKER CERTIFIED SOLUTION
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you this is what I wanted.
Another 500 p's are comming to you, again.

Greetings,
Peter
here is a modified Settings unit. Apart some minor adjustments and the Get/Set methods I was talking about, I renamed SpVoice2 to SpVoice, so if you haven't done so already you should do it to change the dfm as well before replacing the .PAS code with this
unit Settings;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls,
  Buttons, ComCtrls, ExtCtrls, Spin, IniFiles, DBCtrls, OleServer, SpeechLib_TLB;

type
  TSettingsDlg = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    OKBtn: TButton;
    CancelBtn: TButton;
    HelpBtn: TButton;
    Label2: TLabel;
    Label7: TLabel;
    reText: TRichEdit;
    SpVoice: TSpVoice;
    TestBtn: TButton;
    LbVoices: TListBox;
    tbRate: TTrackBar;
    tbVolume: TTrackBar;
    tbPitch: TTrackBar;
    StaticText1: TStaticText;
    StaticText2: TStaticText;
    StaticText3: TStaticText;
    lblRate: TLabel;
    lblVolume: TLabel;
    lblPitch: TLabel;
    procedure SpVoice2StartStream(ASender: TObject; StreamNumber: Integer;
      StreamPosition: OleVariant);
    procedure SpVoice2EndStream(ASender: TObject; StreamNumber: Integer;
      StreamPosition: OleVariant);
    procedure tbPitchChange(Sender: TObject);
    procedure tbRateChange(Sender: TObject);
    procedure tbVolumeChange(Sender: TObject);
    procedure TestBtnClick(Sender: TObject);
    procedure LbVoicesClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    SettingsFile: string;
    procedure LoadSettings;
    procedure SaveSettings;
  public
    { Public declarations }
    
	procedure Set(voiceIndex,Pitch,Rate,Volume:Integer);
	procedure Get(Var voiceIndex,Pitch,Rate,Volume:Integer);
  end;

var
  SettingsDlg: TSettingsDlg;

implementation

uses Main;

{$R *.dfm}

procedure TSettingsDlg.FormCreate(Sender: TObject);
var
  I: Integer;
  SOToken: ISpeechObjectToken;
  SOTokens: ISpeechObjectTokens;
begin
  SettingsFile := ChangeFileExt(Application.ExeName, '.ini');
  SpVoice.EventInterests := SVEAllEvents;
  SOTokens := SpVoice.GetVoices('', '');
  for I := 0 to SOTokens.Count - 1 do
  begin
    SOToken := SOTokens.Item(I);
    lbVoices.Items.AddObject(SOToken.GetDescription(0), TObject(SOToken));
    SOToken._AddRef;
  end;
  tbPitch.Position := SpVoice.Pitch;
  tbRate.Position := SpVoice.Rate;
  tbVolume.Position := SpVoice.Volume;
  LoadSettings;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.FormDestroy(Sender: TObject);
var
  I: Integer;
begin
  SaveSettings;
  for I := 0 to lbVoices.Items.Count - 1 do
  ISpeechObjectToken(Pointer(lbVoices.Items.Objects[I]))._Release;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.LbVoicesClick(Sender: TObject);
var
  SOToken: ISpeechObjectToken; 
begin 
 SOToken := ISpeechObjectToken(Pointer( lbVoices.Items.Objects[lbVoices.ItemIndex])); 
 SpVoice.Voice := SOToken; 
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.LoadSettings;
var
 ini: TIniFile;
 defVoice: string;
begin
 ini := TIniFile.Create(SettingsFile);
  if lbVoices.Items.Count > 0
   then defVoice := lbVoices.Items[0]
   Else defVoice := '';
 Set(lbVoices.Items.IndexOf(ini.ReadString('Voice','Voice', defVoice)),
 ini.ReadInteger('Voice', 'Pitch', SpVoice.Pitch),
 ini.ReadInteger('Voice', 'Rate', SpVoice.Rate),
 ini.ReadInteger('Voice', 'Volume', SpVoice.Volume));
 FreeAndNil(ini);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.SaveSettings;
var ini: TIniFile;
    defVoice: string;
begin
  ini := TIniFile.Create(SettingsFile);
  try
  defVoice := '';
  if lbVoices.ItemIndex >= 0 then
  defVoice := lbVoices.Items[lbVoices.ItemIndex];
    ini.WriteString('Voice', 'Voice', defVoice);
    ini.WriteInteger('Voice', 'Pitch', SpVoice.Pitch);
    ini.WriteInteger('Voice', 'Volume', SpVoice.Volume);
    ini.WriteInteger('Voice', 'Rate', SpVoice.Rate);
  finally
    FreeAndNil(ini)
  end;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.SpVoice2EndStream(ASender: TObject;
  StreamNumber: Integer; StreamPosition: OleVariant);
begin
  TestBtn.Caption := 'Test';
  tbPitch.Enabled := true;
  tbVolume.Enabled := true;
  tbRate.Enabled := true;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.SpVoice2StartStream(ASender: TObject;
  StreamNumber: Integer; StreamPosition: OleVariant);
begin
  TestBtn.Caption := 'Stop';
  tbPitch.Enabled := false;
  tbVolume.Enabled := false;
  tbRate.Enabled := false;
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.tbPitchChange(Sender: TObject);
begin
  lblPitch.Caption := IntToStr(tbPitch.Position);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.tbRateChange(Sender: TObject);
begin
  SpVoice.Rate := tbRate.Position;
  lblRate.Caption := IntToStr(tbRate.Position);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.tbVolumeChange(Sender: TObject);
begin
  SpVoice.Volume := tbVolume.Position;
  lblVolume.Caption := IntToStr(tbVolume.Position);
end;
(*---------------------------------------------------*)
procedure TSettingsDlg.TestBtnClick(Sender: TObject);
begin
 If TestBtn.Caption = 'Test' then
 begin
   TestBtn.Caption := 'Stop';
   SpVoice.Speak(reText.Text, SVSFlagsAsync);
 end else begin
   TestBtn.Caption := 'Test';
   SpVoice.Skip('Sentence', MaxInt);
 end;
end;
(*---------------------------------------------------*)

procedure TSettingsDlg.Set(voiceIndex,Pitch,Rate,Volume:Integer);
begin
 lbVoices.ItemIndex := voiceIndex;
 lbVoicesClick(lbVoices);
 tbPitch.Position := Pitch;
 tbRate.Position := Rate;
 tbVolume.Position := Volume;
 lblVolume.Caption := IntToStr(tbVolume.Position);
 lblRate.Caption := IntToStr(tbRate.Position);
end;

procedure TSettingsDlg.Get(Var voiceIndex,Pitch,Rate,Volume:Integer);
begin
 voiceIndex:=lbVoices.ItemIndex;
 Pitch := tbPitch.Position;
 Rate  := tbRate.Position ;
 Volume:= tbVolume.Position;
end;

end.

Open in new window