LOTS OF CHANGES. was hoping to get revision 5000 perfect, but really that's never going to happen. this has gone on for too long now.

vulkan, wasapi, quake injector features added.
irc, avplug, cef plugins/drivers reworked/updated/added
openal reverb, doppler effects added.
'dir' console command now attempts to view clicked files.
lots of warning fixes, should now only be deprecation warnings for most targets (depending on compiler version anyway...).
SendEntity finally reworked to use flags properly.
effectinfo improved, other smc-targetted fixes.
mapcluster stuff now has support for linux.
.basebone+.baseframe now exist in ssqc.
qcc: -Fqccx supports qccx syntax, including qccx hacks. don't expect these to work in fteqw nor dp though.
qcc: rewrote function call handling to use refs rather than defs. this makes struct passing more efficient and makes the __out keyword usable with fields etc.
qccgui: can cope a little better with non-unicode files. can now represent most quake chars.
qcc: suppressed warnings from *extensions.qc

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5000 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2016-07-12 00:40:13 +00:00
parent 5920bf05fb
commit 27a59a0cbc
271 changed files with 101001 additions and 64352 deletions

View file

@ -2,11 +2,13 @@
#windows is special as always, but we don't support itanium, and microsoft don't support anything else (not even arm with the nt win32 api)
ifeq ($(FTE_TARGET),win32)
PLUG_NATIVE_EXT=_x86.dll
PLUG_LDFLAGS=-Lavplug/lib32 -L../engine/libs/mingw-libs -lzlib
PLUG_LDFLAGS=-L../engine/libs/mingw-libs -lzlib
BITS=32
endif
ifeq ($(FTE_TARGET),win64)
PLUG_NATIVE_EXT=_amd.dll
PLUG_LDFLAGS=-Lavplug/lib64 -L../engine/libs/mingw64-libs -lz -Wl,--support-old-code
PLUG_NATIVE_EXT=_x64.dll
PLUG_LDFLAGS=-L../engine/libs/mingw64-libs -lz -Wl,--support-old-code
BITS=64
endif
PLUG_LDFLAGS?=-L/usr/local/lib -Wl,-R/usr/local/lib -lz -lm
@ -15,15 +17,14 @@ ifneq ($(PLUG_NATIVE_EXT),)
#if we're on windows, we'll put our windows-specific hacks here.
PLUG_DEFFILE=plugin.def
PLUG_CFLAGS=
$(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT): avplug/libavformat/avformat.h
PLUG_CXXFLAGS=
endif
#cygwin uses dll naming.
ifeq ($(FTE_TARGET),cygwin)
ifeq ($(BITS),64)
PLUG_DEFFILE=plugin.def
PLUG_NATIVE_EXT=_amd.dll
PLUG_NATIVE_EXT=_amd64.dll
endif
ifneq ($(BITS),64)
PLUG_DEFFILE=plugin.def
@ -36,7 +37,7 @@ endif
ifeq ($(PLUG_NATIVE_EXT),)
LIBRESOLV=-lresolv
ifneq ($(shell echo|$(CC) -E -dM -|grep __amd64__),)
PLUG_NATIVE_EXT=_amd.so
PLUG_NATIVE_EXT=_amd64.so
endif
ifneq ($(shell echo|$(CC) -E -dM -|grep __i386__),)
PLUG_NATIVE_EXT=_x86.so
@ -53,12 +54,13 @@ endif
PLUG_NATIVE_EXT?=_unk.so
PLUG_DEFFILE?=
PLUG_CFLAGS?=-fPIC -Wl,--no-undefined -Bsymbolic
PLUG_CFLAGS?=-fPIC -Wl,--no-undefined -Bsymbolic -fvisibility=hidden
PLUG_CXXFLAGS?=-fPIC -Wl,--no-undefined -Bsymbolic -fvisibility=hidden
PLUG_LDFLAGS?=
all: ezscript hud irc
all: ezscript qi hud irc
clean: ezscript-clean hud-clean irc-clean
clean: ezscript-clean qi-clean hud-clean irc-clean
.PHONY: all ezscript hud irc native distclean clean
@ -77,6 +79,12 @@ hud:
hud-clean:
$(MAKE) clean -C hud
qi:
$(MAKE) -C qi
qi-clean:
$(MAKE) clean -C qi
irc:
$(MAKE) -C irc
@ -87,49 +95,108 @@ irc-clean:
#linux users are expected to have the library installed locally already. If your version is too old or missing, run the following command to install it (to /usr/local), then delete the gz and directory.
#wget http://ffmpeg.org/releases/ffmpeg-1.2.tar.gz && cd tar xvfz ffmpeg-1.2.tar.gz && cd ffmpeg-1.2/ && ./configure --disable-yasm --enable-shared && make && sudo make install
#we use ffmpeg's version for some reason, as opposed to libav. not sure what the differences are meant to be, but libav seemed to have non-depricated functions defined, docs that say to use them, and these functions missing.
AV7Z_VER=ffmpeg-1.2
AV7Z_VER=ffmpeg-3.0.1
AV7Z_W32=$(AV7Z_VER)-win32-dev.7z
AV7Z_URL32=http://ffmpeg.zeranoe.com/builds/win32/dev/$(AV7Z_W32)
AV7Z_PRE32=$(AV7Z_VER)-win32-dev/
AV7Z_W64=$(AV7Z_VER)-win64-dev.7z
AV7Z_URL64=http://ffmpeg.zeranoe.com/builds/win64/dev/$(AV7Z_W64)
AV7Z_PRE64=$(AV7Z_VER)-win64-dev/
avplug/libavformat/avformat.h:
wget $(AV7Z_URL32)
mkdir -p avplug/libavformat && cd avplug/libavformat && 7z e -y ../../$(AV7Z_W32) $(AV7Z_PRE32)include/libavformat/ && cd -
mkdir -p avplug/libavcodec && cd avplug/libavcodec && 7z e -y ../../$(AV7Z_W32) $(AV7Z_PRE32)include/libavcodec/ && cd -
mkdir -p avplug/libavutil && cd avplug/libavutil && 7z e -y ../../$(AV7Z_W32) $(AV7Z_PRE32)include/libavutil/ && cd -
mkdir -p avplug/libswscale && cd avplug/libswscale && 7z e -y ../../$(AV7Z_W32) $(AV7Z_PRE32)include/libswscale/ && cd -
mkdir -p avplug/lib32 && cd avplug/lib32 && 7z e -y ../../$(AV7Z_W32) $(AV7Z_PRE32)lib/avformat.lib $(AV7Z_PRE32)lib/avcodec.lib $(AV7Z_PRE32)lib/avutil.lib $(AV7Z_PRE32)lib/swscale.lib && cd -
rm $(AV7Z_W32)
wget $(AV7Z_URL64)
mkdir -p avplug/lib64 && cd avplug/lib64 && 7z e -y ../../$(AV7Z_W64) $(AV7Z_PRE64)lib/avformat.lib $(AV7Z_PRE64)lib/avcodec.lib $(AV7Z_PRE64)lib/avutil.lib $(AV7Z_PRE64)lib/swscale.lib && cd -
rm $(AV7Z_W64)
AV_BASE=$(OUT_DIR)/../fte_libav_$(AV7Z_VER)/
ifeq ($(FTE_TARGET),win32)
#NATIVE_PLUGINS+=avplug
endif
ifeq ($(FTE_TARGET),win64)
#NATIVE_PLUGINS+=avplug
endif
$(AV_BASE)libavformat/avformat.h:
mkdir -p $(AV_BASE)
wget $(AV7Z_URL32) -O $(AV_BASE)$(AV7Z_W32)
mkdir -p $(AV_BASE)libavformat && cd $(AV_BASE)libavformat && 7z e -y ../$(AV7Z_W32) $(AV7Z_PRE32)include/libavformat/ && cd -
mkdir -p $(AV_BASE)libavcodec && cd $(AV_BASE)libavcodec && 7z e -y ../$(AV7Z_W32) $(AV7Z_PRE32)include/libavcodec/ && cd -
mkdir -p $(AV_BASE)libavutil && cd $(AV_BASE)libavutil && 7z e -y ../$(AV7Z_W32) $(AV7Z_PRE32)include/libavutil/ && cd -
mkdir -p $(AV_BASE)libswscale && cd $(AV_BASE)libswscale && 7z e -y ../$(AV7Z_W32) $(AV7Z_PRE32)include/libswscale/ && cd -
mkdir -p $(AV_BASE)lib32 && cd $(AV_BASE)lib32 && 7z e -y ../$(AV7Z_W32) $(AV7Z_PRE32)lib/avformat.lib $(AV7Z_PRE32)lib/avcodec.lib $(AV7Z_PRE32)lib/avutil.lib $(AV7Z_PRE32)lib/swscale.lib && cd -
rm $(AV_BASE)$(AV7Z_W32)
wget $(AV7Z_URL64) -O $(AV_BASE)$(AV7Z_W64)
mkdir -p $(AV_BASE)lib64 && cd $(AV_BASE)lib64 && 7z e -y ../$(AV7Z_W64) $(AV7Z_PRE64)lib/avformat.lib $(AV7Z_PRE64)lib/avcodec.lib $(AV7Z_PRE64)lib/avutil.lib $(AV7Z_PRE64)lib/swscale.lib && cd -
rm $(AV_BASE)$(AV7Z_W64)
distclean:
rm avplug/libavformat/avformat.h
rm $(AV_BASE)libavformat/avformat.h
$(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT): $(AV_BASE)libavformat/avformat.h
$(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT): avplug/avencode.c avplug/avdecode.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -s -o $@ -shared $(PLUG_CFLAGS) -L$(AV_BASE)lib$(BITS) -I$(AV_BASE) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -lavcodec -lavformat -lavutil -lswscale
#small script for ode
#FIXME: ode fails to compile under cygwin
ODE_ARCH=$(FTE_TARGET)
ifeq ($(ODE_ARCH),)
ODE_ARCH=unknown
endif
ODE_VER=0.14
ODE_URL=https://bitbucket.org/odedevs/ode/downloads/ode-$(ODE_VER).tar.gz
ODE_BASE=$(OUT_DIR)/../ode-$(ODE_VER)_$(ODE_ARCH)/
ODE_LIB=$(ODE_BASE)ode-$(ODE_VER)/ode/src/.libs/libode.a
$(OUT_DIR)/../ode-$(ODE_VER).tar.gz:
mkdir -p $(ODE_BASE)
wget $(ODE_URL) -O $@
$(ODE_LIB): $(OUT_DIR)/../ode-$(ODE_VER).tar.gz
mkdir -p $(ODE_BASE) && cd $(ODE_BASE) && tar xvfz $<
cd $(ODE_BASE)ode-$(ODE_VER)/ && ./bootstrap && ./configure --enable-double-precision --disable-demos --without-x --with-pic CC="$(CC) $(PLUG_CXXFLAGS)" CXX="$(CC) $(PLUG_CXXFLAGS)" --host=`$(CC) -dumpmachine` && make
ODE_FILES=../engine/common/com_phys_ode.c ../engine/common/mathlib.c plugin.c qvm_api.c $(ODE_LIB)
$(OUT_DIR)/fteplug_ode$(PLUG_NATIVE_EXT): $(ODE_FILES)
$(CC) -s $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -DODE_STATIC -o $@ -shared $(PLUG_CFLAGS) -I$(ODE_BASE)ode-$(ODE_VER)/include $(ODE_FILES) $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -lstdc++ -lpthread
#NATIVE_PLUGINS+=ode
BULLET_VER=2.83.7
BULLET_URL=https://github.com/bulletphysics/bullet3/archive/$(BULLET_VER).tar.gz
BULLET_BASE=$(OUT_DIR)/../bullet3-$(ODE_VER)_$(FTE_TARGET)/
BULLET_LIB=$(ODE_BASE)bullet3-$(ODE_VER)/ode/src/.libs/libode.a
$(OUT_DIR)/../bullet3-$(BULLET_VER).tar.gz:
mkdir -p $(BULLET_BASE)
wget $(BULLET_URL) -O $@
$(BULLET_LIB): $(OUT_DIR)/../bullet3-$(BULLET_VER).tar.gz
mkdir -p $(BULLET_BASE) && cd $(BULLET_BASE) && tar xvfz $<
cd $(BULLET_BASE)bullet3-$(BULLET_VER)/ && ./bootstrap && ./configure --enable-double-precision --disable-demos --without-x CXX="$(CC)" CFLAGS="$(PLUG_CFLAGS)" CXXFLAGS="$(PLUG_CXXFLAGS)" --host=`$(CC) -dumpmachine` && make
$(OUT_DIR)/fteplug_bullet$(PLUG_NATIVE_EXT): bullet/bulletplug.c plugin.c qvm_api.c $(BULLET_LIB)
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
#NATIVE_PLUGINS+=bullet
-include Makefile.private
$(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT): avplug/avencode.c avplug/avdecode.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -s -o $(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iavplug/msvc_lib $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -lavcodec -lavformat -lavutil -lswscale
#native: $(OUT_DIR)/fteplug_avplug$(PLUG_NATIVE_EXT)
$(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT): mpq/fs_mpq.c mpq/blast.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Impq $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
native: $(OUT_DIR)/fteplug_mpq$(PLUG_NATIVE_EXT)
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Impq $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=mpq
$(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT): jabber/jabberclient.c jabber/jingle.c jabber/sift.c jabber/xml.c plugin.c qvm_api.c ../engine/common/sha1.c emailnot/md5.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(LIBRESOLV)
native: $(OUT_DIR)/fteplug_xmpp$(PLUG_NATIVE_EXT)
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) $(LIBRESOLV)
NATIVE_PLUGINS+=xmpp
$(OUT_DIR)/fteplug_qi$(PLUG_NATIVE_EXT): qi/qi.c jabber/xml.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Ijabber $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=qi
$(OUT_DIR)/fteplug_cef$(PLUG_NATIVE_EXT): cef/cef.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Icef/2623 $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS) -Wl,-rpath,. -ldl
#NATIVE_PLUGINS+=cef
#irc plugin can still be built as a qvm.
$(OUT_DIR)/fteplug_irc$(PLUG_NATIVE_EXT): irc/ircclient.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_irc$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iirc $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
native: $(OUT_DIR)/fteplug_irc$(PLUG_NATIVE_EXT)
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Iirc $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=irc
#for compat with ezquake
$(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT): ezhud/ezquakeisms.c ezhud/hud.c ezhud/hud_common.c ezhud/hud_editor.c plugin.c qvm_api.c
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT) -shared $(PLUG_CFLAGS) -Iezhud $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
native: $(OUT_DIR)/fteplug_ezhud$(PLUG_NATIVE_EXT)
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Iezhud $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
NATIVE_PLUGINS+=ezhud
native:
native: $(foreach FOO,$(NATIVE_PLUGINS), $(OUT_DIR)/fteplug_$(FOO)$(PLUG_NATIVE_EXT))

