Merge branch 'master' of git://mumble.git.sourceforge.net/gitroot/mumble

This commit is contained in:
Mikkel Krautz 2009-03-04 20:55:26 +01:00
commit 8a7f67ce5c
49 changed files with 6611 additions and 6557 deletions

View File

@ -1,33 +1,35 @@
TEMPLATE = subdirs
CONFIG *= ordered debug_and_release
!CONFIG(no-client) {
unix:!CONFIG(bundled-speex):system(pkg-config --atleast-version=1.2 speexdsp) {
CONFIG *= no-bundled-speex
}
!CONFIG(no-bundled-speex) {
SUBDIRS *= speexbuild
}
SUBDIRS *= src/mumble plugins
win32 {
SUBDIRS *= overlay
!CONFIG(no-g15) {
SUBDIRS *= g15helper
}
}
unix:!macx {
SUBDIRS *= overlay_gl
}
macx {
SUBDIRS *= overlay_macx
}
}
!CONFIG(no-server) {
SUBDIRS *= src/murmur
}
DIST=LICENSE INSTALL README README.Linux CHANGES compiler.pri
TEMPLATE = subdirs
CONFIG *= ordered debug_and_release
!CONFIG(no-client) {
unix:!CONFIG(bundled-speex):system(pkg-config --atleast-version=1.2 speexdsp) {
CONFIG *= no-bundled-speex
}
!CONFIG(no-bundled-speex) {
SUBDIRS *= speexbuild
}
SUBDIRS *= src/mumble plugins
win32 {
SUBDIRS *= overlay
!CONFIG(no-g15) {
SUBDIRS *= g15helper
}
}
unix:!macx {
SUBDIRS *= overlay_gl
}
macx {
SUBDIRS *= overlay_macx
}
}
!CONFIG(no-server) {
SUBDIRS *= src/murmur
}
DIST=LICENSE INSTALL README README.Linux CHANGES
include(scripts/scripts.pro)

File diff suppressed because it is too large Load Diff

View File

@ -1,109 +1,109 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LIB_H
#define _LIB_H
#define _UNICODE
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <windows.h>
#include <math.h>
#include <map>
#include <vector>
#include <string>
#include "overlay.h"
#define lround(x) static_cast<long int>((x) + (((x) >= 0.0) ? 0.5 : -0.5))
using namespace std;
void __cdecl fods(const char *format, ...);
void __cdecl ods(const char *format, ...);
typedef void *(*voidFunc)();
struct HardHook {
unsigned char *baseptr;
unsigned char orig[6];
unsigned char replace[6];
bool bTrampoline;
voidFunc call;
static void *pCode;
static unsigned int uiCode;
HardHook();
void *cloneCode(void **orig);
void setup(voidFunc func, voidFunc replacement);
void setupInterface(IUnknown *intf, LONG funcoffset, voidFunc replacement);
void inject(bool force = false);
void restore(bool force = false);
void print();
};
struct Direct3D9Data {
char cFileName[2048];
int iOffsetCreate;
};
struct FakeInterface {
typedef ULONG(FakeInterface::* voidMemberFunc)();
void **vtbl;
IUnknown *pOriginal;
IUnknown *pNew;
void *pAssembly;
FakeInterface(IUnknown *orig, int entries);
~FakeInterface();
void replace(LONG funcoffset, voidMemberFunc replacement);
};
class Mutex {
protected:
static CRITICAL_SECTION cs;
public:
static void init();
Mutex();
~Mutex();
};
extern void checkD3D9Hook(bool preonly = false);
extern void checkOpenGLHook();
extern SharedMem *sm;
extern Direct3D9Data *d3dd;
extern HANDLE hSharedMutex;
extern HMODULE hSelf;
extern unsigned int uiAudioCount;
extern bool bVideoHooked;
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LIB_H
#define _LIB_H
#define _UNICODE
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <windows.h>
#include <math.h>
#include <map>
#include <vector>
#include <string>
#include "overlay.h"
#define lround(x) static_cast<long int>((x) + (((x) >= 0.0) ? 0.5 : -0.5))
using namespace std;
void __cdecl fods(const char *format, ...);
void __cdecl ods(const char *format, ...);
typedef void *(*voidFunc)();
struct HardHook {
unsigned char *baseptr;
unsigned char orig[6];
unsigned char replace[6];
bool bTrampoline;
voidFunc call;
static void *pCode;
static unsigned int uiCode;
HardHook();
void *cloneCode(void **orig);
void setup(voidFunc func, voidFunc replacement);
void setupInterface(IUnknown *intf, LONG funcoffset, voidFunc replacement);
void inject(bool force = false);
void restore(bool force = false);
void print();
};
struct Direct3D9Data {
char cFileName[2048];
int iOffsetCreate;
};
struct FakeInterface {
typedef ULONG(FakeInterface::* voidMemberFunc)();
void **vtbl;
IUnknown *pOriginal;
IUnknown *pNew;
void *pAssembly;
FakeInterface(IUnknown *orig, int entries);
~FakeInterface();
void replace(LONG funcoffset, voidMemberFunc replacement);
};
class Mutex {
protected:
static CRITICAL_SECTION cs;
public:
static void init();
Mutex();
~Mutex();
};
extern void checkD3D9Hook(bool preonly = false);
extern void checkOpenGLHook();
extern SharedMem *sm;
extern Direct3D9Data *d3dd;
extern HANDLE hSharedMutex;
extern HMODULE hSelf;
extern unsigned int uiAudioCount;
extern bool bVideoHooked;
#endif

View File

@ -1,415 +1,415 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "lib.h"
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef void GLvoid;
typedef int GLint;
typedef unsigned char GLubyte;
typedef unsigned int GLuint;
typedef int GLsizei;
typedef float GLfloat;
typedef double GLdouble;
#define GL_TEXTURE_2D 0x0DE1
#define GL_UNSIGNED_BYTE 0x1401
#define GL_QUADS 0x0007
#define GL_RGBA 0x1908
#define GL_BGRA 0x80E1
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_CLAMP_TO_EDGE 0x812F
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_LINEAR 0x2601
#define GL_FRONT_AND_BACK 0x0408
#define GL_AMBIENT_AND_DIFFUSE 0x1602
#define GL_SRC_ALPHA 0x0302
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
#define GL_TEXTURE_GEN_S 0x0C60
#define GL_TEXTURE_GEN_T 0x0C61
#define GL_TEXTURE_GEN_R 0x0C62
#define GL_TEXTURE_GEN_Q 0x0C63
#define GL_STENCIL_TEST 0x0B90
#define GL_SCISSOR_TEST 0x0C11
#define GL_SEPARABLE_2D 0x8012
#define GL_MINMAX 0x802E
#define GL_LIGHTING 0x0B50
#define GL_INDEX_LOGIC_OP 0x0BF1
#define GL_HISTOGRAM 0x8024
#define GL_FOG 0x0B60
#define GL_DITHER 0x0BD0
#define GL_DEPTH_TEST 0x0B71
#define GL_CULL_FACE 0x0B44
#define GL_CONVOLUTION_1D 0x8010
#define GL_CONVOLUTION_2D 0x8011
#define GL_COLOR_TABLE 0x80D0
#define GL_COLOR_MATERIAL 0x0B57
#define GL_AUTO_NORMAL 0x0D80
#define GL_ALPHA_TEST 0x0BC0
#define GL_COLOR_LOGIC_OP 0x0BF2
#define GL_MATRIX_MODE 0x0BA0
#define GL_MODELVIEW 0x1700
#define GL_PROJECTION 0x1701
#define GL_BLEND 0x0BE2
#define TDEF(ret, name, arg) typedef ret (__stdcall * t##name) arg
#define GLDEF(ret, name, arg) TDEF(ret, name, arg); t##name o##name = NULL
GLDEF(HGLRC, wglCreateContext, (HDC));
GLDEF(void, glGenTextures, (GLsizei, GLuint *));
GLDEF(void, glEnable, (GLenum));
GLDEF(void, glDisable, (GLenum));
GLDEF(void, glBlendFunc, (GLenum, GLenum));
GLDEF(void, glColorMaterial, (GLenum, GLenum));
GLDEF(void, glViewport, (GLint, GLint, GLsizei, GLsizei));
GLDEF(void, glMatrixMode, (GLenum));
GLDEF(void, glLoadIdentity, (void));
GLDEF(void, glOrtho, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble));
GLDEF(void, glBindTexture, (GLenum, GLuint));
GLDEF(void, glPushMatrix, (void));
GLDEF(void, glColor4ub, (GLubyte, GLubyte, GLubyte, GLubyte));
GLDEF(void, glTranslatef, (GLfloat, GLfloat, GLfloat));
GLDEF(void, glBegin, (GLenum));
GLDEF(void, glEnd, (void));
GLDEF(void, glTexCoord2f, (GLfloat, GLfloat));
GLDEF(void, glVertex2f, (GLfloat, GLfloat));
GLDEF(void, glPopMatrix, (void));
GLDEF(void, glTexParameteri, (GLenum, GLenum, GLint));
GLDEF(void, glTexImage2D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *));
GLDEF(void, wglMakeCurrent, (HDC, HGLRC));
GLDEF(HGLRC, wglGetCurrentContext, (void));
GLDEF(HDC, wglGetCurrentDC, (void));
GLDEF(int, GetDeviceCaps, (HDC, int));
#define INJDEF(ret, name, arg) GLDEF(ret, name, arg); static HardHook hh##name
#define INJECT(name) { o##name = reinterpret_cast<t##name>(GetProcAddress(hGL, #name)); if (o##name) { hh##name.setup(reinterpret_cast<voidFunc>(o##name), reinterpret_cast<voidFunc>(my##name)); o##name = (t##name) hh##name.call; } else { ods("OpenGL: No GetProc for %s", #name);} }
INJDEF(BOOL, wglSwapLayerBuffers, (HDC, UINT));
INJDEF(BOOL, wglSwapBuffers, (HDC));
INJDEF(BOOL, SwapBuffers, (HDC));
static bool bHooked = false;
static bool bChaining = false;
struct Context {
HGLRC ctx;
GLuint textures[NUM_TEXTS];
unsigned int uiCounter[NUM_TEXTS];
Context(HDC hdc);
void draw(HDC hdc);
};
Context::Context(HDC hdc) {
ctx = owglCreateContext(hdc);
owglMakeCurrent(hdc, ctx);
oglGenTextures(NUM_TEXTS, textures);
// Here we go. From the top. Where is glResetState?
oglDisable(GL_ALPHA_TEST);
oglDisable(GL_AUTO_NORMAL);
oglEnable(GL_BLEND);
// Skip clip planes, there are thousands of them.
oglDisable(GL_COLOR_LOGIC_OP);
oglEnable(GL_COLOR_MATERIAL);
oglDisable(GL_COLOR_TABLE);
oglDisable(GL_CONVOLUTION_1D);
oglDisable(GL_CONVOLUTION_2D);
oglDisable(GL_CULL_FACE);
oglDisable(GL_DEPTH_TEST);
oglDisable(GL_DITHER);
oglDisable(GL_FOG);
oglDisable(GL_HISTOGRAM);
oglDisable(GL_INDEX_LOGIC_OP);
oglDisable(GL_LIGHTING);
// Skip line smmooth
// Skip map
oglDisable(GL_MINMAX);
// Skip polygon offset
oglDisable(GL_SEPARABLE_2D);
oglDisable(GL_SCISSOR_TEST);
oglDisable(GL_STENCIL_TEST);
oglEnable(GL_TEXTURE_2D);
oglDisable(GL_TEXTURE_GEN_Q);
oglDisable(GL_TEXTURE_GEN_R);
oglDisable(GL_TEXTURE_GEN_S);
oglDisable(GL_TEXTURE_GEN_T);
oglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
oglColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L);
if (dwWaitResult != WAIT_OBJECT_0)
return;
for (int i=0;i<NUM_TEXTS;++i)
uiCounter[i] = 0;
ReleaseMutex(hSharedMutex);
}
void Context::draw(HDC hdc) {
sm->bHooked = true;
// DEBUG
// sm->bDebug = true;
unsigned int width, height;
int i;
width = oGetDeviceCaps(hdc, HORZRES);
height = oGetDeviceCaps(hdc, VERTRES);
ods("DrawStart: Screen is %d x %d", width, height);
if (sm->fFontSize < 0.01f)
sm->fFontSize = 0.01f;
else if (sm->fFontSize > 1.0f)
sm->fFontSize = 1.0f;
int iHeight = (int)((height * 1.0) * sm->fFontSize);
if (iHeight > TEXT_HEIGHT)
iHeight = TEXT_HEIGHT;
float s = iHeight / 60.0f;
int y = 0;
int idx = 0;
int texs[NUM_TEXTS];
int widths[NUM_TEXTS];
int yofs[NUM_TEXTS];
unsigned int color[NUM_TEXTS];
DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L);
if (dwWaitResult != WAIT_OBJECT_0)
return;
oglViewport(0, 0, width, height);
oglMatrixMode(GL_PROJECTION);
oglLoadIdentity();
oglOrtho(0, width, height, 0, -100.0, 100.0);
oglMatrixMode(GL_MODELVIEW);
for (i = 0; i < NUM_TEXTS; i++) {
if (sm->texts[i].width == 0) {
y += iHeight / 4;
} else if (sm->texts[i].width > 0) {
if (sm->texts[i].uiCounter != uiCounter[i]) {
ods("OpenGL: Updating %d %d texture", sm->texts[i].width, TEXT_HEIGHT);
oglBindTexture(GL_TEXTURE_2D, textures[i]);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
oglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXT_WIDTH, TEXT_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, sm->texts[i].texture);
uiCounter[i] = sm->texts[i].uiCounter;
}
texs[idx] = textures[i];
widths[idx] = sm->texts[i].width;
color[idx] = sm->texts[i].color;
yofs[idx] = y;
y += iHeight;
idx++;
}
}
ReleaseMutex(hSharedMutex);
int h = y;
y = (int)(height * sm->fY);
if (sm->bTop) {
y -= h;
} else if (sm->bBottom) {
} else {
y -= h / 2;
}
if (y < 1)
y = 1;
if ((y + h + 1) > (int)height)
y = height - h - 1;
for (i = 0; i < idx; i++) {
int w = (int)(widths[i] * s);
int x = (int)(width * sm->fX);
if (sm->bLeft) {
x -= w;
} else if (sm->bRight) {
} else {
x -= w / 2;
}
if (x < 1)
x = 1;
if ((x + w + 1) > (int)width)
x = width - w - 1;
ods("OpenGL: Drawing text at %d %d %d %d", x, y + yofs[i], w, iHeight);
oglBindTexture(GL_TEXTURE_2D, texs[i]);
oglPushMatrix();
oglLoadIdentity();
float xm = 0.0;
float ym = 0.0;
float xmx = (1.0f * widths[i]) / TEXT_WIDTH;
float ymx = 1.0f;
unsigned int c = color[i];
oglColor4ub((c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF, (c >> 24) & 0xFF);
oglTranslatef(static_cast<float>(x), static_cast<float>(y + yofs[i]), 0.0f);
oglBegin(GL_QUADS);
oglTexCoord2f(xm, ymx);
oglVertex2f(0.0f, static_cast<float>(iHeight));
oglTexCoord2f(xm, ym);
oglVertex2f(0.0f, 0.0f);
oglTexCoord2f(xmx, ym);
oglVertex2f(static_cast<float>(w), 0.0f);
oglTexCoord2f(xmx, ymx);
oglVertex2f(static_cast<float>(w), static_cast<float>(iHeight));
oglEnd();
oglPopMatrix();
}
}
static map<HDC, Context *> contexts;
static void doSwap(HDC hdc) {
HGLRC oldctx = owglGetCurrentContext();
HDC oldhdc = owglGetCurrentDC();
Context *c = contexts[hdc];
if (!c) {
ods("OpenGL: New context for device %p", hdc);
c = new Context(hdc);
contexts[hdc] = c;
} else {
ods("OpenGL: Reusing old context");
owglMakeCurrent(hdc, c->ctx);
}
c->draw(hdc);
owglMakeCurrent(oldhdc, oldctx);
}
static BOOL __stdcall mywglSwapBuffers(HDC hdc) {
ods("OpenGL: wglSwapBuffers");
doSwap(hdc);
hhwglSwapBuffers.restore();
BOOL ret=owglSwapBuffers(hdc);
hhwglSwapBuffers.inject();
return ret;
}
static BOOL __stdcall mySwapBuffers(HDC hdc) {
ods("OpenGL: SwapBuffers");
hhSwapBuffers.restore();
BOOL ret=oSwapBuffers(hdc);
hhSwapBuffers.inject();
return ret;
}
static BOOL __stdcall mywglSwapLayerBuffers(HDC hdc, UINT fuPlanes) {
ods("OpenGL: SwapLayerBuffers %x",fuPlanes);
hhwglSwapLayerBuffers.restore();
BOOL ret=owglSwapLayerBuffers(hdc, fuPlanes);
hhwglSwapLayerBuffers.inject();
return ret;
}
#undef GLDEF
#define GLDEF(name) o##name = reinterpret_cast<t##name>(GetProcAddress(hGL, #name))
void checkOpenGLHook() {
if (bChaining) {
return;
ods("Causing a chain");
}
bChaining = true;
HMODULE hGL = GetModuleHandle("OpenGL32.DLL");
if (hGL != NULL) {
if (! bHooked) {
char procname[1024];
GetModuleFileName(NULL, procname, 1024);
fods("OpenGL: Unhooked OpenGL App %s", procname);
bHooked = true;
INJECT(wglSwapBuffers);
// INJECT(wglSwapLayerBuffers);
GLDEF(wglCreateContext);
GLDEF(glGenTextures);
GLDEF(glEnable);
GLDEF(glDisable);
GLDEF(glBlendFunc);
GLDEF(glColorMaterial);
GLDEF(glViewport);
GLDEF(glMatrixMode);
GLDEF(glLoadIdentity);
GLDEF(glOrtho);
GLDEF(glBindTexture);
GLDEF(glPushMatrix);
GLDEF(glColor4ub);
GLDEF(glTranslatef);
GLDEF(glBegin);
GLDEF(glEnd);
GLDEF(glTexCoord2f);
GLDEF(glVertex2f);
GLDEF(glPopMatrix);
GLDEF(glTexParameteri);
GLDEF(glTexImage2D);
GLDEF(wglMakeCurrent);
GLDEF(wglGetCurrentContext);
GLDEF(wglGetCurrentDC);
hGL = GetModuleHandle("GDI32.DLL");
if (hGL) {
// INJECT(SwapBuffers);
GLDEF(GetDeviceCaps);
} else {
ods("OpenGL: Failed to find GDI32");
}
}
}
bChaining = false;
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "lib.h"
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef void GLvoid;
typedef int GLint;
typedef unsigned char GLubyte;
typedef unsigned int GLuint;
typedef int GLsizei;
typedef float GLfloat;
typedef double GLdouble;
#define GL_TEXTURE_2D 0x0DE1
#define GL_UNSIGNED_BYTE 0x1401
#define GL_QUADS 0x0007
#define GL_RGBA 0x1908
#define GL_BGRA 0x80E1
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_CLAMP_TO_EDGE 0x812F
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_LINEAR 0x2601
#define GL_FRONT_AND_BACK 0x0408
#define GL_AMBIENT_AND_DIFFUSE 0x1602
#define GL_SRC_ALPHA 0x0302
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
#define GL_TEXTURE_GEN_S 0x0C60
#define GL_TEXTURE_GEN_T 0x0C61
#define GL_TEXTURE_GEN_R 0x0C62
#define GL_TEXTURE_GEN_Q 0x0C63
#define GL_STENCIL_TEST 0x0B90
#define GL_SCISSOR_TEST 0x0C11
#define GL_SEPARABLE_2D 0x8012
#define GL_MINMAX 0x802E
#define GL_LIGHTING 0x0B50
#define GL_INDEX_LOGIC_OP 0x0BF1
#define GL_HISTOGRAM 0x8024
#define GL_FOG 0x0B60
#define GL_DITHER 0x0BD0
#define GL_DEPTH_TEST 0x0B71
#define GL_CULL_FACE 0x0B44
#define GL_CONVOLUTION_1D 0x8010
#define GL_CONVOLUTION_2D 0x8011
#define GL_COLOR_TABLE 0x80D0
#define GL_COLOR_MATERIAL 0x0B57
#define GL_AUTO_NORMAL 0x0D80
#define GL_ALPHA_TEST 0x0BC0
#define GL_COLOR_LOGIC_OP 0x0BF2
#define GL_MATRIX_MODE 0x0BA0
#define GL_MODELVIEW 0x1700
#define GL_PROJECTION 0x1701
#define GL_BLEND 0x0BE2
#define TDEF(ret, name, arg) typedef ret (__stdcall * t##name) arg
#define GLDEF(ret, name, arg) TDEF(ret, name, arg); t##name o##name = NULL
GLDEF(HGLRC, wglCreateContext, (HDC));
GLDEF(void, glGenTextures, (GLsizei, GLuint *));
GLDEF(void, glEnable, (GLenum));
GLDEF(void, glDisable, (GLenum));
GLDEF(void, glBlendFunc, (GLenum, GLenum));
GLDEF(void, glColorMaterial, (GLenum, GLenum));
GLDEF(void, glViewport, (GLint, GLint, GLsizei, GLsizei));
GLDEF(void, glMatrixMode, (GLenum));
GLDEF(void, glLoadIdentity, (void));
GLDEF(void, glOrtho, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble));
GLDEF(void, glBindTexture, (GLenum, GLuint));
GLDEF(void, glPushMatrix, (void));
GLDEF(void, glColor4ub, (GLubyte, GLubyte, GLubyte, GLubyte));
GLDEF(void, glTranslatef, (GLfloat, GLfloat, GLfloat));
GLDEF(void, glBegin, (GLenum));
GLDEF(void, glEnd, (void));
GLDEF(void, glTexCoord2f, (GLfloat, GLfloat));
GLDEF(void, glVertex2f, (GLfloat, GLfloat));
GLDEF(void, glPopMatrix, (void));
GLDEF(void, glTexParameteri, (GLenum, GLenum, GLint));
GLDEF(void, glTexImage2D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *));
GLDEF(void, wglMakeCurrent, (HDC, HGLRC));
GLDEF(HGLRC, wglGetCurrentContext, (void));
GLDEF(HDC, wglGetCurrentDC, (void));
GLDEF(int, GetDeviceCaps, (HDC, int));
#define INJDEF(ret, name, arg) GLDEF(ret, name, arg); static HardHook hh##name
#define INJECT(name) { o##name = reinterpret_cast<t##name>(GetProcAddress(hGL, #name)); if (o##name) { hh##name.setup(reinterpret_cast<voidFunc>(o##name), reinterpret_cast<voidFunc>(my##name)); o##name = (t##name) hh##name.call; } else { ods("OpenGL: No GetProc for %s", #name);} }
INJDEF(BOOL, wglSwapLayerBuffers, (HDC, UINT));
INJDEF(BOOL, wglSwapBuffers, (HDC));
INJDEF(BOOL, SwapBuffers, (HDC));
static bool bHooked = false;
static bool bChaining = false;
struct Context {
HGLRC ctx;
GLuint textures[NUM_TEXTS];
unsigned int uiCounter[NUM_TEXTS];
Context(HDC hdc);
void draw(HDC hdc);
};
Context::Context(HDC hdc) {
ctx = owglCreateContext(hdc);
owglMakeCurrent(hdc, ctx);
oglGenTextures(NUM_TEXTS, textures);
// Here we go. From the top. Where is glResetState?
oglDisable(GL_ALPHA_TEST);
oglDisable(GL_AUTO_NORMAL);
oglEnable(GL_BLEND);
// Skip clip planes, there are thousands of them.
oglDisable(GL_COLOR_LOGIC_OP);
oglEnable(GL_COLOR_MATERIAL);
oglDisable(GL_COLOR_TABLE);
oglDisable(GL_CONVOLUTION_1D);
oglDisable(GL_CONVOLUTION_2D);
oglDisable(GL_CULL_FACE);
oglDisable(GL_DEPTH_TEST);
oglDisable(GL_DITHER);
oglDisable(GL_FOG);
oglDisable(GL_HISTOGRAM);
oglDisable(GL_INDEX_LOGIC_OP);
oglDisable(GL_LIGHTING);
// Skip line smmooth
// Skip map
oglDisable(GL_MINMAX);
// Skip polygon offset
oglDisable(GL_SEPARABLE_2D);
oglDisable(GL_SCISSOR_TEST);
oglDisable(GL_STENCIL_TEST);
oglEnable(GL_TEXTURE_2D);
oglDisable(GL_TEXTURE_GEN_Q);
oglDisable(GL_TEXTURE_GEN_R);
oglDisable(GL_TEXTURE_GEN_S);
oglDisable(GL_TEXTURE_GEN_T);
oglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
oglColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L);
if (dwWaitResult != WAIT_OBJECT_0)
return;
for (int i=0;i<NUM_TEXTS;++i)
uiCounter[i] = 0;
ReleaseMutex(hSharedMutex);
}
void Context::draw(HDC hdc) {
sm->bHooked = true;
// DEBUG
// sm->bDebug = true;
unsigned int width, height;
int i;
width = oGetDeviceCaps(hdc, HORZRES);
height = oGetDeviceCaps(hdc, VERTRES);
ods("DrawStart: Screen is %d x %d", width, height);
if (sm->fFontSize < 0.01f)
sm->fFontSize = 0.01f;
else if (sm->fFontSize > 1.0f)
sm->fFontSize = 1.0f;
int iHeight = (int)((height * 1.0) * sm->fFontSize);
if (iHeight > TEXT_HEIGHT)
iHeight = TEXT_HEIGHT;
float s = iHeight / 60.0f;
int y = 0;
int idx = 0;
int texs[NUM_TEXTS];
int widths[NUM_TEXTS];
int yofs[NUM_TEXTS];
unsigned int color[NUM_TEXTS];
DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L);
if (dwWaitResult != WAIT_OBJECT_0)
return;
oglViewport(0, 0, width, height);
oglMatrixMode(GL_PROJECTION);
oglLoadIdentity();
oglOrtho(0, width, height, 0, -100.0, 100.0);
oglMatrixMode(GL_MODELVIEW);
for (i = 0; i < NUM_TEXTS; i++) {
if (sm->texts[i].width == 0) {
y += iHeight / 4;
} else if (sm->texts[i].width > 0) {
if (sm->texts[i].uiCounter != uiCounter[i]) {
ods("OpenGL: Updating %d %d texture", sm->texts[i].width, TEXT_HEIGHT);
oglBindTexture(GL_TEXTURE_2D, textures[i]);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
oglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXT_WIDTH, TEXT_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, sm->texts[i].texture);
uiCounter[i] = sm->texts[i].uiCounter;
}
texs[idx] = textures[i];
widths[idx] = sm->texts[i].width;
color[idx] = sm->texts[i].color;
yofs[idx] = y;
y += iHeight;
idx++;
}
}
ReleaseMutex(hSharedMutex);
int h = y;
y = (int)(height * sm->fY);
if (sm->bTop) {
y -= h;
} else if (sm->bBottom) {
} else {
y -= h / 2;
}
if (y < 1)
y = 1;
if ((y + h + 1) > (int)height)
y = height - h - 1;
for (i = 0; i < idx; i++) {
int w = (int)(widths[i] * s);
int x = (int)(width * sm->fX);
if (sm->bLeft) {
x -= w;
} else if (sm->bRight) {
} else {
x -= w / 2;
}
if (x < 1)
x = 1;
if ((x + w + 1) > (int)width)
x = width - w - 1;
ods("OpenGL: Drawing text at %d %d %d %d", x, y + yofs[i], w, iHeight);
oglBindTexture(GL_TEXTURE_2D, texs[i]);
oglPushMatrix();
oglLoadIdentity();
float xm = 0.0;
float ym = 0.0;
float xmx = (1.0f * widths[i]) / TEXT_WIDTH;
float ymx = 1.0f;
unsigned int c = color[i];
oglColor4ub((c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF, (c >> 24) & 0xFF);
oglTranslatef(static_cast<float>(x), static_cast<float>(y + yofs[i]), 0.0f);
oglBegin(GL_QUADS);
oglTexCoord2f(xm, ymx);
oglVertex2f(0.0f, static_cast<float>(iHeight));
oglTexCoord2f(xm, ym);
oglVertex2f(0.0f, 0.0f);
oglTexCoord2f(xmx, ym);
oglVertex2f(static_cast<float>(w), 0.0f);
oglTexCoord2f(xmx, ymx);
oglVertex2f(static_cast<float>(w), static_cast<float>(iHeight));
oglEnd();
oglPopMatrix();
}
}
static map<HDC, Context *> contexts;
static void doSwap(HDC hdc) {
HGLRC oldctx = owglGetCurrentContext();
HDC oldhdc = owglGetCurrentDC();
Context *c = contexts[hdc];
if (!c) {
ods("OpenGL: New context for device %p", hdc);
c = new Context(hdc);
contexts[hdc] = c;
} else {
ods("OpenGL: Reusing old context");
owglMakeCurrent(hdc, c->ctx);
}
c->draw(hdc);
owglMakeCurrent(oldhdc, oldctx);
}
static BOOL __stdcall mywglSwapBuffers(HDC hdc) {
ods("OpenGL: wglSwapBuffers");
doSwap(hdc);
hhwglSwapBuffers.restore();
BOOL ret=owglSwapBuffers(hdc);
hhwglSwapBuffers.inject();
return ret;
}
static BOOL __stdcall mySwapBuffers(HDC hdc) {
ods("OpenGL: SwapBuffers");
hhSwapBuffers.restore();
BOOL ret=oSwapBuffers(hdc);
hhSwapBuffers.inject();
return ret;
}
static BOOL __stdcall mywglSwapLayerBuffers(HDC hdc, UINT fuPlanes) {
ods("OpenGL: SwapLayerBuffers %x",fuPlanes);
hhwglSwapLayerBuffers.restore();
BOOL ret=owglSwapLayerBuffers(hdc, fuPlanes);
hhwglSwapLayerBuffers.inject();
return ret;
}
#undef GLDEF
#define GLDEF(name) o##name = reinterpret_cast<t##name>(GetProcAddress(hGL, #name))
void checkOpenGLHook() {
if (bChaining) {
return;
ods("Causing a chain");
}
bChaining = true;
HMODULE hGL = GetModuleHandle("OpenGL32.DLL");
if (hGL != NULL) {
if (! bHooked) {
char procname[1024];
GetModuleFileName(NULL, procname, 1024);
fods("OpenGL: Unhooked OpenGL App %s", procname);
bHooked = true;
INJECT(wglSwapBuffers);
// INJECT(wglSwapLayerBuffers);
GLDEF(wglCreateContext);
GLDEF(glGenTextures);
GLDEF(glEnable);
GLDEF(glDisable);
GLDEF(glBlendFunc);
GLDEF(glColorMaterial);
GLDEF(glViewport);
GLDEF(glMatrixMode);
GLDEF(glLoadIdentity);
GLDEF(glOrtho);
GLDEF(glBindTexture);
GLDEF(glPushMatrix);
GLDEF(glColor4ub);
GLDEF(glTranslatef);
GLDEF(glBegin);
GLDEF(glEnd);
GLDEF(glTexCoord2f);
GLDEF(glVertex2f);
GLDEF(glPopMatrix);
GLDEF(glTexParameteri);
GLDEF(glTexImage2D);
GLDEF(wglMakeCurrent);
GLDEF(wglGetCurrentContext);
GLDEF(wglGetCurrentDC);
hGL = GetModuleHandle("GDI32.DLL");
if (hGL) {
// INJECT(SwapBuffers);
GLDEF(GetDeviceCaps);
} else {
ods("OpenGL: Failed to find GDI32");
}
}
}
bChaining = false;
}

