📄 unaconfserver.pas
字号:
{$ENDIF }
end;
//
finally
f_clientLock.leave();
end;
end;
// -- --
procedure unaConfServerClass.onCodecOutDA(sender: unavclInOutPipe; data: pointer; len: unsigned);
var
res: bool;
clientIndex: int;
begin
if ((0 < len) and (nil <> data)) then begin
//
clientIndex := getClientIndex(sender);
if (0 > clientIndex) then
clientIndex := -1;
//
if ((0 <= clientIndex) and (0 < f_clients[clientIndex].r_connId)) then begin
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onCodecOutDA() - need to send ' + int2str(len) + ' bytes to client, index=' + int2str(clientIndex));
{$ENDIF }
// send audio back to specific client
//res := f_ipServer.doSendPacket(f_clients[clientIndex].r_connId, cmd_inOutIPPacket_audio, data, len);
res := f_senderThread.addSendRecord(f_clients[clientIndex].r_connId, cmd_inOutIPPacket_audio, data, len);
//
if (res) then
inc(f_bytesSent, len);
//
end
else
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onCodecOutDA() - cannot locate index for sender=' + int2str(uint(sender), 16));
{$ENDIF }
end;
end;
// -- --
procedure unaConfServerClass.onPacketEvent2(connectionId: unsigned; const packet: unavclInOutIPPacket);
var
clientIndex: int;
begin
if ((0 < clientCount) and (0 < packet.r_dataSize) and f_clientLock.enter(500)) then begin
try
//
inc(f_bytesReceived, packet.r_dataSize);
//
clientIndex := getClientIndex(connectionId);
if (0 <= clientIndex) then begin
//
case (packet.r_command) of
cmd_inOutIPPacket_audio: begin
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onPacketEvent2() - NetA -> CodecIn, connId=' + int2str(connectionId) + '; index=' + int2str(clientIndex) + '; size=' + int2str(packet.r_dataSize));
{$ENDIF }
f_clients[clientIndex].r_codecIn.write(@packet.r_data, packet.r_dataSize);
end;
cmd_inOutIPPacket_formatAudio: begin
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onPacketEvent2() - got new audio format packet, connId=' + int2str(connectionId) + '; index=' + int2str(clientIndex) + '; size=' + int2str(packet.r_dataSize));
{$ENDIF }
// apply codecIn format
with (punavclWavePipeFormatExchange(@packet.r_data)^) do begin
//
if ((int(r_format.formatOriginal.pcmSamplesPerSecond) = f_samplingRate) and
(int(r_format.formatOriginal.pcmBitsPerSample) = f_bitsPerSample) and
(int(r_format.formatOriginal.pcmNumChannels) = f_numChannels)) then begin
//
with (f_clients[clientIndex]) do begin
//
if (r_codecIn.active) then begin
// should not be here
r_codecIn.close();
end;
//
if (r_codecOut.active) then begin
// should not be here
r_codecOut.close();
end;
//
r_codecIn.pcm_samplesPerSec := r_format.formatOriginal.pcmSamplesPerSecond;
r_codecIn.pcm_bitsPerSample := r_format.formatOriginal.pcmBitsPerSample;
r_codecIn.pcm_numChannels := r_format.formatOriginal.pcmNumChannels;
r_codecIn.formatTag := r_format.formatTag; // DEBUG_DUMMY_CODEC: 12345678
//
r_codecOut.pcm_samplesPerSec := r_format.formatOriginal.pcmSamplesPerSecond;
r_codecOut.pcm_bitsPerSample := r_format.formatOriginal.pcmBitsPerSample;
r_codecOut.pcm_numChannels := r_format.formatOriginal.pcmNumChannels;
//
if (0 > f_outFormatTag) then
r_codecOut.formatTag := r_format.formatTag
else
r_codecOut.formatTag := f_outFormatTag;
//
checkDriver(r_codecIn);
checkDriver(r_codecOut);
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onPacketEvent2() - IN CODEC [' + codecInfo(r_codecIn) + '] OUT CODEC [' + codecInfo(r_codecOut) + ']');
{$ENDIF }
end;
//
end;
end;
end;
cmd_inOutIPPacket_userData: begin
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onPacketEvent2() - got new user data packet, connId=' + int2str(connectionId) + '; index=' + int2str(clientIndex) + '; size=' + int2str(packet.r_dataSize));
{$ENDIF }
// distribute client's data among all clients
f_ipServer.sendPacket(0, cmd_inOutIPPacket_userData, @packet.r_data, packet.r_dataSize);
end;
end;
end
else begin
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onPacketEvent2() - could not locate the client for connId=' + int2str(connectionId));
{$ENDIF }
end;
//
finally
f_clientLock.leave();
end;
end
else begin
{$IFDEF CS_LOG_MAX }
logMessage(className + '.onPacketEvent2() - could not lock the gate, no data or no clients..');
{$ENDIF }
end;
end;
// -- --
function unaConfServerClass.setAudioFormat(samplingRate, bitsPerSample, numChannels, outFormatTag: int): HRESULT;
var
q: double;
begin
if ((1000 <= samplingRate) and (8 <= bitsPerSample) and (1 <= numChannels) and
(200000 >= samplingRate) and (32 >= bitsPerSample) and (16 >= numChannels)
) then begin
//
q := (samplingRate * numChannels * (bitsPerSample shr 3)) / c_ticksPerSecond;
if (trunc(q) * c_ticksPerSecond = (samplingRate * numChannels * (bitsPerSample shr 3))) then begin
//
f_samplingRate := samplingRate;
f_bitsPerSample := bitsPerSample;
f_numChannels := numChannels;
//
f_outFormatTag := outFormatTag;
//
f_mixer.setSampling(f_samplingRate, f_bitsPerSample, f_numChannels);
//
f_mixBufSize := (f_samplingRate * f_numChannels * (f_bitsPerSample shr 3)) div c_ticksPerSecond;
mrealloc(f_mixBuf, f_mixBufSize);
//
result := S_OK;
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.setAudioFormat() - set (formatTag=' + int2str(f_outFormatTag) + '; SPS=' + int2str(f_samplingRate) + '; BPS=' + int2str(f_bitsPerSample) + '; NC=' + int2str(f_numChannels) + '; MIX BUFFER SIZE=' + int2str(f_mixBufSize) + ')');
{$ENDIF }
end
else begin
//
result := -2;
{$IFDEF CS_LOG_MAX }
logMessage(className + '.setAudioFormat() - bad Q');
{$ENDIF }
end;
//
end
else begin
//
result := -1;
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.setAudioFormat() - bad params');
{$ENDIF }
end;
end;
// -- --
procedure unaConfServerClass.setClientOptions(clientIndex: unsigned; value: unsigned);
begin
f_ipServer.clientOptions[clientIndex] := value;
end;
// -- --
function unaConfServerClass.start(const port: string; connType: tunavclProtoType): HRESULT;
var
format: unavclWavePipeFormatExchange;
begin
{$IFDEF CS_LOG_MAX }
logMessage(className + '.start() - server about to be started..');
{$ENDIF }
//
f_ipServer.port := port;
f_ipServer.proto := connType;
//
f_bytesSent := 0;
f_bytesReceived := 0;
//
getAudioFormat(format);
//
f_ipServer.open();
f_ipServer.applyFormat(@format, sizeof(format));
//
inherited start();
//
if (f_ipServer.active) then
result := S_OK
else
result := -1;
//
end;
// -- --
procedure unaConfServerClass.stop();
begin
{$IFDEF CS_LOG_MAX }
logMessage(className + '.start() - server about to be stopped..');
{$ENDIF }
//
inherited stop();
//
f_senderThread.stop();
//
f_ipServer.close();
end;
// -- --
procedure unaConfServerClass.timer();
var
i: unsigned;
sz: unsigned;
bufClean: bool;
begin
if ((0 < f_lastTimerTick) or (4 < timeElapsed32(f_lastTimerTick))) then begin
//
f_lastTimerTick := timeMark();
// mix buffers
if ((0 < clientCount) and f_clientLock.enter(interval - 10)) then begin
//
try
i := 0;
bufClean := false;
while (i < c_maxClients) do begin
//
if (0 <> f_clients[i].r_connId) then begin // no need, since mixer will fill missing buffer automatically
//
sz := f_clients[i].r_codecIn.read(f_mixBuf, f_mixBufSize);
if (sz < f_mixBufSize) then begin
//
if (bufClean and (1 > sz)) then
else
// fill buffer with silence
fillChar(f_mixBuf[sz], f_mixBufSize - sz, #0);
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.timer() - silence has to be added, SoS=' + int2str(f_mixBufSize - sz) + ' bytes; index=' + int2str(i));
{$ENDIF }
bufClean := (1 > sz);
end
else
bufClean := false;
//
f_clients[i].r_mixerStream.write(f_mixBuf, f_mixBufSize);
end
else
f_clients[i].r_mixerStream.clear();
//
inc(i);
end;
//
inc(f_bcMixed, f_mixer.pump(f_mixBufSize));
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.timer() - mixed ' + int2str(f_mixBufSize) + ' bytes; ');
{$ENDIF }
//
i := 0;
while (i < c_maxClients) do begin
//
if (0 <> f_clients[i].r_connId) then begin // we can skip reading from a stream, since mixer will clean it internally anyway
//
sz := f_clients[i].r_mixerStream.read(f_mixBuf, f_mixBufSize);
if (0 < sz) then begin
//
{$IFDEF CS_LOG_MAX }
logMessage(className + '.timer() - about to feed codec#' + int2str(i));
{$ENDIF }
f_clients[i].r_codecOut.write(f_mixBuf, sz);
end;
end;
//
inc(i);
end;
//
finally
f_clientLock.leave();
end;
end;
end;
end;
{$IFDEF DEBUG }
// -- --
function unaConfServerClass.selfTest(): string;
var
i: int;
res: bool;
cad: array[boolean, boolean] of int64;
th: unaSocksThread;
begin
th := f_ipServer.socks.getThreadByID(f_ipServer.socksId);
//
if (nil <> th) then
result := 'Server is running, port=' + th.socket.getPort() + '; type=' + int2str(th.socket.socketType)
else
result := 'Server seems to be not activated';
//
// 1. check how many active clients we have now
result := result + #13#10'Active Clients:';
//
i := 0;
while (i < int(c_maxClients)) do begin
//
try
cad[false][false] := f_clients[i].r_codecIn.inBytes;
cad[false][true] := f_clients[i].r_codecIn.outBytes;
cad[true][false] := f_clients[i].r_codecOut.inBytes;
cad[true][true] := f_clients[i].r_codecOut.outBytes;
//
result := result + #13#10'[' + int2str(i) + '] - connId=' + int2str(f_clients[i].r_connId) +
'; CIA=' + bool2strStr(f_clients[i].r_codecIn.active) +
'; COA=' + bool2strStr(f_clients[i].r_codecOut.active) + ' [' + int2str(getClientIndex(f_clients[i].r_codecOut)) + ']' +
'; '
;
if (0 < f_clients[i].r_connId) then begin
//
res := f_senderThread.addSendRecord(f_clients[i].r_connId, cmd_inOutIPPacket_userData, @i, sizeOf(i));
//
result := result + 'ASR=' + bool2strStr(res) + '; S_OK=' + int2str(f_senderThread.f_sentOK[i]) + '; S_FAIL=' + int2str(f_senderThread.f_sentFail[i]);
end;
//
sleep(200);
//
cad[false][false] := f_clients[i].r_codecIn.inBytes - cad[false][false];
cad[false][true] := f_clients[i].r_codecIn.outBytes - cad[false][true];
cad[true][false] := f_clients[i].r_codecOut.inBytes - cad[true][false];
cad[true][true] := f_clients[i].r_codecOut.outBytes - cad[true][true];
//
result := result + ' [ iI:' + int2str(cad[false][false]) + ' / ' +
'iO:' + int2str(cad[false][true]) + ' / ' +
'oI:' + int2str(cad[true][false]) + ' / ' +
'oO:' + int2str(cad[true][true]) +
' ]';
except
//
{$IFDEF DEBUG_NASTY_EXCEPTION }
on E: EExternal do begin
//
result := result + ' ..EExternal.. ';
logMessage(className + '.selfTest() - got exception [' + E.Message + '], info: ' + getEEInfo(E.ExceptionRecord));
end;
on E: Exception do begin
//
result := result + ' ..Exception.. ';
logMessage(className + '.selfTest() - got exception [' + E.Message + ']');
end;
{$ELSE }
//
{$ENDIF }
end;
//
inc(i);
end;
//
end;
{$ENDIF }
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -