Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Methode/Klasse "Modal" aufrufen? (https://www.delphipraxis.net/209215-methode-klasse-modal-aufrufen.html)

MorrisF 10. Nov 2021 10:27


Methode/Klasse "Modal" aufrufen?
 
Hallo liebe Delphi-Praxis Community:-D,
Ich bin auf ein Problem mit einem meiner Delphi-Projekte gestoßen. Habe eine SIP-Phone-Klasse geschrieben, um Clients anzurufen.
Funktioniert soweit tadellos, aber ich will, dass das Programm wartet, bis der Anruf abgeschlossen ist.
So rufe ich einen Client an:
Delphi-Quellcode:
procedure TDialog_TelefonVOIP_Test.ButtonQuickCallClick(Sender: TObject);
var
  tmpTel: TTelefon;
begin
  tmpTel := TTelefon.Create(Self, '192.168.x.y', 'xy', '******', True, True);
  try
    tmpTel.Anrufen('001726599722', True, 'This is a text to speech test. Is this working?', True);
  finally
    FreeAndNil(tmpTel);
  end;
end;
Das Problem ist, dass das Programm in FreeAndNil(tmpTel) geht, bevor der Aufruf fertig/überhaupt gestartet ist.
Hier ist der vereinfachte Code meiner TTelefon-Klasse:
Delphi-Quellcode:
unit TEST_Telefon;

interface

uses
  Classes, SysUtils, Controls, Dialogs, Vcl.ExtCtrls, Vcl.Forms, System.Threading,
  sipclient, call, ringtone;

type
  RCallData = record
    Call: ICall;
    Number: string;
    TTS: Boolean;
    TTSText: string;
  end;

var
  CallData: RCallData;
  SIP_Client: Tsipclient;

type
  TTelefon = class(TObject)
  private
    FServerConnected: Boolean;
    FRinging: Boolean;
    FCallConnected: Boolean;

    Caller: TComponent;

    procedure OnAnswer(Sender: TObject; const aCall: ICall);
    procedure OnHangUp(Sender: TObject; const aCall: ICall);

  protected
    function Connect(const aServer, aUser, aPass: string): Boolean;
    function Disconnect(): Boolean;

  public
    Server: string;
    User: string;
    Pass: string;

    property ServerConnected: Boolean read FServerConnected;
    property Ringing: Boolean read FRinging;
    property CallConnected: Boolean read FCallConnected;

    constructor Create(aCaller: TComponent; const aServer, aUser, aPass: string; aConnect: Boolean=True);
    destructor Destroy(); override;

    function Call(aNumber: string; aTTS: Boolean=False; aTTSText: String=''): Boolean;
    function HangUp(aDisconnect: Boolean=False): Boolean;

    function GetAnrufStatus(aAnruf: ICall=nil): string;
  end;

implementation

{ TTelefon }

constructor TTelefon.Create(aCaller: TComponent; const aServer, aUser, aPass: string; aConnect: Boolean=True);
begin
  try
    Caller := aCaller;

    if not Assigned(SIP_Client) then
      SIP_Client := TSIPclient.Create(Caller);

    SIP_Client.OnAnswer := OnAnswer;
    SIP_Client.OnBye := OnHangup;

    Server := aServer;
    User := aUser;
    Pass := aPass;

    FServerConnected := False;
    FCallConnected := False;
    FRinging := False;

    if aConnect then
      FServerConnected := Connect(Server, User, Pass);
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

function TTelefon.Connect(const aServer, aUser, aPass: string): Boolean;
var
  tmpConnected: Boolean;
begin
  Result := False;
  try
    tmpConnected := False;

    SIP_Client.Host := aServer;
    SIP_Client.User := aUser;
    SIP_Client.Password := aPass;
    SIP_Client.Proxy := aServer;
    SIP_Client.Active := True;
    SIP_Client.Register;
    tmpConnected := True;

    Result := tmpConnected;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

function TTelefon.Call(aNumber: string; aTTS: Boolean=False; aTTSText: String=''): Boolean;
var
  tmpOK: Boolean;
begin
  try
    tmpOK := False;
    if not FServerConnected then
      FServerConnected := Connect(Server, User, Pass);

    if FServerConnected then
    begin
      CallData.Number := aNumber;
      CallData.TTS := aTTS;
      CallData.TTSText := aTTSText;

      if not Assigned(CallData.Call) then
        CallData.Call := SIP_Client.Call(CallData.Number)
      else if CallData.Call.State = csRinging then
        CallData.Call.Answer()
    end;

    Result := tmpOK;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

function TTelefon.HangUp(aDisconnect: Boolean=False): Boolean;
var
  tmpAufgelegt: Boolean;
begin
  Result := False;
  try
    tmpAufgelegt := False;

    if FCallConnected then
    begin
      if Assigned(CallData.Call) then
        CallData.Call.EndCall();
      tmpAufgelegt := True;

      if aDisconnect and FServerConnected then
        tmpAufgelegt := Disconnect();
    end
    else
      tmpAufgelegt := True;

    OnHangUp(nil, CallData.Call);

    Result := tmpAufgelegt;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

function TTelefon.Disconnect(): Boolean;
begin
  Result := False;
  try
    SIP_Client.Active := False;
    FServerConnected := False;
    Result := not FServerConnected;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

procedure TTelefon.OnAnswer(Sender: TObject; const aCall: ICall);
begin
  inherited;
  try
    if Assigned(aCall) then
      CallData.Call := aCall;
    FCallConnected := True;
    FRinging := False;

    if CallData.TTS AND (CallData.TTSText <> '') then
    begin
      Sleep(50);
      if not Assigned(CallData.Call) then
        CallData.Call := aCall;
      CallData.Call.PlayText(CallData.TTSText, Integer(0));
    end;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

procedure TTelefon.OnHangUp(Sender: TObject; const aCall: ICall);
begin
  inherited;
  try
    if Assigned(aCall) then
      CallData.Call := aCall;
    FCallConnected := False;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

destructor TTelefon.Destroy();
begin
  try
    try
      if FCallConnected then
        HangUp();
      if FServerConnected then
        Disconnect();
    finally
      FreeAndNil(SIP_Client);
    end;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;


end.
Ich glaube, ich brauche die Funktionalität von ShowModal() innerhalb der Anrufen()-Methode. Ist das möglich?
Ich würde mich freuen, wenn mir jemand helfen könnte!

Grüße

Morris F

Uwe Raabe 10. Nov 2021 12:25

AW: Methode "Modal" aufrufen mit TThreads?
 
Erstmal, warum die Kombination aus Thread und Task?

HolgerX 10. Nov 2021 17:09

AW: Methode "Modal" aufrufen mit TThreads?
 
Hmm...

Zitat:

Zitat von MorrisF (Beitrag 1497344)
Delphi-Quellcode:
procedure TDialog_TelefonVOIP_Test.ButtonQuickCallClick(Sender: TObject);
var
  tmpTel: TTelefon;
begin
  tmpTel := TTelefon.Create(Self, '192.168.x.y', 'xy', '******', True, True);
  try
    tmpTel.Anrufen('001726599722', True, 'This is a text to speech test. Is this working?', True);
  finally
    FreeAndNil(tmpTel);
  end;
end;


Wenn Du den Thread mit FreeOnTerminate := True; erzeugst, wieso gibst Du in dann mit FreeAndNil(tmpTel); frei?
Lass dass FreeAndNil weg und fertig.

Wenn das Gespräch dann fertig ist, gibt sich der Thread selber frei....

venice2 10. Nov 2021 17:13

AW: Methode "Modal" aufrufen mit TThreads?
 
Richtig ;)
Und füge bei FreeAndNil(tmpTel); lieber einen exception Handler ein.
Delphi-Quellcode:
   
