📄 frame.c
字号:
mreq.imr_multiaddr.s_addr = multiAddr[i].s_addr;
if (setsockopt(s->asdata, IPPROTO_IP, what,
(char *) &mreq, sizeof mreq) == -1) {
int serr = WSAGetLastError();
MsgBox(hwnd, MB_ICONSTOP | MB_OK,
Format(9),
(LPSTR) (join ? Format(10) : Format(11)), inet_ntoa(multiAddr[i]),
serr, SockerrToString(serr));
} else {
setsockopt(s->asctrl, IPPROTO_IP, what, (char *) &mreq, sizeof mreq);
}
}
}
}
s = s->asnext;
}
}
what = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
for (i = 0; i < multiMemberships; i++) {
mreq.imr_multiaddr.s_addr = multiAddr[i].s_addr;
if (setsockopt(sCommand, IPPROTO_IP, what,
(char *) &mreq, sizeof mreq) == -1) {
int serr = WSAGetLastError();
MsgBox(hwnd, MB_ICONSTOP | MB_OK,
Format(9),
(LPSTR) (join ? Format(10) : Format(11)), inet_ntoa(multiAddr[i]),
serr, SockerrToString(serr));
} else {
setsockopt(sControl, IPPROTO_IP, what, (char *) &mreq, sizeof mreq);
}
if (!join && multiName[i] != NULL) {
GlobalFreePtr(multiName[i]);
multiName[i] = NULL;
}
}
recursed--;
}
#endif
/* ISHALFDUPLEX -- Try to open audio input and output simultaneously.
If it fails, mark the hardware half-duplex. */
static int isHalfDuplex(HWND hwnd)
{
PCMWAVEFORMAT wfi;
MMRESULT woo;
int hdx = FALSE;
#ifdef POINTY_HEAD
{
HGLOBAL h, h1;
LPSTR p;
h = GlobalAlloc(GPTR, 1024);
p = GlobalLock(h);
h1 = GlobalHandle(p);
GlobalUnlockPtr(h);
GlobalFree(h);
}
#endif
if (waAudio11025) {
samplesPerSecond = 11025;
bytesPerSecond = samplesPerSecond * 2;
}
wfi.wf.wFormatTag = WAVE_FORMAT_PCM;
wfi.wf.nChannels = audioChannels;
// Input initialisation
while (TRUE) {
wfi.wf.nSamplesPerSec = samplesPerSecond;
wfi.wf.nAvgBytesPerSec = bytesPerSecond;
wfi.wf.nBlockAlign = sampleAlignment;
wfi.wBitsPerSample = bitsPerSample;
woo = waveInOpen(&hWaveIn, waAudioInDevice, (LPWAVEFORMATxx) &wfi,
0L, 0L, WAVE_FORMAT_QUERY);
if (bitsPerSample > 8 && woo == WAVERR_BADFORMAT) {
audioIs8Bit = TRUE;
}
/* If our preferred mode (16 bit) isn't supported, try falling
back to bottom-feeder 8 bit per sample mode. */
if ((audioUse8Bit || woo == WAVERR_BADFORMAT) && (bitsPerSample > 8)) {
bitsPerSample /= 2;
sampleAlignment /= 2;
bytesPerSecond /= 2;
wfi.wf.nAvgBytesPerSec = bytesPerSecond;
wfi.wf.nBlockAlign = sampleAlignment;
wfi.wBitsPerSample = bitsPerSample;
woo = waveInOpen(&hWaveIn, waAudioInDevice, (LPWAVEFORMATxx) &wfi,
0L, 0L, WAVE_FORMAT_QUERY);
}
/* If we've failed to initialise in either 16 or 8 bit mode
at 8000 samples per second, it's possible the sound card
doesn't support any sampling mode below the Windows standard
of 11025 samples per second. Have another go-round and see
if 11025 works. */
if (woo == WAVERR_BADFORMAT && samplesPerSecond == 8000) {
samplesPerSecond = 11025;
bitsPerSample = 16;
sampleAlignment = bitsPerSample / 8;
bytesPerSecond = samplesPerSecond * sampleAlignment;
} else {
break;
}
}
if (woo != 0) {
MessageBox(hwnd, rstring(IDS_T_WAVE_RECORD_FORMAT_ERR),
NULL, MB_OK | MB_ICONEXCLAMATION);
return -1;
}
if ((woo = waveInOpen(&hWaveIn, waAudioInDevice,
(LPWAVEFORMATxx) &wfi, (DWORD) (UINT) hwnd, 0L, (DWORD) CALLBACK_WINDOW)) != 0) {
char et[MAXERRORLENGTH];
waveInGetErrorText(woo, et, sizeof et);
MessageBox(hwnd, et, rstring(IDS_T_ERR_OPEN_WAVE_INPUT), MB_OK | MB_ICONEXCLAMATION);
return -1;
}
aboutInBits = bitsPerSample;
aboutInSamples = samplesPerSecond;
/* If workaround is set, close input now and mark half-duplex
without waiting for the open of output to fail. */
if (waAudioHalf) {
waveInClose(hWaveIn);
hdx = halfDuplex = TRUE;
}
// Output initialisation
while (TRUE) {
woo = waveOutOpen(&hWaveOut, waAudioOutDevice, (LPWAVEFORMATxx) &wfi,
0L, 0L, WAVE_FORMAT_QUERY);
if (bitsPerSample > 8 && woo == WAVERR_BADFORMAT) {
audioIs8Bit = TRUE;
}
/* If our preferred mode (16 bit, 11025 samples/second) isn't
supported, try falling back to bottom-feeder 8 bit per sample
mode. */
if ((audioUse8Bit || woo == WAVERR_BADFORMAT) && bitsPerSample > 8) {
bitsPerSample /= 2;
sampleAlignment /= 2;
bytesPerSecond /= 2;
wfi.wf.nAvgBytesPerSec = bytesPerSecond;
wfi.wf.nBlockAlign = sampleAlignment;
wfi.wBitsPerSample = bitsPerSample;
woo = waveOutOpen(&hWaveOut, waAudioOutDevice, (LPWAVEFORMATxx) &wfi,
0L, 0L, WAVE_FORMAT_QUERY);
}
/* If we've failed to initialise in either 16 or 8 bit mode
at 8000 samples per second, it's possible the sound card
doesn't support any sampling mode below the Windows standard
of 11025 samples per second. Have another go-round and see
if 11025 works. */
if (woo == WAVERR_BADFORMAT && samplesPerSecond == 8000) {
samplesPerSecond = 11025;
bitsPerSample = 16;
sampleAlignment = bitsPerSample / 8;
bytesPerSecond = samplesPerSecond * sampleAlignment;
} else {
break;
}
}
if (woo != 0) {
char et[MAXERRORLENGTH];
waveOutGetErrorText(woo, et, sizeof et);
MessageBox(hwnd, et, rstring(IDS_T_WAVE_PLAY_FORMAT_ERR),
MB_OK | MB_ICONEXCLAMATION);
hdx = -1;
goto FatalAudioExit;
}
if ((woo = waveOutOpen(&hWaveOut, waAudioOutDevice,
(LPWAVEFORMATxx) &wfi, (DWORD) (UINT) hwnd, 0, (DWORD) CALLBACK_WINDOW)) != 0) {
char et[MAXERRORLENGTH];
/* The next line looks wrong, doesn't it? But I've seen drivers
for half-duplex sound boards that return NOTSUPPORTED instead
of ALLOCATED when you try to open input and output at the
same time. */
if (!waAudioHalf && (woo == MMSYSERR_ALLOCATED || woo == MMSYSERR_NOTSUPPORTED)) {
hdx = halfDuplex = TRUE;
waveInClose(hWaveIn);
if (waveOutOpen(&hWaveOut, waAudioOutDevice,
(LPWAVEFORMATxx) &wfi, (DWORD) (UINT) hwnd, 0,
(DWORD) CALLBACK_WINDOW) == 0) {
aboutOutBits = bitsPerSample;
aboutOutSamples = samplesPerSecond;
waveOutClose(hWaveOut);
goto HdxAudioExit;
}
} else {
waveOutGetErrorText(woo, et, sizeof et);
MessageBox(hwnd, et, rstring(IDS_T_ERR_OPEN_WAVE_OUTPUT),
MB_OK | MB_ICONEXCLAMATION);
hdx = -1;
}
} else {
aboutOutBits = bitsPerSample;
aboutOutSamples = samplesPerSecond;
waveOutClose(hWaveOut);
}
FatalAudioExit:
if (!waAudioHalf) {
waveInClose(hWaveIn);
}
HdxAudioExit:
return hdx;
}
/* WAVEOUTSHUTDOWN -- Shutdown wave audio output, if open. */
static void waveOutShutdown(void)
{
if (outputActive) {
V waveOutReset(hWaveOut);
if (outputPending) {
outputInShutdown = TRUE;
propUpdateAudio();
} else {
V waveOutClose(hWaveOut);
outputActive = FALSE;
propUpdateAudio();
}
}
}
/* INPUTSAMPLECOUNT -- Calculate best sample count for an audio input
buffer based on the current compression
modes and the characteristics of the audio
hardware. */
int inputSampleCount(void)
{
int l = 0;
switch (protocolSent) {
case PROTOCOL_SPEAKFREE:
l = lpc10compress ? (180 * (compression ? 20 : 10)) :
(lpccompress ? (compression ? LPC_FRAME_SIZE * 20 : LPC_FRAME_SIZE * 10) :
((gsmcompress || voxcompress) ?
(compression ? 3200 : 1600) :
((512 - (sizeof(soundbuf) - BUFL)) * (compression ? 2 : 1))));
if (adpcmcompress) {
l *= 2;
l -= 4; // Leave room for state at the end
}
break;
case PROTOCOL_RTP:
if (waProtUseLargerRTCPackets) {
l = lpccompress ? (LPC_FRAME_SIZE * 10) :
(gsmcompress ? 1600 : 480);
} else {
l = (gsmcompress | lpccompress | adpcmcompress) ? (160 * 4) : 480;
}
break;
case PROTOCOL_VAT:
l = (gsmcompress | lpccompress | adpcmcompress) ? (160 * 4) : 320;
break;
}
return l;
}
/* INPUTBUFFERLENGTH -- Calculate best length in bytes for an audio input
buffer based on the current compression
modes and the characteristics of the audio
hardware. */
static int inputBufferLength(void)
{
return (bitsPerSample / 8) * inputSampleCount();
}
/* STARTWAVEINPUT -- Activate wave audio input. Returns TRUE
if successful, FALSE if no input will be
forthcoming for some twiddley reason or
another. The window handle is simply used
as the parent for the message boxes announcing
the bad news. */
int startWaveInput(HWND hwnd)
{
// Attempt to initialise the audio input port
if (!inputActive) {
int i;
PCMWAVEFORMAT wfi;
MMRESULT woo;
wfi.wf.wFormatTag = WAVE_FORMAT_PCM;
wfi.wf.nChannels = audioChannels;
while (TRUE) {
wfi.wf.nSamplesPerSec = samplesPerSecond;
wfi.wf.nAvgBytesPerSec = bytesPerSecond;
wfi.wf.nBlockAlign = sampleAlignment;
wfi.wBitsPerSample = bitsPerSample;
woo = waveInOpen(&hWaveIn, waAudioInDevice, (LPWAVEFORMATxx) &wfi,
0L, 0L, WAVE_FORMAT_QUERY);
if (bitsPerSample > 8 && woo == WAVERR_BADFORMAT) {
audioIs8Bit = TRUE;
}
/* If our preferred mode (16 bit) isn't supported, try falling
back to bottom-feeder 8 bit per sample mode. */
if ((audioUse8Bit || woo == WAVERR_BADFORMAT) && (bitsPerSample > 8)) {
bitsPerSample /= 2;
sampleAlignment /= 2;
bytesPerSecond /= 2;
wfi.wf.nAvgBytesPerSec = bytesPerSecond;
wfi.wf.nBlockAlign = sampleAlignment;
wfi.wBitsPerSample = bitsPerSample;
woo = waveInOpen(&hWaveIn, waAudioInDevice, (LPWAVEFORMATxx) &wfi,
0L, 0L, WAVE_FORMAT_QUERY);
}
/* If we've failed to initialise in either 16 or 8 bit mode
at 8000 samples per second, it's possible the sound card
doesn't support any sampling mode below the Windows standard
of 11025 samples per second. Have another go-round and see
if 11025 works. */
if (woo == WAVERR_BADFORMAT && samplesPerSecond == 8000) {
samplesPerSecond = 11025;
bitsPerSample = 16;
sampleAlignment = bitsPerSample / 8;
bytesPerSecond = samplesPerSecond * sampleAlignment;
} else {
break;
}
}
if (woo != 0) {
MessageBox(hwnd, rstring(IDS_T_WAVE_RECORD_FORMAT_ERR),
NULL, MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
for (i = 0; i < 2; i++) {
if ((woo = waveInOpen(&hWaveIn, waAudioInDevice,
(LPWAVEFORMATxx) &wfi, (DWORD) (UINT) hwndMDIFrame, 0L, (DWORD) CALLBACK_WINDOW)) != 0) {
char et[MAXERRORLENGTH];
/* The next line looks wrong, doesn't it? But I've seen drivers
for half-duplex sound boards that return NOTSUPPORTED instead
of ALLOCATED when you try to open input and output at the
same time. */
if (i == 0 && outputActive && (woo == MMSYSERR_ALLOCATED ||
woo == MMSYSERR_NOTSUPPORTED)) {
/* Okay, the preponderance of evidence points at our
machine being burdened with a half-duplex audio
device--one where the fact that we're playing audio
prevents from from simultaneously receiving it.
This is bad. Let's proceed as we'd have done on
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -