AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Methode/Klasse "Modal" aufrufen?

Ein Thema von MorrisF · begonnen am 10. Nov 2021 · letzter Beitrag vom 11. Nov 2021
Antwort Antwort
MorrisF

Registriert seit: 3. Apr 2019
41 Beiträge
 
#1

Methode/Klasse "Modal" aufrufen?

  Alt 10. Nov 2021, 11:27
Hallo liebe Delphi-Praxis Community,
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

Geändert von MorrisF (11. Nov 2021 um 10:50 Uhr) Grund: Mit Threads zu arbeiten macht hier keinen Sinn, da TSIPClient schon eine synkrone Klasse ist
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.445 Beiträge
 
Delphi 12 Athens
 
#2

AW: Methode "Modal" aufrufen mit TThreads?

  Alt 10. Nov 2021, 13:25
Erstmal, warum die Kombination aus Thread und Task?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
969 Beiträge
 
Delphi 6 Professional
 
#3

AW: Methode "Modal" aufrufen mit TThreads?

  Alt 10. Nov 2021, 18:09
Hmm...

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....
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#4

AW: Methode "Modal" aufrufen mit TThreads?

  Alt 10. Nov 2021, 18:13
Richtig
Und füge bei FreeAndNil(tmpTel); lieber einen exception Handler ein.
Delphi-Quellcode:
    
except
  on e: Exception do
      ShowMessage(e.Message);
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.445 Beiträge
 
Delphi 12 Athens
 
#5

AW: Methode "Modal" aufrufen mit TThreads?

  Alt 10. Nov 2021, 22:32
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
warum die Kombination aus Thread und Task?
Entweder das eine oder das andere, aber nicht beides!
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
MorrisF

Registriert seit: 3. Apr 2019
41 Beiträge
 
#6

AW: Methode/Klasse "Modal" aufrufen?

  Alt 11. Nov 2021, 10:50
Habe grade meine Frage geupdated, weil die Herangehensweise falsch war
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.445 Beiträge
 
Delphi 12 Athens
 
#7

AW: Methode/Klasse "Modal" aufrufen?

  Alt 11. Nov 2021, 11:47
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?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:22 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