indy Spirating Server and client and broadcast audio

iam creating audio stream chat application i stick with problems because i started the project and puts client and server in same project and and iam unable to broadcast  data to all connected clients i searched alot and i see something said i have  to separated the server and client without understanding what does that means and how to implement this in my current code here is my current code

const
  WAVE_FORMAT_GSM610 = $0031;

type
  PGSM610WaveFormat = ^TGSM610WaveFormat;
  TGSM610WaveFormat = record
  wfx: TWaveFormatEx;
  wSamplesPerBlock: Word;
  end;

type
  TAudioBuffer = class
  private
    CS: RTL_CRITICAL_SECTION;
    Data: Pointer;
    Size: Cardinal;
  public
    EnterCritial : Boolean;
    constructor Create;
    destructor Destroy; override;
    procedure Clear;
    function BeginUpdate(ExtraSize: Cardinal): Pointer;
    procedure EndUpdate;
    function Get(out Buffer: Pointer; out BufferSize: Cardinal): Boolean;
  end;

{ TAudioBuffers }

constructor TAudioBuffer.Create;
begin
  InitializeCriticalSection(CS);
end;

destructor TAudioBuffer.Destroy;
begin
  Clear;
  DeleteCriticalSection(CS);
  inherited Destroy;
end;

procedure TAudioBuffer.Clear;
begin
  EnterCriticalSection(CS);
  try
    ReallocMem(Data, 0);
    Size := 0;
  finally
    LeaveCriticalSection(CS);
  end;
end;

function TAudioBuffer.BeginUpdate(ExtraSize: Cardinal): Pointer;
begin
  EnterCriticalSection(CS);
  EnterCritial := True;
  ReallocMem(Data, Size + ExtraSize);
  Result := Pointer(Cardinal(Data) + Size);
  Inc(Size, ExtraSize);
end;

procedure TAudioBuffer.EndUpdate;
begin
  LeaveCriticalSection(CS);
  EnterCritial := False;
end;

function TAudioBuffer.Get(out Buffer: Pointer; out BufferSize: Cardinal): Boolean;
begin
  EnterCriticalSection(CS);
  try
    Result := False;
    if Assigned(Data) then
    begin
      Buffer := Data;
      BufferSize := Size;
      Data := nil;
      Size := 0;
      Result := True;
    end;
  finally
    LeaveCriticalSection(CS);
  end;
end;
//send audio
procedure TChatFo.recorderData(Sender: TObject; const Buffer: Pointer;
  BufferSize: Cardinal; var FreeIt: Boolean);
var
  Bytes: TIdBytes;
begin
  Freeit := True;
  if Tcli.Connected then
  begin
    if (Buffer <> nil) and (Buffersize > 0) then
    begin
      try
        Bytes := RawToBytes(Buffer^, Buffersize);
      except
        micstop.Caption := 'Invalid !';
        Exit;
      end;
      begin
      Tcli.IOHandler.WriteLn('AUDIO');
      Tcli.IOHandler.Write(BufferSize);
      Tcli.IOHandler.Write(Bytes);
    end;
    end
     else
      micstop.Caption := 'Server error!';
  end else
    micstop.Caption := 'Not connected';
end;


procedure TChatFo.BroadcastAudio(Audio: string);
var
  List: TList;
  I: Integer;
begin
  List := Tserv.Contexts.LockList;
  try
    for I := 0 to List.Count - 1 do
      TIdContext(List[i]).Connection.IOHandler.Write(Audio);
  finally
    Tserv.Contexts.UnlockList;
  end;
end;

// server execute part

procedure TChatFo.TservExecute(AContext: TIdContext);
var
 Cmd,
  TextMessage: String;
  AUDIO: String;
  AudioDataSize: Integer;
  AudioDataBytes: TIdBytes;
  AudioData : Pointer;
begin
  Cmd :=  AContext.Connection.IOHandler.ReadLn;
  if Cmd = 'TEXTMESSAGE' then
  begin
    TextMessage := AContext.Connection.IOHandler.ReadLn;
    BroadcastMessage(TextMessage);
    with TMemoSync.Create do
  try
    FText := TextMessage;
    Synchronize;
  finally
    Free;
  end;
  end
  else if Cmd = 'AUDIO' then