View File

@ -2,4 +2,3 @@ TEMPLATE = subdirs
CONFIG += debug_and_release
SUBDIRS = injector overlay stub
DIST = bundle.pri

View File

@ -1,184 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Age of Chivalry (Build 3740)", L"Mumble AOC Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems AOC is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have AOC running
/*
position tuple: client.dll+0xb72ad0 (x,y,z, float)
orientation tuple: client.dll+0xb73b90 (v,h float)
ID string: client.dll+0xb2e6e0 = "ageofchivalry" (13 characters, text)
spawn state: client.dll+0xb33ae8 (0 when at main menu, 1 when at team selection, 2 when not spawned,
6 when spawned on red team, 7 when spawned on blue team, byte)
*/
char sMagic[13];
if(!peekProc(mod + 0xb2e6e0, sMagic, 13) || strncmp("ageofchivalry", sMagic, 13)!=0)
return false;
// Remember addresses for later
posptr = mod + 0xb72ad0;
rotptr = mod + 0xb73b90;
stateptr = mod + 0xb33ae8;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are spawned
if (state == 0 || state == 1 || state == 2)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin aocplug = {
MUMBLE_PLUGIN_MAGIC,
L"Age of Chivalry (Build 3740)",
L"Age of Chivalry",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &aocplug;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Age of Chivalry (Build 3740)", L"Mumble AOC Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems AOC is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have AOC running
/*
position tuple: client.dll+0xb72ad0 (x,y,z, float)
orientation tuple: client.dll+0xb73b90 (v,h float)
ID string: client.dll+0xb2e6e0 = "ageofchivalry" (13 characters, text)
spawn state: client.dll+0xb33ae8 (0 when at main menu, 1 when at team selection, 2 when not spawned,
6 when spawned on red team, 7 when spawned on blue team, byte)
*/
char sMagic[13];
if (!peekProc(mod + 0xb2e6e0, sMagic, 13) || strncmp("ageofchivalry", sMagic, 13)!=0)
return false;
// Remember addresses for later
posptr = mod + 0xb72ad0;
rotptr = mod + 0xb73b90;
stateptr = mod + 0xb33ae8;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are spawned
if (state == 0 || state == 1 || state == 2)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin aocplug = {
MUMBLE_PLUGIN_MAGIC,
L"Age of Chivalry (Build 3740)",
L"Age of Chivalry",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &aocplug;
}

View File

@ -1,7 +1,7 @@
include(../plugins.pri)
TARGET = aoc
SOURCES = aoc.cpp
LIBS += -luser32
include(../plugins.pri)
TARGET = aoc
SOURCES = aoc.cpp
LIBS += -luser32

View File

@ -1,184 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Counter-Strike: Source (Build 3698)", L"Mumble CSS Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -180.0f) || (v > 180.0f) || (h < -180.0f) || (h > 180.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems CSS is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have CSS running
/*
position tuple: client.dll+0x39b504 (x,y,z, float)
orientation tuple: client.dll+0x3ec684 (v,h float)
ID string: client.dll+0x39cde9 = "CSSpectatorGUI@@" (16 characters, text)
spawn state: client.dll+0x38e050 (0 in main menu, 3 when at team selection menu, 5 when spawned as CT, 6 when spawns as T)
*/
char sMagic[16];
if(!peekProc(mod + 0x39cde9, sMagic, 16) || strncmp("CSSpectatorGUI@@", sMagic, 16)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x39b504;
rotptr = mod + 0x3ec684;
stateptr = mod + 0x38e050;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
float ipos[3], rot[3];
bool ok;
char state;
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr , &state, 1);
if (!ok)
return false;
//Check to see if you are in a server
//spawn state: client.dll+0x38e050 (0 in main menu, 3 when at team selection menu, 5 when spawned as CT, 6 when spawns as T)
if (state == 0 || state == 3)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin cssplug = {
MUMBLE_PLUGIN_MAGIC,
L"Counter-Strike: Source (Build 3698)",
L"Counter-Strike: Source",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &cssplug;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Counter-Strike: Source (Build 3698)", L"Mumble CSS Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -180.0f) || (v > 180.0f) || (h < -180.0f) || (h > 180.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems CSS is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have CSS running
/*
position tuple: client.dll+0x39b504 (x,y,z, float)
orientation tuple: client.dll+0x3ec684 (v,h float)
ID string: client.dll+0x39cde9 = "CSSpectatorGUI@@" (16 characters, text)
spawn state: client.dll+0x38e050 (0 in main menu, 3 when at team selection menu, 5 when spawned as CT, 6 when spawns as T)
*/
char sMagic[16];
if (!peekProc(mod + 0x39cde9, sMagic, 16) || strncmp("CSSpectatorGUI@@", sMagic, 16)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x39b504;
rotptr = mod + 0x3ec684;
stateptr = mod + 0x38e050;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
float ipos[3], rot[3];
bool ok;
char state;
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr , &state, 1);
if (!ok)
return false;
//Check to see if you are in a server
//spawn state: client.dll+0x38e050 (0 in main menu, 3 when at team selection menu, 5 when spawned as CT, 6 when spawns as T)
if (state == 0 || state == 3)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin cssplug = {
MUMBLE_PLUGIN_MAGIC,
L"Counter-Strike: Source (Build 3698)",
L"Counter-Strike: Source",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &cssplug;
}

View File

@ -1,7 +1,7 @@
include(../plugins.pri)
TARGET = css
SOURCES = css.cpp
LIBS += -luser32
include(../plugins.pri)
TARGET = css
SOURCES = css.cpp
LIBS += -luser32

View File

@ -1,183 +1,183 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Garry's Mod 11 (Build 3740)", L"Mumble Gmod Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems Gmod is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have Gmod running
/*
position tuple: client.dll+0x5ee120 (x,y,z, float)
orientation tuple: client.dll+0x43e2dc (v,h float)
ID string: client.dll+0x44e740 = "GMod@@" (6 characters, text)
spawn state: client.dll+0x5b6a9d (0 when at main menu, 8 when spawned, byte)
*/
char sMagic[6];
if(!peekProc(mod + 0x44e740, sMagic, 6) || strncmp("GMod@@", sMagic, 6)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x5ee120;
rotptr = mod + 0x43e2dc;
stateptr = mod + 0x5b6a9d;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are in a server
if (state == 0)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin gmodplug = {
MUMBLE_PLUGIN_MAGIC,
L"Garry's Mod 11 (Build 3740)",
L"Garry's Mod 11",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &gmodplug;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Garry's Mod 11 (Build 3740)", L"Mumble Gmod Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems Gmod is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have Gmod running
/*
position tuple: client.dll+0x5ee120 (x,y,z, float)
orientation tuple: client.dll+0x43e2dc (v,h float)
ID string: client.dll+0x44e740 = "GMod@@" (6 characters, text)
spawn state: client.dll+0x5b6a9d (0 when at main menu, 8 when spawned, byte)
*/
char sMagic[6];
if (!peekProc(mod + 0x44e740, sMagic, 6) || strncmp("GMod@@", sMagic, 6)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x5ee120;
rotptr = mod + 0x43e2dc;
stateptr = mod + 0x5b6a9d;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are in a server
if (state == 0)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin gmodplug = {
MUMBLE_PLUGIN_MAGIC,
L"Garry's Mod 11 (Build 3740)",
L"Garry's Mod 11",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &gmodplug;
}

View File

@ -1,7 +1,7 @@
include(../plugins.pri)
TARGET = gmod
SOURCES = gmod.cpp
LIBS += -luser32
include(../plugins.pri)
TARGET = gmod
SOURCES = gmod.cpp
LIBS += -luser32

View File

@ -1,184 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Half-Life 2: Deathmatch (Build 3698)", L"Mumble HL2DM Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems HL2DM is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have HL2DM running
/*
position tuple: client.dll+0x3dcad4 (x,y,z, float)
orientation tuple: client.dll+0x3dcae0 (v,h float)
ID string: client.dll+0x3a5674 = "Dm/$" (4 characters, text)
spawn state: client.dll+0x37e180 (0 when at main menu, 2 when not spawned, 7 when spawned, byte)
*/
char sMagic[4];
if(!peekProc(mod + 0x3a5674, sMagic, 4) || strncmp("Dm/$", sMagic, 4)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x3dcad4;
rotptr = mod + 0x3dcae0;
stateptr = mod + 0x37e180;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are spawned
if (state == 0 || state == 2)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin hl2dmplug = {
MUMBLE_PLUGIN_MAGIC,
L"Half-Life 2: Deathmatch (Build 3698)",
L"Half-Life 2: Deathmatch",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &hl2dmplug;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Half-Life 2: Deathmatch (Build 3698)", L"Mumble HL2DM Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems HL2DM is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have HL2DM running
/*
position tuple: client.dll+0x3dcad4 (x,y,z, float)
orientation tuple: client.dll+0x3dcae0 (v,h float)
ID string: client.dll+0x3a5674 = "Dm/$" (4 characters, text)
spawn state: client.dll+0x37e180 (0 when at main menu, 2 when not spawned, 7 when spawned, byte)
*/
char sMagic[4];
if (!peekProc(mod + 0x3a5674, sMagic, 4) || strncmp("Dm/$", sMagic, 4)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x3dcad4;
rotptr = mod + 0x3dcae0;
stateptr = mod + 0x37e180;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are spawned
if (state == 0 || state == 2)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin hl2dmplug = {
MUMBLE_PLUGIN_MAGIC,
L"Half-Life 2: Deathmatch (Build 3698)",
L"Half-Life 2: Deathmatch",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &hl2dmplug;
}

View File

@ -1,7 +1,7 @@
include(../plugins.pri)
TARGET = hl2dm
SOURCES = hl2dm.cpp
LIBS += -luser32
include(../plugins.pri)
TARGET = hl2dm
SOURCES = hl2dm.cpp
LIBS += -luser32

View File

@ -1,183 +1,183 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Insurgency: Modern Infantry Combat (Build 3698)", L"Mumble Insurgency Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems Insurgency is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have Insurgency running
/*
position tuple: client.dll+0x38a950 (x,y,z, float)
orientation tuple: client.dll+0x38abc0 (v,h float)
ID string: client.dll+0x31a80a = "CombatWeapon@@" (14 characters, text)
spawn state: client.dll+0x3536a8 (0 when at main menu, 1 when not spawned, 4 when spawned)
*/
char sMagic[14];
if(!peekProc(mod + 0x31a80a, sMagic, 14) || strncmp("CombatWeapon@@", sMagic, 14)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x38a950;
rotptr = mod + 0x38abc0;
stateptr = mod + 0x3536a8;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are spawned
if (state == 0 || state == 1)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin insurgencyplug = {
MUMBLE_PLUGIN_MAGIC,
L"Insurgency: Modern Infantry Combat (Build 3698)",
L"Insurgency: Modern Infantry Combat",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &insurgencyplug;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Insurgency: Modern Infantry Combat (Build 3698)", L"Mumble Insurgency Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems Insurgency is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have Insurgency running
/*
position tuple: client.dll+0x38a950 (x,y,z, float)
orientation tuple: client.dll+0x38abc0 (v,h float)
ID string: client.dll+0x31a80a = "CombatWeapon@@" (14 characters, text)
spawn state: client.dll+0x3536a8 (0 when at main menu, 1 when not spawned, 4 when spawned)
*/
char sMagic[14];
if (!peekProc(mod + 0x31a80a, sMagic, 14) || strncmp("CombatWeapon@@", sMagic, 14)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x38a950;
rotptr = mod + 0x38abc0;
stateptr = mod + 0x3536a8;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are spawned
if (state == 0 || state == 1)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin insurgencyplug = {
MUMBLE_PLUGIN_MAGIC,
L"Insurgency: Modern Infantry Combat (Build 3698)",
L"Insurgency: Modern Infantry Combat",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &insurgencyplug;
}

View File

@ -1,7 +1,7 @@
include(../plugins.pri)
TARGET = insurgency
SOURCES = insurgency.cpp
LIBS += -luser32
include(../plugins.pri)
TARGET = insurgency
SOURCES = insurgency.cpp
LIBS += -luser32

View File

@ -1,166 +1,166 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Left 4 Dead (Build 3730)", L"Mumble L4D Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -180.0f) || (v > 180.0f) || (h < -180.0f) || (h > 180.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems L4D is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
/*
printf("Poll\n");
printf("%f %f %f : %f %f\n",pos[0],pos[1],pos[2], rot[0], rot[1]);
printf("%f %f %f :: %.2f %.2f %.2f :: %.2f %.2f %.2f\n", opos[0], opos[1], opos[2], front[0], front[1], front[2], top[0], top[1], top[2]);
*/
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"left4dead.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
posptr = mod + 0x576240;
rotptr = mod + 0x576240 + 24;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
float ipos[3], rot[3];
bool ok;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(ipos, rot, pos, front, top);
return false;
}
static MumblePlugin l4dplug = {
MUMBLE_PLUGIN_MAGIC,
L"Left 4 Dead (Build 3730)",
L"Left 4 Dead",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &l4dplug;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Left 4 Dead (Build 3730)", L"Mumble L4D Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -180.0f) || (v > 180.0f) || (h < -180.0f) || (h > 180.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems L4D is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
/*
printf("Poll\n");
printf("%f %f %f : %f %f\n",pos[0],pos[1],pos[2], rot[0], rot[1]);
printf("%f %f %f :: %.2f %.2f %.2f :: %.2f %.2f %.2f\n", opos[0], opos[1], opos[2], front[0], front[1], front[2], top[0], top[1], top[2]);
*/
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"left4dead.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
posptr = mod + 0x576240;
rotptr = mod + 0x576240 + 24;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
float ipos[3], rot[3];
bool ok;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(ipos, rot, pos, front, top);
return false;
}
static MumblePlugin l4dplug = {
MUMBLE_PLUGIN_MAGIC,
L"Left 4 Dead (Build 3730)",
L"Left 4 Dead",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &l4dplug;
}

View File

@ -1,126 +1,126 @@
#ifndef QT_NO_DEBUG
#include <stdio.h>
#include <stdlib.h>
#endif
#include <windows.h>
#include <math.h>
#include "../mumble_plugin.h"
static wchar_t wcPluginName[256];
struct LinkedMem {
UINT32 uiVersion;
DWORD dwcount;
float fPosition[3];
float fFront[3];
float fTop[3];
wchar_t name[256];
};
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from linked game", L"Mumble Link Plugin", MB_OK);
}
static HANDLE hMapObject = NULL;
static LinkedMem *lm = NULL;
static DWORD last_count = 0;
static DWORD last_tick = 0;
static void unlock() {
lm->dwcount = last_count = 0;
lm->uiVersion = 0;
lm->name[0] = 0;
wcscpy_s(wcPluginName, 256, L"Link");
return;
}
static int trylock() {
if (lm->uiVersion == 1) {
if (lm->dwcount != last_count) {
last_count = lm->dwcount;
last_tick = GetTickCount();
if (lm->name[0]) {
errno_t err = wcscpy_s(wcPluginName, 256, lm->name);
if (err != 0) {
wcscpy_s(wcPluginName, 256, L"Link");
return false;
}
}
return true;
}
}
return false;
}
static int fetch(float *pos, float *front, float *top) {
if (lm->dwcount != last_count) {
last_count = lm->dwcount;
last_tick = GetTickCount();
} else if ((GetTickCount() - last_tick) > 5000)
return false;
if (lm->uiVersion != 1)
return false;
for (int i=0;i<3;i++)
pos[i]=lm->fPosition[i];
for (int i=0;i<3;i++)
front[i]=lm->fFront[i];
for (int i=0;i<3;i++)
top[i]=lm->fTop[i];
return true;
}
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) {
bool bCreated = false;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
wcscpy_s(wcPluginName, 256, L"Link");
hMapObject = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink");
if (hMapObject == NULL) {
hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(LinkedMem), L"MumbleLink");
bCreated = true;
if (hMapObject == NULL)
return false;
}
lm = (LinkedMem *) MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lm == NULL) {
CloseHandle(hMapObject);
hMapObject = NULL;
return false;
}
if (bCreated)
memset(lm, 0, sizeof(LinkedMem));
break;
case DLL_PROCESS_DETACH:
if (lm) {
UnmapViewOfFile(lm);
lm = NULL;
}
if (hMapObject) {
CloseHandle(hMapObject);
hMapObject = NULL;
}
break;
}
return true;
}
static MumblePlugin linkplug = {
MUMBLE_PLUGIN_MAGIC,
L"Link v1.0.1",
wcPluginName,
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &linkplug;
}
#ifndef QT_NO_DEBUG
#include <stdio.h>
#include <stdlib.h>
#endif
#include <windows.h>
#include <math.h>
#include "../mumble_plugin.h"
static wchar_t wcPluginName[256];
struct LinkedMem {
UINT32 uiVersion;
DWORD dwcount;
float fPosition[3];
float fFront[3];
float fTop[3];
wchar_t name[256];
};
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from linked game", L"Mumble Link Plugin", MB_OK);
}
static HANDLE hMapObject = NULL;
static LinkedMem *lm = NULL;
static DWORD last_count = 0;
static DWORD last_tick = 0;
static void unlock() {
lm->dwcount = last_count = 0;
lm->uiVersion = 0;
lm->name[0] = 0;
wcscpy_s(wcPluginName, 256, L"Link");
return;
}
static int trylock() {
if (lm->uiVersion == 1) {
if (lm->dwcount != last_count) {
last_count = lm->dwcount;
last_tick = GetTickCount();
if (lm->name[0]) {
errno_t err = wcscpy_s(wcPluginName, 256, lm->name);
if (err != 0) {
wcscpy_s(wcPluginName, 256, L"Link");
return false;
}
}
return true;
}
}
return false;
}
static int fetch(float *pos, float *front, float *top) {
if (lm->dwcount != last_count) {
last_count = lm->dwcount;
last_tick = GetTickCount();
} else if ((GetTickCount() - last_tick) > 5000)
return false;
if (lm->uiVersion != 1)
return false;
for (int i=0;i<3;i++)
pos[i]=lm->fPosition[i];
for (int i=0;i<3;i++)
front[i]=lm->fFront[i];
for (int i=0;i<3;i++)
top[i]=lm->fTop[i];
return true;
}
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) {
bool bCreated = false;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
wcscpy_s(wcPluginName, 256, L"Link");
hMapObject = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink");
if (hMapObject == NULL) {
hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(LinkedMem), L"MumbleLink");
bCreated = true;
if (hMapObject == NULL)
return false;
}
lm = (LinkedMem *) MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lm == NULL) {
CloseHandle(hMapObject);
hMapObject = NULL;
return false;
}
if (bCreated)
memset(lm, 0, sizeof(LinkedMem));
break;
case DLL_PROCESS_DETACH:
if (lm) {
UnmapViewOfFile(lm);
lm = NULL;
}
if (hMapObject) {
CloseHandle(hMapObject);
hMapObject = NULL;
}
break;
}
return true;
}
static MumblePlugin linkplug = {
MUMBLE_PLUGIN_MAGIC,
L"Link v1.0.1",
wcPluginName,
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &linkplug;
}

View File

@ -1,9 +1,9 @@
TEMPLATE = subdirs
CONFIG += debug_and_release
SUBDIRS = link
DIST = plugins.pri
win32 {
SUBDIRS += aoc bf2 cod2 cod4 cod5 css gmod hl2dm insurgency l4d tf2 wolfet wow
}
TEMPLATE = subdirs
CONFIG += debug_and_release
SUBDIRS = link
DIST = plugins.pri
win32 {
SUBDIRS += aoc bf2 cod2 cod4 cod5 css gmod hl2dm insurgency l4d tf2 wolfet wow
}

View File

@ -1,184 +1,184 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Team Fortress 2 (Build 3755)", L"Mumble TF2 Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems TF2 is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have TF2 running
/*
position tuple: client.dll+0x4cd594 (x,y,z, float)
orientation tuple: client.dll+0x52529c (v,h float)
ID string: client.dll+0x47726b = "teamJet@@" (9 characters, text)
spawn state: client.dll+0x466b84 (0 when at main menu, 1 when spectator, 3 when at team selection menu, and 6 or 9 when on a team (depending on the team side and gamemode), byte)
*/
char sMagic[9];
if(!peekProc(mod + 0x47726b, sMagic, 9) || strncmp("teamJet@@", sMagic, 9)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x4cd594;
rotptr = mod + 0x52529c;
stateptr = mod + 0x466b84;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are in a server
if (state == 0 || state == 1 || state == 3)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin tf2plug = {
MUMBLE_PLUGIN_MAGIC,
L"Team Fortress 2 (Build 3755)",
L"Team Fortress 2",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &tf2plug;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "../mumble_plugin.h"
HANDLE h;
BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
static DWORD getProcess(const wchar_t *exename) {
PROCESSENTRY32 pe;
DWORD pid = 0;
pe.dwSize = sizeof(pe);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32First(hSnap, &pe);
while (ok) {
if (wcscmp(pe.szExeFile, exename)==0) {
pid = pe.th32ProcessID;
break;
}
ok = Process32Next(hSnap, &pe);
}
CloseHandle(hSnap);
}
return pid;
}
static BYTE *getModuleAddr(DWORD pid, const wchar_t *modname) {
MODULEENTRY32 me;
BYTE *addr = NULL;
me.dwSize = sizeof(me);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Module32First(hSnap, &me);
while (ok) {
if (wcscmp(me.szModule, modname)==0) {
addr = me.modBaseAddr;
break;
}
ok = Module32Next(hSnap, &me);
}
CloseHandle(hSnap);
}
return addr;
}
static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
SIZE_T r;
BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
return (ok && (r == len));
}
static void about(HWND h) {
::MessageBox(h, L"Reads audio position information from Team Fortress 2 (Build 3755)", L"Mumble TF2 Plugin", MB_OK);
}
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
float h = rot[0];
float v = rot[1];
if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
return false;
h *= static_cast<float>(M_PI / 180.0f);
v *= static_cast<float>(M_PI / 180.0f);
// Seems TF2 is in inches. INCHES?!?
opos[0] = pos[0] / 39.37f;
opos[1] = pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
front[0] = cos(v) * cos(h);
front[1] = -sin(h);
front[2] = sin(v) * cos(h);
h -= static_cast<float>(M_PI / 2.0f);
top[0] = cos(v) * cos(h);
top[1] = -sin(h);
top[2] = sin(v) * cos(h);
return true;
}
static int trylock() {
h = NULL;
posptr = rotptr = NULL;
DWORD pid=getProcess(L"hl2.exe");
if (!pid)
return false;
BYTE *mod=getModuleAddr(pid, L"client.dll");
if (!mod)
return false;
h=OpenProcess(PROCESS_VM_READ, false, pid);
if (!h)
return false;
// Check if we really have TF2 running
/*
position tuple: client.dll+0x4cd594 (x,y,z, float)
orientation tuple: client.dll+0x52529c (v,h float)
ID string: client.dll+0x47726b = "teamJet@@" (9 characters, text)
spawn state: client.dll+0x466b84 (0 when at main menu, 1 when spectator, 3 when at team selection menu, and 6 or 9 when on a team (depending on the team side and gamemode), byte)
*/
char sMagic[9];
if (!peekProc(mod + 0x47726b, sMagic, 9) || strncmp("teamJet@@", sMagic, 9)!=0)
return false;
// Remember addresses for later
posptr = mod + 0x4cd594;
rotptr = mod + 0x52529c;
stateptr = mod + 0x466b84;
float pos[3];
float rot[3];
float opos[3], top[3], front[3];
bool ok = peekProc(posptr, pos, 12) &&
peekProc(rotptr, rot, 12);
if (ok)
return calcout(pos, rot, opos, top, front);
// If it failed clean up
CloseHandle(h);
h = NULL;
return false;
}
static void unlock() {
if (h) {
CloseHandle(h);
h = NULL;
}
return;
}
static int fetch(float *pos, float *front, float *top) {
for (int i=0;i<3;i++)
pos[i] = front[i] = top[i] = 0;
float ipos[3], rot[3];
bool ok;
char state;
ok = peekProc(posptr, ipos, 12) &&
peekProc(rotptr, rot, 12) &&
peekProc(stateptr, &state, 1);
if (!ok)
return false;
// Check to see if you are in a server
if (state == 0 || state == 1 || state == 3)
return true; // Deactivate plugin
return calcout(ipos, rot, pos, front, top);
}
static MumblePlugin tf2plug = {
MUMBLE_PLUGIN_MAGIC,
L"Team Fortress 2 (Build 3755)",
L"Team Fortress 2",
about,
NULL,
trylock,
unlock,
fetch
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &tf2plug;
}

View File

@ -26,6 +26,8 @@ INIFILE=/etc/mumble-server.ini
DAEMON_OPTS="-ini $INIFILE"
MURMUR_DAEMON_START=0
MURMUR_USE_CAPABILITIES=0
MURMUR_LIMIT_NOFILE=0
MURMUR_LIMIT_RTPRIO=0
# Include murmur defaults if available
if [ -f /etc/default/$NAME ] ; then
@ -35,6 +37,13 @@ fi
. /lib/init/vars.sh
. /lib/lsb/init-functions
if [ "$MURMUR_LIMIT_NOFILE" -gt 0 ] ; then
ulimit -n $MURMUR_LIMIT_NOFILE
fi
if [ "$MURMUR_LIMIT_RTPRIO" -gt 0 ]; then
ulimit -r 1
fi
case "$1" in
start)
if [ "$MURMUR_DAEMON_START" != "1" ] ; then

View File

