Mistery solved
To send a WAV File using the SendBytes method on the TRtcHttpGateClient component (provided the file is less than 16MB in size, since that is the limit for a single SendBytes method call), you can use something like this:
if GateClient.Ready then
GateClient.SendBytes(
MyReceiverID, 0,
cid_MyTestCall, Read_FileEx(
MyFileToSend));
*
GateClient is a TRtcHttpGateClient component, set up and connected to the Gateway
*
MyReceiverID is the UserID of the receiver
*
cid_MyTestCall is the CallID you are using for this command
*
MyFileToSend is the name of the WAV file you want to sent
To make that file play on the receiver side when it arrives by using the PlaySound API on Windows, you can write the OnDataReceived event for the TRtcHttpGateClient or a connected a TRtcGateClientLink component, like this:
var
Cli:TRtcHttpGateClient;
begin
Cli:=TRtcHttpGateClient(Sender.Owner);
if (Cli.Data.CallID=
cid_MyTestCall) and (Cli.Data.Header) then
if Cli.Data.Footer then
PlaySound( Addr(Cli.Data.Content[0]), 0, SND_MEMORY)
else
Cli.Data.ToBuffer:=True;
end;
Naturally, playing the audio file directly from RTC event in blocking mode (as above) will also pause data reception on the receiver side (because audio is being played inside the event used to receive data from the Gateway), which (in turn) will pause data transmission to this Client on the Gateway and also pause data transmission from the Client sending the data.
If you do NOT want to block the receiver thread while playing the sound and you do not need seemless streaming, but just want any sound to be played immediately when it arrives, while stopping any sounds which might have been playing before, you can use a global RtcByteArray variable to store the content received and use the PlaySound API with in asynchronous mode, like this:
var
Cli:TRtcHttpGateClient;
begin
Cli:=TRtcHttpGateClient(Sender.Owner);
if (Cli.Data.CallID=
cid_MyTestCall) and (Cli.Data.Header) then
if Cli.Data.Footer then
begin
PlaySound(NIL,0,0); // stop any other sounds playing, before changing the global sound variable
GlobalSound:=Cli.Data.Content; // make a global copy of the audio file received
PlaySound( Addr(
GlobalSound- ), 0, SND_MEMORY or SND_ASYNC); // play the global sound, asynchronously
end
else
Cli.Data.ToBuffer:=True;
end;
Using the event code above, a new "GlobalSound" variable has to be declared (somewhere in your unit) as a "RtcByteArray". This global variable is necessary for asynchronous execution of the PlaySound API, because the "Cli.Data.Content" variable will be cleared as soon as more data arrives.
Or ... if you want your Client to receive data from the Gateway as soon as possible, but do NOT want the currently playing sound to be stopped when a new file arrives (as was in the example above), for example - if you want seamless audio streaming, you can either implementing your own data queue and implement your own TThread class, or ... you can use the TRtcQuickJob component, which has its own data queue and utilizes the RTC Thread pool.
Simply drop one TRtcQuickJob component on your Form or DataModule, give it a name (for example: "SoundJob"), set its "Serialized" property to TRUE (which makes the execution of jobs serialized - one job at a time) and write its OnExecute event to play a sound using using the ByteArray receved as a parameter ...
begin
PlaySound(Addr(Data.asByteArray[0]),0,SND_MEMORY);
end;
... then, modify the OnDataReceived event of your TRtcHttpGateClient or connected TRtcGateClientLink component (see code above) to post the content receive to the SoundJob component, instead of playing it directly, like this:
var
Cli:TRtcHttpGateClient;
begin
Cli:=TRtcHttpGateClient(Sender.Owner);
if (Cli.Data.CallID=cid_TestFileSend) and (Cli.Data.Header) then
begin
if Cli.Data.Footer then
SoundJob.Post(TRtcByteArray.Create(Cli.Data.Content))
else
Cli.Data.ToBuffer:=True;
end;
end;
Best Regards,
Danijel Tkalcec