Solved

indy Spirating Server and client and broadcast audio

Posted on 2014-09-27
9
392 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
9 Comments
 
LVL 27

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 27

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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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
 

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 27

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 27

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

[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

Question has a verified solution.

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

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
Suggested Courses
Course of the Month7 days, 9 hours left to enroll

632 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