mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
Merge branch 'master' of git://mumble.git.sourceforge.net/gitroot/mumble
This commit is contained in:
commit
8a7f67ce5c
68
main.pro
68
main.pro
@ -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)
|
||||
|
||||
1360
overlay/d3d9.cpp
1360
overlay/d3d9.cpp
File diff suppressed because it is too large
Load Diff
218
overlay/lib.h
218
overlay/lib.h
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -2,4 +2,3 @@ TEMPLATE = subdirs
|
||||
|
||||
CONFIG += debug_and_release
|
||||
SUBDIRS = injector overlay stub
|
||||
DIST = bundle.pri
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = aoc
|
||||
SOURCES = aoc.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = aoc
|
||||
SOURCES = aoc.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = css
|
||||
SOURCES = css.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = css
|
||||
SOURCES = css.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = gmod
|
||||
SOURCES = gmod.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = gmod
|
||||
SOURCES = gmod.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = hl2dm
|
||||
SOURCES = hl2dm.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = hl2dm
|
||||
SOURCES = hl2dm.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = insurgency
|
||||
SOURCES = insurgency.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
include(../plugins.pri)
|
||||
|
||||
TARGET = insurgency
|
||||
SOURCES = insurgency.cpp
|
||||
LIBS += -luser32
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
2
scripts/scripts.pro
Normal 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
|
||||
88
src/OSInfo.h
88
src/OSInfo.h
@ -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
|
||||
|
||||
176
src/Timer.cpp
176
src/Timer.cpp
@ -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
|
||||
|
||||
94
src/Timer.h
94
src/Timer.h
@ -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
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1 +1 @@
|
||||
#include "mumble_pch.hpp"
|
||||
#include "mumble_pch.hpp"
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.");
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user