begin
try
 InitializeCriticalSection(Section);
    EnterCriticalSection(Section);
    try
      Sleep(0);
      AudioDataSize := AContext.Connection.IOHandler.ReadLongInt();
      AContext.Connection.IOHandler.ReadBytes(AudioDataBytes, AudioDataSize);
      BroadcastMessage(AUDIO);
      if AudioDataSize > 10 then
      begin
        if not IsPlaying then AudioDataSize := 0;
        if AudioDataSize <> 0 then
      begin
        try
          if not ChatFo.Player.Active then
          begin
            ChatFo.Player.Active := True;
            ChatFo.Player.WaitForStart;
          end;
        except
        end;
        if BlockAlign > 1 then
          Dec(AudioDataSize, AudioDataSize mod BlockAlign);
        AudioData := AudioBuffer.BeginUpdate(AudioDataSize);
        try
          BytesToRaw(AudioDataBytes, AudioData^, AudioDataSize);
        finally
          AudioBuffer.EndUpdate;
        end;
      end else
      begin
        Player.Active := False;
        Player.WaitForStop;
      end;
      end;
    finally
      LeaveCriticalSection(Section);
    end;
except
    on e: exception do showmessage(e.Message)
  end;
end;
end;

Open in new window



i dont know how to do the same purpose if i separated the server and add the on execute code i will have errors because the components of audio that i use is only on client side to play sound can any body give me an example with my code how to do it in stand alone client and server ?
drama22Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Sinisa VukSoftware architectCommented:
For such application - I use ICS components. But for example in Indy there are few in Delphi's Demos folder (ex. UPDClientServer). Depending what you want - peer to peer chat (when each side knows address of other clients) or server based chat - you should put client/server components. In peer to peer - each client is a server too. In server (central) based chat system - you must have one server app and few clients.
Decide what you want. Note: peer to peer - results in no load issue on server side ....
0
drama22Author Commented:
In udp is easy to broadcast but udp cant work will on public server tcp is my using prefer I will try this ics but can you tell me now about indy tcp audio broadcast ? I already broadcsted text message but I fail in audio broadcasting .
0
Sinisa VukSoftware architectCommented:
Indy, ICS ,.... components are just transport layer - all other is up to you. So, you decide to build one server-multiple client approach? What is a source of audio? Voice?
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

drama22Author Commented:
iam using wave audio component

i be able to broadcast to all connected client a text message like this

this code on client side
procedure TChatFo.SendCommand(TCPClient: TIdTCPClient; Command: string);
begin
  if not TCPClient.Connected then
    Exit;
  TCPClient.Socket.WriteLn(Command);
end;

procedure TChatFo.SendCommandWithParams(TCPClient: TIdTCPClient; Command, Params: String);
var
 PackedParams: TPackedParams;
begin
  if not TCPClient.Connected then
    Exit;
  TCPClient.Socket.WriteLn('1' + Command);
  PackedParams.Params := ShortString(Params);
  TCPClient.Socket.Write(RawToBytes(PackedParams, SizeOf(PackedParams)));
end

Open in new window

;

and i send message like this
SendCommandWithParams(TCPClient, 'TEXTMESSAGE', strMsg + Sep);

Open in new window


i broadcast message in server side like this

procedure TServobj.BroadCastTextMessage(const TextMessage: String; const FromUniqueID: DWord;
  const FromName: string);
var
  I: Integer;
  Connection: TConnection;
begin
  for I := 0 to Connections.Count - 1 do
  begin
    Connection := Connections.Items[I];
    if Connection.UniqueID <> FromUniqueID then
      SendCommandWithParams(Connection, 'TEXTMESSAGE', FromName + Sep + TextMessage + Sep);
  end;
end;

Open in new window


but the audio part i cant figure it after i separated the server and client

before i separated the server and client i was doing it this way

This is how i send audio

procedure TChatFo.recorderData(Sender: TObject; const Buffer: Pointer;
  BufferSize: Cardinal; var FreeIt: Boolean);
var
  Bytes: TIdBytes;