View file

@ -4,6 +4,7 @@
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
//between av 52.31 and 54.35, lots of constants etc got renamed to gain an extra AV_ prefix.
/*
@ -44,18 +45,18 @@ struct decctx
AVCodecContext *pVCodecCtx;
AVFrame *pVFrame;
int64_t num, denum;
int64_t lasttime;
AVPicture pFrameRGB;
uint8_t *rgb_data;
int rgb_linesize;
struct SwsContext *pScaleCtx;
unsigned int starttime;
unsigned int lastframe;
};
static qboolean AVDec_SetSize (void *vctx, int width, int height)
{
struct decctx *ctx = (struct decctx*)vctx;
AVPicture newscaled;
uint8_t *rgb_data[1];
int rgb_linesize[1];
//colourspace conversions will be fastest if we
// if (width > ctx->pCodecCtx->width)
@ -67,15 +68,16 @@ static qboolean AVDec_SetSize (void *vctx, int width, int height)
if (width == ctx->width && height == ctx->height && ctx->pScaleCtx)
return true;
if (avpicture_alloc(&newscaled, AV_PIX_FMT_BGRA, width, height) >= 0)
if (av_image_alloc(rgb_data, rgb_linesize, width, height, AV_PIX_FMT_BGRA, 16) >= 0)
{
//update the scale context as required
//clear the old stuff out
avpicture_free(&ctx->pFrameRGB);
av_free(ctx->rgb_data);
ctx->width = width;
ctx->height = height;
ctx->pFrameRGB = newscaled;
ctx->rgb_data = rgb_data[0];
ctx->rgb_linesize = rgb_linesize[0];
return qtrue;
}
return qfalse; //unsupported
@ -93,12 +95,12 @@ static int AVIO_Read(void *opaque, uint8_t *buf, int buf_size)
static int64_t AVIO_Seek(void *opaque, int64_t offset, int whence)
{
struct decctx *ctx = opaque;
int64_t ret = ctx->fileofs;
whence &= ~AVSEEK_FORCE;
switch(whence)
{
case SEEK_SET:
default:
return -1;
case SEEK_SET:
ctx->fileofs = offset;
break;
case SEEK_CUR:
@ -119,7 +121,7 @@ static void AVDec_Destroy(void *vctx)
struct decctx *ctx = (struct decctx*)vctx;
// Free the video stuff
avpicture_free(&ctx->pFrameRGB);
av_free(ctx->rgb_data);
if (ctx->pVCodecCtx)
avcodec_close(ctx->pVCodecCtx);
av_free(ctx->pVFrame);
@ -138,7 +140,7 @@ static void AVDec_Destroy(void *vctx)
free(ctx);
}
static void *AVDec_Create(char *medianame)
static void *AVDec_Create(const char *medianame)
{
struct decctx *ctx;
@ -163,16 +165,13 @@ static void *AVDec_Create(char *medianame)
ctx = malloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
//so we always decode the first frame instantly.
ctx->starttime = pSys_Milliseconds();
ctx->lasttime = -1;
ctx->file = -1;
if (useioctx)
{
// Create internal Buffer for FFmpeg:
const int iBufSize = 32 * 1024;
char *pBuffer = malloc(iBufSize);
char *pBuffer = av_malloc(iBufSize);
AVIOContext *ioctx;
ctx->filelen = pFS_Open(medianame, &ctx->file, 1);
@ -180,7 +179,7 @@ static void *AVDec_Create(char *medianame)
{
Con_Printf("Unable to open %s\n", medianame);
free(ctx);
free(pBuffer);
av_free(pBuffer);
return NULL;
}
@ -230,7 +229,7 @@ having them tied to the libavformat network IO.
ctx->pACodecCtx=ctx->pFormatCtx->streams[ctx->audioStream]->codec;
pCodec=avcodec_find_decoder(ctx->pACodecCtx->codec_id);
ctx->pAFrame=avcodec_alloc_frame();
ctx->pAFrame=av_frame_alloc();
if(pCodec!=NULL && ctx->pAFrame && avcodec_open2(ctx->pACodecCtx, pCodec, NULL) >= 0)
{
@ -260,7 +259,7 @@ having them tied to the libavformat network IO.
if(pCodec!=NULL && avcodec_open2(ctx->pVCodecCtx, pCodec, NULL) >= 0)
{
// Allocate video frame
ctx->pVFrame=avcodec_alloc_frame();
ctx->pVFrame=av_frame_alloc();
if(ctx->pVFrame!=NULL)
{
if (AVDec_SetSize(ctx, ctx->pVCodecCtx->width, ctx->pVCodecCtx->height))
@ -276,30 +275,27 @@ having them tied to the libavformat network IO.
return NULL;
}
static void *AVDec_DisplayFrame(void *vctx, qboolean nosound, uploadfmt_t *fmt, int *width, int *height)
static qboolean VARGS AVDec_DisplayFrame(void *vctx, qboolean nosound, qboolean forcevideo, double mediatime, void (QDECL *uploadtexture)(void *ectx, uploadfmt_t fmt, int width, int height, void *data, void *palette), void *ectx)
{
struct decctx *ctx = (struct decctx*)vctx;
AVPacket packet;
int frameFinished;
qboolean repainted = false;
int64_t curtime, lasttime;
int64_t curtime;
curtime = ((pSys_Milliseconds() - ctx->starttime) * ctx->denum);
curtime /= (ctx->num * 1000);
curtime = (mediatime * ctx->denum) / ctx->num;
*fmt = TF_BGRA32;
while (1)
{
lasttime = av_frame_get_best_effort_timestamp(ctx->pVFrame);
if (lasttime > curtime)
if (ctx->lasttime > curtime)
break;
// We're ahead of the previous frame. try and read the next.
if (av_read_frame(ctx->pFormatCtx, &packet) < 0)
{
*fmt = TF_INVALID;
break;
if (repainted)
break;
return false;
}
// Is this a packet from the video stream?
@ -314,10 +310,11 @@ static void *AVDec_DisplayFrame(void *vctx, qboolean nosound, uploadfmt_t *fmt,
ctx->pScaleCtx = sws_getCachedContext(ctx->pScaleCtx, ctx->pVCodecCtx->width, ctx->pVCodecCtx->height, ctx->pVCodecCtx->pix_fmt, ctx->width, ctx->height, AV_PIX_FMT_BGRA, SWS_POINT, 0, 0, 0);
// Convert the image from its native format to RGB
sws_scale(ctx->pScaleCtx, (void*)ctx->pVFrame->data, ctx->pVFrame->linesize, 0, ctx->pVCodecCtx->height, ctx->pFrameRGB.data, ctx->pFrameRGB.linesize);
sws_scale(ctx->pScaleCtx, (void*)ctx->pVFrame->data, ctx->pVFrame->linesize, 0, ctx->pVCodecCtx->height, &ctx->rgb_data, &ctx->rgb_linesize);
repainted = true;
}
ctx->lasttime = av_frame_get_best_effort_timestamp(ctx->pVFrame);
}
else if(packet.stream_index==ctx->audioStream && !nosound)
{
@ -335,6 +332,7 @@ static void *AVDec_DisplayFrame(void *vctx, qboolean nosound, uploadfmt_t *fmt,
if (okay)
{
int width = 2;
int channels = ctx->pACodecCtx->channels;
unsigned int auddatasize = av_samples_get_buffer_size(NULL, ctx->pACodecCtx->channels, ctx->pAFrame->nb_samples, ctx->pACodecCtx->sample_fmt, 1);
void *auddata = ctx->pAFrame->data[0];
switch(ctx->pACodecCtx->sample_fmt)
@ -342,13 +340,24 @@ static void *AVDec_DisplayFrame(void *vctx, qboolean nosound, uploadfmt_t *fmt,
default:
auddatasize = 0;
break;
case AV_SAMPLE_FMT_U8P:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_U8:
width = 1;
break;
case AV_SAMPLE_FMT_S16P:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_S16:
width = 2;
break;
case AV_SAMPLE_FMT_FLTP:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_FLT:
//FIXME: support float audio internally.
{
float *in = (void*)auddata;
signed short *out = (void*)auddata;
@ -366,23 +375,43 @@ static void *AVDec_DisplayFrame(void *vctx, qboolean nosound, uploadfmt_t *fmt,
auddatasize/=2;
width = 2;
}
case AV_SAMPLE_FMT_DBLP:
auddatasize /= channels;
channels = 1;
case AV_SAMPLE_FMT_DBL:
{
double *in = (double*)auddata;
signed short *out = (void*)auddata;
int v;
unsigned int i;
for (i = 0; i < auddatasize/sizeof(*in); i++)
{
v = (short)(in[i]*32767);
if (v < -32767)
v = -32767;
else if (v > 32767)
v = 32767;
out[i] = v;
}
auddatasize/=4;
width = 2;
}
break;
}
pS_RawAudio(-1, auddata, ctx->pACodecCtx->sample_rate, auddatasize/(ctx->pACodecCtx->channels*width), ctx->pACodecCtx->channels, width, 1);
pS_RawAudio(-1, auddata, ctx->pACodecCtx->sample_rate, auddatasize/(channels*width), channels, width, 1);
}
}
packet.data = odata;
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
av_packet_unref(&packet);
}
*width = ctx->width;
*height = ctx->height;
if (!repainted)
return NULL;
return ctx->pFrameRGB.data[0];
if (forcevideo || repainted)
uploadtexture(ectx, TF_BGRA32, ctx->width, ctx->height, ctx->rgb_data, NULL);
return true;
}
static void AVDec_GetSize (void *vctx, int *width, int *height)
{
@ -407,11 +436,16 @@ static void AVDec_Rewind(void *vctx)
{
struct decctx *ctx = (struct decctx*)vctx;
if (ctx->videoStream >= 0)
av_seek_frame(ctx->pFormatCtx, ctx->videoStream, 0, AVSEEK_FLAG_BACKWARD);
{
av_seek_frame(ctx->pFormatCtx, ctx->videoStream, 0, AVSEEK_FLAG_FRAME|AVSEEK_FLAG_BACKWARD);
avcodec_flush_buffers(ctx->pVCodecCtx);
}
if (ctx->audioStream >= 0)
av_seek_frame(ctx->pFormatCtx, ctx->audioStream, 0, AVSEEK_FLAG_BACKWARD);
ctx->starttime = pSys_Milliseconds();
{
av_seek_frame(ctx->pFormatCtx, ctx->audioStream, 0, AVSEEK_FLAG_FRAME|AVSEEK_FLAG_BACKWARD);
avcodec_flush_buffers(ctx->pACodecCtx);
}
ctx->lasttime = -1;
}
/*
@ -424,10 +458,10 @@ static qintptr_t AVDec_Shutdown(qintptr_t *args)
static media_decoder_funcs_t decoderfuncs =
{
sizeof(media_decoder_funcs_t),
"avplug",
AVDec_Create,
AVDec_DisplayFrame,
NULL,//doneframe
AVDec_Destroy,
AVDec_Rewind,
@ -452,6 +486,15 @@ static qboolean AVDec_Init(void)
return true;
}
static void AVLogCallback(void *avcl, int level, const char *fmt, va_list vl)
{ //needs to be reenterant
#ifdef _DEBUG
char string[1024];
Q_vsnprintf (string, sizeof(string), fmt, vl);
pCon_Print(string);
#endif
}
//get the encoder/decoders to register themselves with the engine, then make sure avformat/avcodec have registered all they have to give.
qboolean AVEnc_Init(void);
qintptr_t Plug_Init(qintptr_t *args)
@ -464,6 +507,9 @@ qintptr_t Plug_Init(qintptr_t *args)
{
av_register_all();
avcodec_register_all();
av_log_set_level(AV_LOG_WARNING);
av_log_set_callback(AVLogCallback);
}
return okay;
}

View file

@ -5,6 +5,8 @@
#include "libavformat/avio.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
//#include <libavutil/channel_layout.h>
/*
@ -14,6 +16,7 @@ http://svn.gnumonks.org/tags/21c3-video/upstream/ffmpeg-0.4.9-pre1/output_exampl
struct encctx
{
char abspath[MAX_OSPATH];
AVFormatContext *fc;
qboolean doneheaders;
@ -25,27 +28,33 @@ struct encctx
AVStream *audio_st;
AVFrame *audio;
uint8_t *audio_outbuf;
uint32_t audio_outcount;
int64_t audio_pts;
};
#define VARIABLE_AUDIO_FRAME_MIN_SIZE 512 //audio frames smaller than a certain size are just wasteful
#define VARIABLE_AUDIO_FRAME_MAX_SIZE 1024
static void AVEnc_End (void *ctx);
static AVFrame *alloc_frame(enum PixelFormat pix_fmt, int width, int height)
static AVFrame *alloc_frame(enum AVPixelFormat pix_fmt, int width, int height)
{
AVFrame *picture;
uint8_t *picture_buf;
int size;
picture = avcodec_alloc_frame();
picture = av_frame_alloc();
if(!picture)
return NULL;
size = avpicture_get_size(pix_fmt, width, height);
size = av_image_get_buffer_size(pix_fmt, width, height, 1);
picture_buf = (uint8_t*)(av_malloc(size));
if (!picture_buf)
{
av_free(picture);
return NULL;
}
avpicture_fill((AVPicture *) picture, picture_buf, pix_fmt, width, height);
av_image_fill_arrays(picture->data, picture->linesize, picture_buf, pix_fmt, width, height, 1/*fixme: align*/);
picture->width = width;
picture->height = height;
return picture;
@ -61,10 +70,7 @@ AVStream *add_video_stream(struct encctx *ctx, AVCodec *codec, int fps, int widt
st = avformat_new_stream(ctx->fc, codec);
if (!st)
{
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
return NULL;
c = st->codec;
c->codec_id = codec->id;
@ -78,14 +84,14 @@ AVStream *add_video_stream(struct encctx *ctx, AVCodec *codec, int fps, int widt
/* frames per second */
c->time_base.num = 1;
c->time_base.den = fps;
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
c->pix_fmt = PIX_FMT_YUV420P;
if (c->codec_id == CODEC_ID_MPEG2VIDEO)
//c->gop_size = 12; /* emit one intra frame every twelve frames at most */
c->pix_fmt = AV_PIX_FMT_YUV420P;
if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
{
/* just for testing, we also add B frames */
c->max_b_frames = 2;
}
if (c->codec_id == CODEC_ID_MPEG1VIDEO)
if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
{
/* needed to avoid using macroblocks in which some coeffs overflow
this doesnt happen with normal video, it just happens here as the
@ -96,9 +102,13 @@ AVStream *add_video_stream(struct encctx *ctx, AVCodec *codec, int fps, int widt
if (ctx->fc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
*prof = 0;
pCvar_GetString("avplug_format", prof, sizeof(prof));
// av_opt_set(c->priv_data, "profile", prof, AV_OPT_SEARCH_CHILDREN);
pCvar_GetString("avplug_videopreset", prof, sizeof(prof));
if (*prof)
av_opt_set(c->priv_data, "preset", prof, AV_OPT_SEARCH_CHILDREN);
pCvar_GetString("avplug_video_crf", prof, sizeof(prof));
if (*prof)
av_opt_set(c->priv_data, "crf", prof, AV_OPT_SEARCH_CHILDREN);
return st;
}
@ -124,6 +134,7 @@ static void AVEnc_Video (void *vctx, void *data, int frame, int width, int heigh
AVPacket pkt;
int avpfmt;
int inbpp;
int err;
if (!ctx->video_st)
return;
@ -146,28 +157,39 @@ static void AVEnc_Video (void *vctx, void *data, int frame, int width, int heigh
//convert RGB to whatever the codec needs (ie: yuv...).
//also rescales, but only if the user resizes the video while recording. which is a stupid thing to do.
ctx->scale_ctx = sws_getCachedContext(ctx->scale_ctx, width, height, qpfmt, ctx->picture->width, ctx->picture->height, ctx->video_st->codec->pix_fmt, SWS_POINT, 0, 0, 0);
ctx->scale_ctx = sws_getCachedContext(ctx->scale_ctx, width, height, avpfmt, ctx->picture->width, ctx->picture->height, ctx->video_st->codec->pix_fmt, SWS_POINT, 0, 0, 0);
sws_scale(ctx->scale_ctx, srcslices, srcstride, 0, height, ctx->picture->data, ctx->picture->linesize);
av_init_packet(&pkt);
ctx->picture->pts = av_rescale_q(frame, ctx->video_st->codec->time_base, ctx->video_st->time_base);
ctx->picture->pts = frame;
success = 0;
pkt.data = ctx->video_outbuf;
pkt.size = ctx->video_outbuf_size;
if (avcodec_encode_video2(ctx->video_st->codec, &pkt, ctx->picture, &success) == 0 && success)
ctx->picture->format = ctx->video_st->codec->pix_fmt;
err = avcodec_encode_video2(ctx->video_st->codec, &pkt, ctx->picture, &success);
if (err)
{
pkt.pts = ctx->video_st->codec->coded_frame->pts;
if(ctx->video_st->codec->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
char buf[512];
Con_Printf("avcodec_encode_video2: error: %s\n", av_make_error_string(buf, sizeof(buf), err));
}
else if (err == 0 && success)
{
// pkt.pts = ctx->video_st->codec->coded_frame->pts;
// if(ctx->video_st->codec->coded_frame->key_frame)
// pkt.flags |= AV_PKT_FLAG_KEY;
av_packet_rescale_ts(&pkt, ctx->video_st->codec->time_base, ctx->video_st->time_base);
pkt.stream_index = ctx->video_st->index;
pkt.data = ctx->video_outbuf;
// pkt.size = psize;
av_write_frame(ctx->fc, &pkt);
err = av_interleaved_write_frame(ctx->fc, &pkt);
if (err)
{
char buf[512];
Con_Printf("av_interleaved_write_frame: error: %s\n", av_make_error_string(buf, sizeof(buf), err));
}
}
}
AVStream *add_audio_stream(struct encctx *ctx, AVCodec *codec, int samplerate, int bits, int channels)
AVStream *add_audio_stream(struct encctx *ctx, AVCodec *codec, int samplerate, int *bits, int channels)
{
AVCodecContext *c;
AVStream *st;
@ -175,11 +197,9 @@ AVStream *add_audio_stream(struct encctx *ctx, AVCodec *codec, int samplerate, i
st = avformat_new_stream(ctx->fc, codec);
if (!st)
{
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
return NULL;
st->id = ctx->fc->nb_streams-1;
c = st->codec;
c->codec_id = codec->id;
c->codec_type = codec->type;
@ -187,25 +207,46 @@ AVStream *add_audio_stream(struct encctx *ctx, AVCodec *codec, int samplerate, i
/* put sample parameters */
c->bit_rate = bitrate;
/* frames per second */
c->sample_fmt = ((bits==16)?AV_SAMPLE_FMT_S16:AV_SAMPLE_FMT_U8);
c->time_base.num = 1;
c->time_base.den = samplerate;
c->sample_rate = samplerate;
c->channels = channels;
#if 0
switch(channels)
{
case 1:
c->channel_layout = AV_CH_FRONT_CENTER;
c->channel_layout = AV_CH_LAYOUT_MONO;
break;
case 2:
c->channel_layout = AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT;
c->channel_layout = AV_CH_LAYOUT_STEREO;
break;
default:
break;
}
#else
c->channel_layout = av_get_default_channel_layout(c->channels);
#endif
c->channel_layout = av_get_default_channel_layout(c->channels);
c->sample_fmt = codec->sample_fmts[0];
// if (c->sample_fmt == AV_SAMPLE_FMT_FLTP || c->sample_fmt == AV_SAMPLE_FMT_FLT)
// *bits = 32; //get the engine to mix 32bit audio instead of whatever its currently set to.
// else if (c->sample_fmt == AV_SAMPLE_FMT_U8P || c->sample_fmt == AV_SAMPLE_FMT_U8)
// *bits = 8; //get the engine to mix 32bit audio instead of whatever its currently set to.
// else if (c->sample_fmt == AV_SAMPLE_FMT_S16P || c->sample_fmt == AV_SAMPLE_FMT_S16)
// *bits = 16;
// else
*bits = 32;
c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
// some formats want stream headers to be seperate
if (ctx->fc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
// avcodec_parameters_from_context(st->codecpar, c);
return st;
}
void close_audio(struct encctx *ctx)
@ -220,25 +261,159 @@ static void AVEnc_Audio (void *vctx, void *data, int bytes)
struct encctx *ctx = vctx;
int success;
AVPacket pkt;
int err;
ctx->audio->nb_samples = ctx->audio_st->codec->frame_size;
if (avcodec_fill_audio_frame(ctx->audio, ctx->audio_st->codec->channels, ctx->audio_st->codec->sample_fmt, data, bytes, 0) < 0)
if (!ctx->audio_st)
return;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
success = 0;
if (avcodec_encode_audio2(ctx->audio_st->codec, &pkt, ctx->audio, &success) == 0 && success)
while (bytes)
{
pkt.pts = ctx->audio_st->codec->coded_frame->pts;
if(ctx->audio_st->codec->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = ctx->audio_st->index;
// pkt.data = ctx->video_outbuf;
// pkt.size = psize;
int i, p, chans = ctx->audio_st->codec->channels;
int blocksize = sizeof(float)*chans;
int count = bytes / blocksize;
int planesize = ctx->audio_st->codec->frame_size;
float *in;
int offset;
av_write_frame(ctx->fc, &pkt);
if (!planesize) //variable-sized frames. yay
{
planesize = count;
if (count > VARIABLE_AUDIO_FRAME_MAX_SIZE - ctx->audio_outcount)
count = VARIABLE_AUDIO_FRAME_MAX_SIZE - ctx->audio_outcount;
}
else if (count > ctx->audio_st->codec->frame_size - ctx->audio_outcount)
count = ctx->audio_st->codec->frame_size - ctx->audio_outcount;
in = (float*)data;
offset = ctx->audio_outcount;
ctx->audio_outcount += count;
data = (qbyte*)data + count * blocksize;
bytes -= count * blocksize;
//input is always float audio, because I'm lazy.
//output is whatever the codec needs (may be packed or planar, gah).
//the engine's mixer will do all rate scaling for us, as well as channel selection
switch(ctx->audio_st->codec->sample_fmt)
{
case AV_SAMPLE_FMT_DBL:
offset *= chans;
count *= chans;
planesize *= chans;
chans = 1;
case AV_SAMPLE_FMT_DBLP:
for (p = 0; p < chans; p++)
{
double *f = (double*)ctx->audio_outbuf + p*planesize + offset;
for (i = 0; i < count*chans; i+=chans)
*f++ = in[i];
in++;
}
break;
case AV_SAMPLE_FMT_FLT:
offset *= chans;
count *= chans;
planesize *= chans;
chans = 1;
case AV_SAMPLE_FMT_FLTP:
for (p = 0; p < chans; p++)
{
float *f = (float *)ctx->audio_outbuf + p*planesize + offset;
for (i = 0; i < count*chans; i+=chans)
*f++ = in[i];
in++;
}
break;
case AV_SAMPLE_FMT_S32:
offset *= chans;
count *= chans;
planesize *= chans;
chans = 1;
case AV_SAMPLE_FMT_S32P:
for (p = 0; p < chans; p++)
{
int32_t *f = (int32_t *)ctx->audio_outbuf + p*planesize + offset;
for (i = 0; i < count*chans; i+=chans)
*f++ = bound(0x80000000, (in[i] * 0x7fffffff), 0x7fffffff);
in++;
}
break;
case AV_SAMPLE_FMT_S16:
offset *= chans;
count *= chans;
planesize *= chans;
chans = 1;
case AV_SAMPLE_FMT_S16P:
for (p = 0; p < chans; p++)
{
int16_t *f = (int16_t *)ctx->audio_outbuf + p*planesize + offset;
for (i = 0; i < count*chans; i+=chans)
*f++ = bound(-32768, (int)(in[i] * 32767), 32767);
//sin((ctx->audio_pts+ctx->audio_outcount-count+i/chans)*0.1) * 32767;//
in++;
}
break;
case AV_SAMPLE_FMT_U8:
offset *= chans;
count *= chans;
planesize *= chans;
chans = 1;
case AV_SAMPLE_FMT_U8P:
for (p = 0; p < chans; p++)
{
uint8_t *f = (uint8_t*)ctx->audio_outbuf + p*planesize + offset;
for (i = 0; i < count*chans; i+=chans)
*f++ = bound(0, 128+(int)(in[i] * 127), 255);
in++;
}
break;
default:
return;
}
if (ctx->audio_st->codec->frame_size)
{
if (ctx->audio_outcount < ctx->audio_st->codec->frame_size)
break; //not enough data yet.
}
else
{
if (ctx->audio_outcount < VARIABLE_AUDIO_FRAME_MIN_SIZE)
break; //not enough data yet.
}
ctx->audio->nb_samples = ctx->audio_outcount;
avcodec_fill_audio_frame(ctx->audio, ctx->audio_st->codec->channels, ctx->audio_st->codec->sample_fmt, ctx->audio_outbuf, av_get_bytes_per_sample(ctx->audio_st->codec->sample_fmt)*ctx->audio_outcount*ctx->audio_st->codec->channels, 1);
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
success = 0;
ctx->audio->pts = ctx->audio_pts;
ctx->audio_pts += ctx->audio_outcount;
ctx->audio_outcount = 0;
err = avcodec_encode_audio2(ctx->audio_st->codec, &pkt, ctx->audio, &success);
if (err)
{
char buf[512];
Con_Printf("avcodec_encode_audio2: error: %s\n", av_make_error_string(buf, sizeof(buf), err));
}
else if (success)
{
// pkt.pts = ctx->audio_st->codec->coded_frame->pts;
// if(ctx->audio_st->codec->coded_frame->key_frame)
// pkt.flags |= AV_PKT_FLAG_KEY;
av_packet_rescale_ts(&pkt, ctx->audio_st->codec->time_base, ctx->audio_st->time_base);
pkt.stream_index = ctx->audio_st->index;
err = av_interleaved_write_frame(ctx->fc, &pkt);
if (err)
{
char buf[512];
Con_Printf("av_interleaved_write_frame: error: %s\n", av_make_error_string(buf, sizeof(buf), err));
}
}
}
}
@ -249,8 +424,9 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
AVCodec *videocodec = NULL;
AVCodec *audiocodec = NULL;
char formatname[64];
int err;
formatname[0] = 0;
pCvar_GetString("avplug_format", formatname, sizeof(formatname));
pCvar_GetString("avplug_format_force", formatname, sizeof(formatname));
if (*formatname)
{
@ -349,49 +525,56 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
//pick default codecs
ctx->video_st = NULL;
if (videocodec)
{
ctx->video_st = add_video_stream(ctx, videocodec, videorate, width, height);
if (ctx->video_st)
{
AVCodecContext *c = ctx->video_st->codec;
if (avcodec_open2(c, videocodec, NULL) < 0)
{
Con_Printf("avplug: Could not init codec instance \"%s\". Maybe try a different framerate/resolution/bitrate\n", videocodec->name);
AVEnc_End(ctx);
return NULL;
}
ctx->picture = alloc_frame(c->pix_fmt, c->width, c->height);
ctx->video_outbuf_size = 200000;
ctx->video_outbuf = av_malloc(ctx->video_outbuf_size);
if (!ctx->video_outbuf)
ctx->video_outbuf_size = 0;
}
}
if (audiocodec)
{
ctx->audio_st = add_audio_stream(ctx, audiocodec, *sndkhz, *sndbits, *sndchannels);
if (ctx->audio_st)
{
AVCodecContext *c = ctx->audio_st->codec;
if (avcodec_open2(c, audiocodec, NULL) < 0)
{
Con_Printf("avplug: Could not init codec instance \"%s\".\n", audiocodec->name);
AVEnc_End(ctx);
return NULL;
}
ctx->audio_st = add_audio_stream(ctx, audiocodec, *sndkhz, sndbits, *sndchannels);
ctx->audio = avcodec_alloc_frame();
if (ctx->video_st)
{
AVCodecContext *c = ctx->video_st->codec;
err = avcodec_open2(c, videocodec, NULL);
if (err < 0)
{
char buf[512];
Con_Printf("avplug: Could not init codec instance \"%s\" - %s\nMaybe try a different framerate/resolution/bitrate\n", videocodec->name, av_make_error_string(buf, sizeof(buf), err));
AVEnc_End(ctx);
return NULL;
}
ctx->picture = alloc_frame(c->pix_fmt, c->width, c->height);
ctx->video_outbuf_size = 200000;
ctx->video_outbuf = av_malloc(ctx->video_outbuf_size);
if (!ctx->video_outbuf)
ctx->video_outbuf_size = 0;
}
if (ctx->audio_st)
{
int sz;
AVCodecContext *c = ctx->audio_st->codec;
err = avcodec_open2(c, audiocodec, NULL);
if (err < 0)
{
char buf[512];
Con_Printf("avplug: Could not init codec instance \"%s\" - %s\n", audiocodec->name, av_make_error_string(buf, sizeof(buf), err));
AVEnc_End(ctx);
return NULL;
}
ctx->audio = av_frame_alloc();
sz = ctx->audio_st->codec->frame_size;
if (!sz)
sz = VARIABLE_AUDIO_FRAME_MAX_SIZE;
sz *= av_get_bytes_per_sample(ctx->audio_st->codec->sample_fmt) * ctx->audio_st->codec->channels;
ctx->audio_outbuf = av_malloc(sz);
}
av_dump_format(ctx->fc, 0, streamname, 1);
if (!(fmt->flags & AVFMT_NOFILE))
{
if (avio_open(&ctx->fc->pb, streamname, AVIO_FLAG_WRITE) < 0)
//okay, this is annoying, but I'm too lazy to figure out the issue I was having with avio stuff.
if (!pFS_NativePath(streamname, FS_GAMEONLY, ctx->abspath, sizeof(ctx->abspath)) || avio_open(&ctx->fc->pb, ctx->abspath, AVIO_FLAG_WRITE) < 0)
{
Con_Printf("Could not open '%s'\n", streamname);
AVEnc_End(ctx);
@ -400,7 +583,14 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
}
//nearly complete, can make the file dirty now.
avformat_write_header(ctx->fc, NULL);
err = avformat_write_header(ctx->fc, NULL);
if (err < 0)
{
char buf[512];
Con_Printf("avformat_write_header: failed %s\n", av_make_error_string(buf, sizeof(buf), err));
AVEnc_End(ctx);
return NULL;
}
ctx->doneheaders = true;
return ctx;
}
@ -413,18 +603,26 @@ static void AVEnc_End (void *vctx)
//don't write trailers if this is an error case and we never even wrote the headers.
if (ctx->doneheaders)
{
av_write_trailer(ctx->fc);
if (*ctx->abspath)
Con_Printf("Finished writing %s\n", ctx->abspath);
}
for(i = 0; i < ctx->fc->nb_streams; i++)
av_freep(&ctx->fc->streams[i]);
// if (!(fmt->flags & AVFMT_NOFILE))
avio_close(ctx->fc->pb);
av_free(ctx->audio_outbuf);
av_free(ctx->fc);
free(ctx);
}
static media_encoder_funcs_t encoderfuncs =
{
sizeof(media_encoder_funcs_t),
"avplug",
"Use ffmpeg's various codecs. Various settings are configured with the avplug_* cvars.",
".mp4",
AVEnc_Begin,
AVEnc_Video,
AVEnc_Audio,
@ -457,22 +655,28 @@ menutext 0 24 "Cancel"
qboolean AVEnc_Init(void)
{
pCvar_Register("avplug_format", "mp4", 0, "avplug");
pCvar_Register("avplug_videocodec", "mpeg4", 0, "avplug");
pCvar_Register("avplug_videocodecprofile", "", 0, "avplug");
pCvar_Register("avplug_videobitrate", "4000000", 0, "avplug");
pCvar_Register("avplug_videoforcewidth", "", 0, "avplug");
pCvar_Register("avplug_videoforceheight", "", 0, "avplug");
pCvar_Register("avplug_audiocodec", "libmp3lame", 0, "avplug");
pCvar_Register("avplug_audiobitrate", "64000", 0, "avplug");
CHECKBUILTIN(FS_NativePath);
if (!BUILTINISVALID(FS_NativePath))
{
Con_Printf("avplug: Engine too old\n");
return false;
}
if (!pPlug_ExportNative("Media_VideoEncoder", &encoderfuncs))
{
Con_Printf("avplug: Engine doesn't support media encoder plugins\n");
return false;
}
pCvar_Register("avplug_format_force", "", 0, "avplug");
pCvar_Register("avplug_videocodec", "", 0, "avplug");
pCvar_Register("avplug_videobitrate", "4000000", 0, "avplug");
pCvar_Register("avplug_videoforcewidth", "", 0, "avplug");
pCvar_Register("avplug_videoforceheight", "", 0, "avplug");
pCvar_Register("avplug_videopreset", "veryfast", 0, "avplug");
pCvar_Register("avplug_audiocodec", "", 0, "avplug");
pCvar_Register("avplug_audiobitrate", "64000", 0, "avplug");
// if (Plug_Export("ExecuteCommand", AVEnc_ExecuteCommand))
// Cmd_AddCommand("avcapture");

View file

@ -54,7 +54,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="berkelium/berkelium.lib"
OutputFile="../../fteplug_berkeliumx86.dll"
OutputFile="../../fteplug_berkelium_x86.dll"
LinkIncremental="2"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"

View file

@ -181,7 +181,7 @@ public:
MyDelegate(decctx *_ctx) : ctx(_ctx) {};
};
static void *Dec_Create(char *medianame)
static void *Dec_Create(const char *medianame)
{
/*only respond to berkelium: media prefixes*/
if (!strncmp(medianame, "berkelium:", 10))
@ -220,19 +220,17 @@ static void *Dec_Create(char *medianame)
return ctx;
}
static void *Dec_DisplayFrame(void *vctx, qboolean nosound, enum uploadfmt_e *fmt, int *width, int *height)
static qboolean VARGS Dec_DisplayFrame(void *vctx, qboolean nosound, qboolean forcevideo, double mediatime, void (QDECL *uploadtexture)(void *ectx, uploadfmt_t fmt, int width, int height, void *data, void *palette), void *ectx)
{
decctx *ctx = (decctx*)vctx;
*fmt = TF_BGRA32;
*width = ctx->width;
*height = ctx->height;
if (!ctx->repainted)
return NULL;
ctx->paintedwidth = ctx->width;
ctx->paintedheight = ctx->height;
ctx->repainted = false;
return ctx->buffer;
if (forcevideo || ctx->repainted)
{
uploadtexture(ectx, TF_BGRA32, ctx->width, ctx->height, ctx->buffer, NULL);
ctx->paintedwidth = ctx->width;
ctx->paintedheight = ctx->height;
ctx->repainted = false;
}
return qtrue;
}
static void Dec_Destroy(void *vctx)
{
@ -340,7 +338,7 @@ static void Dec_Key (void *vctx, int code, int unicode, int isup)
}
}
static void Dec_ChangeStream(void *vctx, char *newstream)
static void Dec_ChangeStream(void *vctx, const char *newstream)
{
decctx *ctx = (decctx*)vctx;
@ -413,10 +411,11 @@ static qintptr_t Dec_Shutdown(qintptr_t *args)
static media_decoder_funcs_t decoderfuncs =
{
sizeof(media_decoder_funcs_t),
"berkelium",
Dec_Create,
Dec_DisplayFrame,
NULL,//doneframe
Dec_Destroy,
NULL,//rewind

1969
plugins/cef/cef.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,37 +1,46 @@
#ifndef FTEPLUGIN
#ifndef VARGS
#define VARGS QDECL
#endif
typedef enum uploadfmt_e
{
TF_INVALID,
TF_RGBA32,
TF_BGRA32,
TF_RGBX32,
TF_BGRX32
TF_BGRX32,
TF_RGB24,
TF_BGR24
} uploadfmt_t;
typedef struct
{
char *drivername;
void *(QDECL *createdecoder)(char *name); //needed
void *(QDECL *decodeframe)(void *ctx, qboolean nosound, uploadfmt_t *fmt, int *width, int *height); //needed
void (QDECL *doneframe)(void *ctx, void *img); //basically a free()
void (QDECL *shutdown)(void *ctx); //probably needed...
void (QDECL *rewind)(void *ctx);
size_t structsize;
const char *drivername;
void *(VARGS *createdecoder)(const char *name);
qboolean (VARGS *decodeframe)(void *ctx, qboolean nosound, qboolean forcevideo, double mediatime, void (QDECL *uploadtexture)(void *ectx, uploadfmt_t fmt, int width, int height, void *data, void *palette), void *ectx);
void (VARGS *shutdown)(void *ctx);
void (VARGS *rewind)(void *ctx);
//these are any interactivity functions you might want...
void (QDECL *cursormove) (void *ctx, float posx, float posy); //pos is 0-1
void (QDECL *key) (void *ctx, int code, int unicode, int event); //key event! event=1=down
qboolean (QDECL *setsize) (void *ctx, int width, int height); //updates the desired screen-space size
void (QDECL *getsize) (void *ctx, int *width, int *height); //retrieves the screen-space size
void (QDECL *changestream) (void *ctx, char *streamname); //can be used to accept commands from qc
} media_decoder_funcs_t;
void (VARGS *cursormove) (void *ctx, float posx, float posy); //pos is 0-1
void (VARGS *key) (void *ctx, int code, int unicode, int event);
qboolean (VARGS *setsize) (void *ctx, int width, int height);
void (VARGS *getsize) (void *ctx, int *width, int *height);
void (VARGS *changestream) (void *ctx, const char *streamname);
size_t (VARGS *gettext) (void *ctx, const char *field, char *out, size_t outlen); //if out is null, returns required buffer size. returns 0 on failure / buffer too small
} media_decoder_funcs_t;
typedef struct
{
char *drivername;
void *(QDECL *capture_begin) (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits);
void (QDECL *capture_video) (void *ctx, void *data, int frame, int width, int height);
void (QDECL *capture_audio) (void *ctx, void *data, int bytes);
void (QDECL *capture_end) (void *ctx);
size_t structsize;
const char *drivername;
const char *description;
const char *defaultextension;
void *(VARGS *capture_begin) (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits);
void (VARGS *capture_video) (void *ctx, void *data, int frame, int width, int height, enum uploadfmt fmt);
void (VARGS *capture_audio) (void *ctx, void *data, int bytes);
void (VARGS *capture_end) (void *ctx);
} media_encoder_funcs_t;
#endif

View file

@ -127,7 +127,8 @@ char *TP_ItemName(unsigned int itbit);
#define Util_SkipEZColors(src,dst,dstlen) strlcpy(dst,src,dstlen)
void Replace_In_String(char *string, size_t strsize, char leadchar, int patterns, ...);
static qbool Utils_RegExpMatch(char *regexp, char *term) {return true;}
//static qbool Utils_RegExpMatch(char *regexp, char *term) {return true;}
#define Utils_RegExpMatch(regexp,term) (true)
#define clamp(v,min,max) v=bound(min,v,max)
#define strlen_color(line) (pDraw_StringWidth(8, 0, line)/8.0)

View file

@ -793,12 +793,18 @@ void HUD_Export_f(void)
cvar_t *var;
int i;
char *fname = "foo";
char *fdesc = "OMG ITS FOO";
char fname[64];
char fdesc[256];
pCmd_Argv(1, fname, sizeof(fname));
pCmd_Argv(2, fdesc, sizeof(fdesc));
if (!*fdesc)
snprintf(fdesc, sizeof(fdesc), "%s", fname);
snprintf(line, sizeof(line), "configs/hud_%s.cfg", fname);
if (pFS_Open(line, &handle, 0) < 0)
if (pFS_Open(line, &handle, 2) < 0)
Com_Printf("Couldn't open %s\n", line);
else
{
@ -1353,7 +1359,7 @@ hud_t * HUD_Register(char *name, char *var_alias, char *description,
void HUD_ParamsCleanup(void)
{
int i = 0;
// int i = 0;
hud_t *hud = hud_huds;
while (hud)

View file

@ -510,10 +510,12 @@ void SCR_HUD_DrawMouserate(hud_t *hud)
void SCR_HUD_DrawTracking(hud_t *hud)
{
#ifdef HAXX
static char tracked_strings[MV_VIEWS][MAX_TRACKING_STRING];
static int tracked[MV_VIEWS] = {-1, -1, -1, -1};
int views = 1;
int view = 0;
#endif
int views = 1;
int x = 0, y = 0, width = 0, height = 0;
char track_string[MAX_TRACKING_STRING];
@ -847,8 +849,9 @@ void SCR_HUD_DrawGameClock(hud_t *hud)
*hud_gameclock_style,
*hud_gameclock_blink,
*hud_gameclock_countdown,
*hud_gameclock_scale,
*hud_gameclock_offset;
*hud_gameclock_scale
// *hud_gameclock_offset
;
if (hud_gameclock_big == NULL) // first time
{
@ -857,7 +860,7 @@ void SCR_HUD_DrawGameClock(hud_t *hud)
hud_gameclock_blink = HUD_FindVar(hud, "blink");
hud_gameclock_countdown = HUD_FindVar(hud, "countdown");
hud_gameclock_scale = HUD_FindVar(hud, "scale");
hud_gameclock_offset = HUD_FindVar(hud, "offset");
// hud_gameclock_offset = HUD_FindVar(hud, "offset");
// gameclockoffset = &hud_gameclock_offset->ival;
}
@ -1170,7 +1173,7 @@ void SCR_HUD_DrawSpeed2(hud_t *hud)
int x, y;
static cvar_t *hud_speed2_xyz = NULL,
*hud_speed2_opacity,
// *hud_speed2_opacity,
*hud_speed2_color_stopped,
*hud_speed2_color_normal,
*hud_speed2_color_fast,
@ -1183,7 +1186,7 @@ void SCR_HUD_DrawSpeed2(hud_t *hud)
if (hud_speed2_xyz == NULL) // first time
{
hud_speed2_xyz = HUD_FindVar(hud, "xyz");
hud_speed2_opacity = HUD_FindVar(hud, "opacity");
// hud_speed2_opacity = HUD_FindVar(hud, "opacity");
hud_speed2_color_stopped = HUD_FindVar(hud, "color_stopped");
hud_speed2_color_normal = HUD_FindVar(hud, "color_normal");
hud_speed2_color_fast = HUD_FindVar(hud, "color_fast");
@ -1418,6 +1421,13 @@ void SCR_HUD_DrawSpeed2(hud_t *hud)
// Draw the speed needle.
Draw_AlphaLineRGB (needle_start_x, needle_start_y, needle_end_x, needle_end_y, 1, RGBA_TO_COLOR(250, 250, 250, 255 * hud_speed2_opacity->value));
#else
(void)color1;
(void)color2;
(void)needle_start_x;
(void)needle_start_y;
(void)needle_end_x;
(void)needle_end_y;
#endif
// Draw the speed.
@ -2268,7 +2278,6 @@ void Amf_Reset_DamageStats(void)
void Draw_AMFStatLoss (int stat, hud_t* hud) {
//fixme: should reset these on pov change
int * vxdmgcnt, * vxdmgcnt_t, * vxdmgcnt_o;
int x;
float alpha;
int elem;
@ -2276,13 +2285,11 @@ void Draw_AMFStatLoss (int stat, hud_t* hud) {
vxdmgcnt = &vxdamagecount;
vxdmgcnt_t = &vxdamagecount_time;
vxdmgcnt_o = &vxdamagecount_oldhealth;
x = 136;
elem = 0;
} else {
vxdmgcnt = &vxdamagecountarmour;
vxdmgcnt_t = &vxdamagecountarmour_time;
vxdmgcnt_o = &vxdamagecountarmour_oldhealth;
x = 24;
elem = 1;
}
@ -5102,9 +5109,9 @@ static void SCR_HUD_DrawTeamHoldBar(hud_t *hud)
void TeamHold_OnChangeItemFilterInfo(cvar_t *var, char *oldvalue)
{
char *start = var->string;
char *end = start;
int order = 0;
// char *start = var->string;
// char *end = start;
// int order = 0;
// Parse the item filter.
teamhold_show_rl = Utils_RegExpMatch("RL", var->string);

File diff suppressed because it is too large Load diff

View file

@ -55,7 +55,7 @@
/>
<Tool
Name="VCLinkerTool"
OutputFile="../../fteplug_$(ProjectName)x86.dll"
OutputFile="../../fteplug_xmpp_x86.dll"
LinkIncremental="2"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"

View file

@ -90,15 +90,6 @@ enum
#define Q_strncpyz(o, i, l) do {strncpy(o, i, l-1);o[l-1]='\0';}while(0)
#define ARGNAMES ,sock,certhostname
BUILTINR(int, Net_SetTLSClient, (qhandle_t sock, const char *certhostname));
#undef ARGNAMES
#define ARGNAMES ,funcname
BUILTINR(void *, Plug_GetNativePointer, (const char *funcname));
#undef ARGNAMES
void (*Con_TrySubPrint)(const char *conname, const char *message);
void Fallback_ConPrint(const char *conname, const char *message)
{
@ -252,7 +243,6 @@ static VOID (WINAPI *pDnsRecordListFree)(PDNS_RECORD pRecordList, DNS_FREE_TYPE
static HMODULE dnsapi_lib;
qboolean NET_DNSLookup_SRV(char *host, char *out, int outlen)
{
HRESULT hr;
DNS_RECORD *result = NULL;
if (!dnsapi_lib)
{
@ -264,7 +254,7 @@ qboolean NET_DNSLookup_SRV(char *host, char *out, int outlen)
if (!pDnsQuery_UTF8 || !pDnsRecordListFree)
return false;
//do lookup
hr = pDnsQuery_UTF8(host, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &result, NULL);
pDnsQuery_UTF8(host, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &result, NULL);
if (result)
{
Q_snprintf(out, outlen, "[%s]:%i", result->Data.SRV.pNameTarget, result->Data.SRV.wPort);
@ -283,10 +273,9 @@ qboolean NET_DNSLookup_SRV(char *host, char *out, int outlen)
qbyte answer[512];
qbyte dname[512];
int len, i;
static qboolean inited;
qbyte *msg, *eom, *cp;
qbyte *msg, *eom;
len = res_query(host, C_IN, T_SRV, &answer, sizeof(answer));
len = res_query(host, C_IN, T_SRV, answer, sizeof(answer));
if (len < 12)
{
Con_Printf("srv lookup failed for %s\n", host);
@ -569,7 +558,6 @@ qintptr_t Plug_Init(qintptr_t *args)
Plug_Export("Shutdown", JCL_Shutdown) &&
Plug_Export("ExecuteCommand", JCL_ExecuteCommand))
{
CHECKBUILTIN(Net_SetTLSClient);
if (!BUILTINISVALID(Net_SetTLSClient))
Con_Printf("XMPP Plugin Loaded ^1without^7 TLS\n"); //most servers REQUIRE tls now
else
@ -609,7 +597,6 @@ qintptr_t Plug_Init(qintptr_t *args)
pCvar_Register("xmpp_debug", "0", 0, "xmpp");
#ifdef JINGLE
CHECKBUILTIN(Plug_GetNativePointer);
if (BUILTINISVALID(Plug_GetNativePointer))
piceapi = pPlug_GetNativePointer(ICE_API_CURRENT);
#endif
@ -1345,7 +1332,7 @@ qintptr_t JCL_ConsoleLinkMouseOver(qintptr_t *args)
char which[256];
char *actiontext;
int i;
buddy_t *b, *me;
buddy_t *b, *me = NULL;
bresource_t *br;
float x = *(float*)&args[0];
float y = *(float*)&args[1];
@ -1751,6 +1738,16 @@ qintptr_t JCL_ConExecuteCommand(qintptr_t *args)
{
case ACT_NONE:
break;
case ACT_OAUTH:
jcl = jclient_action_cl;
if (jcl)
{
free(jcl->oauth2.authtoken);
jcl->oauth2.authtoken = strdup(args);
if (jcl->status == JCL_INACTIVE)
jcl->status = JCL_DEAD;
}
break;
case ACT_NEWACCOUNT:
if (!*args)
break; //they didn't enter anything! oh well.
@ -2789,7 +2786,7 @@ static qboolean JCL_BuddyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s
const char *nickname;
const char *photomime;
buddy_t *b;
buddy_t *b = NULL;
char *from = iq->to;
if (!*from)
@ -2923,11 +2920,8 @@ static qboolean JCL_MyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s *i
}
else
{
char *hex = "0123456789abcdef";
int photosize;
int digestsize;
photosize = Base64_Decode(photodata, sizeof(photodata), photobinval->body, strlen(photobinval->body));
digestsize = SHA1(digest, sizeof(digest), photodata, photosize);
int photosize = Base64_Decode(photodata, sizeof(photodata), photobinval->body, strlen(photobinval->body));
SHA1(digest, sizeof(digest), photodata, photosize);
if (jcl->vcardphotohashstatus != VCP_KNOWN || memcmp(jcl->vcardphotohash, digest, sizeof(jcl->vcardphotohash)))
{
memcpy(jcl->vcardphotohash, digest, sizeof(jcl->vcardphotohash));
@ -3148,13 +3142,13 @@ char *buildcapsvcardpresence(jclient_t *jcl, char *caps, size_t sizeofcaps)
}
else if (jcl->vcardphotohashstatus == VCP_KNOWN)
{
char *hex = "0123456789abcdef";
unsigned char *hex = "0123456789abcdef";
char inhex[41];
int i, o;
for (i = 0, o = 0; i < sizeof(jcl->vcardphotohash); i++)
{
inhex[o++] = hex[jcl->vcardphotohash[(i>>4) & 0xf]];
inhex[o++] = hex[jcl->vcardphotohash[(i>>0) & 0xf]];
inhex[o++] = hex[(jcl->vcardphotohash[i]>>4) & 0xf];
inhex[o++] = hex[(jcl->vcardphotohash[i]>>0) & 0xf];
}
inhex[o] = 0;
@ -4857,8 +4851,8 @@ static void JCL_RegenerateBuddyList(qboolean force)
for (c2c = jcl->c2c; c2c; c2c = c2c->next)
{
buddy_t *peer;
qboolean voice = false, video = false, server = false, client = false;
buddy_t *peer = NULL;
qboolean voice = false, video = false, server = false;
int c;
JCL_FindBuddy(jcl, c2c->with, &peer, NULL, true);
if (peer == b)
@ -4867,10 +4861,11 @@ static void JCL_RegenerateBuddyList(qboolean force)
{
switch(c2c->content[c].mediatype)
{
case ICEP_INVALID: break;
case ICEP_VOICE: voice = true; break;
case ICEP_VIDEO: video = true; break;
case ICEP_QWSERVER: server = true; break;
case ICEP_QWCLIENT: client = true; break;
case ICEP_QWCLIENT: /*client = true;*/ break;
}
}
if (server)
@ -4883,7 +4878,7 @@ static void JCL_RegenerateBuddyList(qboolean force)
JCL_GenLink(jcl, convolink, sizeof(convolink), "jdeny", c2c->with, NULL, c2c->sid, "%s", "Hang Up");
voiceres = NULL;
}
else
else /*if (client)*/
{
JCL_GenLink(jcl, convolink, sizeof(convolink), "jdeny", c2c->with, NULL, c2c->sid, "%s", "Disconnect");
gameres = NULL;
@ -4979,6 +4974,7 @@ static void JCL_PrintBuddyList(char *console, jclient_t *jcl, qboolean all)
{
switch(c2c->content[c].mediatype)
{
case ICEP_INVALID: break;
case ICEP_VOICE: voice = true; break;
case ICEP_VIDEO: video = true; break;
case ICEP_QWSERVER: server = true; break;
@ -5588,7 +5584,7 @@ void JCL_Command(int accid, char *console)
msg = JCL_ParseOut(msg, arg[0], sizeof(arg[0]));
msg = JCL_ParseOut(msg, arg[1], sizeof(arg[1]));
while(*msg == ' ')
*msg++;
msg++;
JCL_SendMessage(jcl, jcl->defaultdest, msg);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -62,7 +62,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="zlib.lib"
OutputFile="../../fteplug_mpqx86.dll"
OutputFile="../../fteplug_mpq_x86.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="../..\engine\libs"
ModuleDefinitionFile="../plugin.def"

View file

@ -0,0 +1,204 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="odeplug"
ProjectGUID="{ED16B405-BDCD-4EB8-BF70-761964301368}"
RootNamespace="odeplug"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common;."
PreprocessorDefinitions="FTEPLUGIN;ODE_STATIC"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
BrowseInformation="1"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ode/ode_doubled.lib"
OutputFile="../../fteplug_ode_x86.dll"
LinkIncremental="2"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"
GenerateDebugInformation="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
PreprocessorDefinitions="FTEPLUGIN"
CallingConvention="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ode/ode_double.lib"
OutputFile="../../fteplug_odex86.dll"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
>
<File
RelativePath="..\..\engine\common\com_phys_ode.c"
>
</File>
<File
RelativePath="..\..\engine\common\mathlib.c"
>
</File>
<File
RelativePath="..\plugin.c"
>
</File>
<File
RelativePath="..\qvm_api.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
>
</Filter>
<File
RelativePath="..\plugin.def"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -49,6 +49,10 @@ BUILTINR(int, Plug_ExportToEngine, (const char *funcname, int expnum));
#define ARGNAMES ,funcname,func
BUILTINR(qboolean, Plug_ExportNative, (const char *funcname, void *func));
#undef ARGNAMES
#define ARGNAMES ,funcname
BUILTINR(void *, Plug_GetNativePointer, (const char *funcname));
#undef ARGNAMES
#endif
#define ARGNAMES ,text
@ -159,6 +163,20 @@ BUILTINR(int, GetLastInputFrame, (int seat, usercmd_t *playercmd));
BUILTINR(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize));
#undef ARGNAMES
#ifndef Q3_VM
#define ARGNAMES ,vmid
BUILTINR(struct pubprogfuncs_s*, PR_GetVMInstance, (int vmid/*0=ss,1=cs,2=m*/));
#undef ARGNAMES
#ifdef MULTITHREAD
#define ARGNAMES ,threadingsize
BUILTINR(struct threading_s*, Sys_GetThreadingFuncs, (int threadingsize));
#undef ARGNAMES
#endif
#define ARGNAMES ,version
BUILTINR(struct modplugfuncs_s*, Mod_GetPluginModelFuncs, (int version));
#undef ARGNAMES
#endif
#define ARGNAMES ,pos,buffer,bufferlen
BUILTIN(void, GetLocationName, (const float *pos, char *buffer, int bufferlen));
@ -233,7 +251,7 @@ BUILTIN(void, Draw_Colour4f, (float r, float g, float b, float a));
#undef ARGNAMES
#define ARGNAMES ,s
BUILTIN(void, SCR_CenterPrint, (char *s));
BUILTIN(void, SCR_CenterPrint, (const char *s));
#undef ARGNAMES
#define ARGNAMES ,mnum
@ -241,16 +259,19 @@ BUILTIN(void, Menu_Control, (int mnum));
#undef ARGNAMES
#define ARGNAMES ,keyname
BUILTINR(int, Key_GetKeyCode, (char *keyname));
BUILTINR(int, Key_GetKeyCode, (const char *keyname));
#undef ARGNAMES
#if !defined(Q3_VM) && defined(FTEPLUGIN)
#define ARGNAMES ,name,handle,mode
BUILTINR(qboolean, VFS_Open, (char *name, vfsfile_t **handle, char *mode));//opens a direct vfs file. no access checks, and so can be used in threaded plugins
BUILTINR(qboolean, VFS_Open, (const char *name, vfsfile_t **handle, const char *mode));//opens a direct vfs file. no access checks, and so can be used in threaded plugins
#undef ARGNAMES
#define ARGNAMES ,name,relativeto,out,outlen
BUILTINR(qboolean, FS_NativePath, (const char *name, enum fs_relative relativeto, char *out, int outlen));
#undef ARGNAMES
#endif
#define ARGNAMES ,name,handle,mode
BUILTINR(int, FS_Open, (char *name, qhandle_t *handle, int mode));
BUILTINR(int, FS_Open, (const char *name, qhandle_t *handle, int mode));
#undef ARGNAMES
#define ARGNAMES ,handle
BUILTIN(void, FS_Close, (qhandle_t handle));
@ -264,7 +285,9 @@ BUILTINR(int, FS_Read, (qhandle_t handle, void *data, int len));
#define ARGNAMES ,handle,offsetlow,offsethigh
BUILTINR(int, FS_Seek, (qhandle_t handle, unsigned int offsetlow, unsigned int offsethigh));
#undef ARGNAMES
#define ARGNAMES ,handle,sizelow,sizehigh
BUILTINR(qboolean, FS_GetLen, (qhandle_t handle, unsigned int *sizelow, unsigned int *sizehigh));
#undef ARGNAMES
#define ARGNAMES ,ip,port
BUILTINR(qhandle_t, Net_TCPConnect, (char *ip, int port));
@ -284,6 +307,9 @@ BUILTINR(int, Net_Send, (qhandle_t socket, void *buffer, int len));
#define ARGNAMES ,socket
BUILTIN(void, Net_Close, (qhandle_t socket));
#undef ARGNAMES
#define ARGNAMES ,sock,certhostname
BUILTINR(int, Net_SetTLSClient, (qhandle_t sock, const char *certhostname));
#undef ARGNAMES
#define ARGNAMES ,inputbuffer,buffersize
BUILTINR(int, ReadInputBuffer, (void *inputbuffer, int buffersize));
@ -382,6 +408,7 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(Plug_ExportToEngine);
#ifndef Q3_VM
CHECKBUILTIN(Plug_ExportNative);
CHECKBUILTIN(Plug_GetNativePointer);
#endif
CHECKBUILTIN(Sys_Error);
@ -422,6 +449,8 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(FS_Read);
CHECKBUILTIN(FS_Write);
CHECKBUILTIN(FS_Close);
CHECKBUILTIN(FS_Seek);
CHECKBUILTIN(FS_GetLen);
//networking
CHECKBUILTIN(Net_TCPConnect);
@ -430,6 +459,7 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(Net_Recv);
CHECKBUILTIN(Net_Send);
CHECKBUILTIN(Net_Close);
CHECKBUILTIN(Net_SetTLSClient);
//random things
CHECKBUILTIN(CL_GetStats);
@ -450,6 +480,10 @@ void Plug_InitStandardBuiltins(void)
CHECKBUILTIN(GetWeaponStats);
CHECKBUILTIN(GetNetworkInfo);
#ifndef Q3_VM
CHECKBUILTIN(PR_GetVMInstance);
#endif
//drawing routines
CHECKBUILTIN(Draw_LoadImageData);
CHECKBUILTIN(Draw_LoadImageShader);

View file

@ -74,7 +74,7 @@ void BadBuiltin(void);
#include <math.h>
#ifndef _VM_H
#if __STDC_VERSION__ >= 199901L
#if __STDC_VERSION__ >= 199901L || defined(__GNUC__)
//C99 has a stdint header which hopefully contains an intptr_t
//its optional... but if its not in there then its unlikely you'll actually be able to get the engine to a stage where it *can* load anything
#include <stdint.h>
@ -129,7 +129,7 @@ extern "C" {
#define BUILTINR(t, n, args) qintptr_t BUILTIN_##n; t n args {qintptr_t res = plugin_syscall(BUILTIN_##n ARGNAMES); return *(t*)&res;}
#define BUILTIN(t, n, args) qintptr_t BUILTIN_##n; t n args {plugin_syscall(BUILTIN_##n ARGNAMES);}
#endif
#define CHECKBUILTIN(n) BUILTIN_##n = (qintptr_t)pPlug_GetEngineFunction(#n);
#define CHECKBUILTIN(n) ((BUILTIN_##n = (qintptr_t)pPlug_GetEngineFunction(#n)))
#define BUILTINISVALID(n) (BUILTIN_##n != 0)
#ifndef QDECL
#ifdef _WIN32
@ -138,7 +138,7 @@ extern "C" {
#define QDECL
#endif
#endif
extern qintptr_t (*plugin_syscall)( qintptr_t arg, ... );
extern qintptr_t (QDECL *plugin_syscall)( qintptr_t arg, ... );
void Q_strlcpy(char *d, const char *s, int n);
void Q_strlcat(char *d, const char *s, int n);
@ -181,8 +181,8 @@ typedef struct {
int starttime;
int userid;
int spectator;
char userinfo[1024];
char team[8];
char userinfo[2048];
char team[64];
} plugclientinfo_t;
@ -194,6 +194,7 @@ EBUILTIN(funcptr_t, Plug_GetEngineFunction, (const char *funcname)); //set up in
#else
#ifndef Q3_VM
EBUILTIN(qboolean, Plug_ExportNative, (const char *funcname, void *func)); //set up in vmMain, use this to get all other builtins
EBUILTIN(void *, Plug_GetNativePointer, (const char *funcname));
#endif
EBUILTIN(void, Con_Print, (const char *text)); //on to main console.
@ -240,6 +241,17 @@ EBUILTIN(int, GetLastInputFrame, (int seat, usercmd_t *playercmd));
#endif
EBUILTIN(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize));
#ifndef Q3_VM
struct pubprogfuncs_s;
EBUILTIN(struct pubprogfuncs_s*, PR_GetVMInstance, (int vmid/*0=ss,1=cs,2=m*/));
struct modplugfuncs_s;
EBUILTIN(struct modplugfuncs_s*, Mod_GetPluginModelFuncs, (int version));
#ifdef MULTITHREAD
struct threading_s;
EBUILTIN(struct threading_s*, Sys_GetThreadingFuncs, (int threadingsize));
#endif
#endif
typedef struct
{
unsigned int client;
@ -299,7 +311,7 @@ EBUILTIN(int, GetNetworkInfo, (vmnetinfo_t *ni, unsigned int sizeofni));
EBUILTIN(void, Menu_Control, (int mnum));
#define MENU_CLEAR 0
#define MENU_GRAB 1
EBUILTIN(int, Key_GetKeyCode, (char *keyname));
EBUILTIN(int, Key_GetKeyCode, (const char *keyname));
EBUILTIN(qhandle_t, Draw_LoadImageData, (const char *name, const char *mime, const void *data, unsigned int datasize)); //load/replace a named texture
EBUILTIN(qhandle_t, Draw_LoadImageShader, (const char *name, const char *defaultshader)); //loads a shader.
@ -317,7 +329,7 @@ EBUILTIN(void, Draw_Colourpa, (int palcol, float a));
EBUILTIN(void, Draw_Colourp, (int palcol));
EBUILTIN(void, Draw_Colour3f, (float r, float g, float b));
EBUILTIN(void, Draw_Colour4f, (float r, float g, float b, float a));
EBUILTIN(void, SCR_CenterPrint, (char *s));
EBUILTIN(void, SCR_CenterPrint, (const char *s));
EBUILTIN(void, S_RawAudio, (int sourceid, void *data, int speed, int samples, int channels, int width, float volume));
@ -325,13 +337,15 @@ EBUILTIN(int, ReadInputBuffer, (void *inputbuffer, int buffersize));
EBUILTIN(int, UpdateInputBuffer, (void *inputbuffer, int bytes));
#if !defined(Q3_VM) && defined(FTEPLUGIN)
EBUILTIN(qboolean, VFS_Open, (char *name, vfsfile_t **handle, char *mode));//opens a direct vfs file. no access checks, and so can be used in threaded plugins
EBUILTIN(qboolean, VFS_Open, (const char *name, vfsfile_t **handle, const char *mode));//opens a direct vfs file. no access checks, and so can be used in threaded plugins
EBUILTIN(qboolean, FS_NativePath, (const char *name, enum fs_relative relativeto, char *out, int outlen));
#endif
EBUILTIN(int, FS_Open, (char *name, qhandle_t *handle, int mode));
EBUILTIN(int, FS_Open, (const char *name, qhandle_t *handle, int mode));
EBUILTIN(void, FS_Close, (qhandle_t handle));
EBUILTIN(int, FS_Write, (qhandle_t handle, void *data, int len));
EBUILTIN(int, FS_Read, (qhandle_t handle, void *data, int len));
EBUILTIN(int, FS_Seek, (qhandle_t handle, unsigned int offsetlow, unsigned int offsethigh));
EBUILTIN(qboolean, FS_GetLen, (qhandle_t handle, unsigned int *sizelow, unsigned int *sizehigh));
EBUILTIN(qhandle_t, Net_TCPConnect, (char *ip, int port));
EBUILTIN(qhandle_t, Net_TCPListen, (char *ip, int port, int maxcount));
@ -339,6 +353,7 @@ EBUILTIN(qhandle_t, Net_Accept, (qhandle_t socket, char *address, int addresssiz
EBUILTIN(int, Net_Recv, (qhandle_t socket, void *buffer, int len));
EBUILTIN(int, Net_Send, (qhandle_t socket, void *buffer, int len));
EBUILTIN(void, Net_Close, (qhandle_t socket));
EBUILTIN(int, Net_SetTLSClient, (qhandle_t sock, const char *certhostname));
#define N_WOULDBLOCK 0
#define NET_CLIENTPORT -1
#define NET_SERVERPORT -2
@ -415,7 +430,7 @@ extern vmvideo_t pvid;
#ifndef MAX_INFO_KEY
#define MAX_INFO_KEY 64
#endif
char *Info_ValueForKey (const char *s, const char *key);
char *Plug_Info_ValueForKey (const char *s, const char *key, char *out, size_t outsize);
void Info_RemoveKey (char *s, const char *key);
void Info_RemovePrefixedKeys (char *start, char prefix);
void Info_RemoveNonStarKeys (char *start);

680
plugins/qi/qi.c Normal file
View file

@ -0,0 +1,680 @@
#include "../plugin.h"
#include "../jabber/xml.h"
#define DATABASEURL "https://www.quaddicted.com/reviews/quaddicted_database.xml"
#define FILEIMAGEURL "https://www.quaddicted.com/reviews/screenshots/%s_injector.jpg"
#define FILEDOWNLOADURL "https://www.quaddicted.com/filebase/%s.zip"
#define WINDOWTITLE "Quaddicted Map+Mod Archive"
#define WINDOWNAME "QI"
/*
<file id="downloadname" type="1=map. 2=mod" rating="5-star-rating">
<author>meh</author>
<title>some readable name</title>
<md5sum>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</md5sum>
<size>size-in-kb</size>
<date>dd.mm.yy</date>
<description>HTML-encoded text. just to be awkward</description>
<techinfo>
<zipbasedir>additional path needed to make it relative to the quake directory</zipbasedir>
<requirements>
<file id="quoth" />
</requirements>
</techinfo>
</file>
*/
xmltree_t *thedatabase;
qhandle_t dlcontext = -1;
struct
{
char namefilter[256];
int minrating;
int maxrating;
int type;
} filters;
void Con_SubPrintf(const char *subname, char *format, ...)
{
va_list argptr;
static char string[8192];
va_start (argptr, format);
Q_vsnprintf (string, sizeof(string), format,argptr);
va_end (argptr);
pCon_SubPrint(subname, string);
}
qintptr_t QI_Shutdown(qintptr_t *args)
{
if (dlcontext != -1)
{ //we're still downloading something? :o
pFS_Close(dlcontext);
dlcontext = -1;
}
if (thedatabase)
XML_Destroy(thedatabase);
thedatabase = NULL;
return false;
}
qboolean QI_SetupWindow(const char *console, qboolean force)
{
if (!BUILTINISVALID(Con_GetConsoleFloat))
return false;
//only redraw the window if it actually exists. if they closed it, then don't mess things up.
if (!force && pCon_GetConsoleFloat(console, "iswindow") <= 0)
return false;
if (pCon_GetConsoleFloat(console, "iswindow") != true)
{
pCon_SetConsoleString(console, "title", WINDOWTITLE);
pCon_SetConsoleFloat(console, "iswindow", true);
pCon_SetConsoleFloat(console, "forceutf8", true);
pCon_SetConsoleFloat(console, "linebuffered", false);
pCon_SetConsoleFloat(console, "maxlines", 16384); //the line limit is more a sanity thing than anything else. so long as we explicitly clear before spamming more, then its not an issue...
pCon_SetConsoleFloat(console, "wnd_x", 8);
pCon_SetConsoleFloat(console, "wnd_y", 8);
pCon_SetConsoleFloat(console, "wnd_w", pvid.width-16);
pCon_SetConsoleFloat(console, "wnd_h", pvid.height-16);
pCon_SetConsoleString(console, "footer", "");
}
pCon_SetConsoleFloat(console, "linecount", 0); //clear it
if (force)
pCon_SetActive(console);
return true;
}
void QI_DeHTML(const char *in, char *out, size_t outsize)
{
outsize--;
while(*in && outsize > 0)
{
if (*in == '\r' || *in == '\n')
in++;
else if (*in == '<')
{
char tag[256];
int i;
qboolean open = false;
qboolean close = false;
in++;
if (*in == '/')
{
in++;
close = true;
}
else
open = true;
while (*in == ' ' || *in == '\n' || *in == '\t' || *in == '\r')
in++;
for (i = 0; i < countof(tag)-1; )
{
if (*in == '>')
break;
if (!*in || *in == ' ' || *in == '\n' || *in == '\t' || *in == '\r' || (in[0] == '/' && in[1] == '>'))
break;
tag[i++] = *in++;
}
tag[i] = 0;
while (*in && *in)
{
if (*in == '/' && in[1] == '>')
{
in += 2;
close = true;
break;
}
if (*in++ == '>')
break;
}
if (!strcmp(tag, "br") && open && outsize > 0)
{ //new lines!
*out++ = '\n';
outsize--;
}
else if (!strcmp(tag, "b") && open != close && outsize > 1)
{ //bold
*out++ = '^';
outsize--;
*out++ = 'a';
outsize--;
}
else if (!strcmp(tag, "i") && open != close && outsize > 1)
{ //italics
*out++ = '^';
outsize--;
*out++ = 'b';
outsize--;
}
}
else if (*in == '^')
{
if (outsize > 1)
{
*out++ = *in;
outsize--;
*out++ = *in++;
outsize--;
}
}
else
{
*out++ = *in++;
outsize--;
}
}
*out = 0;
}
static char *QI_strcasestr(const char *haystack, const char *needle)
{
int c1, c2, c2f;
int i;
c2f = *needle;
if (c2f >= 'a' && c2f <= 'z')
c2f -= ('a' - 'A');
if (!c2f)
return (char*)haystack;
while (1)
{
c1 = *haystack;
if (!c1)
return NULL;
if (c1 >= 'a' && c1 <= 'z')
c1 -= ('a' - 'A');
if (c1 == c2f)
{
for (i = 1; ; i++)
{
c1 = haystack[i];
c2 = needle[i];
if (c1 >= 'a' && c1 <= 'z')
c1 -= ('a' - 'A');
if (c2 >= 'a' && c2 <= 'z')
c2 -= ('a' - 'A');
if (!c2)
return (char*)haystack; //end of needle means we found a complete match
if (!c1) //end of haystack means we can't possibly find needle in it any more
return NULL;
if (c1 != c2) //mismatch means no match starting at haystack[0]
break;
}
}
haystack++;
}
return NULL; //didn't find it
}
void QI_RefreshMapList(qboolean forcedisplay)
{
xmltree_t *file;
const char *console = WINDOWNAME;
char descbuf[1024];
if (!QI_SetupWindow(console, forcedisplay))
return;
if (!thedatabase)
{
if (dlcontext != -1)
Con_SubPrintf(console, "Downloading database...\n");
else
Con_SubPrintf(console, "Unable to download HTTP database\n");
return;
}
if (!thedatabase->child)
{
Con_SubPrintf(console, "No maps in database... SPIRIT! YOU BROKE IT!\n");
return;
}
for (file = thedatabase->child; file; file = file->sibling)
{
char *id = XML_GetParameter(file, "id", "unnamed");
char *rating = XML_GetParameter(file, "rating", "");
int ratingnum = atoi(rating);
char *author = XML_GetChildBody(file, "author", "unknown");
char *desc = XML_GetChildBody(file, "description", "<NO DESCRIPTION>");
char *type;
char *date;
int year, month, day;
int startmapnum, i;
char ratingtext[65];
xmltree_t *tech;
xmltree_t *startmap;
if (strcmp(file->name, "file"))
continue; //erk?
if (atoi(XML_GetParameter(file, "hide", "")) || atoi(XML_GetParameter(file, "fte_hide", "")))
continue;
type = XML_GetParameter(file, "type", "");
if (filters.type && atoi(type) != filters.type)
continue;
switch(atoi(type))
{
case 1:
type = "map";
break;
case 2:
type = "mod";
break;
case 5:
type = "otr";
break;
default:
type = "???";
break;
}
if (filters.maxrating>=0 && ratingnum > filters.maxrating)
continue;
if (filters.minrating>=0 && ratingnum < filters.minrating)
continue;
tech = XML_ChildOfTree(file, "techinfo", 0);
//if the filter isn't contained in the id/desc then don't display it.
if (filters.namefilter)
{
if (!QI_strcasestr(id, filters.namefilter) && !QI_strcasestr(desc, filters.namefilter) && !QI_strcasestr(author, filters.namefilter))
{
//check map list too
for (startmapnum = 0; ; startmapnum++)
{
startmap = XML_ChildOfTree(tech, "startmap", startmapnum);
if (!startmap)
break;
if (QI_strcasestr(startmap->body, filters.namefilter))
break;
}
if (!startmap)
continue;
}
}
if (ratingnum > (sizeof(ratingtext)-5)/6)
ratingnum = (sizeof(ratingtext)-5)/6;
if (ratingnum)
{
Q_snprintf(ratingtext, sizeof(ratingtext), "^a");
for (i = 0; i < ratingnum; i++)
Q_snprintf(ratingtext + i+2, sizeof(ratingtext)-i*2+2, "*");
Q_snprintf(ratingtext + i+2, sizeof(ratingtext)-i*2+2, "^a");
}
else if (*rating)
Q_snprintf(ratingtext, sizeof(ratingtext), "%s", rating);
else
Q_snprintf(ratingtext, sizeof(ratingtext), "%s", "unrated");
date = XML_GetChildBody(file, "date", "1.1.1990");
day = atoi(date?date:"1");
date = date?strchr(date, '.'):NULL;
month = atoi(date?date+1:"1");
date = date?strchr(date, '.'):NULL;
year = atoi(date?date+1:"1990");
if (year < 90)
year += 2000;
else if (year < 1900)
year += 1900;
Q_snprintf(descbuf, sizeof(descbuf), "Id: %s\nAuthor: %s\nDate: %04u-%02u-%02u\nRating: %s\n\n", id, author, year, month, day, ratingtext);
QI_DeHTML(desc, descbuf + strlen(descbuf), sizeof(descbuf) - strlen(descbuf));
desc = descbuf;
for (startmapnum = 0; ; startmapnum++)
{
startmap = XML_ChildOfTree(tech, "startmap", startmapnum);
if (!startmap)
break;
Con_SubPrintf(console, "%s ^[%s (%s)\\tip\\%s\\tipimg\\"FILEIMAGEURL"\\id\\%s\\startmap\\%s^]\n", type, XML_GetChildBody(file, "title", "<NO TITLE>"), startmap->body, desc, id, id, startmap->body);
}
if (!startmapnum)
Con_SubPrintf(console, "%s ^[%s\\tip\\%s\\tipimg\\"FILEIMAGEURL"\\id\\%s^]\n", type, XML_GetChildBody(file, "title", "<NO TITLE>"), desc, id, id);
}
Con_SubPrintf(console, "\nFilter:\n");
if (*filters.namefilter)
Con_SubPrintf(console, "Contains: %s ", filters.namefilter);
Con_SubPrintf(console, "^[Change Filter^]\n");
Con_SubPrintf(console, "^[Maps^] %s\n", (filters.type!=2)?"shown":"hidden");
Con_SubPrintf(console, "^[Mods^] %s\n", (filters.type!=1)?"shown":"hidden");
if (filters.minrating == filters.maxrating)
{
char *gah[] = {"Any Rating", "Unrated", "1","2","3","4","5"};
int i;
Con_SubPrintf(console, "Rating");
for (i = 0; i < countof(gah); i++)
{
if (i == filters.minrating+1)
Con_SubPrintf(console, " %s", gah[i]);
else
Con_SubPrintf(console, " ^[%s^]", gah[i]);
}
Con_SubPrintf(console, "\n");
}
else
{
if (filters.minrating)
Con_SubPrintf(console, "Min Rating: %i stars\n", filters.minrating);
if (filters.maxrating)
Con_SubPrintf(console, "Max Rating: %i stars\n", filters.maxrating);
}
}
static void QI_UpdateFilter(char *filtertext)
{
if (!strcmp(filtertext, "all"))
{
filters.type = 0;
filters.minrating = filters.maxrating = -1;
Q_strlcpy(filters.namefilter, "", sizeof(filters.namefilter));
}
else if (*filtertext == '>')
filters.minrating = atoi(filtertext+1);
else if (*filtertext == '<')
filters.maxrating = atoi(filtertext+1);
else if (*filtertext == '=')
filters.minrating = filters.maxrating = atoi(filtertext+1);
else if (!strcmp(filtertext, "any"))
{
filters.type = 0;
filters.minrating = filters.maxrating = -1;
}
else if (!strcmp(filtertext, "maps"))
filters.type = 1;
else if (!strcmp(filtertext, "mods"))
filters.type = 2;
else
Q_strlcpy(filters.namefilter, filtertext, sizeof(filters.namefilter));
}
static xmltree_t *QI_FindArchive(const char *name)
{
xmltree_t *file;
for (file = thedatabase->child; file; file = file->sibling)
{
char *id = XML_GetParameter(file, "id", "unnamed");
if (strcmp(file->name, "file"))
continue; //erk?
if (!strcmp(id, name))
return file;
}
return NULL;
}
static void QI_AddPackages(xmltree_t *qifile)
{
char *id;
char extra[1024];
char clean[512];
unsigned int i;
xmltree_t *tech;
const char *basedir;
xmltree_t *requires;
xmltree_t *req;
//quaddicted's database contains various zips that are meant to be extracted to various places.
//this can either be the quake root (no path), a mod directory (typically the name of the mod), or the maps directory (id1/maps or some such)
//unfortunately, quake files are relative to the subdir, so we need to strip the first subdir. anyone that tries to put dlls in there is evil. and if there isn't one, we need to get the engine to compensate.
//we also need to clean up the paths so they're not badly formed
tech = XML_ChildOfTree(qifile, "techinfo", 0);
basedir = XML_GetChildBody(tech, "zipbasedir", "");
//skip any dodgy leading slashes
while (*basedir == '/' || *basedir == '\\')
basedir++;
if (!*basedir)
strcpy(clean, ".."); //err, there wasn't a directory... we still need to 'strip' it though.
else
{
//skip the gamedir
while (*basedir && *basedir != '/' && *basedir != '\\')
basedir++;
//skip any trailing
while (*basedir == '/' || *basedir == '\\')
basedir++;
for (i = 0; *basedir; i++)
{
if (i >= sizeof(clean)-1)
break;
if (*basedir == '\\') //sigh
clean[i] = '/';
else
clean[i] = *basedir;
basedir++;
}
while (i > 0 && clean[i-1] == '/')
i--;
clean[i] = 0;
}
requires = XML_ChildOfTree(tech, "requirements", 0);
if (requires)
{
for (i = 0; ; i++)
{
req = XML_ChildOfTree(requires, "file", i);
if (!req)
break;
id = XML_GetParameter(req, "id", "unknown");
QI_AddPackages(QI_FindArchive(id));
}
}
id = XML_GetParameter(qifile, "id", "unknown");
if (strchr(clean, '\\') || strchr(clean, '\"') || strchr(clean, '\n') || strchr(clean, ';'))
return;
if (strchr(id, '\\') || strchr(id, '\"') || strchr(id, '\n') || strchr(id, ';'))
return;
Q_snprintf(extra, sizeof(extra), " package \""FILEDOWNLOADURL"\" prefix \"%s\"", id, clean);
pCmd_AddText(extra, false);
}
static void QI_RunMap(xmltree_t *qifile, const char *map)
{
if (!qifile)
{
return;
}
//type 1 (maps) often don't list any map names
if (!*map)// && atoi(XML_GetParameter(qifile, "type", "0")) == 1)
map = XML_GetParameter(qifile, "id", "unknown");
if (!*map || strchr(map, '\\') || strchr(map, '\"') || strchr(map, '\n') || strchr(map, ';'))
map = "";
pCmd_AddText("fs_changemod map \"", false);
pCmd_AddText(map, false);
pCmd_AddText("\"", false);
QI_AddPackages(qifile);
// Con_Printf("Command: %s\n", cmd);
pCmd_AddText("\n", false);
}
qintptr_t QI_ConsoleLink(qintptr_t *args)
{
xmltree_t *file;
char *map;
char *id;
char *e;
char text[2048];
char link[8192];
pCmd_Argv(0, text, sizeof(text));
pCmd_Argv(1, link, sizeof(link));
if (!strcmp(text, "Change Filter") && !*link)
{
const char *console = WINDOWNAME;
pCon_SetConsoleFloat(console, "linebuffered", true);
pCon_SetConsoleString(console, "footer", "Please enter filter:");
return true;
}
if (!strcmp(text, "Maps") && !*link)
{
filters.type = (filters.type==2)?0:2;
QI_RefreshMapList(true);
return true;
}
if (!strcmp(text, "Mods") && !*link)
{
filters.type = (filters.type==1)?0:1;
QI_RefreshMapList(true);
return true;
}
if (!strcmp(text, "Any Rating") && !*link)
{
filters.minrating = filters.maxrating = -1;
QI_RefreshMapList(true);
return true;
}
if ((atoi(text) || !strcmp(text, "Unrated")) && !*link)
{
filters.minrating = filters.maxrating = atoi(text);
QI_RefreshMapList(true);
return true;
}
id = strstr(link, "\\id\\");
map = strstr(link, "\\startmap\\");
if (id)
{
id+=4;
e = strchr(id, '\\');
if (e)
*e = 0;
if (map)
{
map += 10;
e = strchr(map, '\\');
if (e)
*e = 0;
}
else
map = "";
file = QI_FindArchive(id);
if (!file)
{
Con_Printf("Unknown file \"%s\"\n", id);
return true;
}
QI_RunMap(file, map);
return true;
}
return false;
}
qintptr_t QI_Tick(qintptr_t *args)
{
if (dlcontext != -1)
{
unsigned int flen;
if (pFS_GetLen(dlcontext, &flen, NULL))
{
int ofs = 0;
char *file;
qboolean archive = true;
if (flen == 0)
{
pFS_Close(dlcontext);
flen = pFS_Open("**plugconfig", &dlcontext, 1);
if (dlcontext == -1)
{
QI_RefreshMapList(false);
return false;
}
archive = false;
}
file = malloc(flen+1);
file[flen] = 0;
pFS_Read(dlcontext, file, flen);
pFS_Close(dlcontext);
if (archive)
{
pFS_Open("**plugconfig", &dlcontext, 2);
if (dlcontext != -1)
{
pFS_Write(dlcontext, file, flen);
pFS_Close(dlcontext);
}
}
dlcontext = -1;
do
{
if (thedatabase)
XML_Destroy(thedatabase);
thedatabase = XML_Parse(file, &ofs, flen, false, "");
} while(thedatabase && !thedatabase->child);
free(file);
QI_RefreshMapList(false);
// XML_ConPrintTree(thedatabase, "quadicted_xml", 0);
}
}
return false;
}
qintptr_t QI_ConExecuteCommand(qintptr_t *args)
{
char console[256];
char filter[256];
pCmd_Argv(0, console, sizeof(console));
pCmd_Args(filter, sizeof(filter));
QI_UpdateFilter(filter);
QI_RefreshMapList(true);
pCon_SetConsoleFloat(console, "linebuffered", false);
pCon_SetConsoleString(console, "footer", "");
return true;
}
qintptr_t QI_ExecuteCommand(qintptr_t *args)
{
char cmd[256];
pCmd_Argv(0, cmd, sizeof(cmd));
if (!strcmp(cmd, "qi") || !strcmp(cmd, "quaddicted"))
{
if (pCmd_Argc() > 1)
{
pCmd_Args(cmd, sizeof(cmd));
QI_UpdateFilter(cmd);
}
else if (QI_SetupWindow(WINDOWNAME, false))
{
pCon_SetActive(WINDOWNAME);
return true;
}
if (!thedatabase && dlcontext == -1)
pFS_Open(DATABASEURL, &dlcontext, 1);
QI_RefreshMapList(true);
return true;
}
return false;
}
extern void (*Con_TrySubPrint)(const char *conname, const char *message);
qintptr_t Plug_Init(qintptr_t *args)
{
filters.minrating = filters.maxrating = -1;
Con_TrySubPrint = pCon_SubPrint;
if (Plug_Export("Tick", QI_Tick) &&
Plug_Export("Shutdown", QI_Shutdown) &&
Plug_Export("ExecuteCommand", QI_ExecuteCommand) &&
Plug_Export("ConExecuteCommand", QI_ConExecuteCommand) &&
Plug_Export("ConsoleLink", QI_ConsoleLink))
{
pCmd_AddCommand("qi");
pCmd_AddCommand("quaddicted");
return true;
}
return false;
}

362
plugins/qi/qi.vcproj Normal file
View file

@ -0,0 +1,362 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="qi"
ProjectGUID="{909E9AE0-0617-469C-954E-1ED09367F90E}"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
PreprocessorDefinitions="FTEPLUGIN"
EnableFunctionLevelLinking="true"
BrowseInformation="1"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="../../fteplug_$(ProjectName)_x86.dll"
LinkIncremental="2"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"
GenerateDebugInformation="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
PreprocessorDefinitions="FTEPLUGIN"
EnableFunctionLevelLinking="true"
BrowseInformation="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="../../fteplug_$(ProjectName)x86.dll"
LinkIncremental="2"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"
GenerateDebugInformation="true"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
EmbedManifest="false"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
PreprocessorDefinitions="FTEPLUGIN"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="../../fteplug_$(ProjectName)x86.dll"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
PreprocessorDefinitions="FTEPLUGIN"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="../../fteplug_$(ProjectName)_x64.dll"
GenerateManifest="false"
ModuleDefinitionFile="..\plugin.def"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\emailnot\md5.c"
>
</File>
<File
RelativePath="..\plugin.c"
>
</File>
<File
RelativePath=".\qi.c"
>
</File>
<File
RelativePath="..\qvm_api.c"
>
</File>
<File
RelativePath="..\jabber\xml.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\plugin.h"
>
</File>
<File
RelativePath="..\jabber\xml.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath="..\plugin.def"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -105,6 +105,10 @@ retry:
*buffer++ = _int;
tokens++;
break;
case 'p':
if (1)
_uint = (size_t)va_arg(vargs, void*);
else
case 'x':
_uint = va_arg(vargs, unsigned int);
i = sizeof(tempbuffer)-2;
@ -590,3 +594,50 @@ void Q_strlcat(char *d, const char *s, int n)
d[n - 1] = 0;
}
}
char *Plug_Info_ValueForKey (const char *s, const char *key, char *out, size_t outsize)
{
int isvalue = 0;
const char *start;
char *oout = out;
*out = 0;
if (*s != '\\')
return out; //gah, get lost with your corrupt infostrings.
start = ++s;
while(1)
{
while(s[0] == '\\' && s[1] == '\\')
s+=2;
if (s[0] != '\\' && *s)
{
s++;
continue;
}
//okay, it terminates here
isvalue = !isvalue;
if (isvalue)
{
if (strlen(key) == s - start && !strncmp(start, key, s - start))
{
s++;
while (outsize --> 1)
{
if (s[0] == '\\' && s[1] == '\\')
s++;
else if (s[0] == '\\' || !s[0])
break;
*out++ = *s++;
}
*out++ = 0;
return oout;
}
}
if (*s)
start = ++s;
else
break;
}
return oout;
}

View file

@ -13,7 +13,7 @@
int mousecursor_x, mousecursor_y;
static xclient_t *xclients;
static qhandle_t xlistensocket=NULL;
static qhandle_t xlistensocket;
xwindow_t *xfocusedwindow;
@ -479,7 +479,7 @@ qboolean XWindows_TendToClient(xclient_t *cl) //true says drop
}
len = cl->inbuffermaxlen - cl->inbufferlen;
//Con_Printf("recving\n");
len = Net_Recv(cl->socket, cl->inbuffer + cl->inbufferlen, len);
len = pNet_Recv(cl->socket, cl->inbuffer + cl->inbufferlen, len);
//Con_Printf("recved %i\n", len);
if (len == 0) //connection was closed. bummer.
{
@ -632,7 +632,7 @@ nextmessage:
len = cl->outbufferlen;
if (len > 8000)
len = 8000;
len = Net_Send(cl->socket, cl->outbuffer, len);
len = pNet_Send(cl->socket, cl->outbuffer, len);
if (len>0)
{
memmove(cl->outbuffer, cl->outbuffer+len, cl->outbufferlen - len);
@ -768,9 +768,9 @@ void XWindows_TendToClients(void)
unsigned int _false = 0;
#endif
if (xlistensocket != NULL)
if (xlistensocket)
{
newclient = Net_Accept(xlistensocket, NULL, 0);
newclient = pNet_Accept(xlistensocket, NULL, 0);
if ((int)newclient != -1)
{
cl = malloc(sizeof(xclient_t));
@ -816,7 +816,7 @@ void XWindows_TendToClients(void)
break;
}
#endif
Net_Close(cl->socket);
pNet_Close(cl->socket);
if (cl->inbuffer)
free(cl->inbuffer);
if (cl->outbuffer)
@ -835,15 +835,15 @@ void XWindows_Startup(void) //initialise the server socket and do any initial se
int port = 6000;
Cmd_Argv(1, buffer, sizeof(buffer));
pCmd_Argv(1, buffer, sizeof(buffer));
port += atoi(buffer);
if (xlistensocket == NULL)
if (!xlistensocket)
{
xlistensocket = Net_TCPListen(NULL, port, 3);
if ((int)xlistensocket < 0)
xlistensocket = pNet_TCPListen(NULL, port, 3);
if (xlistensocket < 0)
{
xlistensocket = NULL;
xlistensocket = 0;
Con_Printf("Failed to create tcp listen socket\n");
return;
}
@ -1055,7 +1055,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
xwindow_t *nw = ew;
xwindow_t *oc[MAX_WINDOW_CHAIN];
xwindow_t *nc[MAX_WINDOW_CHAIN];
unsigned int curtime = Sys_Milliseconds();
unsigned int curtime = pSys_Milliseconds();
if (!nw)
@ -1101,7 +1101,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
//LeaveNotify with detail Inferior is generated on A.
ev.u.u.type = LeaveNotify;
ev.u.u.detail = NotifyInferior;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = oc[0]->res.id;
ev.u.enterLeave.child = None;
@ -1119,7 +1119,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
{
ev.u.u.type = EnterNotify;
ev.u.u.detail = NotifyVirtual;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = oc[i]->res.id;
ev.u.enterLeave.child = oc[i-1]->res.id;
@ -1136,7 +1136,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
//EnterNotify with detail Ancestor is generated on B.
ev.u.u.type = EnterNotify;
ev.u.u.detail = NotifyInferior;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = nc[0]->res.id;
ev.u.enterLeave.child = None;
@ -1155,7 +1155,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
//LeaveNotify with detail Ancestor is generated on A.
ev.u.u.type = LeaveNotify;
ev.u.u.detail = NotifyAncestor;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = oc[0]->res.id;
ev.u.enterLeave.child = None;
@ -1173,7 +1173,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
{
ev.u.u.type = LeaveNotify;
ev.u.u.detail = NotifyVirtual;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = nc[i]->res.id;
ev.u.enterLeave.child = nc[i-1]->res.id;
@ -1190,7 +1190,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
//EnterNotify with detail Inferior is generated on B.
ev.u.u.type = EnterNotify;
ev.u.u.detail = NotifyInferior;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = nc[0]->res.id;
ev.u.enterLeave.child = None;
@ -1210,7 +1210,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
//LeaveNotify with detail Nonlinear is generated on A.
ev.u.u.type = LeaveNotify;
ev.u.u.detail = NotifyNonlinear;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = oc[0]->res.id;
ev.u.enterLeave.child = None;
@ -1228,7 +1228,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
{
ev.u.u.type = LeaveNotify;
ev.u.u.detail = NotifyNonlinearVirtual;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = nc[i]->res.id;
ev.u.enterLeave.child = nc[i-1]->res.id;
@ -1246,7 +1246,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
{
ev.u.u.type = EnterNotify;
ev.u.u.detail = NotifyNonlinearVirtual;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = oc[i]->res.id;
ev.u.enterLeave.child = oc[i-1]->res.id;
@ -1263,7 +1263,7 @@ void X_MoveCursorWindow(xwindow_t *ew, int mx, int my, int movemode)
//EnterNotify with detail Nonlinear is generated on B.
ev.u.u.type = EnterNotify;
ev.u.u.detail = NotifyNonlinear;
ev.u.enterLeave.time = Sys_Milliseconds();
ev.u.enterLeave.time = pSys_Milliseconds();
ev.u.enterLeave.root = rootwindow->res.id;
ev.u.enterLeave.event = nc[0]->res.id;
ev.u.enterLeave.child = None;
@ -1394,7 +1394,7 @@ void X_EvalutateCursorOwner(int movemode)
ev.u.u.type = MotionNotify;
ev.u.u.detail = 0;
ev.u.u.sequenceNumber = 0;
ev.u.keyButtonPointer.time = Sys_Milliseconds();
ev.u.keyButtonPointer.time = pSys_Milliseconds();
ev.u.keyButtonPointer.root = rootwindow->res.id;
ev.u.keyButtonPointer.event = cursorowner->res.id;
ev.u.keyButtonPointer.child = (x_windowwithcursor == cursorowner->res.id)?None:x_windowwithcursor;
@ -1767,7 +1767,7 @@ void XWindows_KeyDown(int key)
ev.u.keyButtonPointer.child = x_windowwithfocus;
}
ev.u.u.sequenceNumber = 0;
ev.u.keyButtonPointer.time = Sys_Milliseconds();
ev.u.keyButtonPointer.time = pSys_Milliseconds();
ev.u.keyButtonPointer.rootX = x_mousex;
ev.u.keyButtonPointer.rootY = x_mousey;
ev.u.keyButtonPointer.sameScreen= true;
@ -1865,7 +1865,7 @@ void XWindows_Keyup(int key)
ev.u.keyButtonPointer.child = x_windowwithfocus;
}
ev.u.u.sequenceNumber = 0;
ev.u.keyButtonPointer.time = Sys_Milliseconds();
ev.u.keyButtonPointer.time = pSys_Milliseconds();
ev.u.keyButtonPointer.rootX = x_mousex;
ev.u.keyButtonPointer.rootY = x_mousey;
ev.u.keyButtonPointer.state = 0;
@ -1924,7 +1924,7 @@ int Plug_MenuEvent(int *args)
qintptr_t Plug_ExecuteCommand(qintptr_t *args)
{
char cmd[256];
Cmd_Argv(0, cmd, sizeof(cmd));
pCmd_Argv(0, cmd, sizeof(cmd));
if (!strcmp("startx", cmd))
{
XWindows_Startup();
@ -1939,7 +1939,7 @@ qintptr_t Plug_Tick(qintptr_t *args)
return 0;
}
static void *XWindows_Create(char *medianame) //initialise the server socket and do any initial setup as required.
static void *XWindows_Create(const char *medianame) //initialise the server socket and do any initial setup as required.
{
if (!strcmp(medianame, "x11"))
{
@ -1949,24 +1949,21 @@ static void *XWindows_Create(char *medianame) //initialise the server socket and
return NULL;
}
qbyte *XWindows_DisplayFrame(void *ctx, qboolean nosound, enum uploadfmt *fmt, int *width, int *height)
static qboolean VARGS XWindows_DisplayFrame(void *ctx, qboolean nosound, qboolean forcevideo, double mediatime, void (QDECL *uploadtexture)(void *ectx, uploadfmt_t fmt, int width, int height, void *data, void *palette), void *ectx)
{
XWindows_Draw();
*fmt = TF_BGRX32;
*width = xscreenwidth;
*height = xscreenheight;
if (!xscreenmodified)
return NULL;
if (forcevideo || xscreenmodified)
uploadtexture(ectx, TF_BGRX32, xscreenwidth, xscreenheight, xscreen, NULL);
xscreenmodified = false;
return xscreen;
return true;
}
static void XWindows_Shutdown(void *ctx)
{
Net_Close(xlistensocket);
xlistensocket = NULL;
pNet_Close(xlistensocket);
xlistensocket = 0;
}
static qboolean XWindows_SetSize (void *ctx, int width, int height)
@ -2012,9 +2009,10 @@ static void XWindows_Key (void *ctx, int code, int unicode, int isup)
media_decoder_funcs_t decoderfuncs =
{
sizeof(media_decoder_funcs_t),
"x11",
XWindows_Create,
XWindows_DisplayFrame,
NULL,//doneframe
XWindows_Shutdown,
NULL,//rewind
@ -2036,7 +2034,7 @@ qintptr_t Plug_Init(qintptr_t *args)
return false;
}
if (!Plug_ExportNative("Media_VideoDecoder", &decoderfuncs))
if (!pPlug_ExportNative("Media_VideoDecoder", &decoderfuncs))
{
Con_Printf("XServer plugin failed: Engine doesn't support media decoder plugins\n");
return false;
@ -2044,17 +2042,17 @@ qintptr_t Plug_Init(qintptr_t *args)
Con_Printf("XServer plugin started\n");
Cmd_AddCommand("startx");
pCmd_AddCommand("startx");
K_CTRL = Key_GetKeyCode("ctrl");
K_ALT = Key_GetKeyCode("alt");
K_MOUSE1 = Key_GetKeyCode("mouse1");
K_MOUSE2 = Key_GetKeyCode("mouse2");
K_MOUSE3 = Key_GetKeyCode("mouse3");
K_MOUSE4 = Key_GetKeyCode("mouse4");
K_MOUSE5 = Key_GetKeyCode("mouse5");
K_BACKSPACE = Key_GetKeyCode("backspace");
K_CTRL = pKey_GetKeyCode("ctrl");
K_ALT = pKey_GetKeyCode("alt");
K_MOUSE1 = pKey_GetKeyCode("mouse1");
K_MOUSE2 = pKey_GetKeyCode("mouse2");
K_MOUSE3 = pKey_GetKeyCode("mouse3");
K_MOUSE4 = pKey_GetKeyCode("mouse4");
K_MOUSE5 = pKey_GetKeyCode("mouse5");
K_BACKSPACE = pKey_GetKeyCode("backspace");
/*
K_UPARROW = Key_GetKeyCode("uparrow");
K_DOWNARROW = Key_GetKeyCode("downarrow");

View file

@ -380,7 +380,7 @@ void XR_GetProperty (xclient_t *cl, xReq *request)
ev.u.u.sequenceNumber = 0;
ev.u.property.window = req->window;
ev.u.property.atom = req->property;
ev.u.property.time = Sys_Milliseconds();
ev.u.property.time = pSys_Milliseconds();
ev.u.property.state = PropertyDelete;
ev.u.property.pad1 = 0;
@ -485,7 +485,7 @@ void XR_ChangeProperty (xclient_t *cl, xReq *request)
ev.u.u.sequenceNumber = 0;
ev.u.property.window = req->window;
ev.u.property.atom = req->property;
ev.u.property.time = Sys_Milliseconds();
ev.u.property.time = pSys_Milliseconds();
ev.u.property.state = PropertyNewValue;
ev.u.property.pad1 = 0;
@ -523,7 +523,7 @@ void XR_DeleteProperty(xclient_t *cl, xReq *request)
ev.u.u.sequenceNumber = 0;
ev.u.property.window = req->window;
ev.u.property.atom = req->property;
ev.u.property.time = Sys_Milliseconds();
ev.u.property.time = pSys_Milliseconds();
ev.u.property.state = PropertyDelete;
ev.u.property.pad1 = 0;