{
 -------------------------------------------------------------------------
 Copyright (C) 1998-2003 Häger+Busch                   / >>>>>>>>> /-----
 Ingenieurbuero fuer Kommunikationslösungen           / <<<<<<<<< /
 ----------------------------------------------------/ >>>>>>>>> /
 All rights reserved.
                                                    http://www.commso.com

 Project     : hbTapi Components
 Modul       : Sample Calls

 Description : This sample shows you one way to handle multiple calls and
               uses the asynchronous mode.

 History     : [-] Fixed [+] Added [*] Improved

 01/01/03   Creation
}
unit uMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ToolWin, ComCtrls, ImgList, StdCtrls, ExtCtrls,
  ActnList, Menus, Buttons, uCallDisplay, hbTapi, hbTapiUtils, Tapi;

type
  TMainForm = class(TForm)
    TapiLine1: TTapiLine;
    ImageList_Calls: TImageList;
    ActionList1: TActionList;
    Action_AnswerCall: TAction;
    Action_CancelCall: TAction;
    Action_HoldCall: TAction;
    Action_PageCalls: TAction;
    Action_Pagebook: TAction;
    Action_PageJournal: TAction;
    Action_PageLog: TAction;
    ImageList_Actions: TImageList;
    Action_MakeCall: TAction;
    Action_BlindTransfer: TAction;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    ListView_Log: TListView;
    Panel_Calls: TPanel;
    ListView_Journal: TListView;
    Panel2: TPanel;
    Label1: TLabel;
    ComboBox_Line: TComboBox;
    TapiPhone1: TTapiPhone;
    Panel3: TPanel;
    CheckBox_TapiMessages: TCheckBox;
    Button_ClearProt: TButton;
    CheckBox_CallStates: TCheckBox;
    CheckBox_CallInfos: TCheckBox;
    ImageList_Prot: TImageList;
    Label3: TLabel;
    Edit_PhoneNo: TEdit;
    Button1: TButton;
    procedure TapiLine1CallState(Sender: TTapiLine; Call: TTapiCall; State: Cardinal);
    procedure TapiLine1CallBegin(Sender: TTapiLine; Call: TTapiCall);
    procedure TapiLine1CallEnd(Sender: TTapiLine; Call: TTapiCall);
    procedure TapiLine1CallInfo(Sender: TTapiLine; Call: TTapiCall;
      CallInfo: Cardinal);
    procedure TapiLine1CallInfo_CallerID(Sender: TTapiLine;
      Call: TTapiCall);
    procedure TapiLine1CallInfo_CalledID(Sender: TTapiLine;
      Call: TTapiCall);
    procedure TapiLine1CallDeallocate(Sender: TTapiLine; Call: TTapiCall);
    procedure FormCreate(Sender: TObject);
    procedure Action_MakeCallExecute(Sender: TObject);
    procedure ComboBox_LineChange(Sender: TObject);
    procedure TapiLine1NewCall(Sender: TTapiLine; Call: TTapiCall);
    procedure TapiLine1TapiReply(Sender: TObject; RequestID,
      ReplyCode: Cardinal);
    procedure TapiLine1TapiMessage(Sender: TObject; MessageID, Param1,
      Param2, Param3: Cardinal);
    procedure TapiPhone1DigitPressed(Sender: TTapiPhone; Digit: Char);
    procedure TapiPhone1DigitReleased(Sender: TTapiPhone; Digit: Char);
    procedure TapiPhone1HeadsetVolume(Sender: TObject);
    procedure TapiPhone1HandsetVolume(Sender: TObject);
    procedure Button_ClearProtClick(Sender: TObject);
    procedure TapiLine1DeviceClose(Sender: TObject);
    procedure TapiLine1DeviceRemove(Sender: TObject);
    procedure TapiLine1Ring(Sender: TTapiLine; RingMode,
      RingCount: Cardinal);
  protected
  private
    FCallDisp    : TList;
    procedure SetDevice(DevID: Integer; DevName: String);
    procedure UpdateCallView;
  private

    procedure AddCallToJournal(Call: TTapiCall);
    procedure RemoveCallDisplay(Call: TTapiCall);

  public
    procedure Log(S: string; aType: Char = 'I');
    procedure LogFmt(const aFormat: string; const aArgs: array of const; aType: Char = 'I');
    function DisplayCount: Integer;
    function GetDisplay(index : integer): TFrameCallDisplay; overload;
    function GetDisplay_Call(Call: TTapiCall): TFrameCallDisplay; overload;
    property Display[index: integer] : TFrameCallDisplay read GetDisplay;
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

{*******************************************************************}
procedure TMainForm.LogFmt(const aFormat: string; const aArgs: array of const; aType: Char);
{*******************************************************************}
begin
  Log(Format(aFormat, aArgs), aType);
end;

{*******************************************************************}
procedure TMainForm.Log(S: string; aType: Char);
{*******************************************************************}
begin
  if s = '' then exit;
  with ListView_Log.Items.add do
  begin
    while SubItems.Count < 1 do
      SubItems.Add( '' );
    Caption     := FormatDateTime('hh:nn:ss', now);
    SubItems[0] := S;
    if Pos('TapiLine', S) > 0 then
      ImageIndex := 0
    else if Pos('TapiPhone', S) > 0 then
      ImageIndex := 1
    else case aType of
      'I' : ImageIndex := 3;
      'W' : ImageIndex := 4;
      'E' : ImageIndex := 5;
      'A' : ImageIndex := 6;
    else
      ImageIndex := 4;
    end;
  end;
end;

function TMainForm.DisplayCount: Integer;
var i: integer;
begin
  result := 0;
  i := 0;
  while i < Panel_Calls.ControlCount do
  begin
    if Panel_Calls.Controls[i] is TFrameCallDisplay then
    begin
      inc(result);
    end;
    inc(i);
  end;
end;

function TMainForm.GetDisplay(index : integer): TFrameCallDisplay;
var i, n: integer;
begin
  result := nil;
  i      := 0;
  n      := 0;
  while i < Panel_Calls.ControlCount do
  begin
    if Panel_Calls.Controls[i] is TFrameCallDisplay then
    begin
      if Index = n then
      begin
        result := TFrameCallDisplay(Panel_Calls.Controls[i]);
        exit;
      end;
      inc(n);
    end;
    inc(i);
  end;
end;

function TMainForm.GetDisplay_Call(Call: TTapiCall): TFrameCallDisplay;
var i, n: integer;
begin
  i := 0;
  n := DisplayCount;
  while i < n do
  begin
    if Call = Display[i].Call then
    begin
      result := Display[i];
      exit;
    end
    else if Display[i].Call = nil then
    begin
      result       := Display[i];
      Call.Tag     := Integer(Result);
      Result.Call  := Call;
      exit;
    end;
    inc(i);
  end;

  result       := TFrameCallDisplay.Create(self);
  result.Name  := '';
  result.Align := alTop;
  FCallDisp.Add(Result);
  if Call <> nil then
    Call.Tag     := Integer(Result);
  Result.Call  := Call;
  Panel_Calls.InsertControl(result);
end;

procedure TMainForm.RemoveCallDisplay(Call: TTapiCall);
var o : TFrameCallDisplay;
    i, n : integer;
begin
  o := nil;
  i := 0;
  n := DisplayCount;
  while i < n do
  begin
    if Call = Display[i].Call then
    begin
      o := Display[i];
      break;
    end;
    inc(i);
  end;

  if (o <> nil)  then
  begin
    if (n > 1) then
    begin
      Panel_Calls.RemoveControl(o);
      o.Free;
    end
    else
    begin
      o.Init;
    end;
  end;
end;

procedure TMainForm.SetDevice(DevID: Integer; DevName: String);
var i: integer;
begin
  TapiLine1.Active  := FALSE;
  TapiPhone1.Active := FALSE;

  i := 0;
  while i < DisplayCount do
  begin
    Display[i].Call := nil;
    inc(i);
  end;

  try
    if DevID >= 0 then
    begin
      TapiLine1.DeviceID        := DevID;
      ComboBox_Line.ItemIndex   := ComBoBox_Line.Items.IndexOf(TapiLine1.DeviceName);
    end
    else
    begin
      TapiLine1.DeviceName      := DevName;
      ComboBox_Line.ItemIndex   := ComBoBox_Line.Items.IndexOf(DevName);
    end;
    if ComboBox_Line.ItemIndex = -1 then
      ComboBox_Line.ItemIndex := 0;

    TapiLine1.Active := TapiLine1.DeviceName <> '';

    if TapiLine1.Phones.Available then
    begin
      TapiPhone1.DeviceID := TapiLine1.Phones.DeviceID[0];
      TapiPhone1.Active := TRUE;
      LogFmt('TTapiPhone1.RingMode= 0x%x', [TapiPhone1.Status.RingMode]);
    end;
    Caption := Format('Calls - A hbTapi Sample - %s', [TapiLine1.DeviceName]);
  except
    on E:Exception do
    begin
      Caption := Format('Calls - A hbTapi Sample - %s', ['No Device']);
      raise;
    end;
  end;
  UpdateCallView;
end;

procedure TMainForm.UpdateCallView;
var i: integer; call : TTapiCall;
begin
  i := 0;
  while i < DisplayCount do
  begin
    if (TapiLine1.Calls.IndexOf(Display[i].Call) = -1)  then
    begin
      Display[i].Free;
    end
    else
      inc(i);
  end;

  for i := 0 to TapiLine1.Calls.Count -1 do
  begin
    Call := TapiLine1.Calls[i];
    with GetDisplay_Call(Call) do
    begin
      UpdateView;
      UpdateActionList;
    end;
  end;

  if DisplayCount = 0 then
    GetDisplay_Call(nil);

