Solved

indy Spirating Server and client and broadcast audio

Posted on 2014-09-27
9
322 Views
Last Modified: 2014-10-02
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 ?
0
Comment
Question by:drama22
  • 5
  • 4
9 Comments
 
LVL 26

Expert Comment

by:Sinisa Vuk
ID: 40350872
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
 

Author Comment

by:drama22
ID: 40351167
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
 
LVL 26

Expert Comment

by:Sinisa Vuk
ID: 40352143
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
 

Author Comment

by:drama22
ID: 40353474
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:drama22
ID: 40357779
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
 
LVL 26

Accepted Solution

by:
Sinisa Vuk earned 500 total points
ID: 40356884
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
 

Author Comment

by:drama22
ID: 40357778
i will find another way then Thank you Sinsa Vuk
0
 
LVL 26

Expert Comment

by:Sinisa Vuk
ID: 40358013
Please Delphi version? I work on example so I need to know.
0
 

Author Comment

by:drama22
ID: 40358286
Delphi xe 5
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
delphi prevent click fast 2 189
error 1.1 400 Bad request idhttp delphi 18 54
QRReport  TQrmemo vertical stretching 1 42
Adoquery sql  left join does not work 25 80
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now