unit uIVRServer;

interface

uses
  Classes, SysUtils, syncobjs, Windows;

type TTask = (SIPNone,SIPConnect, SIPRecord, SIPPlay, SIPDisconnect,
    SIPDigits, SIPCall, SIPSendDTMF, SIPResume);


type
  TIVR = class(TThread)
  private
    { Private declarations }
     Digits: string;
     LockIVR: TCriticalSection;
  protected
    procedure Execute; override;
  public
    Connected: Boolean;
    chan: Integer;
    PlayFileName: string;
    RecordFileName: string;
    Task: TTask;
    WaitingTask: TTask;
    SIPAddr: string;
    Author: string;
    Subject: string;
    DTMFDigit: Char;
    Worktype: string;
    StartupDir: string;
    FileLength: Integer;
    JobName: string;
    Count: Integer;
    IVRStatus: ShortString;
    IamSuspended: Boolean;
    Logging: Boolean;
    procedure GetAuthor;
    procedure GetSubject;
    procedure GetWorktype;
    procedure GetRecording;
    procedure PlayRecording;
    procedure DoDisconnect;
    procedure Connect;
    procedure Disconnect;
    procedure PlayFile(FileName: string);
    procedure RecordFile(FileName: string);
    function Getdigits(NumDigits: Integer): string;
    function GetNextDigit: string;
    function GetImmediateDigit: string;
    procedure Log(s: string);
    procedure LogBad(s: string);
    procedure AddDigit(d: Char);
    procedure Send(s: string);
    procedure SendDigit(c: char);
    procedure SendJobInfo;
    procedure SuspendThisThread(MyTask: TTask);
    function  GetTaskName(Task: TTask): String;
  end;

implementation


function GetFileSizeFromName(FileName: string): Integer;

var
f: file of Byte;

begin
 Result := 0;
 try
    if FileExists(FileName) = true then begin
        AssignFile(f, FileName);
        // 02/25/03 placed try/except around Reset and FileSize
        // to insure that CloseFile is called.
        try
            Reset(f);
            Result := FileSize(f);
        except

        end;
        CloseFile(f);
    end;
 except

 end;

end;


procedure TIVR.Execute;
var
FirstTime: Boolean;
MaxCount: Integer;
t: Integer;
s: string;
begin
  { Place thread code here }

  StartupDir:= GetCurrentDir;

  LockIVR:= TCriticalSection.Create;
  FirstTime:= True;
  Count:= 0;
  MaxCount := 1000;
  IamSuspended:= False;
  JobName := 'job' + IntToStr(Chan) + '.mlw';

  Sleep(500 * Chan);

  FileLength := GetFileSizeFromName(StartupDir + '\Prompts\author.mlw');
  IVRStatus:= '???';
  
  While (Terminated = False) do
  begin
       Connected:= False;
       Count:= Count + 1;
       task:= SIPNone;
       WaitingTask:= SIPNone;
       Worktype:= '';
       Digits := '';
       DTMFDigit:= '0';
       Subject:= '';
       Connect;
       Log('Begin Conversation: ' + SIPAddr);
       GetAuthor;
       GetWorktype;
       GetSubject;
       while Connected and Not Terminated do
       begin
            s:= GetNextDigit;
            if Not Connected then break;
            if s = '2' then
                GetRecording
            else if s = '7' then
                PlayRecording
            else if s = '8' then
                SendJobInfo
            else
                Log('Unknown DTMF[' + s + ']');

       end;
       DoDisconnect;
  end;
  Log('<<<< Terminated >>>>');
  LockIVR.Free;
end;

procedure TIVR.GetAuthor;
begin
    Log('Enter GetAuthor');
    PlayFile('author.mlw');
    if Connected then
        Author := GetDigits(4)
    else
        Author := '';

    Log('Exit GetAuthor:' + Author);
end;
procedure TIVR.GetSubject;
begin
    Log('Enter GetSubject');
    PlayFile('subject.mlw');
    if Connected then
        Subject := GetDigits(9)
    else
        Subject := '';

    Log('Exit GetSubject:' + Subject);
end;
procedure TIVR.GetWorktype;
begin
    Log('Enter Worktype');
    PlayFile('worktype.mlw');
    if Connected then
        Worktype := GetDigits(2)
    else
        Worktype := '';

    Log('Exit Worktype:' + Worktype);
end;
procedure TIVR.GetRecording;
begin
    Log('Enter GetRecording');
    if Connected then RecordFile(JobName);
    Log('Exit GetRecording');
end;
procedure TIVR.PlayRecording;
begin
    Log('Enter PlayRecording');
    if Connected then PlayFile(JobName);
    Log('Exit PlayRecording');
end;
procedure TIVR.DoDisconnect;
begin
    Log('Enter DoDisconnet');
    if Connected then Disconnect;
    Log('Exit DoDisconnet');
end;
procedure TIVR.Connect;
begin
    Log('Enter Connect');
    SuspendThisThread(SIPConnect);
    Log('Exit Connect');
end;

procedure TIVR.Disconnect;
begin
    Log('Enter Disconnect');
    SuspendThisThread(SIPDisConnect);
    Log('Exit Disconnect');
end;

procedure TIVR.SuspendThisThread(MyTask: TTask);
begin
    Log('Enter SuspendThisThread:' + GetTaskName(MyTask));
    Task:= MyTask;
    IamSuspended:= True;

    While(IamSuspended) do begin
       Sleep(50);
    end;
    Task:= SIPNone;
    WaitingTask:= SIPNone;
    IamSuspended:= False;
    Log('Thread Resumed');
    Log('Exit SuspendThisThread');
end;

procedure TIVR.PlayFile(FileName: string);
begin
   Log('Enter PlayFile: ' + FileName);
   PlayFileName:= FileName;
   SuspendThisThread(SIPPLay);
   Log('Exit PlayFile');
end;
procedure TIVR.RecordFile(FileName: string);
begin
    Log('Enter RecordFile: ' + FileName);
    RecordFileName:= FileName;
    SuspendThisThread(SIPRecord);
    Log('Exit RecordFile');
end;

function TIVR.Getdigits(NumDigits: Integer): string;
var
i: Integer;
d: string;
begin
    Log('Enter Getdigits');
    Result := '';
    for i := 1 to Numdigits do begin
        d := GetNextDigit;
        if (d = '*') or (d = '#') or (d = '') then break;
        Result := Result + d;
    end;
    Log('Exit Getdigits');
end;


procedure TIVR.Send(s: string);
var
i, Len: Integer;
begin
    Log('Enter Send[' + s + ']');
    Len := Length(s);
    for i := 1 to Len do begin
       SendDigit(s[i]);
       if Not Connected then break;
    end;
    Log('Exit Send');
end;

procedure TIVR.SendDigit(c: Char);
var
s: string;
begin
    s:= c;
    Log('Enter SendDigit[' + s + ']');
    DTMFDigit:= c;
    SuspendThisThread(SIPSendDTMF);
    Sleep(100);
    Log('Exit SendDigit[' + s + ']');
end;


function TIVR.GetNextDigit: string;
begin
    Log('Enter GetNextDigit');
    Result :=  GetImmediateDigit;
    if Result = ''  then begin
        SuspendThisThread(SIPDigits);
        Result :=  GetImmediateDigit;
    end;
    Log('Exit GetNextDigit[' + Result + ']');
end;

function TIVR.GetImmediateDigit: string;
begin
    Log('Enter GetImmediateDigit');
    Result := '';
    LockIVR.acquire;
    try
        if Length(Digits) > 0 then begin
            Result := Digits[1];
            Digits := Copy(Digits, 2, Length(Digits) - 1);
        end;
    finally
         LockIVR.Release;
    end;
    Log('Exit GetImmediateDigit[' + Result + ']');
end;

procedure TIVR.AddDigit(d: Char);                       
begin
   Log('Enter AddDigit[' + d + ']');
   LockIVR.acquire;
    try
        Digits := Digits + d;
        Log('Exit AddDigit]' + Digits + ']');
    finally
     LockIVR.Release;
    end;
end;

procedure TIVR.Log(s: string);

var
    Filename: string;
    LogFile: TextFile;
begin
    try
        if Not Logging then exit;
        Filename := StartupDir + '\IVRSERVER' + IntToStr(chan) + ' .log';
        AssignFile(LogFile, Filename);
        if FileExists(Filename) then
            Append(LogFile)
        else
            Rewrite(LogFile);

        Writeln(LogFile, DateTimeToStr(Now) + ':IVR:' + s);
    except

    end;

    try
        CloseFile(LogFile);
    except

    end;

end;

procedure TIVR.LogBad(s: string);

var
    Filename: string;
    LogFile: TextFile;
begin
    try
        Filename := StartupDir + '\BAD_IVR' + IntToStr(chan) + ' .log';
        AssignFile(LogFile, Filename);
        if FileExists(Filename) then
            Append(LogFile)
        else
            Rewrite(LogFile);

        Writeln(LogFile, DateTimeToStr(Now) + ':IVR:' + s);
    except

    end;

    try
        CloseFile(LogFile);
    except

    end;

end;
procedure  TIVR.SendJobInfo;
var
s: string;
FileSize: Integer;
begin
      FileSize:=  GetFileSizeFromName(StartupDir + '\Prompts\' + JobName);
      s:= IntToStr(Count) + 'A' + Author + 'B' + Subject + 'C' + Worktype
        + 'D' + IntToStr(FileSize) + '#';
      Log('Sending Job Info[' + s + ']');
      Send(s);

end;

function TIVR.GetTaskName(Task: TTask): String;
begin

    Result:= 'Unknown';

    Case Task of
        SIPPlay: Result:= 'SIPPlay';
        SIPRecord: Result:= 'SIPRecord';
        SIPConnect: Result:= 'SIPConnect';
        SIPDisconnect: Result:= 'SIPDisconnect';
        SIPDigits: Result:= 'SIPDigits';
        SIPNone: Result:= 'SIPNone';
        SIPCall: Result:= 'SIPCall';
        SIPSendDTMF: Result:= 'SIPSendDTMF';
        SIPResume: Result:= 'SIPResume';
    end;
end;


end.