@ -31,41 +31,58 @@ my %filevars = ( 'sources' => 1, 'headers' => 1, 'rc_file' => 1, 'dist' => 1, 'f
system("rm mumble-*");
my @pro = ("main.pro", "src/mumble.pri");
adddir(".", \@pro);
my @pro = ("main.pro");
#, "src/mumble.pri");
#adddir(".", \@pro);
foreach my $pro (@pro) {
while (my $pro = shift @pro) {
open(F, $pro) or croak "Failed to open $pro";
print "Processing $pro\n";
$files{$pro}=1;
my $basedir=$pro;
$basedir =~ s/[^\/]+\Z//g;
my @vpath = ($basedir);
while(<F>) {
chomp();
if (/^\s*(\w+)\s*?[\+\-\*]{0,1}=\s*(.+)$/) {
if (/^include\((.+)\)/) {
my $f = $basedir . $1;
$f =~ s/(\/|\A)[^\/]+\/\.\.\//$1/g;
$f =~ s/(\/|\A)[^\/]+\/\.\.\//$1/g;
$f =~ s/(\/|\A)[^\/]+\/\.\.\//$1/g;
push @pro, $f;
} elsif (/^\s*(\w+)\s*?[\+\-\*]{0,1}=\s*(.+)$/) {
my ($var,$value)=(lc $1,$2);
switch ($var) {
case "version" {
croak "Versions don't match" if (defined($ver) && ($ver ne $value));
$ver=$value;
}
case "vpath" {
push @vpath,map { "$basedir$_/"} split(/\s/, $value);
}
case "subdirs" {
push @pro,map { my ($b,$p) = ($_,$_); $p =~ s/^.+\///g; "$basedir$b/$p.pro" } split(/\s/, $value);
}
case %filevars {
foreach my $f (split(/\s+/,$value)) {
$f =~ s/^.+\///g;
if (-f "${basedir}$f") {
$files{$basedir.$f}=1;
} else {
my $ok = 0;
foreach my $d ("", "speexbuild/", "speexbuild/speex/", "src/", "src/mumble/", "src/murmur/", "icons/", "scripts/", "plugins/", "overlay/", "overlay_gl/", "speex/libspeex/", "g15helper/") {
foreach my $d (@vpath) {
if (-f "$d$f") {
$files{$d.$f}=1;
$f = $d.$f;
$ok = 1;
last;
}
}
if (! $ok) {
croak "Failed to find $f";
croak "Failed to find $f in ".join(" ",@vpath);
} else {
if ($f =~ /\.\./) {
$f =~ s/(\/|\A)[^\/]+\/\.\.\//$1/g;
$f =~ s/(\/|\A)[^\/]+\/\.\.\//$1/g;
$f =~ s/(\/|\A)[^\/]+\/\.\.\//$1/g;
}
$files{$f}=1;
}
}
}
}
}
@ -80,7 +97,11 @@ while(<F>) {
if (/\<file\>(.+)<\/file\>/) {
$files{$1}=1;
} elsif (/\<file alias=\"(.+)\"\>/) {
$files{"icons/$1"}=1;
if ( -f "icons/$1") {
$files{"icons/$1"}=1;
} else {
$files{"samples/$1"}=1;
}
}
}
close(F);

2
scripts/scripts.pro Normal file
View File

@ -0,0 +1,2 @@
DIST *= murmur.pl murmur.ini murmur.ini.system murmur.init murmur.conf murmur.logrotate dbusauth.pl weblist.pl weblist.php icedemo.php murmur-user-wrapper
DIST *= mumble-overlay mumble.desktop mumble.protocol 11-input-mumble-policy.fdi

View File

@ -1,44 +1,44 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _OSINFO_H
#define _OSINFO_H
#include "murmur_pch.h"
class OSInfo {
public:
static QString getMacHash(const QHostAddress & = QHostAddress(QHostAddress::Any));
static QString getOS();
static QString getOSVersion();
static void fillXml(QDomDocument &doc, QDomElement &root, const QString &os = OSInfo::getOS(), const QString &osver = OSInfo::getOSVersion(), const QHostAddress & = QHostAddress(QHostAddress::Any));
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _OSINFO_H
#define _OSINFO_H
#include "murmur_pch.h"
class OSInfo {
public:
static QString getMacHash(const QHostAddress & = QHostAddress(QHostAddress::Any));
static QString getOS();
static QString getOSVersion();
static void fillXml(QDomDocument &doc, QDomElement &root, const QString &os = OSInfo::getOS(), const QString &osver = OSInfo::getOSVersion(), const QHostAddress & = QHostAddress(QHostAddress::Any));
};
#endif

View File

@ -1,88 +1,88 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <QtCore>
#include "Timer.h"
Timer::Timer() {
uiStart = now();
}
quint64 Timer::elapsed() const {
return now() - uiStart;
}
bool Timer::isElapsed(quint64 us) {
if (elapsed() > us) {
uiStart += us;
return true;
}
return false;
}
quint64 Timer::restart() {
quint64 n = now();
quint64 e = n - uiStart;
uiStart = n;
return e;
}
#if defined(Q_OS_WIN)
quint64 Timer::now() {
static quint64 f = 0LL;
if (f == 0LL) {
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
f = freq.QuadPart;
}
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
quint64 e = li.QuadPart;
return (e * 1000000LL) / f;
}
#elif defined(Q_OS_UNIX)
#include <sys/time.h>
quint64 Timer::now() {
struct timeval tv;
gettimeofday(&tv, NULL);
quint64 e= tv.tv_sec * 1000000LL;
e += tv.tv_usec;
return e;
}
#else
quint64 Timer::now() {
static QTime ticker;
quint64 elapsed = ticker.elapsed();
return elapsed * 1000LL;
}
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <QtCore>
#include "Timer.h"
Timer::Timer() {
uiStart = now();
}
quint64 Timer::elapsed() const {
return now() - uiStart;
}
bool Timer::isElapsed(quint64 us) {
if (elapsed() > us) {
uiStart += us;
return true;
}
return false;
}
quint64 Timer::restart() {
quint64 n = now();
quint64 e = n - uiStart;
uiStart = n;
return e;
}
#if defined(Q_OS_WIN)
quint64 Timer::now() {
static quint64 f = 0LL;
if (f == 0LL) {
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
f = freq.QuadPart;
}
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
quint64 e = li.QuadPart;
return (e * 1000000LL) / f;
}
#elif defined(Q_OS_UNIX)
#include <sys/time.h>
quint64 Timer::now() {
struct timeval tv;
gettimeofday(&tv, NULL);
quint64 e= tv.tv_sec * 1000000LL;
e += tv.tv_usec;
return e;
}
#else
quint64 Timer::now() {
static QTime ticker;
quint64 elapsed = ticker.elapsed();
return elapsed * 1000LL;
}
#endif

View File

@ -1,47 +1,47 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TIMER_H
#define _TIMER_H
// All timer resolutions are in microseconds.
struct Timer {
protected:
quint64 uiStart;
static quint64 now();
public:
Timer();
bool isElapsed(quint64 us);
quint64 elapsed() const;
quint64 restart();
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TIMER_H
#define _TIMER_H
// All timer resolutions are in microseconds.
struct Timer {
protected:
quint64 uiStart;
static quint64 now();
public:
Timer();
bool isElapsed(quint64 us);
quint64 elapsed() const;
quint64 restart();
};
#endif

View File

@ -1,7 +1,7 @@
include(../compiler.pri)
VERSION = 1.1.8
DIST = mumble.pro murmur.pro mumble.pri mumble.ico Message.h mumble_plugin.h PacketDataStream.h CryptState.h Timer.h Version.h OSInfo.h
DIST = mumble.pri Message.h PacketDataStream.h CryptState.h Timer.h Version.h OSInfo.h
CONFIG += qt thread debug_and_release warn_on
DEFINES *= MUMBLE_VERSION_STRING=$$VERSION

File diff suppressed because it is too large Load Diff

View File

@ -1,140 +1,140 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _AUDIOWIZARD_H
#define _AUDIOWIZARD_H
#include "Settings.h"
#include "AudioStats.h"
#include "AudioOutput.h"
#include "GlobalShortcut.h"
class CompletablePage : public QWizardPage {
Q_OBJECT
protected:
bool bComplete;
public:
CompletablePage(QWizard *p = NULL);
void setComplete(bool);
bool isComplete() const;
};
class AudioWizard: public QWizard {
private:
Q_OBJECT
Q_DISABLE_COPY(AudioWizard)
protected:
QComboBox *qcbInput, *qcbInputDevice;
QComboBox *qcbOutput, *qcbOutputDevice;
QCheckBox *qcbEcho;
QCheckBox *qcbPositional;
QSlider *qsOutputDelay;
QLabel *qlOutputDelay;
AudioBar *abAmplify;
QSlider *qsMaxAmp;
QWidget *qwVAD;
AudioBar *abVAD;
QRadioButton *qrAmplitude, *qrSNR, *qrPTT;
QSlider *qsMinVAD, *qsMaxVAD;
ShortcutKeyWidget *skwPTT;
bool bTransmitChanged;
QSlider *qsHoldtime;
QLabel *qlHoldtime;
QLabel *qlAudioPath;
QGraphicsView *qgvView;
QGraphicsScene *qgsScene;
QGraphicsItem *qgiSource;
QCheckBox *qcbHeadphone;
AudioOutputSample *aosSource;
float fAngle;
float fX, fY;
QCheckBox *qcbUsage;
CompletablePage *qwpIntro, *qwpDevice, *qwpVolume, *qwpTrigger, *qwpDeviceTuning, *qwpPositional, *qwpDone;
CompletablePage *introPage();
CompletablePage *devicePage();
CompletablePage *volumePage();
CompletablePage *triggerPage();
CompletablePage *deviceTuningPage();
CompletablePage *positionalPage();
CompletablePage *donePage();
Settings sOldSettings;
QTimer *ticker;
bool bInit;
bool bDelay;
int iMaxPeak;
int iTicks;
void restartAudio();
void playChord();
bool eventFilter(QObject *, QEvent *);
public slots:
void on_Input_activated(int);
void on_InputDevice_activated(int);
void on_Output_activated(int);
void on_OutputDevice_activated(int);
void on_OutputDelay_valueChanged(int);
void on_MaxAmp_valueChanged(int);
void on_Ticker_timeout();
void on_VADmin_valueChanged(int);
void on_VADmax_valueChanged(int);
void on_Holdtime_valueChanged(int);
void on_Amplitude_clicked(bool);
void on_SNR_clicked(bool);
void on_PTT_clicked(bool);
void on_Echo_clicked(bool);
void on_Headphone_clicked(bool);
void on_Positional_clicked(bool);
void on_PTTKey_keySet(bool);
void showPage(int);
void updateTriggerWidgets(bool);
public:
AudioWizard(QWidget *parent);
void reject();
void accept();
bool validateCurrentPage();
virtual int nextId() const;
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _AUDIOWIZARD_H
#define _AUDIOWIZARD_H
#include "Settings.h"
#include "AudioStats.h"
#include "AudioOutput.h"
#include "GlobalShortcut.h"
class CompletablePage : public QWizardPage {
Q_OBJECT
protected:
bool bComplete;
public:
CompletablePage(QWizard *p = NULL);
void setComplete(bool);
bool isComplete() const;
};
class AudioWizard: public QWizard {
private:
Q_OBJECT
Q_DISABLE_COPY(AudioWizard)
protected:
QComboBox *qcbInput, *qcbInputDevice;
QComboBox *qcbOutput, *qcbOutputDevice;
QCheckBox *qcbEcho;
QCheckBox *qcbPositional;
QSlider *qsOutputDelay;
QLabel *qlOutputDelay;
AudioBar *abAmplify;
QSlider *qsMaxAmp;
QWidget *qwVAD;
AudioBar *abVAD;
QRadioButton *qrAmplitude, *qrSNR, *qrPTT;
QSlider *qsMinVAD, *qsMaxVAD;
ShortcutKeyWidget *skwPTT;
bool bTransmitChanged;
QSlider *qsHoldtime;
QLabel *qlHoldtime;
QLabel *qlAudioPath;
QGraphicsView *qgvView;
QGraphicsScene *qgsScene;
QGraphicsItem *qgiSource;
QCheckBox *qcbHeadphone;
AudioOutputSample *aosSource;
float fAngle;
float fX, fY;
QCheckBox *qcbUsage;
CompletablePage *qwpIntro, *qwpDevice, *qwpVolume, *qwpTrigger, *qwpDeviceTuning, *qwpPositional, *qwpDone;
CompletablePage *introPage();
CompletablePage *devicePage();
CompletablePage *volumePage();
CompletablePage *triggerPage();
CompletablePage *deviceTuningPage();
CompletablePage *positionalPage();
CompletablePage *donePage();
Settings sOldSettings;
QTimer *ticker;
bool bInit;
bool bDelay;
int iMaxPeak;
int iTicks;
void restartAudio();
void playChord();
bool eventFilter(QObject *, QEvent *);
public slots:
void on_Input_activated(int);
void on_InputDevice_activated(int);
void on_Output_activated(int);
void on_OutputDevice_activated(int);
void on_OutputDelay_valueChanged(int);
void on_MaxAmp_valueChanged(int);
void on_Ticker_timeout();
void on_VADmin_valueChanged(int);
void on_VADmax_valueChanged(int);
void on_Holdtime_valueChanged(int);
void on_Amplitude_clicked(bool);
void on_SNR_clicked(bool);
void on_PTT_clicked(bool);
void on_Echo_clicked(bool);
void on_Headphone_clicked(bool);
void on_Positional_clicked(bool);
void on_PTTKey_keySet(bool);
void showPage(int);
void updateTriggerWidgets(bool);
public:
AudioWizard(QWidget *parent);
void reject();
void accept();
bool validateCurrentPage();
virtual int nextId() const;
};
#endif

View File

@ -1,57 +1,57 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DBUS_H
#define _DBUS_H
#include "mumble_pch.hpp"
class MumbleDBus : public QDBusAbstractAdaptor {
private:
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "net.sourceforge.mumble.Mumble")
Q_DISABLE_COPY(MumbleDBus)
Q_PROPERTY(bool mute READ isSelfMuted WRITE setSelfMuted)
Q_PROPERTY(bool deaf READ isSelfDeaf WRITE setSelfDeaf)
public:
MumbleDBus(QObject *parent);
public slots:
void openUrl(const QString &url, const QDBusMessage &);
void getCurrentUrl(const QDBusMessage &);
void focus();
void setSelfMuted(bool mute);
void setSelfDeaf(bool deafen);
bool isSelfMuted();
bool isSelfDeaf();
};
#else
class MumbleDBus;
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DBUS_H
#define _DBUS_H
#include "mumble_pch.hpp"
class MumbleDBus : public QDBusAbstractAdaptor {
private:
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "net.sourceforge.mumble.Mumble")
Q_DISABLE_COPY(MumbleDBus)
Q_PROPERTY(bool mute READ isSelfMuted WRITE setSelfMuted)
Q_PROPERTY(bool deaf READ isSelfDeaf WRITE setSelfDeaf)
public:
MumbleDBus(QObject *parent);
public slots:
void openUrl(const QString &url, const QDBusMessage &);
void getCurrentUrl(const QDBusMessage &);
void focus();
void setSelfMuted(bool mute);
void setSelfDeaf(bool deafen);
bool isSelfMuted();
bool isSelfDeaf();
};
#else
class MumbleDBus;
#endif

View File

@ -1,461 +1,461 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "GlobalShortcut.h"
#include "MainWindow.h"
#include "Global.h"
GlobalShortcutEngine *GlobalShortcutEngine::engine = NULL;
static ConfigWidget *GlobalShortcutConfigDialogNew(Settings &st) {
return new GlobalShortcutConfig(st);
}
static ConfigRegistrar registrar(1200, GlobalShortcutConfigDialogNew);
ShortcutKeyWidget::ShortcutKeyWidget(QWidget *p) : QLineEdit(p) {
setReadOnly(true);
clearFocus();
bModified = false;
displayKeys();
}
QList<QVariant> ShortcutKeyWidget::getShortcut() const {
return qlButtons;
}
void ShortcutKeyWidget::setShortcut(const QList<QVariant> &buttons) {
qlButtons = buttons;
displayKeys();
}
void ShortcutKeyWidget::focusInEvent(QFocusEvent *) {
setText(tr("Press Shortcut"));
QPalette pal=parentWidget()->palette();
pal.setColor(QPalette::Base, pal.color(QPalette::Base).dark(120));
setPalette(pal);
setForegroundRole(QPalette::Button);
GlobalShortcutEngine::engine->resetMap();
connect(GlobalShortcutEngine::engine, SIGNAL(buttonPressed(bool)), this, SLOT(updateKeys(bool)));
installEventFilter(this);
}
void ShortcutKeyWidget::focusOutEvent(QFocusEvent *e) {
if ((e->reason() == Qt::TabFocusReason) || (e->reason() == Qt::BacktabFocusReason))
return;
setPalette(parentWidget()->palette());
clearFocus();
disconnect(GlobalShortcutEngine::engine, SIGNAL(buttonPressed(bool)), this, SLOT(updateKeys(bool)));
displayKeys();
removeEventFilter(this);
}
bool ShortcutKeyWidget::eventFilter(QObject *, QEvent *evt) {
if ((evt->type() == QEvent::KeyPress) || (evt->type() == QEvent::MouseButtonPress))
return true;
return false;
}
void ShortcutKeyWidget::mouseDoubleClickEvent(QMouseEvent *) {
bModified = true;
qlButtons.clear();
clearFocus();
displayKeys();
}
void ShortcutKeyWidget::updateKeys(bool last) {
qlButtons = GlobalShortcutEngine::engine->qlActiveButtons;
bModified = true;
if (qlButtons.isEmpty())
return;
if (last)
clearFocus();
else
displayKeys();
}
void ShortcutKeyWidget::displayKeys() {
QStringList keys;
foreach(QVariant button, qlButtons) {
QString id = GlobalShortcutEngine::engine->buttonName(button);
if (! id.isEmpty())
keys << id;
}
setText(keys.join(QLatin1String(" + ")));
emit keySet(keys.count() > 0);
}
ShortcutActionWidget::ShortcutActionWidget(QWidget *p) : QComboBox(p) {
int idx = 0;
insertItem(idx, tr("Unassigned"));
setItemData(idx, -1);
idx++;
bool expert = true;
while (p) {
GlobalShortcutConfig *gsc = qobject_cast<GlobalShortcutConfig *>(p);
if (gsc) {
expert = gsc->bExpert;
break;
}
p = p->parentWidget();
}
foreach(GlobalShortcut *gs, GlobalShortcutEngine::engine->qmShortcuts) {
if (expert || ! gs->bExpert) {
insertItem(idx, gs->name);
setItemData(idx, gs->idx);
if (! gs->qsToolTip.isEmpty())
setItemData(idx, gs->qsToolTip, Qt::ToolTipRole);
if (! gs->qsWhatsThis.isEmpty())
setItemData(idx, gs->qsWhatsThis, Qt::WhatsThisRole);
idx++;
}
}
}
void ShortcutActionWidget::setIndex(int idx) {
setCurrentIndex(findData(idx));
}
int ShortcutActionWidget::index() const {
return itemData(currentIndex()).toInt();
}
ShortcutDelegate::ShortcutDelegate(QObject *p) : QStyledItemDelegate(p) {
QItemEditorFactory *factory = new QItemEditorFactory;
QItemEditorCreatorBase *shortcutCreator = new QStandardItemEditorCreator<ShortcutKeyWidget>();
QItemEditorCreatorBase *indexCreator = new QStandardItemEditorCreator<ShortcutActionWidget>();
factory->registerEditor(QVariant::List, shortcutCreator);
factory->registerEditor(QVariant::Int, indexCreator);
setItemEditorFactory(factory);
}
ShortcutDelegate::~ShortcutDelegate() {
delete itemEditorFactory();
setItemEditorFactory(NULL);
}
QString ShortcutDelegate::displayText(const QVariant &item, const QLocale &loc) const {
if (item.type() == QVariant::List)
return GlobalShortcutEngine::buttonText(item.toList());
else if (item.type() == QVariant::Int) {
GlobalShortcut *gs = GlobalShortcutEngine::engine->qmShortcuts.value(item.toInt());
if (gs)
return gs->name;
else
return tr("Unassigned");
}
return QStyledItemDelegate::displayText(item,loc);
}
GlobalShortcutConfig::GlobalShortcutConfig(Settings &st) : ConfigWidget(st) {
setupUi(this);
bool canSuppress = GlobalShortcutEngine::engine->canSuppress();
qtwShortcuts->setColumnCount(canSuppress ? 3 : 2);
qtwShortcuts->setItemDelegate(new ShortcutDelegate(qtwShortcuts));
}
void GlobalShortcutConfig::on_qpbAdd_clicked(bool) {
Shortcut sc;
sc.iIndex = -1;
sc.bSuppress = false;
qlShortcuts << sc;
reload();
}
void GlobalShortcutConfig::on_qpbRemove_clicked(bool) {
QTreeWidgetItem *qtwi = qtwShortcuts->currentItem();
if (! qtwi)
return;
qlShortcuts.removeAt(qtwShortcuts->indexOfTopLevelItem(qtwi));
delete qtwi;
}
void GlobalShortcutConfig::on_qtwShortcuts_currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) {
qpbRemove->setEnabled(item ? true : false);
}
void GlobalShortcutConfig::on_qtwShortcuts_itemChanged(QTreeWidgetItem *item, int) {
int idx = qtwShortcuts->indexOfTopLevelItem(item);
Shortcut &sc = qlShortcuts[idx];
sc.iIndex = item->data(0, Qt::DisplayRole).toInt();
sc.qlButtons = item->data(1, Qt::DisplayRole).toList();
sc.bSuppress = item->checkState(2) == Qt::Checked;
}
QString GlobalShortcutConfig::title() const {
return tr("Shortcuts");
}
QIcon GlobalShortcutConfig::icon() const {
return QIcon(QLatin1String("skin:config_shortcuts.png"));
}
void GlobalShortcutConfig::load(const Settings &r) {
qlShortcuts = r.qlShortcuts;
bExpert = r.bExpert;
reload();
}
void GlobalShortcutConfig::save() const {
s.qlShortcuts = qlShortcuts;
}
QTreeWidgetItem *GlobalShortcutConfig::itemForShortcut(const Shortcut &sc) const {
QTreeWidgetItem *item = new QTreeWidgetItem();
item->setData(0, Qt::DisplayRole, sc.iIndex);
item->setData(1, Qt::DisplayRole, sc.qlButtons);
item->setCheckState(2, sc.bSuppress ? Qt::Checked : Qt::Unchecked);
item->setFlags(item->flags() | Qt::ItemIsEditable);
::GlobalShortcut *gs = GlobalShortcutEngine::engine->qmShortcuts.value(sc.iIndex);
if (gs) {
if (! gs->qsToolTip.isEmpty())
item->setData(0, Qt::ToolTipRole, gs->qsToolTip);
if (! gs->qsWhatsThis.isEmpty())
item->setData(0, Qt::WhatsThisRole, gs->qsWhatsThis);
}
item->setData(1, Qt::ToolTipRole, tr("Shortcut button combination."));
item->setData(1, Qt::WhatsThisRole, tr("<b>This is the global shortcut key combination.</b><br />"
"Double-click this field and then the desired key/button combo "
"to rebind."));
item->setData(2, Qt::ToolTipRole, tr("Suppress keys from other applications"));
item->setData(2, Qt::WhatsThisRole, tr("<b>This hides the button presses from other applications.</b><br />"
"Enabling this will hide the button (or the last button of a multi-button combo) "
"from other applications. Note that not all buttons can be suppressed."));
return item;
}
void GlobalShortcutConfig::reload() {
qStableSort(qlShortcuts);
qtwShortcuts->clear();
foreach(const Shortcut &sc, qlShortcuts) {
QTreeWidgetItem *item = itemForShortcut(sc);
::GlobalShortcut *gs = GlobalShortcutEngine::engine->qmShortcuts.value(sc.iIndex);
qtwShortcuts->addTopLevelItem(item);
if (gs && gs->bExpert && ! bExpert)
item->setHidden(true);
}
}
void GlobalShortcutConfig::accept() const {
GlobalShortcutEngine::engine->bNeedRemap = true;
GlobalShortcutEngine::engine->needRemap();
}
bool GlobalShortcutConfig::expert(bool exp) {
bExpert = exp;
reload();
return true;
}
GlobalShortcutEngine::GlobalShortcutEngine(QObject *p) : QThread(p) {
bNeedRemap = true;
needRemap();
}
GlobalShortcutEngine::~GlobalShortcutEngine() {
QSet<ShortcutKey *> qs;
foreach(const QList<ShortcutKey*> &ql, qlShortcutList)
qs += ql.toSet();
foreach(ShortcutKey *sk, qs)
delete sk;
}
void GlobalShortcutEngine::remap() {
bNeedRemap = false;
QSet<ShortcutKey *> qs;
foreach(const QList<ShortcutKey*> &ql, qlShortcutList)
qs += ql.toSet();
foreach(ShortcutKey *sk, qs)
delete sk;
qlButtonList.clear();
qlShortcutList.clear();
qlDownButtons.clear();
foreach(const Shortcut &sc, g.s.qlShortcuts) {
GlobalShortcut *gs = qmShortcuts.value(sc.iIndex);
if (gs && ! sc.qlButtons.isEmpty()) {
ShortcutKey *sk = new ShortcutKey;
sk->s = sc;
sk->iNumUp = sc.qlButtons.count();
sk->gs = gs;
foreach(const QVariant &button, sc.qlButtons) {
int idx = qlButtonList.indexOf(button);
if (idx == -1) {
qlButtonList << button;
qlShortcutList << QList<ShortcutKey *>();
idx = qlButtonList.count() - 1;
}
qlShortcutList[idx] << sk;
}
}
}
}
void GlobalShortcutEngine::run() {
}
bool GlobalShortcutEngine::canSuppress() {
return false;
}
void GlobalShortcutEngine::resetMap() {
tReset.restart();
qlActiveButtons.clear();
}
void GlobalShortcutEngine::needRemap() {
}
bool GlobalShortcutEngine::handleButton(const QVariant &button, bool down) {
bool already = qlDownButtons.contains(button);
if (already == down)
return qlSuppressed.contains(button);
if (down)
qlDownButtons << button;
else
qlDownButtons.removeAll(button);
if (tReset.elapsed() > 100000) {
if (down) {
qlActiveButtons.removeAll(button);
qlActiveButtons << button;
}
emit buttonPressed(! down);
}
int idx = qlButtonList.indexOf(button);
if (idx == -1)
return false;
bool suppress = false;
foreach(ShortcutKey *sk, qlShortcutList.at(idx)) {
if (down) {
sk->iNumUp--;
if (sk->iNumUp == 0) {
GlobalShortcut *gs = sk->gs;
if (sk->s.bSuppress) {
suppress = true;
qlSuppressed << button;
}
if (! gs->bActive) {
gs->bActive = true;
emit gs->triggered(sk->gs->bActive);
emit gs->down();
}
} else if (sk->iNumUp < 0) {
sk->iNumUp = 0;
}
} else {
if (qlSuppressed.contains(button)) {
suppress = true;
qlSuppressed.removeAll(button);
}
sk->iNumUp++;
if (sk->iNumUp == 1) {
GlobalShortcut *gs = sk->gs;
if (gs->bActive) {
gs->bActive = false;
emit gs->triggered(sk->gs->bActive);
emit gs->up();
}
} else if (sk->iNumUp > sk->s.qlButtons.count()) {
sk->iNumUp = sk->s.qlButtons.count();
}
}
}
return suppress;
}
void GlobalShortcutEngine::add(GlobalShortcut *gs) {
if (! GlobalShortcutEngine::engine)
GlobalShortcutEngine::engine = GlobalShortcutEngine::platformInit();
GlobalShortcutEngine::engine->qmShortcuts.insert(gs->idx, gs);
GlobalShortcutEngine::engine->bNeedRemap = true;
GlobalShortcutEngine::engine->needRemap();
}
void GlobalShortcutEngine::remove(GlobalShortcut *gs) {
engine->qmShortcuts.remove(gs->idx);
engine->bNeedRemap = true;
engine->needRemap();
if (engine->qmShortcuts.isEmpty()) {
delete engine;
GlobalShortcutEngine::engine = NULL;
}
}
QString GlobalShortcutEngine::buttonText(const QList<QVariant> &list) {
QStringList keys;
foreach(QVariant button, list) {
QString id = GlobalShortcutEngine::engine->buttonName(button);
if (! id.isEmpty())
keys << id;
}
return keys.join(QLatin1String(" + "));
}
GlobalShortcut::GlobalShortcut(QObject *p, int index, QString qsName, bool expert) : QObject(p) {
idx = index;
name=qsName;
bExpert = expert;
bActive = false;
GlobalShortcutEngine::add(this);
}
GlobalShortcut::~GlobalShortcut() {
GlobalShortcutEngine::remove(this);
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "GlobalShortcut.h"
#include "MainWindow.h"
#include "Global.h"
GlobalShortcutEngine *GlobalShortcutEngine::engine = NULL;
static ConfigWidget *GlobalShortcutConfigDialogNew(Settings &st) {
return new GlobalShortcutConfig(st);
}
static ConfigRegistrar registrar(1200, GlobalShortcutConfigDialogNew);
ShortcutKeyWidget::ShortcutKeyWidget(QWidget *p) : QLineEdit(p) {
setReadOnly(true);
clearFocus();
bModified = false;
displayKeys();
}
QList<QVariant> ShortcutKeyWidget::getShortcut() const {
return qlButtons;
}
void ShortcutKeyWidget::setShortcut(const QList<QVariant> &buttons) {
qlButtons = buttons;
displayKeys();
}
void ShortcutKeyWidget::focusInEvent(QFocusEvent *) {
setText(tr("Press Shortcut"));
QPalette pal=parentWidget()->palette();
pal.setColor(QPalette::Base, pal.color(QPalette::Base).dark(120));
setPalette(pal);
setForegroundRole(QPalette::Button);
GlobalShortcutEngine::engine->resetMap();
connect(GlobalShortcutEngine::engine, SIGNAL(buttonPressed(bool)), this, SLOT(updateKeys(bool)));
installEventFilter(this);
}
void ShortcutKeyWidget::focusOutEvent(QFocusEvent *e) {
if ((e->reason() == Qt::TabFocusReason) || (e->reason() == Qt::BacktabFocusReason))
return;
setPalette(parentWidget()->palette());
clearFocus();
disconnect(GlobalShortcutEngine::engine, SIGNAL(buttonPressed(bool)), this, SLOT(updateKeys(bool)));
displayKeys();
removeEventFilter(this);
}
bool ShortcutKeyWidget::eventFilter(QObject *, QEvent *evt) {
if ((evt->type() == QEvent::KeyPress) || (evt->type() == QEvent::MouseButtonPress))
return true;
return false;
}
void ShortcutKeyWidget::mouseDoubleClickEvent(QMouseEvent *) {
bModified = true;
qlButtons.clear();
clearFocus();
displayKeys();
}
void ShortcutKeyWidget::updateKeys(bool last) {
qlButtons = GlobalShortcutEngine::engine->qlActiveButtons;
bModified = true;
if (qlButtons.isEmpty())
return;
if (last)
clearFocus();
else
displayKeys();
}
void ShortcutKeyWidget::displayKeys() {
QStringList keys;
foreach(QVariant button, qlButtons) {
QString id = GlobalShortcutEngine::engine->buttonName(button);
if (! id.isEmpty())
keys << id;
}
setText(keys.join(QLatin1String(" + ")));
emit keySet(keys.count() > 0);
}
ShortcutActionWidget::ShortcutActionWidget(QWidget *p) : QComboBox(p) {
int idx = 0;
insertItem(idx, tr("Unassigned"));
setItemData(idx, -1);
idx++;
bool expert = true;
while (p) {
GlobalShortcutConfig *gsc = qobject_cast<GlobalShortcutConfig *>(p);
if (gsc) {
expert = gsc->bExpert;
break;
}
p = p->parentWidget();
}
foreach(GlobalShortcut *gs, GlobalShortcutEngine::engine->qmShortcuts) {
if (expert || ! gs->bExpert) {
insertItem(idx, gs->name);
setItemData(idx, gs->idx);
if (! gs->qsToolTip.isEmpty())
setItemData(idx, gs->qsToolTip, Qt::ToolTipRole);
if (! gs->qsWhatsThis.isEmpty())
setItemData(idx, gs->qsWhatsThis, Qt::WhatsThisRole);
idx++;
}
}
}
void ShortcutActionWidget::setIndex(int idx) {
setCurrentIndex(findData(idx));
}
int ShortcutActionWidget::index() const {
return itemData(currentIndex()).toInt();
}
ShortcutDelegate::ShortcutDelegate(QObject *p) : QStyledItemDelegate(p) {
QItemEditorFactory *factory = new QItemEditorFactory;
QItemEditorCreatorBase *shortcutCreator = new QStandardItemEditorCreator<ShortcutKeyWidget>();
QItemEditorCreatorBase *indexCreator = new QStandardItemEditorCreator<ShortcutActionWidget>();
factory->registerEditor(QVariant::List, shortcutCreator);
factory->registerEditor(QVariant::Int, indexCreator);
setItemEditorFactory(factory);
}
ShortcutDelegate::~ShortcutDelegate() {
delete itemEditorFactory();
setItemEditorFactory(NULL);
}
QString ShortcutDelegate::displayText(const QVariant &item, const QLocale &loc) const {
if (item.type() == QVariant::List)
return GlobalShortcutEngine::buttonText(item.toList());
else if (item.type() == QVariant::Int) {
GlobalShortcut *gs = GlobalShortcutEngine::engine->qmShortcuts.value(item.toInt());
if (gs)
return gs->name;
else
return tr("Unassigned");
}
return QStyledItemDelegate::displayText(item,loc);
}
GlobalShortcutConfig::GlobalShortcutConfig(Settings &st) : ConfigWidget(st) {
setupUi(this);
bool canSuppress = GlobalShortcutEngine::engine->canSuppress();
qtwShortcuts->setColumnCount(canSuppress ? 3 : 2);
qtwShortcuts->setItemDelegate(new ShortcutDelegate(qtwShortcuts));
}
void GlobalShortcutConfig::on_qpbAdd_clicked(bool) {
Shortcut sc;
sc.iIndex = -1;
sc.bSuppress = false;
qlShortcuts << sc;
reload();
}
void GlobalShortcutConfig::on_qpbRemove_clicked(bool) {
QTreeWidgetItem *qtwi = qtwShortcuts->currentItem();
if (! qtwi)
return;
qlShortcuts.removeAt(qtwShortcuts->indexOfTopLevelItem(qtwi));
delete qtwi;
}
void GlobalShortcutConfig::on_qtwShortcuts_currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) {
qpbRemove->setEnabled(item ? true : false);
}
void GlobalShortcutConfig::on_qtwShortcuts_itemChanged(QTreeWidgetItem *item, int) {
int idx = qtwShortcuts->indexOfTopLevelItem(item);
Shortcut &sc = qlShortcuts[idx];
sc.iIndex = item->data(0, Qt::DisplayRole).toInt();
sc.qlButtons = item->data(1, Qt::DisplayRole).toList();
sc.bSuppress = item->checkState(2) == Qt::Checked;
}
QString GlobalShortcutConfig::title() const {
return tr("Shortcuts");
}
QIcon GlobalShortcutConfig::icon() const {
return QIcon(QLatin1String("skin:config_shortcuts.png"));
}
void GlobalShortcutConfig::load(const Settings &r) {
qlShortcuts = r.qlShortcuts;
bExpert = r.bExpert;
reload();
}
void GlobalShortcutConfig::save() const {
s.qlShortcuts = qlShortcuts;
}
QTreeWidgetItem *GlobalShortcutConfig::itemForShortcut(const Shortcut &sc) const {
QTreeWidgetItem *item = new QTreeWidgetItem();
item->setData(0, Qt::DisplayRole, sc.iIndex);
item->setData(1, Qt::DisplayRole, sc.qlButtons);
item->setCheckState(2, sc.bSuppress ? Qt::Checked : Qt::Unchecked);
item->setFlags(item->flags() | Qt::ItemIsEditable);
::GlobalShortcut *gs = GlobalShortcutEngine::engine->qmShortcuts.value(sc.iIndex);
if (gs) {
if (! gs->qsToolTip.isEmpty())
item->setData(0, Qt::ToolTipRole, gs->qsToolTip);
if (! gs->qsWhatsThis.isEmpty())
item->setData(0, Qt::WhatsThisRole, gs->qsWhatsThis);
}
item->setData(1, Qt::ToolTipRole, tr("Shortcut button combination."));
item->setData(1, Qt::WhatsThisRole, tr("<b>This is the global shortcut key combination.</b><br />"
"Double-click this field and then the desired key/button combo "
"to rebind."));
item->setData(2, Qt::ToolTipRole, tr("Suppress keys from other applications"));
item->setData(2, Qt::WhatsThisRole, tr("<b>This hides the button presses from other applications.</b><br />"
"Enabling this will hide the button (or the last button of a multi-button combo) "
"from other applications. Note that not all buttons can be suppressed."));
return item;
}
void GlobalShortcutConfig::reload() {
qStableSort(qlShortcuts);
qtwShortcuts->clear();
foreach(const Shortcut &sc, qlShortcuts) {
QTreeWidgetItem *item = itemForShortcut(sc);
::GlobalShortcut *gs = GlobalShortcutEngine::engine->qmShortcuts.value(sc.iIndex);
qtwShortcuts->addTopLevelItem(item);
if (gs && gs->bExpert && ! bExpert)
item->setHidden(true);
}
}
void GlobalShortcutConfig::accept() const {
GlobalShortcutEngine::engine->bNeedRemap = true;
GlobalShortcutEngine::engine->needRemap();
}
bool GlobalShortcutConfig::expert(bool exp) {
bExpert = exp;
reload();
return true;
}
GlobalShortcutEngine::GlobalShortcutEngine(QObject *p) : QThread(p) {
bNeedRemap = true;
needRemap();
}
GlobalShortcutEngine::~GlobalShortcutEngine() {
QSet<ShortcutKey *> qs;
foreach(const QList<ShortcutKey*> &ql, qlShortcutList)
qs += ql.toSet();
foreach(ShortcutKey *sk, qs)
delete sk;
}
void GlobalShortcutEngine::remap() {
bNeedRemap = false;
QSet<ShortcutKey *> qs;
foreach(const QList<ShortcutKey*> &ql, qlShortcutList)
qs += ql.toSet();
foreach(ShortcutKey *sk, qs)
delete sk;
qlButtonList.clear();
qlShortcutList.clear();
qlDownButtons.clear();
foreach(const Shortcut &sc, g.s.qlShortcuts) {
GlobalShortcut *gs = qmShortcuts.value(sc.iIndex);
if (gs && ! sc.qlButtons.isEmpty()) {
ShortcutKey *sk = new ShortcutKey;
sk->s = sc;
sk->iNumUp = sc.qlButtons.count();
sk->gs = gs;
foreach(const QVariant &button, sc.qlButtons) {
int idx = qlButtonList.indexOf(button);
if (idx == -1) {
qlButtonList << button;
qlShortcutList << QList<ShortcutKey *>();
idx = qlButtonList.count() - 1;
}
qlShortcutList[idx] << sk;
}
}
}
}
void GlobalShortcutEngine::run() {
}
bool GlobalShortcutEngine::canSuppress() {
return false;
}
void GlobalShortcutEngine::resetMap() {
tReset.restart();
qlActiveButtons.clear();
}
void GlobalShortcutEngine::needRemap() {
}
bool GlobalShortcutEngine::handleButton(const QVariant &button, bool down) {
bool already = qlDownButtons.contains(button);
if (already == down)
return qlSuppressed.contains(button);
if (down)
qlDownButtons << button;
else
qlDownButtons.removeAll(button);
if (tReset.elapsed() > 100000) {
if (down) {
qlActiveButtons.removeAll(button);
qlActiveButtons << button;
}
emit buttonPressed(! down);
}
int idx = qlButtonList.indexOf(button);
if (idx == -1)
return false;
bool suppress = false;
foreach(ShortcutKey *sk, qlShortcutList.at(idx)) {
if (down) {
sk->iNumUp--;
if (sk->iNumUp == 0) {
GlobalShortcut *gs = sk->gs;
if (sk->s.bSuppress) {
suppress = true;
qlSuppressed << button;
}
if (! gs->bActive) {
gs->bActive = true;
emit gs->triggered(sk->gs->bActive);
emit gs->down();
}
} else if (sk->iNumUp < 0) {
sk->iNumUp = 0;
}
} else {
if (qlSuppressed.contains(button)) {
suppress = true;
qlSuppressed.removeAll(button);
}
sk->iNumUp++;
if (sk->iNumUp == 1) {
GlobalShortcut *gs = sk->gs;
if (gs->bActive) {
gs->bActive = false;
emit gs->triggered(sk->gs->bActive);
emit gs->up();
}
} else if (sk->iNumUp > sk->s.qlButtons.count()) {
sk->iNumUp = sk->s.qlButtons.count();
}
}
}
return suppress;
}
void GlobalShortcutEngine::add(GlobalShortcut *gs) {
if (! GlobalShortcutEngine::engine)
GlobalShortcutEngine::engine = GlobalShortcutEngine::platformInit();
GlobalShortcutEngine::engine->qmShortcuts.insert(gs->idx, gs);
GlobalShortcutEngine::engine->bNeedRemap = true;
GlobalShortcutEngine::engine->needRemap();
}
void GlobalShortcutEngine::remove(GlobalShortcut *gs) {
engine->qmShortcuts.remove(gs->idx);
engine->bNeedRemap = true;
engine->needRemap();
if (engine->qmShortcuts.isEmpty()) {
delete engine;
GlobalShortcutEngine::engine = NULL;
}
}
QString GlobalShortcutEngine::buttonText(const QList<QVariant> &list) {
QStringList keys;
foreach(QVariant button, list) {
QString id = GlobalShortcutEngine::engine->buttonName(button);
if (! id.isEmpty())
keys << id;
}
return keys.join(QLatin1String(" + "));
}
GlobalShortcut::GlobalShortcut(QObject *p, int index, QString qsName, bool expert) : QObject(p) {
idx = index;
name=qsName;
bExpert = expert;
bActive = false;
GlobalShortcutEngine::add(this);
}
GlobalShortcut::~GlobalShortcut() {
GlobalShortcutEngine::remove(this);
}

View File

@ -1,300 +1,300 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "GlobalShortcut_win.h"
#include "MainWindow.h"
#include "Global.h"
#undef FAILED
#define FAILED(Status) (static_cast<HRESULT>(Status)<0)
#define DX_SAMPLE_BUFFER_SIZE 512
uint qHash(const GUID &a) {
uint val = a.Data1 ^ a.Data2 ^ a.Data3;
for (int i=0;i<8;i++)
val += a.Data4[i];
return val;
}
GlobalShortcutEngine *GlobalShortcutEngine::platformInit() {
return new GlobalShortcutWin();
}
GlobalShortcutWin::GlobalShortcutWin() {
pDI = NULL;
moveToThread(this);
start(QThread::LowestPriority);
}
GlobalShortcutWin::~GlobalShortcutWin() {
quit();
wait();
}
void GlobalShortcutWin::run() {
HMODULE hSelf;
HRESULT hr;
QTimer *timer;
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, reinterpret_cast<void **>(&pDI), NULL))) {
qFatal("GlobalShortcutWin: Failed to create d8input");
return;
}
/*
* Wait for MainWindow's constructor to finish before we enumerate DirectInput devices.
* We need to do this because adding a new device requires a Window handle. (SetCooperativeLevel())
*/
while (! g.mw)
this->msleep(20);
pDI->EnumDevices(DI8DEVCLASS_ALL, EnumDevicesCB, static_cast<void *>(this), DIEDFL_ALLDEVICES);
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (wchar_t *) &HookKeyboard, &hSelf);
hhKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookKeyboard, hSelf, 0);
hhMouse = SetWindowsHookEx(WH_MOUSE_LL, HookMouse, hSelf, 0);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timeTicked()));
timer->start(20);
setPriority(QThread::TimeCriticalPriority);
exec();
UnhookWindowsHookEx(hhKeyboard);
UnhookWindowsHookEx(hhMouse);
foreach(InputDevice *id, qhInputDevices) {
if (id->pDID) {
id->pDID->Unacquire();
id->pDID->Release();
}
}
pDI->Release();
}
LRESULT CALLBACK GlobalShortcutWin::HookKeyboard(int nCode, WPARAM wParam, LPARAM lParam) {
GlobalShortcutWin *gsw=static_cast<GlobalShortcutWin *>(engine);
KBDLLHOOKSTRUCT *key=reinterpret_cast<KBDLLHOOKSTRUCT *>(lParam);
if (nCode >= 0) {
QList<QVariant> ql;
unsigned int keyid = static_cast<unsigned int>((key->scanCode << 8) | 0x4);
if (key->flags & LLKHF_EXTENDED)
keyid |= 0x8000U;
ql << keyid;
ql << QVariant(QUuid(GUID_SysKeyboard));
if (gsw->handleButton(ql, !(key->flags & LLKHF_UP)))
return 1;
}
return CallNextHookEx(gsw->hhKeyboard, nCode, wParam, lParam);
}
LRESULT CALLBACK GlobalShortcutWin::HookMouse(int nCode, WPARAM wParam, LPARAM lParam) {
GlobalShortcutWin *gsw=static_cast<GlobalShortcutWin *>(engine);
MSLLHOOKSTRUCT *mouse=reinterpret_cast<MSLLHOOKSTRUCT *>(lParam);
if (nCode >= 0) {
bool down = false;
unsigned int btn = 0;
switch (wParam) {
case WM_LBUTTONDOWN:
down = true;
case WM_LBUTTONUP:
btn = 3;
break;
case WM_RBUTTONDOWN:
down = true;
case WM_RBUTTONUP:
btn = 4;
break;
case WM_MBUTTONDOWN:
down = true;
case WM_MBUTTONUP:
btn = 5;
break;
case WM_XBUTTONDOWN:
down = true;
case WM_XBUTTONUP:
btn = 5 + (mouse->mouseData >> 16);
default:
break;
}
if (btn) {
QList<QVariant> ql;
ql << static_cast<unsigned int>((btn << 8) | 0x4);
ql << QVariant(QUuid(GUID_SysMouse));
if (gsw->handleButton(ql, down))
return 1;
}
}
return CallNextHookEx(gsw->hhMouse, nCode, wParam, lParam);
}
BOOL CALLBACK GlobalShortcutWin::EnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) {
InputDevice *id=static_cast<InputDevice *>(pvRef);
QString name = QString::fromUtf16(reinterpret_cast<const ushort *>(lpddoi->tszName));
id->qhNames[lpddoi->dwType] = name;
return DIENUM_CONTINUE;
}
BOOL GlobalShortcutWin::EnumDevicesCB(LPCDIDEVICEINSTANCE pdidi, LPVOID pContext) {
GlobalShortcutWin *cbgsw=static_cast<GlobalShortcutWin *>(pContext);
HRESULT hr;
QString name = QString::fromUtf16(reinterpret_cast<const ushort *>(pdidi->tszProductName));
QString sname = QString::fromUtf16(reinterpret_cast<const ushort *>(pdidi->tszInstanceName));
InputDevice *id = new InputDevice;
id->name = name;
id->guid = pdidi->guidInstance;
id->vguid = QVariant(QUuid(id->guid).toString());
if (FAILED(hr = cbgsw->pDI->CreateDevice(pdidi->guidInstance, &id->pDID, NULL)))
qFatal("GlobalShortcutWin: CreateDevice: %lx", hr);
if (FAILED(hr = id->pDID->EnumObjects(EnumDeviceObjectsCallback, static_cast<void *>(id), DIDFT_BUTTON)))
qFatal("GlobalShortcutWin: EnumObjects: %lx", hr);
if (id->qhNames.count() > 0) {
QList<DWORD> types = id->qhNames.keys();
qSort(types);
int nbuttons = types.count();
DIOBJECTDATAFORMAT *rgodf = new DIOBJECTDATAFORMAT[nbuttons];
DIDATAFORMAT df;
ZeroMemory(&df, sizeof(df));
df.dwSize = sizeof(df);
df.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
df.dwFlags=DIDF_ABSAXIS;
df.dwDataSize = (nbuttons + 3) & (~0x3);
df.dwNumObjs = nbuttons;
df.rgodf = rgodf;
for (int i=0;i<nbuttons;i++) {
ZeroMemory(& rgodf[i], sizeof(DIOBJECTDATAFORMAT));
DWORD dwType = types[i];
DWORD dwOfs = i;
rgodf[i].dwOfs = dwOfs;
rgodf[i].dwType = dwType;
id->qhOfsToType[dwOfs] = dwType;
id->qhTypeToOfs[dwType] = dwOfs;
}
if (FAILED(hr = id->pDID->SetCooperativeLevel(g.mw->winId(), DISCL_NONEXCLUSIVE|DISCL_BACKGROUND)))
qFatal("GlobalShortcutWin: SetCooperativeLevel: %lx", hr);
if (FAILED(hr = id->pDID->SetDataFormat(&df)))
qFatal("GlobalShortcutWin: SetDataFormat: %lx", hr);
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = DX_SAMPLE_BUFFER_SIZE;
if (FAILED(hr = id->pDID->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
qFatal("GlobalShortcutWin::SetProperty");
qWarning("Adding device %s %s %s:%d", qPrintable(QUuid(id->guid).toString()),qPrintable(name),qPrintable(sname),id->qhNames.count());
cbgsw->qhInputDevices[id->guid] = id;
} else {
id->pDID->Release();
delete(id);
}
return DIENUM_CONTINUE;
}
void GlobalShortcutWin::timeTicked() {
if (bNeedRemap)
remap();
foreach(InputDevice *id, qhInputDevices) {
DIDEVICEOBJECTDATA rgdod[DX_SAMPLE_BUFFER_SIZE];
DWORD dwItems = DX_SAMPLE_BUFFER_SIZE;
HRESULT hr;
id->pDID->Acquire();
id->pDID->Poll();
hr = id->pDID->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), rgdod, &dwItems, 0);
if (FAILED(hr))
continue;
if (dwItems <= 0)
continue;
for (DWORD j=0; j<dwItems; j++) {
QList<QVariant> ql;
quint32 uiType = id->qhOfsToType.value(rgdod[j].dwOfs);
ql << uiType;
ql << id->vguid;
handleButton(ql, rgdod[j].dwData & 0x80);
}
}
}
QString GlobalShortcutWin::buttonName(const QVariant &v) {
GlobalShortcutWin *gsw = static_cast<GlobalShortcutWin *>(GlobalShortcutEngine::engine);
const QList<QVariant> &sublist = v.toList();
if (sublist.count() != 2)
return QString();
bool ok = false;
DWORD type = sublist.at(0).toUInt(&ok);
QUuid guid(sublist.at(1).toString());
if (guid.isNull() || (!ok))
return QString();
QString device=guid.toString();
QString name=QLatin1String("Unknown");
InputDevice *id = gsw->qhInputDevices.value(guid);
if (guid == GUID_SysMouse)
device=QLatin1String("M:");
else if (guid == GUID_SysKeyboard)
device=QLatin1String("K:");
else if (id)
device=id->name+QLatin1String(":");
if (id) {
name=id->qhNames.value(type);
}
return device+name;
}
bool GlobalShortcutWin::canSuppress() {
return true;
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "GlobalShortcut_win.h"
#include "MainWindow.h"
#include "Global.h"
#undef FAILED
#define FAILED(Status) (static_cast<HRESULT>(Status)<0)
#define DX_SAMPLE_BUFFER_SIZE 512
uint qHash(const GUID &a) {
uint val = a.Data1 ^ a.Data2 ^ a.Data3;
for (int i=0;i<8;i++)
val += a.Data4[i];
return val;
}
GlobalShortcutEngine *GlobalShortcutEngine::platformInit() {
return new GlobalShortcutWin();
}
GlobalShortcutWin::GlobalShortcutWin() {
pDI = NULL;
moveToThread(this);
start(QThread::LowestPriority);
}
GlobalShortcutWin::~GlobalShortcutWin() {
quit();
wait();
}
void GlobalShortcutWin::run() {
HMODULE hSelf;
HRESULT hr;
QTimer *timer;
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, reinterpret_cast<void **>(&pDI), NULL))) {
qFatal("GlobalShortcutWin: Failed to create d8input");
return;
}
/*
* Wait for MainWindow's constructor to finish before we enumerate DirectInput devices.
* We need to do this because adding a new device requires a Window handle. (SetCooperativeLevel())
*/
while (! g.mw)
this->msleep(20);
pDI->EnumDevices(DI8DEVCLASS_ALL, EnumDevicesCB, static_cast<void *>(this), DIEDFL_ALLDEVICES);
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (wchar_t *) &HookKeyboard, &hSelf);
hhKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, HookKeyboard, hSelf, 0);
hhMouse = SetWindowsHookEx(WH_MOUSE_LL, HookMouse, hSelf, 0);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timeTicked()));
timer->start(20);
setPriority(QThread::TimeCriticalPriority);
exec();
UnhookWindowsHookEx(hhKeyboard);
UnhookWindowsHookEx(hhMouse);
foreach(InputDevice *id, qhInputDevices) {
if (id->pDID) {
id->pDID->Unacquire();
id->pDID->Release();
}
}
pDI->Release();
}
LRESULT CALLBACK GlobalShortcutWin::HookKeyboard(int nCode, WPARAM wParam, LPARAM lParam) {
GlobalShortcutWin *gsw=static_cast<GlobalShortcutWin *>(engine);
KBDLLHOOKSTRUCT *key=reinterpret_cast<KBDLLHOOKSTRUCT *>(lParam);
if (nCode >= 0) {
QList<QVariant> ql;
unsigned int keyid = static_cast<unsigned int>((key->scanCode << 8) | 0x4);
if (key->flags & LLKHF_EXTENDED)
keyid |= 0x8000U;
ql << keyid;
ql << QVariant(QUuid(GUID_SysKeyboard));
if (gsw->handleButton(ql, !(key->flags & LLKHF_UP)))
return 1;
}
return CallNextHookEx(gsw->hhKeyboard, nCode, wParam, lParam);
}
LRESULT CALLBACK GlobalShortcutWin::HookMouse(int nCode, WPARAM wParam, LPARAM lParam) {
GlobalShortcutWin *gsw=static_cast<GlobalShortcutWin *>(engine);
MSLLHOOKSTRUCT *mouse=reinterpret_cast<MSLLHOOKSTRUCT *>(lParam);
if (nCode >= 0) {
bool down = false;
unsigned int btn = 0;
switch (wParam) {
case WM_LBUTTONDOWN:
down = true;
case WM_LBUTTONUP:
btn = 3;
break;
case WM_RBUTTONDOWN:
down = true;
case WM_RBUTTONUP:
btn = 4;
break;
case WM_MBUTTONDOWN:
down = true;
case WM_MBUTTONUP:
btn = 5;
break;
case WM_XBUTTONDOWN:
down = true;
case WM_XBUTTONUP:
btn = 5 + (mouse->mouseData >> 16);
default:
break;
}
if (btn) {
QList<QVariant> ql;
ql << static_cast<unsigned int>((btn << 8) | 0x4);
ql << QVariant(QUuid(GUID_SysMouse));
if (gsw->handleButton(ql, down))
return 1;
}
}
return CallNextHookEx(gsw->hhMouse, nCode, wParam, lParam);
}
BOOL CALLBACK GlobalShortcutWin::EnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) {
InputDevice *id=static_cast<InputDevice *>(pvRef);
QString name = QString::fromUtf16(reinterpret_cast<const ushort *>(lpddoi->tszName));
id->qhNames[lpddoi->dwType] = name;
return DIENUM_CONTINUE;
}
BOOL GlobalShortcutWin::EnumDevicesCB(LPCDIDEVICEINSTANCE pdidi, LPVOID pContext) {
GlobalShortcutWin *cbgsw=static_cast<GlobalShortcutWin *>(pContext);
HRESULT hr;
QString name = QString::fromUtf16(reinterpret_cast<const ushort *>(pdidi->tszProductName));
QString sname = QString::fromUtf16(reinterpret_cast<const ushort *>(pdidi->tszInstanceName));
InputDevice *id = new InputDevice;
id->name = name;
id->guid = pdidi->guidInstance;
id->vguid = QVariant(QUuid(id->guid).toString());
if (FAILED(hr = cbgsw->pDI->CreateDevice(pdidi->guidInstance, &id->pDID, NULL)))
qFatal("GlobalShortcutWin: CreateDevice: %lx", hr);
if (FAILED(hr = id->pDID->EnumObjects(EnumDeviceObjectsCallback, static_cast<void *>(id), DIDFT_BUTTON)))
qFatal("GlobalShortcutWin: EnumObjects: %lx", hr);
if (id->qhNames.count() > 0) {
QList<DWORD> types = id->qhNames.keys();
qSort(types);
int nbuttons = types.count();
DIOBJECTDATAFORMAT *rgodf = new DIOBJECTDATAFORMAT[nbuttons];
DIDATAFORMAT df;
ZeroMemory(&df, sizeof(df));
df.dwSize = sizeof(df);
df.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
df.dwFlags=DIDF_ABSAXIS;
df.dwDataSize = (nbuttons + 3) & (~0x3);
df.dwNumObjs = nbuttons;
df.rgodf = rgodf;
for (int i=0;i<nbuttons;i++) {
ZeroMemory(& rgodf[i], sizeof(DIOBJECTDATAFORMAT));
DWORD dwType = types[i];
DWORD dwOfs = i;
rgodf[i].dwOfs = dwOfs;
rgodf[i].dwType = dwType;
id->qhOfsToType[dwOfs] = dwType;
id->qhTypeToOfs[dwType] = dwOfs;
}
if (FAILED(hr = id->pDID->SetCooperativeLevel(g.mw->winId(), DISCL_NONEXCLUSIVE|DISCL_BACKGROUND)))
qFatal("GlobalShortcutWin: SetCooperativeLevel: %lx", hr);
if (FAILED(hr = id->pDID->SetDataFormat(&df)))
qFatal("GlobalShortcutWin: SetDataFormat: %lx", hr);
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = DX_SAMPLE_BUFFER_SIZE;
if (FAILED(hr = id->pDID->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
qFatal("GlobalShortcutWin::SetProperty");
qWarning("Adding device %s %s %s:%d", qPrintable(QUuid(id->guid).toString()),qPrintable(name),qPrintable(sname),id->qhNames.count());
cbgsw->qhInputDevices[id->guid] = id;
} else {
id->pDID->Release();
delete(id);
}
return DIENUM_CONTINUE;
}
void GlobalShortcutWin::timeTicked() {
if (bNeedRemap)
remap();
foreach(InputDevice *id, qhInputDevices) {
DIDEVICEOBJECTDATA rgdod[DX_SAMPLE_BUFFER_SIZE];
DWORD dwItems = DX_SAMPLE_BUFFER_SIZE;
HRESULT hr;
id->pDID->Acquire();
id->pDID->Poll();
hr = id->pDID->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), rgdod, &dwItems, 0);
if (FAILED(hr))
continue;
if (dwItems <= 0)
continue;
for (DWORD j=0; j<dwItems; j++) {
QList<QVariant> ql;
quint32 uiType = id->qhOfsToType.value(rgdod[j].dwOfs);
ql << uiType;
ql << id->vguid;
handleButton(ql, rgdod[j].dwData & 0x80);
}
}
}
QString GlobalShortcutWin::buttonName(const QVariant &v) {
GlobalShortcutWin *gsw = static_cast<GlobalShortcutWin *>(GlobalShortcutEngine::engine);
const QList<QVariant> &sublist = v.toList();
if (sublist.count() != 2)
return QString();
bool ok = false;
DWORD type = sublist.at(0).toUInt(&ok);
QUuid guid(sublist.at(1).toString());
if (guid.isNull() || (!ok))
return QString();
QString device=guid.toString();
QString name=QLatin1String("Unknown");
InputDevice *id = gsw->qhInputDevices.value(guid);
if (guid == GUID_SysMouse)
device=QLatin1String("M:");
else if (guid == GUID_SysKeyboard)
device=QLatin1String("K:");
else if (id)
device=id->name+QLatin1String(":");
if (id) {
name=id->qhNames.value(type);
}
return device+name;
}
bool GlobalShortcutWin::canSuppress() {
return true;
}