begin
  Freeit := True;
  if Tcli.Connected then
  begin
    if (Buffer <> nil) and (Buffersize > 0) then
    begin
      try
        Bytes := RawToBytes(Buffer^, Buffersize);
      except
        micstop.Caption := 'Invalid !';
        Exit;
      end;
      begin
      Tcli.IOHandler.WriteLn('AUDIO');
      Tcli.IOHandler.Write(BufferSize);
      Tcli.IOHandler.Write(Bytes);
    end;
    end
     else
      micstop.Caption := 'Server error!';
  end else
    micstop.Caption := 'Not connected';
end;
  

Open in new window


this is how i was receive audio before separating the client and server

procedure TChatFo.TservExecute(AContext: TIdContext);
var
 Cmd,
  TextMessage: String;
  AUDIO: String;
  AudioDataSize: Integer;
  AudioDataBytes: TIdBytes;
  AudioData : Pointer;
begin
  Cmd :=  AContext.Connection.IOHandler.ReadLn;
  if Cmd = 'TEXTMESSAGE' then
  begin
    TextMessage := AContext.Connection.IOHandler.ReadLn;
    BroadcastMessage(TextMessage);
    with TMemoSync.Create do
  try
    FText := TextMessage;
    Synchronize;
  finally
    Free;
  end;
  end
  else if Cmd = 'AUDIO' then
begin
try
    EnterCriticalSection(Section);
    try
      Sleep(0);
      AudioDataSize := AContext.Connection.IOHandler.ReadLongInt();
      AContext.Connection.IOHandler.ReadBytes(AudioDataBytes, AudioDataSize);
      BroadcastMessage(AUDIO);
      if AudioDataSize > 10 then
      begin
        if not IsPlaying then AudioDataSize := 0;
        if AudioDataSize <> 0 then
      begin
        try
          if not ChatFo.Player.Active then
          begin
            ChatFo.Player.Active := True;
            ChatFo.Player.WaitForStart;
          end;
        except
        end;
        if BlockAlign > 1 then
          Dec(AudioDataSize, AudioDataSize mod BlockAlign);
        AudioData := AudioBuffer.BeginUpdate(AudioDataSize);
        try
          BytesToRaw(AudioDataBytes, AudioData^, AudioDataSize);
        finally
          AudioBuffer.EndUpdate;
        end;
      end else
      begin
        Player.Active := False;
        Player.WaitForStop;
      end;
      end;
    finally
      LeaveCriticalSection(Section);
    end;
except
    on e: exception do showmessage(e.Message)
  end;
end;
end;

Open in new window



but in the separated server and client i think i have to do somthing like this

How To send audio and correct me please

procedure TChatFo.recorderData(Sender: TObject; const Buffer: Pointer;
  BufferSize: Cardinal; var FreeIt: Boolean);
var
  Bytes: TIdBytes;
begin
  Freeit := True;
  if TCPClient.Connected then
  begin
    if (Buffer <> nil) and (Buffersize > 0) then
    begin
      try
        Bytes := RawToBytes(Buffer^, Buffersize);
      except
        micstop.Caption := 'Invalid !';
        Exit;
      end;
      begin
      SendCommandWithParams(TCPClient, 'AUDIO', BufferSize + Bytes);
    end;
    end
     else
      micstop.Caption := 'Server error!';
  end else
    micstop.Caption := 'Not connected';
end;

Open in new window



but the problem i dont know what to do in broadcast audio code in server project !

and how the client listen to audio that sent from other clients in text i do somthing like this

  if Command = 'TEXTMESSAGE' then
  begin
    memo1.Lines.Add( Params[1] + ' : ' + Params[2]);
  end;

Open in new window


but in audio what i have to do ?
0
drama22Author Commented:
I've requested that this question be deleted for the following reason:

did not found a resolve and i think its completely wrong question.
0
Sinisa VukSoftware architectCommented:
Which version of Delphi do you have?
Small note: when you want to comunnicate through server - it will be very busy - all data from one client should be transfered to other....Do you think about that.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
drama22Author Commented:
i will find another way then Thank you Sinsa Vuk
0
Sinisa VukSoftware architectCommented:
Please Delphi version? I work on example so I need to know.
0
drama22Author Commented:
Delphi xe 5
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.