fteqw/engine/client/snd_sdl.c
Spoike c0680334c7 What could possibly go wrong?...
Multiple consoles can now be printed/cleared via extra con commands.
Fixed the tab-completion alignment, by adding support for \t characters.
Changing the download mechanisms. Don't try downloading an ftp:// file. It'll probably crash you for now.
Trying to fix load time issues on q3bsps with a lot of curves.
Fixed sprites.
Added warning prints/spam where the new backend is bypassed, thus marking things that still need to be fixed.
QTV proxy fixed to not sit on qw servers unless someone is actually watching. Will ping for status requests still.
QTV proxy now supports ipv6.
QTV proxy now attempts to use the fte browser plugin.
Reworked the browser plugin code, now uses threads instead of ugly hacks. This should make cooperation with other such plugins work. Fixes unresponsiveness of opera, and gives an API that can be used from any other bit of software you want, tbh (read: internet explorer/activex plugins).

git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3516 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-03-14 14:35:56 +00:00

137 lines
4 KiB
C

#include "quakedef.h"
#include "winquake.h"
#include <SDL.h>
#pragma comment(lib, "sdl.lib")
//SDL calls a callback each time it needs to repaint the 'hardware' buffers
//This results in extra latency.
//SDL runs does this multithreaded.
//So we tell it a fairly pathetically sized buffer and try and get it to copy often
//hopefully this lowers sound latency, and has no suddenly starting sounds and stuff.
//It still has greater latency than direct access, of course.
//FIXME: One thing I saw in quakeforge was that quakeforge basically leaves the audio locked except for a really short period of time.
//An interesting idea, which ensures the driver can only paint in a small time-frame. this would possibly allow lower latency painting.
static void SSDL_Shutdown(soundcardinfo_t *sc)
{
Con_Printf("Shutdown SDL sound\n");
SDL_CloseAudio();
if (sc->sn.buffer)
free(sc->sn.buffer);
sc->sn.buffer = NULL;
}
static unsigned int SSDL_GetDMAPos(soundcardinfo_t *sc)
{
sc->sn.samplepos = sc->snd_sent / (sc->sn.samplebits/8);
return sc->sn.samplepos;
}
//this function is called from inside SDL.
//transfer the 'dma' buffer into the buffer it requests.
static void VARGS SSDL_Paint(void *userdata, qbyte *stream, int len)
{
soundcardinfo_t *sc = userdata;
int buffersize = sc->sn.samples*(sc->sn.samplebits/8);
if (len > buffersize)
{
len = buffersize; //whoa nellie!
}
if (len + sc->snd_sent%buffersize > buffersize)
{ //buffer will wrap, fill in the rest
memcpy(stream, (char*)sc->sn.buffer + (sc->snd_sent%buffersize), buffersize - (sc->snd_sent%buffersize));
stream += buffersize - sc->snd_sent%buffersize;
len -= buffersize - (sc->snd_sent%buffersize);
if (len < 0)
return;
} //and finish from the start
memcpy(stream, (char*)sc->sn.buffer + (sc->snd_sent%buffersize), len);
sc->snd_sent += len;
}
static void *SSDL_LockBuffer(soundcardinfo_t *sc)
{
SDL_LockAudio();
return sc->sn.buffer;
}
static void SSDL_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{
SDL_UnlockAudio();
}
static void SSDL_SetUnderWater(soundcardinfo_t *sc, qboolean uw)
{
}
static void SSDL_Submit(soundcardinfo_t *sc)
{
//SDL will call SSDL_Paint to paint when it's time, and the sound buffer is always there...
}
static int SDL_InitCard(soundcardinfo_t *sc, int cardnum)
{
SDL_AudioSpec desired, obtained;
if (cardnum)
{ //our init code actually calls this function multiple times, in the case that the user has multiple sound cards
return 2; //erm. SDL won't allow multiple sound cards anyway.
}
Con_Printf("Initing SDL audio.\n");
if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
{
Con_Printf("Couldn't initialize SDL audio subsystem\n");
return false;
}
memset(&desired, 0, sizeof(desired));
desired.freq = sc->sn.speed;
desired.channels = sc->sn.numchannels; //fixme!
desired.samples = 0x0100;
desired.format = AUDIO_S16SYS;
desired.callback = SSDL_Paint;
desired.userdata = sc;
memcpy(&obtained, &desired, sizeof(obtained));
if ( SDL_OpenAudio(&desired, &obtained) < 0 )
{
Con_Printf("SDL: SNDDMA_Init: couldn't open sound device (%s).\n", SDL_GetError());
return false;
}
sc->sn.numchannels = obtained.channels;
sc->sn.speed = obtained.freq;
sc->sn.samplebits = obtained.format&0xff;
sc->sn.samples = 32768;//*sc->sn.numchannels; //doesn't really matter, so long as it's higher than obtained.samples
Con_DPrintf("channels: %i\n", sc->sn.numchannels);
Con_DPrintf("Speed: %i\n", sc->sn.speed);
Con_DPrintf("Samplebits: %i\n", sc->sn.samplebits);
Con_DPrintf("SDLSamples: %i (low for latency)\n", obtained.samples);
Con_DPrintf("FakeSamples: %i\n", sc->sn.samples);
sc->sn.buffer = malloc(sc->sn.samples*sc->sn.samplebits/8);
Con_DPrintf("Got sound %i-%i\n", obtained.freq, obtained.format);
sc->Lock = SSDL_LockBuffer;
sc->Unlock = SSDL_UnlockBuffer;
sc->SetWaterDistortion = SSDL_SetUnderWater;
sc->Submit = SSDL_Submit;
sc->Shutdown = SSDL_Shutdown;
sc->GetDMAPos = SSDL_GetDMAPos;
SDL_PauseAudio(0);
return true;
}
sounddriver pSDL_InitCard = &SDL_InitCard;