end;

procedure TMainForm.AddCallToJournal(Call: TTapiCall);
var iImage      : integer;
    sAddr,
    sName       : String;
    sStart,
    sDuration,
    sDetail     : String;

begin
  if Call.WasIncoming then
  begin
    iImage := 0;
    if Call.CallerID.Blocked then
      sAddr := 'XXX'
    else
      sAddr := Call.CallerID.Address;
    sName  := Call.CallerID.Name;
  end
{$IFDEF HBTAPIEDT_PRO}
  else if Call.WasOutgoing then
  begin
    iImage := 2;
    if (Call.CalledID.Address <> '') then
      sAddr  := Call.CalledID.Address
    else if Call.Info.CalledParty <> '' then
      sAddr  := Call.Info.CalledParty
    else
      saddr := 'XXX';
    sName  := Call.CalledID.Name;
  end
{$ENDIF}
  else
    exit;

  if Call.WasDisconnected then
    sDetail := Call.StateModeText;

  if Call.WasConnected then
    inc(iImage);

  sStart    := DateTimetoStr(Call.BeginTime);
//  sDuration := DurationToStr(Call.EndTime - Call.BeginTime);

  with ListView_Journal.Items.Add do
  begin
    while SubItems.Count < 5 do
      SubItems.Add('');

    ImageIndex  := iImage;
    Caption     := sStart;
    SubItems[0] := sAddr;
    SubItems[1] := sName;
    SubItems[2] := sDuration;
    SubItems[3] := Call.OriginText;
  end;
end;

procedure TMainForm.TapiLine1CallState(Sender: TTapiLine; Call: TTapiCall; State: Cardinal);
begin
  with GetDisplay_Call(Call) do
  begin
    UpdateView;
    UpdateActionList;//State := LineCallStateToStr(Call.State);
  end;
  if CheckBox_CallStates.Checked then
    LogFmt('TapiLine1.OnCallState(%s, %x)', [Call.StateText, Call.StateModetext]);
end;

procedure TMainForm.TapiLine1CallBegin(Sender: TTapiLine; Call: TTapiCall);
begin
  LogFmt('TapiLine1.OnCallBegin (Call=%x)', [Integer(Call)]);
end;

procedure TMainForm.TapiLine1CallEnd(Sender: TTapiLine; Call: TTapiCall);
begin
  LogFmt('TapiLine1.OnCallEnd(Call=%x)', [Integer(Call)]);
  AddCallToJournal(call);
end;

procedure TMainForm.TapiLine1CallDeallocate(Sender: TTapiLine;
  Call: TTapiCall);
begin
  RemoveCallDisplay(Call);
end;

procedure TMainForm.TapiLine1CallInfo(Sender: TTapiLine; Call: TTapiCall; CallInfo: Cardinal);
begin
    if CheckBox_CallInfos.checked then case CallInfo of
    LINECALLINFOSTATE_ORIGIN :
      LogFmt('TapiLine1.OnCallInfo(%s, %s)', [LineCallInfoToStr(CallInfo),LineCallOriginToStr(Call.Info.Origin)]);
    LINECALLINFOSTATE_REASON :
      LogFmt('TapiLine1.OnCallInfo(%s, %s)', [LineCallInfoToStr(CallInfo),LINECALLREASONToStr(Call.Info.Reason)]);
    LINECALLINFOSTATE_CALLERID :
      LogFmt('TapiLine1.OnCallInfo(%s, %s, %s)', [LineCallInfoToStr(CallInfo), Call.CallerID.Address, Call.CallerID.Name]);
    LINECALLINFOSTATE_CALLEDID :
{$IFDEF HBTAPIEDT_PRO}
      LogFmt('TapiLine1.OnCallInfo(%s, %s, %s)', [LineCallInfoToStr(CallInfo), Call.CalledID.Address, Call.CalledID.Name]);
{$ELSE}
      ;
{$ENDIF}
    LINECALLINFOSTATE_REDIRECTINGID :
{$IFDEF HBTAPIEDT_ENT}
      LogFmt('TapiLine1.OnCallInfo(%s, %s, %s)', [LineCallInfoToStr(CallInfo), Call.RedirectingID.Address,Call.RedirectingID.Name]);
{$ELSE}
      ;
{$ENDIF}
    LINECALLINFOSTATE_REDIRECTIONID :
{$IFDEF HBTAPIEDT_ENT}
      LogFmt('TapiLine1.OnCallInfo(%s, %s, %s)', [LineCallInfoToStr(CallInfo), Call.RedirectionID.Address, Call.RedirectionID.Name]);
{$ELSE}
      ;
{$ENDIF}
    LINECALLINFOSTATE_MEDIAMODE     :
  else
    LogFmt('TapiLine1. OnCallInfo(%s)', [LineCallInfoToStr(CallInfo)]);
  end;
  GetDisplay_Call(Call).UpdateView;
end;

procedure TMainForm.TapiLine1CallInfo_CallerID(Sender: TTapiLine; Call: TTapiCall);
begin
  LogFmt('TapiLine1.OnCallerID(%s)', [Call.CallerID.Address]);
  GetDisplay_Call(Call).UpdateView;
end;

procedure TMainForm.TapiLine1CallInfo_CalledID(Sender: TTapiLine; Call: TTapiCall);
begin
{$IFDEF HBTAPIEDT_PRO}
  LogFmt('TapiLine1.OnCalledID(%s)', [Call.CalledID.Address]);
  GetDisplay_Call(Call).UpdateView;
{$ENDIF}
end;

procedure TMainForm.FormCreate(Sender: TObject);
var r : TFrameCallDisplay;
begin
  FCallDisp := TList.Create;
  r := TFrameCallDisplay.Create(self);
  r.Name  := '';
  r.Align := alTop;
  r.Init;
  Panel_Calls.InsertControl(r);
  ComboBox_Line.Items.Assign(TapiLine1.DeviceList);
  ComboBox_Line.Items.Insert(0, '- None -');
end;

procedure TMainForm.Action_MakeCallExecute(Sender: TObject);
var s: string;
begin
  s := Edit_PhoneNo.Text;
  if s <> '' then
  begin
    try
      Log('MakeCall started...');
      TapiLine1.MakeCall(s);
      LogFmt('MakeCall LastRequestID = $%x',[TapiLine1.LastRequestID]);
    except
      on E:Exception do
        LogFmt('MakeCall failed! %s', [E.Message]);
    end;
  end;
end;

procedure TMainForm.ComboBox_LineChange(Sender: TObject);
begin
  if TComboBox(Sender).Text = '- None -' then
    SetDevice(-1, '')
  else
    SetDevice(-1, TComboBox(Sender).Text);
end;

procedure TMainForm.TapiLine1NewCall(Sender: TTapiLine; Call: TTapiCall);
begin
{$IFDEF HBTAPIEDT_ENT}
  LogFmt('TapiLine1.OnNewCall (CallHandle= %x)', [Call.Handle]);
{$ENDIF}
end;

procedure TMainForm.TapiLine1TapiReply(Sender: TObject; RequestID,
  ReplyCode: Cardinal);
begin
  LogFmt('TapiLine1.OnTapiReply RequestID= $%x, ReplyCode= $%x', [RequestID, ReplyCode]);
end;

procedure TMainForm.TapiLine1TapiMessage(Sender: TObject; MessageID,
  Param1, Param2, Param3: Cardinal);
begin
  if CheckBox_TapiMessages.Checked then
    LogFmt('TapiLine1.OnTapiMessage MessageID= $%x, Param1= $%x, Param2= $%x, Param3= $%x', [MessageID, Param1, Param2, Param3]);
end;

procedure TMainForm.TapiPhone1DigitPressed(Sender: TTapiPhone;
  Digit: Char);
begin
  LogFmt('TapiPhone1.OnDigitPressed Digit= %s', [Digit]);
end;

procedure TMainForm.TapiPhone1DigitReleased(Sender: TTapiPhone;
  Digit: Char);
begin
  LogFmt('TapiPhone1.OnDigitReleased Digit= %s', [Digit]);
end;

procedure TMainForm.TapiPhone1HeadsetVolume(Sender: TObject);
begin
{$IFDEF HBTAPIEDT_PRO}
  LogFmt('TapiPhone1.OnHeadsetVolume Volume= %d', [TapiPhone1.Headset.Volume]);
{$ENDIF}
end;

procedure TMainForm.TapiPhone1HandsetVolume(Sender: TObject);
begin
{$IFDEF HBTAPIEDT_PRO}
  LogFmt('TapiPhone1.OnHandsetVolume Volume= %d', [TapiPhone1.Handset.Volume]);
{$ENDIF}
end;

procedure TMainForm.Button_ClearProtClick(Sender: TObject);
begin
  ListView_Log.Items.Clear;
end;

procedure TMainForm.TapiLine1DeviceClose(Sender: TObject);
begin
  LogFmt('Device closed', []);
end;

procedure TMainForm.TapiLine1DeviceRemove(Sender: TObject);
begin
  LogFmt('Device removed', []);
end;

procedure TMainForm.TapiLine1Ring(Sender: TTapiLine; RingMode,
  RingCount: Cardinal);
begin
  LogFmt('Ringing %d', [RingCount]);
end;

end.

