#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#include "dmx.h"
#include "dmxlog.h"
#include "dmxinput.h"
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
static dmxLogLevel dmxCurrentLogLevel = dmxDebug;
dmxLogLevel dmxSetLogLevel(dmxLogLevel newLevel)
{
dmxLogLevel oldLevel = dmxCurrentLogLevel;
if (newLevel > dmxFatal) newLevel = dmxFatal;
dmxCurrentLogLevel = newLevel;
return oldLevel;
}
dmxLogLevel dmxGetLogLevel(void)
{
return dmxCurrentLogLevel;
}
#ifdef DMX_LOG_STANDALONE
void ErrorF(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
}
static void VFatalError(const char *format, va_list args)
{
vfprintf(stderr, format, args);
exit(1);
}
void VErrorF(const char *format, va_list args)
{
vfprintf(stderr, format, args);
}
#else
extern void AbortServer(void);
static void VFatalError(const char *format, va_list args)
{
VErrorF(format, args);
ErrorF("\n");
#ifdef DDXOSFATALERROR
OsVendorFatalError();
#endif
AbortServer();
}
#endif
static void dmxHeader(dmxLogLevel logLevel, DMXInputInfo *dmxInput,
DMXScreenInfo *dmxScreen)
{
const char *type = "??";
switch (logLevel) {
case dmxDebug: type = ".."; break;
case dmxInfo: type = "II"; break;
case dmxWarning: type = "**"; break;
case dmxError: type = "!!"; break;
case dmxFatal: type = "Fatal Error"; break;
}
if (dmxInput && dmxScreen) {
ErrorF("(%s) dmx[i%d/%s;o%d/%s]: ", type,
dmxInput->inputIdx, dmxInput->name,
dmxScreen->index, dmxScreen->name);
} else if (dmxScreen) {
ErrorF("(%s) dmx[o%d/%s]: ", type,
dmxScreen->index, dmxScreen->name);
} else if (dmxInput) {
const char *pt = strchr(dmxInput->name, ',');
int len = (pt
? (size_t)(pt-dmxInput->name)
: strlen(dmxInput->name));
ErrorF("(%s) dmx[i%d/%*.*s]: ", type,
dmxInput->inputIdx, len, len, dmxInput->name);
} else {
ErrorF("(%s) dmx: ", type);
}
}
static void dmxMessage(dmxLogLevel logLevel, const char *format, va_list args)
{
if (logLevel == dmxFatal || logLevel >= dmxCurrentLogLevel) {
if (logLevel == dmxFatal) VFatalError(format, args);
else VErrorF(format, args);
}
}
void dmxLog(dmxLogLevel logLevel, const char *format, ...)
{
va_list args;
dmxHeader(logLevel, NULL, NULL);
va_start(args, format);
dmxMessage(logLevel, format, args);
va_end(args);
}
void dmxLogCont(dmxLogLevel logLevel, const char *format, ...)
{
va_list args;
va_start(args, format);
dmxMessage(logLevel, format, args);
va_end(args);
}
#ifndef DMX_LOG_STANDALONE
void dmxLogOutput(DMXScreenInfo *dmxScreen, const char *format, ...)
{
va_list args;
dmxHeader(dmxInfo, NULL, dmxScreen);
va_start(args, format);
dmxMessage(dmxInfo, format, args);
va_end(args);
}
void dmxLogOutputCont(DMXScreenInfo *dmxScreen, const char *format, ...)
{
va_list args;
va_start(args, format);
dmxMessage(dmxInfo, format, args);
va_end(args);
}
void dmxLogOutputWarning(DMXScreenInfo *dmxScreen, const char *format, ...)
{
va_list args;
dmxHeader(dmxWarning, NULL, dmxScreen);
va_start(args, format);
dmxMessage(dmxWarning, format, args);
va_end(args);
}
void dmxLogInput(DMXInputInfo *dmxInput, const char *format, ...)
{
va_list args;
dmxHeader(dmxInfo, dmxInput, NULL);
va_start(args, format);
dmxMessage(dmxInfo, format, args);
va_end(args);
}
void dmxLogInputCont(DMXInputInfo *dmxInput, const char *format, ...)
{
va_list args;
va_start(args, format);
dmxMessage(dmxInfo, format, args);
va_end(args);
}
void dmxLogArgs(dmxLogLevel logLevel, int argc, char **argv)
{
int i;
for (i = 0; i < argc; i++)
dmxLog(logLevel, " Arg[%d] = \"%s\"\n", i, argv[i]);
}
void dmxLogVisual(DMXScreenInfo *dmxScreen, XVisualInfo *vi, int defaultVisual)
{
const char *class = "Unknown";
switch (vi->class) {
case StaticGray: class = "StaticGray "; break;
case GrayScale: class = "GrayScale "; break;
case StaticColor: class = "StaticColor"; break;
case PseudoColor: class = "PseudoColor"; break;
case TrueColor: class = "TrueColor "; break;
case DirectColor: class = "DirectColor"; break;
}
if (dmxScreen) {
dmxLogOutput(dmxScreen,
"0x%02x %s %2db %db/rgb %3d 0x%04x 0x%04x 0x%04x%s\n",
vi->visualid, class, vi->depth, vi->bits_per_rgb,
vi->colormap_size,
vi->red_mask, vi->green_mask, vi->blue_mask,
defaultVisual ? " *" : "");
} else {
dmxLog(dmxInfo,
" 0x%02x %s %2db %db/rgb %3d 0x%04x 0x%04x 0x%04x%s\n",
vi->visualid, class, vi->depth, vi->bits_per_rgb,
vi->colormap_size,
vi->red_mask, vi->green_mask, vi->blue_mask,
defaultVisual ? " *" : "");
}
}
const char *dmxXInputEventName(int type)
{
switch (type) {
case XI_DeviceValuator: return "XI_DeviceValuator";
case XI_DeviceKeyPress: return "XI_DeviceKeyPress";
case XI_DeviceKeyRelease: return "XI_DeviceKeyRelease";
case XI_DeviceButtonPress: return "XI_DeviceButtonPress";
case XI_DeviceButtonRelease: return "XI_DeviceButtonRelease";
case XI_DeviceMotionNotify: return "XI_DeviceMotionNotify";
case XI_DeviceFocusIn: return "XI_DeviceFocusIn";
case XI_DeviceFocusOut: return "XI_DeviceFocusOut";
case XI_ProximityIn: return "XI_ProximityIn";
case XI_ProximityOut: return "XI_ProximityOut";
case XI_DeviceStateNotify: return "XI_DeviceStateNotify";
case XI_DeviceMappingNotify: return "XI_DeviceMappingNotify";
case XI_ChangeDeviceNotify: return "XI_ChangeDeviceNotify";
case XI_DeviceKeystateNotify: return "XI_DeviceKeystateNotify";
case XI_DeviceButtonstateNotify: return "XI_DeviceButtonstateNotify";
default: return "unknown";
}
}
#endif
const char *dmxEventName(int type)
{
switch (type) {
case KeyPress: return "KeyPress";
case KeyRelease: return "KeyRelease";
case ButtonPress: return "ButtonPress";
case ButtonRelease: return "ButtonRelease";
case MotionNotify: return "MotionNotify";
case EnterNotify: return "EnterNotify";
case LeaveNotify: return "LeaveNotify";
case FocusIn: return "FocusIn";
case FocusOut: return "FocusOut";
case KeymapNotify: return "KeymapNotify";
case Expose: return "Expose";
case GraphicsExpose: return "GraphicsExpose";
case NoExpose: return "NoExpose";
case VisibilityNotify: return "VisibilityNotify";
case CreateNotify: return "CreateNotify";
case DestroyNotify: return "DestroyNotify";
case UnmapNotify: return "UnmapNotify";
case MapNotify: return "MapNotify";
case MapRequest: return "MapRequest";
case ReparentNotify: return "ReparentNotify";
case ConfigureNotify: return "ConfigureNotify";
case ConfigureRequest: return "ConfigureRequest";
case GravityNotify: return "GravityNotify";
case ResizeRequest: return "ResizeRequest";
case CirculateNotify: return "CirculateNotify";
case CirculateRequest: return "CirculateRequest";
case PropertyNotify: return "PropertyNotify";
case SelectionClear: return "SelectionClear";
case SelectionRequest: return "SelectionRequest";
case SelectionNotify: return "SelectionNotify";
case ColormapNotify: return "ColormapNotify";
case ClientMessage: return "ClientMessage";
case MappingNotify: return "MappingNotify";
default: return "<unknown>";
}
}