Solved

indy Spirating Server and client and broadcast audio

Posted on 2014-09-27
9
337 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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 

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 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

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
error 1.1 400 Bad request idhttp delphi 18 86
Help on project with Soap 10 53
select query - oracle 16 100
Delphi: sending SMS on android platform 1 18
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
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…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

786 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