except
  on e: Exception do
      ShowMessage(e.Message);

Uwe Raabe 10. Nov 2021 21:32

AW: Methode "Modal" aufrufen mit TThreads?
 
Zitat:

Zitat von MorrisF (Beitrag 1497344)
Aber das Programm wartet überhaupt nicht.

Dann schauen wir halt mal auf deinen Code.
Delphi-Quellcode:
procedure TCallThread.Execute;
var
  tmpTask: ITask;
begin
  inherited;
  try
    tmpTask := TTask.Create(
      procedure
      begin
        Anruf(CallData);

        while not AnrufFertig do
          tmpTask.Wait();
        WaitFor();
      end
    );
    tmpTask.Start;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;
Das Execute des Threads erzeugt also eine Task (Inhalt erstmal egal) und startet diese. Die Task wird in einem separaten Thread ausgeführt. Also ist die Execute-Methode damit beendet und wird verlassen. Der Code in der Task wird dann zwar noch in dem anderen Thread ausgeführt, aber der TAnrufThread wird wegen FreeOnTerminate nach dem Verlassen von Execute schon freigegeben.

Daher auch meine Frage
Zitat:

Zitat von Uwe Raabe (Beitrag 1497356)
warum die Kombination aus Thread und Task?

Entweder das eine oder das andere, aber nicht beides!

MorrisF 11. Nov 2021 09:50

AW: Methode/Klasse "Modal" aufrufen?
 
Habe grade meine Frage geupdated, weil die Herangehensweise falsch war

Uwe Raabe 11. Nov 2021 10:47

AW: Methode/Klasse "Modal" aufrufen?
 
Zitat:

Zitat von MorrisF (Beitrag 1497412)
Habe grade meine Frage geupdated, weil die Herangehensweise falsch war

Das ist nicht so schön, denn damit verlieren alle bisherigen Antworten ihren Kontext. Wenn du also was updatest, dann mach das ein einem eigenen Beitrag und nicht im Eingangspost. So kann man der Historie besser folgen.

Nebenbei: Das Anrufen heißt offenbar jetzt Call.

Frage: Wo wird HangUp aufgerufen bzw. woran erkennst du dass der Call beendet ist?


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz