Witam,
W swoim programie tworzę funkcję rozmowy głosowej poprzez gniazdka.
Korzystam z komponentu WaveAudio do Delphi XE3.
Samo odbieranie dźwięku i przesyłanie działa i wygląda to mniej więcej tak:
Serwer:
procedure TfrmMain.TcpServerAccept(Sender: TObject; Socket: TCustomWinSocket);
type
TWaveFormatInfo = packed record
WaveFormatSize: Integer;
WaveFormat: TWaveFormatEx;
end;
var
WFI: TWaveFormatInfo;
ClientName: String;
begin
SetPCMAudioFormatS(@WFI.WaveFormat, LiveAudioRecorder.PCMFormat);
WFI.WaveFormatSize := SizeOf(WFI.WaveFormat);
Socket.SendBuf(WFI, SizeOf(WFI));
ClientName := FormatAddress(Socket.RemoteHost, Socket.RemoteAddress);
if MyVoiceCall.Busy then
begin
Socket.SendText('@BUSY');
end
else
begin
MyVoiceCall.IsServer := True;
MyVoiceCall.Busy := True;
if not Assigned(frmVoiceCall) then
begin
Application.CreateForm(TfrmVoiceCall, frmVoiceCall);
Socket.SendText('@CALLING');
frmVoiceCall.VoiceCallFrom(ClientName);
frmVoiceCall.Show;
end
else
frmVoiceCall.Show;
end;
end;
procedure TfrmMain.TcpServerClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Text: AnsiString;
begin
SetString(Text, nil, Socket.ReceiveLength);
Socket.ReceiveBuf(PAnsiChar(Text)^, Length(Text));
if Text = 'READY' then
Socket.Data := Self;
end;
Klient:
procedure TfrmMain.TcpClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
ClientName: String;
WaveFormatSize: Integer;
Data: Pointer;
DataSize: Integer;
Text: AnsiString;
begin
{SetString(Text, nil, Socket.ReceiveLength);
Socket.ReceiveBuf(PAnsiChar(Text)^, Length(Text));
}
ClientName := FormatAddress(Socket.RemoteHost, Socket.RemoteAddress);
ClientName := StringReplace(ClientName, '.systemeg.internal', '', [rfReplaceAll]);
{
if Text = '@CALLING' then
begin
end
else if Text = '@BUSY' then
begin
end
else if pos('@ACCEPTED', Text) > 0 then
begin
Text := StringReplace(Text, '@ACCEPTED', '', [rfReplaceAll]);
MyVoiceCall.ClientName := ClientName;
MyVoiceCall.Calling := True;
end;
if MyVoiceCall.Calling then
begin }
try
if not LiveAudioPlayer.Active then
begin
Socket.ReceiveBuf(WaveFormatSize, SizeOf(WaveFormatSize));
ReallocMem(WaveFormat, WaveFormatSize);
try
Socket.ReceiveBuf(WaveFormat^, WaveFormatSize);
except
ReallocMem(WaveFormat, 0);
raise;
end;
LiveAudioPlayer.Active := True;
end
else
begin
Sleep(0); // giving chance to the player thread for using the audio buffer
DataSize := Socket.ReceiveLength;
if BlockAlign > 1 then
Dec(DataSize, DataSize mod BlockAlign);
if DataSize <> 0 then
begin
Data := AudioBuffer.BeginUpdate(DataSize);
try
Socket.ReceiveBuf(Data^, DataSize);
finally
AudioBuffer.EndUpdate;
end;
end;
end;
except
tcpClient.Active := False;
Application.HandleException(Self);
end;
// end;
end;
Chciałbym, aby cała funkcja TRY EXCEPT była wykonywana w zależności od zawartości otrzymanych danych. Tzn chcę kontrolować odbiór poprzez polecenia np.
Łączymy się z serwerem:
- Klient wysyła polecenie do serwera '@CALLING'
- Serwer sprawdza, czy nie prowadzimy już rozmowy z kimś innym poprzez zmienną w rekordzie MyVoiceCall.Busy: boolean;
- Jeżeli nie, to pokazujemy u klienta okienko dzwonienia a na serwerze okno informujące, że ktoś dzwoni z opcją odrzucenia lub przyjęcia rozmowy. W tym czasie klient jak i serwer ustawiają zmienną Busy na True, aby odrzucać pozostałych klientów, którzy będą chcieli w tym samym czasie dzwonić, i wysyła do nich polecenie '@busy', które ich o tym zdarzeniu powiadomi np. "Klient obecnie prowadzi rozmowę".
- Dopiero, gdy kliknę Odbierz, do serwera leci polecenie '@ACCEPTED' i dopiero wtedy powinien wykonywać się cały Try Except, ale chciałbym też wiedzieć, kiedy klient się rozłączy klikając w Czerwoną słuchawkę, wówczas wyślę polecenie '@CALLEND', które rozłączy obie strony.
Nie jestem specem z gniazdek i proszę o pomoc, w jaki sposób kontrolować zawartość ReceiveBuff.
Jak próbowałem
var
Text: AnsiString;
begin
SetString(Text, nil, Socket.ReceiveLength);
Socket.ReceiveBuf(PAnsiChar(Text)^, Length(Text));
if Text = '@CALLING' then
begin
end
else if Text = '@BUSY' then
begin
end
else if pos('@ACCEPTED', Text) > 0 then
begin
Text := StringReplace(Text, '@ACCEPTED', '', [rfReplaceAll]);
MyVoiceCall.ClientName := ClientName;
MyVoiceCall.Calling := True;
end;
a następnie
if MyVoiceCall.Calling then
begin
try
if not LiveAudioPlayer.Active then
begin
Socket.ReceiveBuf(WaveFormatSize, SizeOf(WaveFormatSize));
ReallocMem(WaveFormat, WaveFormatSize);
try
Socket.ReceiveBuf(WaveFormat^, WaveFormatSize);
except
ReallocMem(WaveFormat, 0);
raise;
end;
LiveAudioPlayer.Active := True;
end
else
begin
Sleep(0); // giving chance to the player thread for using the audio buffer
DataSize := Socket.ReceiveLength;
if BlockAlign > 1 then
Dec(DataSize, DataSize mod BlockAlign);
if DataSize <> 0 then
begin
Data := AudioBuffer.BeginUpdate(DataSize);
try
Socket.ReceiveBuf(Data^, DataSize);
finally
AudioBuffer.EndUpdate;
end;
end;
end;
except
tcpClient.Active := False;
Application.HandleException(Self);
end;
end;
To program się zawiesza. Tak jak by nie można było wykonać
Socket.ReceiveBuff(PAnsiChar(Text)^, Length(Text));
a linijkę niżej Socket.ReceiveBuff(WaveFormatSize, SizeOf(WaveFormatSize));
<span style="color: gray"><i>`dodanie znaczników wypunktowania`</i> - @{furious programming}</span>