View File

@ -1,57 +1,57 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOOKCONFIG_H
#define _LOOKCONFIG_H
#include "ConfigDialog.h"
#include "ui_LookConfig.h"
class LookConfig : public ConfigWidget, Ui::LookConfig {
private:
Q_OBJECT
Q_DISABLE_COPY(LookConfig)
public:
LookConfig(Settings &st);
virtual QString title() const;
virtual QIcon icon() const;
public slots:
void accept() const;
void save() const;
void load(const Settings &r);
bool expert(bool);
void on_qpbSkinFile_clicked(bool);
void on_qcbExpert_clicked(bool);
};
#else
class LookConfig;
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOOKCONFIG_H
#define _LOOKCONFIG_H
#include "ConfigDialog.h"
#include "ui_LookConfig.h"
class LookConfig : public ConfigWidget, Ui::LookConfig {
private:
Q_OBJECT
Q_DISABLE_COPY(LookConfig)
public:
LookConfig(Settings &st);
virtual QString title() const;
virtual QIcon icon() const;
public slots:
void accept() const;
void save() const;
void load(const Settings &r);
bool expert(bool);
void on_qpbSkinFile_clicked(bool);
void on_qcbExpert_clicked(bool);
};
#else
class LookConfig;
#endif

View File

@ -227,10 +227,6 @@ void MainWindow::createActions() {
qstiIcon->setToolTip(tr("Mumble"));
qstiIcon->setObjectName(QLatin1String("Icon"));
qmTray = new QMenu(this);
qmTray->addAction(tr("&Quit"), this, SLOT(on_qaQuit_triggered()));
qstiIcon->setContextMenu(qmTray);
updateTrayIcon();
#ifndef Q_OS_MAC
qstiIcon->show();
#endif
@ -291,6 +287,14 @@ void MainWindow::setupGui() {
qtvPlayers->header()->restoreState(g.s.qbaHeaderState);
setupView(false);
qmTray = new QMenu(this);
qmTray->addAction(qaAudioMute);
qmTray->addAction(qaAudioDeaf);
qmTray->addSeparator();
qmTray->addAction(qaQuit);
qstiIcon->setContextMenu(qmTray);
updateTrayIcon();
}
MainWindow::~MainWindow() {

View File

@ -1,311 +1,311 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "MumbleScript.h"
#include "Global.h"
#include "Log.h"
#include "ServerHandler.h"
ScriptPlayer::ScriptPlayer(ClientPlayer *p) : QObject(p) {
}
QString ScriptPlayer::getName() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->qsName;
}
unsigned int ScriptPlayer::getSession() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->uiSession;
}
int ScriptPlayer::getId() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->iId;
}
QScriptValue ScriptPlayer::getChannel() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
Channel *c = cp->cChannel;
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
return qse->newQObject(ms->qmChannels.value(Channel::get(0)), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
}
bool ScriptPlayer::isMute() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->bMute || cp->bDeaf;
}
bool ScriptPlayer::isDeaf() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->bDeaf;
}
void ScriptPlayer::setMute(bool m) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
qWarning("Want to set mute to %d", m);
}
void ScriptPlayer::setDeaf(bool m) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
qWarning("Want to set deaf to %d", m);
}
void ScriptPlayer::setChannel(const QScriptValue &sv) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
ScriptChannel *sc = qobject_cast<ScriptChannel *>(sv.toQObject());
if (sc) {
Channel *c = qobject_cast<Channel *>(sc->parent());
qWarning("Want to set channel to %d", c->iId);
} else {
context()->throwError(QScriptContext::ReferenceError, QLatin1String("argument is not a channel"));
}
}
void ScriptPlayer::sendMessage(const QString &msg) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
qWarning("Want to send msg %s", qPrintable(msg));
}
ScriptChannel::ScriptChannel(Channel *c) : QObject(c) {
}
QString ScriptChannel::getName() const {
Channel *c = qobject_cast<Channel *>(parent());
return c->qsName;
}
int ScriptChannel::getId() const {
Channel *c = qobject_cast<Channel *>(parent());
return c->iId;
}
int ScriptChannel::getParent() const {
Channel *c = qobject_cast<Channel *>(parent());
return c->cParent ? c->cParent->iId : -1;
}
void ScriptChannel::setName(const QString &name) {
Channel *c = qobject_cast<Channel *>(parent());
qWarning() << "ScriptChannel::setName" << name;
}
void ScriptChannel::setParent(int id) {
Channel *c = qobject_cast<Channel *>(parent());
qWarning() << "ScriptChannel::setParent" << id;
}
void ScriptChannel::sendMessage(const QString &msg, bool tree) {
Channel *c = qobject_cast<Channel *>(parent());
qWarning() << "ScriptChannel::sendMessage" << msg << tree;
}
QScriptValue ScriptChannel::getPlayers() const {
Channel *c = qobject_cast<Channel *>(parent());
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
QScriptValue a = engine()->newArray(c->qlPlayers.count());
quint32 idx = 0;
foreach(Player *p, c->qlPlayers) {
ClientPlayer *cp = static_cast<ClientPlayer *>(p);
QScriptValue sv = qse->newQObject(ms->qmPlayers.value(cp), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
a.setProperty(idx, sv);
idx++;
}
return a;
}
QScriptValue ScriptChannel::getChildren() const {
Channel *c = qobject_cast<Channel *>(parent());
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
QScriptValue a = engine()->newArray(c->qlChannels.count());
quint32 idx = 0;
foreach(Channel *child, c->qlChannels) {
QScriptValue sv = qse->newQObject(ms->qmChannels.value(child), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
a.setProperty(idx, sv);
idx++;
}
return a;
}
ScriptServer::ScriptServer(QObject *p) : QObject(p) {
}
QScriptValue ScriptServer::getRoot() const {
qWarning("getRoot())");
Channel *c = qobject_cast<Channel *>(parent());
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
return qse->newQObject(ms->qmChannels.value(Channel::get(0)), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
}
QScriptValue ScriptServer::loadUi(const QString &name) {
QUiLoader *ui = new QUiLoader();
qWarning() << "ScriptServer::loadUi" << name;
return QScriptValue();
}
void ScriptServer::sendMsg(const QString &keyword, const QStringList &args) {
qWarning() << "ScriptServer::sendMsg" << keyword << args;
}
QScriptValue mumbleScriptPrint(QScriptContext *context, QScriptEngine *engine) {
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(QLatin1String(" "));
result.append(context->argument(i).toString());
}
qWarning() << result;
g.l->log(Log::ScriptError, result, MumbleScript::tr("Script Print"));
return engine->undefinedValue();
}
MumbleScript::MumbleScript(MumbleScripts *p) : QObject(p) {
qseEngine = new QScriptEngine(this);
ssServer = new ScriptServer(qseEngine);
bLocal = true;
qseEngine->globalObject().setProperty(QLatin1String("server"), qseEngine->newQObject(ssServer, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject), QScriptValue::ReadOnly | QScriptValue::Undeletable);
qseEngine->globalObject().setProperty(QLatin1String("print"), qseEngine->newFunction(mumbleScriptPrint), QScriptValue::ReadOnly | QScriptValue::Undeletable);
connect(qseEngine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(errorHandler(const QScriptValue &)));
connect(g.sh, SIGNAL(disconnected(QString)), ssServer, SIGNAL(disconnected(QString)));
}
MumbleScript::~MumbleScript() {
foreach(ScriptPlayer *sp, qmPlayers)
delete sp;
}
void MumbleScript::load(const QString &) {
}
void MumbleScript::evaluate(const QString &code) {
qseEngine->evaluate(code);
if (qseEngine->hasUncaughtException())
errorHandler(qseEngine->uncaughtException());
}
void MumbleScript::errorHandler(const QScriptValue &exception) {
g.l->log(Log::ScriptError, exception.toString() + qseEngine->uncaughtExceptionBacktrace().join(QLatin1String("\n")), tr("Script Error"));
g.ms->qlScripts.removeAll(this);
delete this;
}
void MumbleScript::addPlayer(ClientPlayer *p) {
connect(p, SIGNAL(destroyed(QObject *)), this, SLOT(playerDeleted(QObject *)));
ScriptPlayer *sp = new ScriptPlayer(p);
qmPlayers.insert(p, sp);
emit ssServer->newPlayer(qseEngine->newQObject(sp, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject));
}
void MumbleScript::movePlayer(ClientPlayer *p) {
ScriptPlayer *sp = qmPlayers.value(p);
emit sp->moved();
}
void MumbleScript::addChannel(Channel *c) {
connect(c, SIGNAL(destroyed(QObject *)), this, SLOT(channelDeleted(QObject *)));
ScriptChannel *sc = new ScriptChannel(c);
qmChannels.insert(c, sc);
emit ssServer->newChannel(qseEngine->newQObject(sc, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject));
}
void MumbleScript::moveChannel(Channel *c) {
ScriptChannel *sc = qmChannels.value(c);
emit sc->moved();
}
void MumbleScript::playerDeleted(QObject *obj) {
ClientPlayer *cp=qobject_cast<ClientPlayer *>(obj);
qmPlayers.remove(cp);
}
void MumbleScript::channelDeleted(QObject *obj) {
Channel *c=qobject_cast<Channel *>(obj);
qmChannels.remove(c);
}
void MumbleScript::connected() {
emit ssServer->connected();
}
MumbleScripts::MumbleScripts(QObject *p) : QObject(p) {
}
MumbleScripts::~MumbleScripts() {
foreach(MumbleScript *ms, qlScripts)
delete ms;
}
void MumbleScripts::createEvaluate(const QString &qs) {
MumbleScript *ms = new MumbleScript(this);
qlScripts << ms;
ms->evaluate(qs);
}
void MumbleScripts::addPlayer(ClientPlayer *p) {
foreach(MumbleScript *ms, qlScripts)
ms->addPlayer(p);
}
void MumbleScripts::movePlayer(ClientPlayer *p) {
foreach(MumbleScript *ms, qlScripts)
ms->movePlayer(p);
}
void MumbleScripts::addChannel(Channel *c) {
foreach(MumbleScript *ms, qlScripts)
ms->addChannel(c);
}
void MumbleScripts::moveChannel(Channel *c) {
foreach(MumbleScript *ms, qlScripts)
ms->moveChannel(c);
}
void MumbleScripts::connected() {
foreach(MumbleScript *ms, qlScripts)
ms->connected();
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "MumbleScript.h"
#include "Global.h"
#include "Log.h"
#include "ServerHandler.h"
ScriptPlayer::ScriptPlayer(ClientPlayer *p) : QObject(p) {
}
QString ScriptPlayer::getName() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->qsName;
}
unsigned int ScriptPlayer::getSession() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->uiSession;
}
int ScriptPlayer::getId() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->iId;
}
QScriptValue ScriptPlayer::getChannel() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
Channel *c = cp->cChannel;
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
return qse->newQObject(ms->qmChannels.value(Channel::get(0)), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
}
bool ScriptPlayer::isMute() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->bMute || cp->bDeaf;
}
bool ScriptPlayer::isDeaf() const {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
return cp->bDeaf;
}
void ScriptPlayer::setMute(bool m) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
qWarning("Want to set mute to %d", m);
}
void ScriptPlayer::setDeaf(bool m) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
qWarning("Want to set deaf to %d", m);
}
void ScriptPlayer::setChannel(const QScriptValue &sv) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
ScriptChannel *sc = qobject_cast<ScriptChannel *>(sv.toQObject());
if (sc) {
Channel *c = qobject_cast<Channel *>(sc->parent());
qWarning("Want to set channel to %d", c->iId);
} else {
context()->throwError(QScriptContext::ReferenceError, QLatin1String("argument is not a channel"));
}
}
void ScriptPlayer::sendMessage(const QString &msg) {
ClientPlayer *cp = qobject_cast<ClientPlayer *>(parent());
qWarning("Want to send msg %s", qPrintable(msg));
}
ScriptChannel::ScriptChannel(Channel *c) : QObject(c) {
}
QString ScriptChannel::getName() const {
Channel *c = qobject_cast<Channel *>(parent());
return c->qsName;
}
int ScriptChannel::getId() const {
Channel *c = qobject_cast<Channel *>(parent());
return c->iId;
}
int ScriptChannel::getParent() const {
Channel *c = qobject_cast<Channel *>(parent());
return c->cParent ? c->cParent->iId : -1;
}
void ScriptChannel::setName(const QString &name) {
Channel *c = qobject_cast<Channel *>(parent());
qWarning() << "ScriptChannel::setName" << name;
}
void ScriptChannel::setParent(int id) {
Channel *c = qobject_cast<Channel *>(parent());
qWarning() << "ScriptChannel::setParent" << id;
}
void ScriptChannel::sendMessage(const QString &msg, bool tree) {
Channel *c = qobject_cast<Channel *>(parent());
qWarning() << "ScriptChannel::sendMessage" << msg << tree;
}
QScriptValue ScriptChannel::getPlayers() const {
Channel *c = qobject_cast<Channel *>(parent());
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
QScriptValue a = engine()->newArray(c->qlPlayers.count());
quint32 idx = 0;
foreach(Player *p, c->qlPlayers) {
ClientPlayer *cp = static_cast<ClientPlayer *>(p);
QScriptValue sv = qse->newQObject(ms->qmPlayers.value(cp), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
a.setProperty(idx, sv);
idx++;
}
return a;
}
QScriptValue ScriptChannel::getChildren() const {
Channel *c = qobject_cast<Channel *>(parent());
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
QScriptValue a = engine()->newArray(c->qlChannels.count());
quint32 idx = 0;
foreach(Channel *child, c->qlChannels) {
QScriptValue sv = qse->newQObject(ms->qmChannels.value(child), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
a.setProperty(idx, sv);
idx++;
}
return a;
}
ScriptServer::ScriptServer(QObject *p) : QObject(p) {
}
QScriptValue ScriptServer::getRoot() const {
qWarning("getRoot())");
Channel *c = qobject_cast<Channel *>(parent());
QScriptEngine *qse = engine();
MumbleScript *ms = qobject_cast<MumbleScript *>(qse->parent());
return qse->newQObject(ms->qmChannels.value(Channel::get(0)), QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);
}
QScriptValue ScriptServer::loadUi(const QString &name) {
QUiLoader *ui = new QUiLoader();
qWarning() << "ScriptServer::loadUi" << name;
return QScriptValue();
}
void ScriptServer::sendMsg(const QString &keyword, const QStringList &args) {
qWarning() << "ScriptServer::sendMsg" << keyword << args;
}
QScriptValue mumbleScriptPrint(QScriptContext *context, QScriptEngine *engine) {
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(QLatin1String(" "));
result.append(context->argument(i).toString());
}
qWarning() << result;
g.l->log(Log::ScriptError, result, MumbleScript::tr("Script Print"));
return engine->undefinedValue();
}
MumbleScript::MumbleScript(MumbleScripts *p) : QObject(p) {
qseEngine = new QScriptEngine(this);
ssServer = new ScriptServer(qseEngine);
bLocal = true;
qseEngine->globalObject().setProperty(QLatin1String("server"), qseEngine->newQObject(ssServer, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject), QScriptValue::ReadOnly | QScriptValue::Undeletable);
qseEngine->globalObject().setProperty(QLatin1String("print"), qseEngine->newFunction(mumbleScriptPrint), QScriptValue::ReadOnly | QScriptValue::Undeletable);
connect(qseEngine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(errorHandler(const QScriptValue &)));
connect(g.sh, SIGNAL(disconnected(QString)), ssServer, SIGNAL(disconnected(QString)));
}
MumbleScript::~MumbleScript() {
foreach(ScriptPlayer *sp, qmPlayers)
delete sp;
}
void MumbleScript::load(const QString &) {
}
void MumbleScript::evaluate(const QString &code) {
qseEngine->evaluate(code);
if (qseEngine->hasUncaughtException())
errorHandler(qseEngine->uncaughtException());
}
void MumbleScript::errorHandler(const QScriptValue &exception) {
g.l->log(Log::ScriptError, exception.toString() + qseEngine->uncaughtExceptionBacktrace().join(QLatin1String("\n")), tr("Script Error"));
g.ms->qlScripts.removeAll(this);
delete this;
}
void MumbleScript::addPlayer(ClientPlayer *p) {
connect(p, SIGNAL(destroyed(QObject *)), this, SLOT(playerDeleted(QObject *)));
ScriptPlayer *sp = new ScriptPlayer(p);
qmPlayers.insert(p, sp);
emit ssServer->newPlayer(qseEngine->newQObject(sp, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject));
}
void MumbleScript::movePlayer(ClientPlayer *p) {
ScriptPlayer *sp = qmPlayers.value(p);
emit sp->moved();
}
void MumbleScript::addChannel(Channel *c) {
connect(c, SIGNAL(destroyed(QObject *)), this, SLOT(channelDeleted(QObject *)));
ScriptChannel *sc = new ScriptChannel(c);
qmChannels.insert(c, sc);
emit ssServer->newChannel(qseEngine->newQObject(sc, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject));
}
void MumbleScript::moveChannel(Channel *c) {
ScriptChannel *sc = qmChannels.value(c);
emit sc->moved();
}
void MumbleScript::playerDeleted(QObject *obj) {
ClientPlayer *cp=qobject_cast<ClientPlayer *>(obj);
qmPlayers.remove(cp);
}
void MumbleScript::channelDeleted(QObject *obj) {
Channel *c=qobject_cast<Channel *>(obj);
qmChannels.remove(c);
}
void MumbleScript::connected() {
emit ssServer->connected();
}
MumbleScripts::MumbleScripts(QObject *p) : QObject(p) {
}
MumbleScripts::~MumbleScripts() {
foreach(MumbleScript *ms, qlScripts)
delete ms;
}
void MumbleScripts::createEvaluate(const QString &qs) {
MumbleScript *ms = new MumbleScript(this);
qlScripts << ms;
ms->evaluate(qs);
}
void MumbleScripts::addPlayer(ClientPlayer *p) {
foreach(MumbleScript *ms, qlScripts)
ms->addPlayer(p);
}
void MumbleScripts::movePlayer(ClientPlayer *p) {
foreach(MumbleScript *ms, qlScripts)
ms->movePlayer(p);
}
void MumbleScripts::addChannel(Channel *c) {
foreach(MumbleScript *ms, qlScripts)
ms->addChannel(c);
}
void MumbleScripts::moveChannel(Channel *c) {
foreach(MumbleScript *ms, qlScripts)
ms->moveChannel(c);
}
void MumbleScripts::connected() {
foreach(MumbleScript *ms, qlScripts)
ms->connected();
}

View File

@ -1,160 +1,160 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCRIPT_H
#define _SCRIPT_H
#include "mumble_pch.hpp"
#include "Player.h"
#include "Channel.h"
class ScriptPlayer;
class ScriptChannel;
class MumbleScript;
class MumbleScripts;
class ScriptPlayer : public QObject, protected QScriptable {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(ScriptPlayer)
Q_PROPERTY(QString name READ getName)
Q_PROPERTY(unsigned int session READ getSession)
Q_PROPERTY(int id READ getId)
Q_PROPERTY(QScriptValue channel READ getChannel WRITE setChannel)
Q_PROPERTY(bool mute READ isMute WRITE setMute)
Q_PROPERTY(bool deaf READ isDeaf WRITE setDeaf)
public:
ScriptPlayer(ClientPlayer *p);
QString getName() const;
unsigned int getSession() const;
int getId() const;
QScriptValue getChannel() const;
bool isMute() const;
bool isDeaf() const;
public slots:
void setMute(bool);
void setDeaf(bool);
void setChannel(const QScriptValue &);
void sendMessage(const QString &);
signals:
void moved();
};
class ScriptChannel : public QObject, protected QScriptable {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(ScriptChannel)
Q_PROPERTY(QString name READ getName WRITE setName)
Q_PROPERTY(int id READ getId)
Q_PROPERTY(int parent READ getParent WRITE setParent)
Q_PROPERTY(QScriptValue children READ getChildren)
Q_PROPERTY(QScriptValue players READ getPlayers)
public:
ScriptChannel(Channel *c);
QString getName() const;
int getId() const;
int getParent() const;
public slots:
void setName(const QString &);
void setParent(int);
QScriptValue getPlayers() const;
QScriptValue getChildren() const;
void sendMessage(const QString &, bool);
signals:
void moved();
};
class ScriptServer : public QObject, protected QScriptable {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(ScriptServer)
Q_PROPERTY(QScriptValue playerContextMenu)
Q_PROPERTY(QScriptValue channelContextMenu)
Q_PROPERTY(QScriptValue msgHandler)
Q_PROPERTY(QScriptValue root READ getRoot)
public:
ScriptServer(QObject *p);
QScriptValue getRoot() const;
public slots:
QScriptValue loadUi(const QString &);
void sendMsg(const QString &, const QStringList &);
signals:
void newPlayer(QScriptValue);
void newChannel(QScriptValue);
void connected();
void disconnected(QString reason);
};
class MumbleScript : public QObject {
Q_OBJECT
Q_DISABLE_COPY(MumbleScript)
public:
QScriptEngine *qseEngine;
ScriptServer *ssServer;
QString qsFilename;
QMap<ClientPlayer *, ScriptPlayer *> qmPlayers;
QMap<Channel *, ScriptChannel *> qmChannels;
QMap<QString, QByteArray> qmResources;
bool bLocal;
MumbleScript(MumbleScripts *p);
~MumbleScript();
void load(const QString &source);
void evaluate(const QString &code);
void addPlayer(ClientPlayer *p);
void movePlayer(ClientPlayer *p);
void addChannel(Channel *c);
void moveChannel(Channel *c);
void connected();
public slots:
void playerDeleted(QObject *);
void channelDeleted(QObject *);
void errorHandler(const QScriptValue &);
};
class MumbleScripts : public QObject {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(MumbleScripts)
protected:
QList<MumbleScript *> qlScripts;
public:
MumbleScripts(QObject *p);
~MumbleScripts();
void createEvaluate(const QString &code);
void addPlayer(ClientPlayer *p);
void movePlayer(ClientPlayer *p);
void addChannel(Channel *c);
void moveChannel(Channel *c);
void connected();
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCRIPT_H
#define _SCRIPT_H
#include "mumble_pch.hpp"
#include "Player.h"
#include "Channel.h"
class ScriptPlayer;
class ScriptChannel;
class MumbleScript;
class MumbleScripts;
class ScriptPlayer : public QObject, protected QScriptable {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(ScriptPlayer)
Q_PROPERTY(QString name READ getName)
Q_PROPERTY(unsigned int session READ getSession)
Q_PROPERTY(int id READ getId)
Q_PROPERTY(QScriptValue channel READ getChannel WRITE setChannel)
Q_PROPERTY(bool mute READ isMute WRITE setMute)
Q_PROPERTY(bool deaf READ isDeaf WRITE setDeaf)
public:
ScriptPlayer(ClientPlayer *p);
QString getName() const;
unsigned int getSession() const;
int getId() const;
QScriptValue getChannel() const;
bool isMute() const;
bool isDeaf() const;
public slots:
void setMute(bool);
void setDeaf(bool);
void setChannel(const QScriptValue &);
void sendMessage(const QString &);
signals:
void moved();
};
class ScriptChannel : public QObject, protected QScriptable {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(ScriptChannel)
Q_PROPERTY(QString name READ getName WRITE setName)
Q_PROPERTY(int id READ getId)
Q_PROPERTY(int parent READ getParent WRITE setParent)
Q_PROPERTY(QScriptValue children READ getChildren)
Q_PROPERTY(QScriptValue players READ getPlayers)
public:
ScriptChannel(Channel *c);
QString getName() const;
int getId() const;
int getParent() const;
public slots:
void setName(const QString &);
void setParent(int);
QScriptValue getPlayers() const;
QScriptValue getChildren() const;
void sendMessage(const QString &, bool);
signals:
void moved();
};
class ScriptServer : public QObject, protected QScriptable {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(ScriptServer)
Q_PROPERTY(QScriptValue playerContextMenu)
Q_PROPERTY(QScriptValue channelContextMenu)
Q_PROPERTY(QScriptValue msgHandler)
Q_PROPERTY(QScriptValue root READ getRoot)
public:
ScriptServer(QObject *p);
QScriptValue getRoot() const;
public slots:
QScriptValue loadUi(const QString &);
void sendMsg(const QString &, const QStringList &);
signals:
void newPlayer(QScriptValue);
void newChannel(QScriptValue);
void connected();
void disconnected(QString reason);
};
class MumbleScript : public QObject {
Q_OBJECT
Q_DISABLE_COPY(MumbleScript)
public:
QScriptEngine *qseEngine;
ScriptServer *ssServer;
QString qsFilename;
QMap<ClientPlayer *, ScriptPlayer *> qmPlayers;
QMap<Channel *, ScriptChannel *> qmChannels;
QMap<QString, QByteArray> qmResources;
bool bLocal;
MumbleScript(MumbleScripts *p);
~MumbleScript();
void load(const QString &source);
void evaluate(const QString &code);
void addPlayer(ClientPlayer *p);
void movePlayer(ClientPlayer *p);
void addChannel(Channel *c);
void moveChannel(Channel *c);
void connected();
public slots:
void playerDeleted(QObject *);
void channelDeleted(QObject *);
void errorHandler(const QScriptValue &);
};
class MumbleScripts : public QObject {
friend class MumbleScript;
Q_OBJECT
Q_DISABLE_COPY(MumbleScripts)
protected:
QList<MumbleScript *> qlScripts;
public:
MumbleScripts(QObject *p);
~MumbleScripts();
void createEvaluate(const QString &code);
void addPlayer(ClientPlayer *p);
void movePlayer(ClientPlayer *p);
void addChannel(Channel *c);
void moveChannel(Channel *c);
void connected();
};
#endif

View File

@ -1,59 +1,59 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
Copyright (C) 2008-2009, Mikkel Krautz <mikkel@krautz.dk>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NETWORKCONFIG_H
#define _NETWORKCONFIG_H
#include "ConfigDialog.h"
#include "ui_NetworkConfig.h"
class NetworkConfig : public ConfigWidget, Ui::NetworkConfig {
private:
Q_OBJECT
Q_DISABLE_COPY(NetworkConfig)
public:
NetworkConfig(Settings &st);
virtual QString title() const;
virtual QIcon icon() const;
static void SetupProxy();
static bool TcpModeEnabled();
public slots:
void accept() const;
void save() const;
void load(const Settings &r);
bool expert(bool);
void on_qcbType_currentIndexChanged(int v);
};
#else
class NetworkConfig;
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
Copyright (C) 2008-2009, Mikkel Krautz <mikkel@krautz.dk>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NETWORKCONFIG_H
#define _NETWORKCONFIG_H
#include "ConfigDialog.h"
#include "ui_NetworkConfig.h"
class NetworkConfig : public ConfigWidget, Ui::NetworkConfig {
private:
Q_OBJECT
Q_DISABLE_COPY(NetworkConfig)
public:
NetworkConfig(Settings &st);
virtual QString title() const;
virtual QIcon icon() const;
static void SetupProxy();
static bool TcpModeEnabled();
public slots:
void accept() const;
void save() const;
void load(const Settings &r);
bool expert(bool);
void on_qcbType_currentIndexChanged(int v);
};
#else
class NetworkConfig;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +1,107 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TextMessage.h"
TextMessage::TextMessage(QWidget *p) : QDialog(p) {
setupUi(this);
qtbPreview->document()->setDefaultStyleSheet(qApp->styleSheet());
qteEdit->installEventFilter(this);
qteEdit->setFocus();
}
void TextMessage::on_qcbRawMessage_stateChanged(int) {
on_qteEdit_textChanged();
}
void TextMessage::on_qteEdit_textChanged() {
qsRep = qteEdit->toPlainText();
if (qcbRawMessage->isChecked()) {
qsRep = Qt::convertFromPlainText(qsRep);
}
if (! Qt::mightBeRichText(qsRep) && !qcbRawMessage->isChecked()) {
QRegExp qr;
qr.setMinimal(true);
qr.setPatternSyntax(QRegExp::RegExp2);
qr.setCaseSensitivity(Qt::CaseInsensitive);
qr.setPattern(QLatin1String("[\\r\\n]+"));
qsRep.replace(qr, QLatin1String("<br />"));
qr.setPattern(QLatin1String("\\*(\\w+)\\*"));
qsRep.replace(qr, QLatin1String("<b>\\1</b>"));
qr.setPattern(QLatin1String("\"([^\"]+)\""));
qsRep.replace(qr, QLatin1String("\"<i>\\1</i>\""));
qr.setPattern(QLatin1String("[a-z]+://[^ <$]*"));
qr.setMinimal(false);
int idx = 0;
do {
idx = qr.indexIn(qsRep, idx);
if (idx >= 0) {
QString url = qr.capturedTexts().at(0);
QUrl u(url);
if (u.isValid()) {
int len = qr.matchedLength();
QString replacement = QString::fromLatin1("<a href=\"%1\">%1</a>").arg(url);
qsRep.replace(idx, len, replacement);
idx += replacement.length();
} else {
idx++;
}
}
} while (idx >= 0);
}
qtbPreview->setHtml(qsRep);
}
QString TextMessage::message() {
return qsRep;
}
bool TextMessage::eventFilter(QObject *obj, QEvent *evt) {
if (obj != qteEdit)
return false;
if (evt->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt);
if (((keyEvent->key() == Qt::Key_Enter) || (keyEvent->key() == Qt::Key_Return)) &&
(keyEvent->modifiers() == Qt::NoModifier)) {
accept();
return true;
}
}
return false;
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TextMessage.h"
TextMessage::TextMessage(QWidget *p) : QDialog(p) {
setupUi(this);
qtbPreview->document()->setDefaultStyleSheet(qApp->styleSheet());
qteEdit->installEventFilter(this);
qteEdit->setFocus();
}
void TextMessage::on_qcbRawMessage_stateChanged(int) {
on_qteEdit_textChanged();
}
void TextMessage::on_qteEdit_textChanged() {
qsRep = qteEdit->toPlainText();
if (qcbRawMessage->isChecked()) {
qsRep = Qt::convertFromPlainText(qsRep);
}
if (! Qt::mightBeRichText(qsRep) && !qcbRawMessage->isChecked()) {
QRegExp qr;
qr.setMinimal(true);
qr.setPatternSyntax(QRegExp::RegExp2);
qr.setCaseSensitivity(Qt::CaseInsensitive);
qr.setPattern(QLatin1String("[\\r\\n]+"));
qsRep.replace(qr, QLatin1String("<br />"));
qr.setPattern(QLatin1String("\\*(\\w+)\\*"));
qsRep.replace(qr, QLatin1String("<b>\\1</b>"));
qr.setPattern(QLatin1String("\"([^\"]+)\""));
qsRep.replace(qr, QLatin1String("\"<i>\\1</i>\""));
qr.setPattern(QLatin1String("[a-z]+://[^ <$]*"));
qr.setMinimal(false);
int idx = 0;
do {
idx = qr.indexIn(qsRep, idx);
if (idx >= 0) {
QString url = qr.capturedTexts().at(0);
QUrl u(url);
if (u.isValid()) {
int len = qr.matchedLength();
QString replacement = QString::fromLatin1("<a href=\"%1\">%1</a>").arg(url);
qsRep.replace(idx, len, replacement);
idx += replacement.length();
} else {
idx++;
}
}
} while (idx >= 0);
}
qtbPreview->setHtml(qsRep);
}
QString TextMessage::message() {
return qsRep;
}
bool TextMessage::eventFilter(QObject *obj, QEvent *evt) {
if (obj != qteEdit)
return false;
if (evt->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt);
if (((keyEvent->key() == Qt::Key_Enter) || (keyEvent->key() == Qt::Key_Return)) &&
(keyEvent->modifiers() == Qt::NoModifier)) {
accept();
return true;
}
}
return false;
}

View File

@ -1,52 +1,52 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TEXTMESSAGE_H
#define _TEXTMESSAGE_H
#include "mumble_pch.hpp"
#include "ui_TextMessage.h"
class TextMessage : public QDialog, public Ui::TextMessage {
private:
Q_OBJECT
Q_DISABLE_COPY(TextMessage)
protected:
QString qsRep;
public:
TextMessage(QWidget *parent = NULL);
QString message();
bool eventFilter(QObject *obj, QEvent *event);
public slots:
void on_qteEdit_textChanged();
void on_qcbRawMessage_stateChanged(int);
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TEXTMESSAGE_H
#define _TEXTMESSAGE_H
#include "mumble_pch.hpp"
#include "ui_TextMessage.h"
class TextMessage : public QDialog, public Ui::TextMessage {
private:
Q_OBJECT
Q_DISABLE_COPY(TextMessage)
protected:
QString qsRep;
public:
TextMessage(QWidget *parent = NULL);
QString message();
bool eventFilter(QObject *obj, QEvent *event);
public slots:
void on_qteEdit_textChanged();
void on_qcbRawMessage_stateChanged(int);
};
#endif

View File

@ -1,97 +1,97 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ViewCert.h"
ViewCert::ViewCert(QList<QSslCertificate> cl, QWidget *p) : QDialog(p) {
qlCerts = cl;
setWindowTitle(tr("Certificate Chain Details"));
QHBoxLayout *h;
QVBoxLayout *v;
QGroupBox *qcbChain, *qcbDetails;
qcbChain=new QGroupBox(tr("Certificate chain"), this);
h = new QHBoxLayout(qcbChain);
qlwChain = new QListWidget(qcbChain);
qlwChain->setObjectName(QLatin1String("Chain"));
foreach(QSslCertificate c, qlCerts)
qlwChain->addItem(tr("%1 %2").arg(c.subjectInfo(QSslCertificate::CommonName)).arg(c.subjectInfo(QSslCertificate::Organization)));
h->addWidget(qlwChain);
qcbDetails=new QGroupBox(tr("Certificate details"), this);
h = new QHBoxLayout(qcbDetails);
qlwCert = new QListWidget(qcbDetails);
h->addWidget(qlwCert);
QDialogButtonBox *qdbb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this);
v = new QVBoxLayout(this);
v->addWidget(qcbChain);
v->addWidget(qcbDetails);
v->addWidget(qdbb);
QMetaObject::connectSlotsByName(this);
connect(qdbb, SIGNAL(accepted()), this, SLOT(accept()));
resize(500,300);
}
void ViewCert::on_Chain_currentRowChanged(int idx) {
qlwCert->clear();
if ((idx < 0) || (idx >= qlCerts.size()))
return;
QStringList l;
const QSslCertificate &c=qlCerts.at(idx);
l << tr("Common Name: %1").arg(c.subjectInfo(QSslCertificate::CommonName));
l << tr("Organization: %1").arg(c.subjectInfo(QSslCertificate::Organization));
l << tr("Subunit: %1").arg(c.subjectInfo(QSslCertificate::OrganizationalUnitName));
l << tr("Country: %1").arg(c.subjectInfo(QSslCertificate::CountryName));
l << tr("Locality: %1").arg(c.subjectInfo(QSslCertificate::LocalityName));
l << tr("State: %1").arg(c.subjectInfo(QSslCertificate::StateOrProvinceName));
l << tr("Valid from: %1").arg(c.effectiveDate().toString());
l << tr("Valid to: %1").arg(c.expiryDate().toString());
l << tr("Serial: %1").arg(QString::fromLatin1(c.serialNumber().toHex()));
l << tr("Public Key: %1 bits %2").arg(c.publicKey().length()).arg((c.publicKey().algorithm() == QSsl::Rsa) ? tr("RSA") : tr("DSA"));
l << tr("Digest (MD5): %1").arg(QString::fromLatin1(c.digest().toHex()));
l << QString();
l << tr("Issued by:");
l << tr("Common Name: %1").arg(c.issuerInfo(QSslCertificate::CommonName));
l << tr("Organization: %1").arg(c.issuerInfo(QSslCertificate::Organization));
l << tr("Unit Name: %1").arg(c.issuerInfo(QSslCertificate::OrganizationalUnitName));
l << tr("Country: %1").arg(c.issuerInfo(QSslCertificate::CountryName));
l << tr("Locality: %1").arg(c.issuerInfo(QSslCertificate::LocalityName));
l << tr("State: %1").arg(c.issuerInfo(QSslCertificate::StateOrProvinceName));
qlwCert->addItems(l);
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ViewCert.h"
ViewCert::ViewCert(QList<QSslCertificate> cl, QWidget *p) : QDialog(p) {
qlCerts = cl;
setWindowTitle(tr("Certificate Chain Details"));
QHBoxLayout *h;
QVBoxLayout *v;
QGroupBox *qcbChain, *qcbDetails;
qcbChain=new QGroupBox(tr("Certificate chain"), this);
h = new QHBoxLayout(qcbChain);
qlwChain = new QListWidget(qcbChain);
qlwChain->setObjectName(QLatin1String("Chain"));
foreach(QSslCertificate c, qlCerts)
qlwChain->addItem(tr("%1 %2").arg(c.subjectInfo(QSslCertificate::CommonName)).arg(c.subjectInfo(QSslCertificate::Organization)));
h->addWidget(qlwChain);
qcbDetails=new QGroupBox(tr("Certificate details"), this);
h = new QHBoxLayout(qcbDetails);
qlwCert = new QListWidget(qcbDetails);
h->addWidget(qlwCert);
QDialogButtonBox *qdbb = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this);
v = new QVBoxLayout(this);
v->addWidget(qcbChain);
v->addWidget(qcbDetails);
v->addWidget(qdbb);
QMetaObject::connectSlotsByName(this);
connect(qdbb, SIGNAL(accepted()), this, SLOT(accept()));
resize(500,300);
}
void ViewCert::on_Chain_currentRowChanged(int idx) {
qlwCert->clear();
if ((idx < 0) || (idx >= qlCerts.size()))
return;
QStringList l;
const QSslCertificate &c=qlCerts.at(idx);
l << tr("Common Name: %1").arg(c.subjectInfo(QSslCertificate::CommonName));
l << tr("Organization: %1").arg(c.subjectInfo(QSslCertificate::Organization));
l << tr("Subunit: %1").arg(c.subjectInfo(QSslCertificate::OrganizationalUnitName));
l << tr("Country: %1").arg(c.subjectInfo(QSslCertificate::CountryName));
l << tr("Locality: %1").arg(c.subjectInfo(QSslCertificate::LocalityName));
l << tr("State: %1").arg(c.subjectInfo(QSslCertificate::StateOrProvinceName));
l << tr("Valid from: %1").arg(c.effectiveDate().toString());
l << tr("Valid to: %1").arg(c.expiryDate().toString());
l << tr("Serial: %1").arg(QString::fromLatin1(c.serialNumber().toHex()));
l << tr("Public Key: %1 bits %2").arg(c.publicKey().length()).arg((c.publicKey().algorithm() == QSsl::Rsa) ? tr("RSA") : tr("DSA"));
l << tr("Digest (MD5): %1").arg(QString::fromLatin1(c.digest().toHex()));
l << QString();
l << tr("Issued by:");
l << tr("Common Name: %1").arg(c.issuerInfo(QSslCertificate::CommonName));
l << tr("Organization: %1").arg(c.issuerInfo(QSslCertificate::Organization));
l << tr("Unit Name: %1").arg(c.issuerInfo(QSslCertificate::OrganizationalUnitName));
l << tr("Country: %1").arg(c.issuerInfo(QSslCertificate::CountryName));
l << tr("Locality: %1").arg(c.issuerInfo(QSslCertificate::LocalityName));
l << tr("State: %1").arg(c.issuerInfo(QSslCertificate::StateOrProvinceName));
qlwCert->addItems(l);
}

View File

@ -1,49 +1,49 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _VIEWCERT_H
#define _VIEWCERT_H
#include "mumble_pch.hpp"
class ViewCert : public QDialog {
private:
Q_OBJECT
Q_DISABLE_COPY(ViewCert)
protected:
QList<QSslCertificate> qlCerts;
QListWidget *qlwChain, *qlwCert;
protected slots:
void on_Chain_currentRowChanged(int);
public:
ViewCert(QList<QSslCertificate> c, QWidget *p);
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _VIEWCERT_H
#define _VIEWCERT_H
#include "mumble_pch.hpp"
class ViewCert : public QDialog {
private:
Q_OBJECT
Q_DISABLE_COPY(ViewCert)
protected:
QList<QSslCertificate> qlCerts;
QListWidget *qlwChain, *qlwCert;
protected slots:
void on_Chain_currentRowChanged(int);
public:
ViewCert(QList<QSslCertificate> c, QWidget *p);
};
#endif

View File

@ -8,7 +8,7 @@ SOURCES = BanEditor.cpp ACLEditor.cpp Log.cpp AudioConfigDialog.cpp AudioStats.
HEADERS *= ../ACL.h ../Group.h ../Channel.h ../Connection.h ../Player.h
SOURCES *= ../ACL.cpp ../Group.cpp ../Channel.cpp ../Message.cpp ../Connection.cpp ../Player.cpp ../Timer.cpp ../CryptState.cpp ../OSInfo.cpp
SOURCES *= smallft.cpp
DIST *= licenses.h smallft.h mumble.ico mumble.xpm plugins/mumble_plugin.h mumble-overlay mumble.desktop mumble.protocol murmur_pch.h 11-input-mumble-policy.fdi mumble.plist
DIST *= ../../icons/mumble.ico licenses.h smallft.h ../../icons/mumble.xpm murmur_pch.h mumble.plist
RESOURCES *= mumble.qrc
FORMS *= ConfigDialog.ui MainWindow.ui ConnectDialog.ui BanEditor.ui ACLEditor.ui Plugins.ui Overlay.ui LookConfig.ui AudioInput.ui AudioOutput.ui Log.ui TextMessage.ui AudioStats.ui NetworkConfig.ui LCD.ui GlobalShortcut.ui
TRANSLATIONS = mumble_en.ts mumble_es.ts mumble_de.ts mumble_tr.ts mumble_fr.ts mumble_ru.ts mumble_cs.ts mumble_ja.ts mumble_pl.ts

View File

@ -1 +1 @@
#include "mumble_pch.hpp"
#include "mumble_pch.hpp"

View File

@ -1,166 +1,166 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Server.h"
#include "Meta.h"
int add_ext(X509 * crt, int nid, char *value) {
X509_EXTENSION *ex;
X509V3_CTX ctx;
X509V3_set_ctx_nodb(&ctx);
X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
if (!ex)
return 0;
X509_add_ext(crt, ex, -1);
X509_EXTENSION_free(ex);
return 1;
}
void Server::initializeCert() {
QByteArray crt, key, pass;
if (! QSslSocket::supportsSsl()) {
qFatal("Qt without SSL Support");
}
crt = getConf("certificate", QString()).toByteArray();
key = getConf("key", QString()).toByteArray();
pass = getConf("passphrase", QByteArray()).toByteArray();
if (! crt.isEmpty()) {
qscCert = QSslCertificate(crt);
if (qscCert.isNull()) {
log("Failed to parse certificate.");
} else if (qscCert.issuerInfo(QSslCertificate::CommonName) == QLatin1String("Murmur Autogenerated Certificate")) {
log("Old autogenerated certificate is unusable for registration, invalidating it");
qscCert = QSslCertificate();
}
}
if (! key.isEmpty() && qscCert.isNull()) {
qscCert = QSslCertificate(key);
if (! qscCert.isNull()) {
log("Using certificate from key.");
}
}
if (! qscCert.isNull()) {
QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
if (! key.isEmpty()) {
qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
if (qskKey.isNull()) {
log("Failed to parse key.");
}
}
if (! crt.isEmpty() && qskKey.isNull()) {
qskKey = QSslKey(crt, alg, QSsl::Pem, QSsl::PrivateKey, pass);
if (! qskKey.isNull()) {
log("Using key from certificate.");
}
}
}
if (qscCert.isNull() || qskKey.isNull()) {
if (! key.isEmpty() || ! crt.isEmpty()) {
log("Certificate specified, but failed to load.");
}
qskKey = Meta::mp.qskKey;
qscCert = Meta::mp.qscCert;
if (qscCert.isNull() || qskKey.isNull()) {
log("Generating new server certificate.");
BIO *bio_err;
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
X509 *x509 = X509_new();
EVP_PKEY *pkey = EVP_PKEY_new();
RSA *rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
EVP_PKEY_assign_RSA(pkey, rsa);
X509_set_version(x509, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
X509_gmtime_adj(X509_get_notBefore(x509),0);
X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
X509_set_pubkey(x509, pkey);
X509_NAME *name=X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0);
X509_set_issuer_name(x509, name);
add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
add_ext(x509, NID_subject_key_identifier, "hash");
add_ext(x509, NID_netscape_comment, "Generated from murmur");
X509_sign(x509, pkey, EVP_md5());
crt.resize(i2d_X509(x509, NULL));
unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data());
i2d_X509(x509, &dptr);
qscCert = QSslCertificate(crt, QSsl::Der);
if (qscCert.isNull())
log("Certificate generation failed");
key.resize(i2d_PrivateKey(pkey, NULL));
dptr=reinterpret_cast<unsigned char *>(key.data());
i2d_PrivateKey(pkey, &dptr);
qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der);
if (qskKey.isNull())
log("Key generation failed");
setConf("certificate", qscCert.toPem());
setConf("key", qskKey.toPem());
}
}
QList<QSslCipher> pref;
foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
if (c.usedBits() < 128)
continue;
pref << c;
}
if (pref.isEmpty())
qFatal("No ciphers of at least 128 bit found");
QSslSocket::setDefaultCiphers(pref);
}
const QString Server::getDigest() const {
return QString::fromLatin1(qscCert.digest().toHex());
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Server.h"
#include "Meta.h"
int add_ext(X509 * crt, int nid, char *value) {
X509_EXTENSION *ex;
X509V3_CTX ctx;
X509V3_set_ctx_nodb(&ctx);
X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
if (!ex)
return 0;
X509_add_ext(crt, ex, -1);
X509_EXTENSION_free(ex);
return 1;
}
void Server::initializeCert() {
QByteArray crt, key, pass;
if (! QSslSocket::supportsSsl()) {
qFatal("Qt without SSL Support");
}
crt = getConf("certificate", QString()).toByteArray();
key = getConf("key", QString()).toByteArray();
pass = getConf("passphrase", QByteArray()).toByteArray();
if (! crt.isEmpty()) {
qscCert = QSslCertificate(crt);
if (qscCert.isNull()) {
log("Failed to parse certificate.");
} else if (qscCert.issuerInfo(QSslCertificate::CommonName) == QLatin1String("Murmur Autogenerated Certificate")) {
log("Old autogenerated certificate is unusable for registration, invalidating it");
qscCert = QSslCertificate();
}
}
if (! key.isEmpty() && qscCert.isNull()) {
qscCert = QSslCertificate(key);
if (! qscCert.isNull()) {
log("Using certificate from key.");
}
}
if (! qscCert.isNull()) {
QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
if (! key.isEmpty()) {
qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
if (qskKey.isNull()) {
log("Failed to parse key.");
}
}
if (! crt.isEmpty() && qskKey.isNull()) {
qskKey = QSslKey(crt, alg, QSsl::Pem, QSsl::PrivateKey, pass);
if (! qskKey.isNull()) {
log("Using key from certificate.");
}
}
}
if (qscCert.isNull() || qskKey.isNull()) {
if (! key.isEmpty() || ! crt.isEmpty()) {
log("Certificate specified, but failed to load.");
}
qskKey = Meta::mp.qskKey;
qscCert = Meta::mp.qscCert;
if (qscCert.isNull() || qskKey.isNull()) {
log("Generating new server certificate.");
BIO *bio_err;
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
X509 *x509 = X509_new();
EVP_PKEY *pkey = EVP_PKEY_new();
RSA *rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
EVP_PKEY_assign_RSA(pkey, rsa);
X509_set_version(x509, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
X509_gmtime_adj(X509_get_notBefore(x509),0);
X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
X509_set_pubkey(x509, pkey);
X509_NAME *name=X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0);
X509_set_issuer_name(x509, name);
add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
add_ext(x509, NID_subject_key_identifier, "hash");
add_ext(x509, NID_netscape_comment, "Generated from murmur");
X509_sign(x509, pkey, EVP_md5());
crt.resize(i2d_X509(x509, NULL));
unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data());
i2d_X509(x509, &dptr);
qscCert = QSslCertificate(crt, QSsl::Der);
if (qscCert.isNull())
log("Certificate generation failed");
key.resize(i2d_PrivateKey(pkey, NULL));
dptr=reinterpret_cast<unsigned char *>(key.data());
i2d_PrivateKey(pkey, &dptr);
qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der);
if (qskKey.isNull())
log("Key generation failed");
setConf("certificate", qscCert.toPem());
setConf("key", qskKey.toPem());
}
}
QList<QSslCipher> pref;
foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
if (c.usedBits() < 128)
continue;
pref << c;
}
if (pref.isEmpty())
qFatal("No ciphers of at least 128 bit found");
QSslSocket::setDefaultCiphers(pref);
}
const QString Server::getDigest() const {
return QString::fromLatin1(qscCert.digest().toHex());
}

View File

@ -1,97 +1,97 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Tray.h"
#include "Server.h"
#include "Version.h"
Tray::Tray(QObject *p, LogEmitter *logger) : QObject(p) {
le = logger;
qsti = new QSystemTrayIcon(qApp->windowIcon(), this);
qsti->setObjectName(QLatin1String("Tray"));
qsti->setToolTip(tr("Murmur"));
qaQuit = new QAction(tr("&Quit Murmur"), this);
qaQuit->setShortcut(tr("Ctrl+Q", "Quit"));
qaQuit->setObjectName(QLatin1String("Quit"));
qaShowLog = new QAction(tr("&Show Log"), this);
qaShowLog->setShortcut(tr("Ctrl+L", "Quit"));
qaShowLog->setObjectName(QLatin1String("ShowLog"));
// Can't construct a QMenu which decends from QObject, and qsti is a QObject.
// Qt bug?
qm = new QMenu(tr("Murmur"), NULL);
qm->addAction(qaQuit);
qm->addSeparator();
qm->addAction(qaShowLog);
qsti->setContextMenu(qm);
qsti->show();
connect(le, SIGNAL(newLogEntry(const QString &)), this, SLOT(addLogMessage(const QString &)));
QMetaObject::connectSlotsByName(this);
}
void Tray::on_Tray_activated(QSystemTrayIcon::ActivationReason r) {
if (r == QSystemTrayIcon::Trigger) {
qsti->showMessage(tr("Murmur"), tr("%1 server running.").arg(meta->qhServers.count()), QSystemTrayIcon::Information, 5000);
}
}
void Tray::on_Quit_triggered() {
if (QMessageBox::question(NULL, tr("Murmur"), tr("Are you sure you wish to quit murmur?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
qApp->quit();
}
}
void Tray::on_ShowLog_triggered() {
QMainWindow *mw = new QMainWindow();
mw->setAttribute(Qt::WA_DeleteOnClose);
QTextBrowser *tb = new QTextBrowser();
mw->setCentralWidget(tb);
mw->setWindowTitle(QString::fromLatin1("Murmur -- %1").arg(MUMBLE_RELEASE));
connect(le, SIGNAL(newLogEntry(const QString &)), tb, SLOT(append(const QString &)));
foreach(const QString &m, qlLog)
tb->append(m);
mw->show();
}
void Tray::addLogMessage(const QString &msg) {
if (qlLog.count() >= 1000)
qlLog.removeFirst();
qlLog.append(msg);
}
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Tray.h"
#include "Server.h"
#include "Version.h"
Tray::Tray(QObject *p, LogEmitter *logger) : QObject(p) {
le = logger;
qsti = new QSystemTrayIcon(qApp->windowIcon(), this);
qsti->setObjectName(QLatin1String("Tray"));
qsti->setToolTip(tr("Murmur"));
qaQuit = new QAction(tr("&Quit Murmur"), this);
qaQuit->setShortcut(tr("Ctrl+Q", "Quit"));
qaQuit->setObjectName(QLatin1String("Quit"));
qaShowLog = new QAction(tr("&Show Log"), this);
qaShowLog->setShortcut(tr("Ctrl+L", "Quit"));
qaShowLog->setObjectName(QLatin1String("ShowLog"));
// Can't construct a QMenu which decends from QObject, and qsti is a QObject.
// Qt bug?
qm = new QMenu(tr("Murmur"), NULL);
qm->addAction(qaQuit);
qm->addSeparator();
qm->addAction(qaShowLog);
qsti->setContextMenu(qm);
qsti->show();
connect(le, SIGNAL(newLogEntry(const QString &)), this, SLOT(addLogMessage(const QString &)));
QMetaObject::connectSlotsByName(this);
}
void Tray::on_Tray_activated(QSystemTrayIcon::ActivationReason r) {
if (r == QSystemTrayIcon::Trigger) {
qsti->showMessage(tr("Murmur"), tr("%1 server running.").arg(meta->qhServers.count()), QSystemTrayIcon::Information, 5000);
}
}
void Tray::on_Quit_triggered() {
if (QMessageBox::question(NULL, tr("Murmur"), tr("Are you sure you wish to quit murmur?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
qApp->quit();
}
}
void Tray::on_ShowLog_triggered() {
QMainWindow *mw = new QMainWindow();
mw->setAttribute(Qt::WA_DeleteOnClose);
QTextBrowser *tb = new QTextBrowser();
mw->setCentralWidget(tb);
mw->setWindowTitle(QString::fromLatin1("Murmur -- %1").arg(MUMBLE_RELEASE));
connect(le, SIGNAL(newLogEntry(const QString &)), tb, SLOT(append(const QString &)));
foreach(const QString &m, qlLog)
tb->append(m);
mw->show();
}
void Tray::addLogMessage(const QString &msg) {
if (qlLog.count() >= 1000)
qlLog.removeFirst();
qlLog.append(msg);
}

View File

@ -1,57 +1,57 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TRAY_H
#define _TRAY_H
#include "murmur_pch.h"
#include "Server.h"
class Tray : public QObject {
private:
Q_OBJECT
Q_DISABLE_COPY(Tray);
protected:
QSystemTrayIcon *qsti;
QMenu *qm;
QAction *qaQuit;
QAction *qaShowLog;
QStringList qlLog;
LogEmitter *le;
public slots:
void on_Tray_activated(QSystemTrayIcon::ActivationReason);
void on_Quit_triggered();
void on_ShowLog_triggered();
void addLogMessage(const QString &);
public:
Tray(QObject *parent, LogEmitter *le);
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TRAY_H
#define _TRAY_H
#include "murmur_pch.h"
#include "Server.h"
class Tray : public QObject {
private:
Q_OBJECT
Q_DISABLE_COPY(Tray);
protected:
QSystemTrayIcon *qsti;
QMenu *qm;
QAction *qaQuit;
QAction *qaShowLog;
QStringList qlLog;
LogEmitter *le;
public slots:
void on_Tray_activated(QSystemTrayIcon::ActivationReason);
void on_Quit_triggered();
void on_ShowLog_triggered();
void addLogMessage(const QString &);
public:
Tray(QObject *parent, LogEmitter *le);
};
#endif

View File

@ -209,6 +209,23 @@ void UnixMurmur::handleSigTerm() {
void UnixMurmur::setuid() {
if (Meta::mp.uiUid != 0) {
#ifdef Q_OS_DARWIN
qCritical("WARNING: You are launching murmurd as root on Mac OS X or Darwin. Murmur does not need "
"special privileges to set itself up on these systems, so this behavior is highly discouraged.");
if (::setgid(Meta::mp.uiGid) != 0)
qFatal("Failed to switch to gid %d", Meta::mp.uiGid);
if (::setuid(Meta::mp.uiUid) != 0)
qFatal("Failed to switch to uid %d", Meta::mp.uiUid);
uid_t uid = getuid(), euid = geteuid();
gid_t gid = getgid(), egid = getegid();
if (uid == Meta::mp.uiUid && euid == Meta::mp.uiUid
&& gid == Meta::mp.uiGid && egid == Meta::mp.uiGid) {
qCritical("Successfully switched to uid %d", Meta::mp.uiUid);
} else
qFatal("Couldn't switch uid/gid.");
#else
if (setregid(Meta::mp.uiGid, Meta::mp.uiGid) != 0)
qCritical("Failed to switch to gid %d", Meta::mp.uiGid);
if (setresuid(Meta::mp.uiUid, Meta::mp.uiUid, 0) != 0) {
@ -217,6 +234,7 @@ void UnixMurmur::setuid() {
qCritical("Successfully switched to uid %d", Meta::mp.uiUid);
initialcap();
}
#endif
} else if (bRoot) {
qCritical("WARNING: You are running murmurd as root, without setting a uname in the ini file. This might be a security risk.");
}

View File

@ -1,71 +1,71 @@
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UNIXMURMUR_H
#define _UNIXMURMUR_H
#include "murmur_pch.h"
class LimitTest : public QThread {
Q_OBJECT
Q_DISABLE_COPY(LimitTest)
protected:
static QMutex *qm;
static QWaitCondition *qw, *qstartw;
LimitTest();
public:
int tid;
void run();
static void testLimits(QCoreApplication &);
};
class UnixMurmur : public QObject {
Q_OBJECT
Q_DISABLE_COPY(UnixMurmur)
protected:
bool bRoot;
static int iHupFd[2], iTermFd[2];
QSocketNotifier *qsnHup, *qsnTerm;
static void hupSignalHandler(int);
static void termSignalHandler(int);
public slots:
void handleSigHup();
void handleSigTerm();
public:
void setuid();
void initialcap();
void finalcap();
UnixMurmur();
~UnixMurmur();
};
#endif
/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UNIXMURMUR_H
#define _UNIXMURMUR_H
#include "murmur_pch.h"
class LimitTest : public QThread {
Q_OBJECT
Q_DISABLE_COPY(LimitTest)
protected:
static QMutex *qm;
static QWaitCondition *qw, *qstartw;
LimitTest();
public:
int tid;
void run();
static void testLimits(QCoreApplication &);
};
class UnixMurmur : public QObject {
Q_OBJECT
Q_DISABLE_COPY(UnixMurmur)
protected:
bool bRoot;
static int iHupFd[2], iTermFd[2];
QSocketNotifier *qsnHup, *qsnTerm;
static void hupSignalHandler(int);
static void termSignalHandler(int);
public slots:
void handleSigHup();
void handleSigTerm();
public:
void setuid();
void initialcap();
void finalcap();
UnixMurmur();
~UnixMurmur();
};
#endif

View File

@ -17,9 +17,8 @@ SOURCES = main.cpp Server.cpp ServerDB.cpp Register.cpp Cert.cpp Messages.cpp Me
HEADERS *= ../ACL.h ../Group.h ../Channel.h ../Connection.h ../Player.h
SOURCES *= ../ACL.cpp ../Group.cpp ../Channel.cpp ../Message.cpp ../Connection.cpp ../Player.cpp ../Timer.cpp ../CryptState.cpp ../OSInfo.cpp
DIST = DBus.h ServerDB.h murmur.ico Murmur.ice MurmurI.h MurmurIceWrapper.cpp
DIST = DBus.h ServerDB.h ../../icons/murmur.ico Murmur.ice MurmurI.h MurmurIceWrapper.cpp
PRECOMPILED_HEADER = murmur_pch.h
DIST *= murmur.pl murmur.ini murmur.ini.system murmur.init murmur.conf murmur.logrotate dbusauth.pl weblist.pl weblist.php icedemo.php murmur-user-wrapper
!CONFIG(no-ice) {
CONFIG *= ice