mumble-voip_mumble/src/mumble/G15LCDEngine_lglcd.cpp

168 lines
4.8 KiB
C++

// Copyright 2009-2023 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#include "G15LCDEngine_lglcd.h"
#define G15_MAX_DEV 5
#define G15_MAX_WIDTH 160
#define G15_MAX_HEIGHT 43
#define G15_MAX_BPP 1
#define G15_MAX_FBMEM (G15_MAX_WIDTH * G15_MAX_HEIGHT * G15_MAX_BPP)
#define G15_MAX_FBMEM_BITS (G15_MAX_FBMEM / 8)
#if defined(WIN32)
# define G15_WIDGET_NAME L"Mumble G15 Display"
#elif defined(APPLE)
# define G15_WIDGET_NAME CFSTR("Mumble G15 Display")
#endif
static LCDEngine *G15LCDEngineNew() {
return new G15LCDEngineLGLCD();
}
static LCDEngineRegistrar registrarG15LCD_lglcd(G15LCDEngineNew);
G15LCDEngineLGLCD::G15LCDEngineLGLCD() : LCDEngine() {
DWORD dwErr;
ZeroMemory(&llcceConnect, sizeof(llcceConnect));
ZeroMemory(&llcContext, sizeof(llcContext));
llcceConnect.appFriendlyName = G15_WIDGET_NAME;
llcceConnect.isAutostartable = FALSE;
llcceConnect.isPersistent = FALSE;
llcceConnect.dwAppletCapabilitiesSupported = LGLCD_APPLET_CAP_BASIC | LGLCD_APPLET_CAP_BW;
llcceConnect.connection = LGLCD_INVALID_CONNECTION;
llcContext.device = LGLCD_INVALID_DEVICE;
dwErr = lgLcdInit();
if (dwErr != ERROR_SUCCESS) {
qWarning() << "LGLCD: Unable to initialize Logitech LCD library" << dwErr;
return;
}
dwErr = lgLcdConnectEx(&llcceConnect);
if (dwErr != ERROR_SUCCESS) {
qWarning() << "LGLCD: Unable to connect to Logitech LCD manager" << dwErr;
return;
}
qlDevices << new G15LCDDeviceLGLCD(this);
QMetaObject::connectSlotsByName(this);
}
G15LCDEngineLGLCD::~G15LCDEngineLGLCD() {
if (llcContext.device != LGLCD_INVALID_DEVICE) {
lgLcdClose(llcContext.device);
llcContext.device = LGLCD_INVALID_DEVICE;
}
if (llcceConnect.connection != LGLCD_INVALID_CONNECTION) {
lgLcdDisconnect(llcceConnect.connection);
llcceConnect.connection = LGLCD_INVALID_CONNECTION;
}
lgLcdDeInit();
}
QList< LCDDevice * > G15LCDEngineLGLCD::devices() const {
return qlDevices;
}
/* -- */
G15LCDDeviceLGLCD::G15LCDDeviceLGLCD(G15LCDEngineLGLCD *e) : LCDDevice(), bEnabled(false) {
engine = e;
}
G15LCDDeviceLGLCD::~G15LCDDeviceLGLCD() {
}
bool G15LCDDeviceLGLCD::enabled() {
return bEnabled;
}
void G15LCDDeviceLGLCD::setEnabled(bool b) {
bEnabled = b;
if (bEnabled && (engine->llcContext.device == LGLCD_INVALID_DEVICE)) {
ZeroMemory(&engine->llcContext, sizeof(engine->llcContext));
engine->llcContext.connection = engine->llcceConnect.connection;
engine->llcContext.device = LGLCD_INVALID_DEVICE;
engine->llcContext.deviceType = LGLCD_DEVICE_BW;
DWORD dwErr = lgLcdOpenByType(&engine->llcContext);
} else if (!bEnabled && (engine->llcContext.device != LGLCD_INVALID_DEVICE)) {
lgLcdClose(engine->llcContext.device);
engine->llcContext.device = LGLCD_INVALID_DEVICE;
}
}
void G15LCDDeviceLGLCD::blitImage(QImage *img, bool alert) {
Q_ASSERT(img);
int len = G15_MAX_FBMEM_BITS;
uchar *tmp = img->bits();
lgLcdBitmap160x43x1 bitmap;
unsigned char *buf = bitmap.pixels;
if (engine->llcContext.device == LGLCD_INVALID_DEVICE)
return;
if (!bEnabled)
return;
/*
* The amount of copying/conversion we're doing is hideous.
*
* To draw to the LCD display using Logitech's SDK, we need to pass
* it a byte array (in which each byte represents a single pixel on
* the LCD.)
*
* Unfortunately, there's no way out, really. We *could* perhaps draw
* directly to a monochrome "bytemap" (via Format_Indexed8, and a mono-
* chrome colormap), but QPainter simply doesn't want to draw to a
* QImage of Format_Indexed8.
*
* (What's even worse is that the byte array passed to the Logitech SDK
* isn't even the native format of the LCD. It has to convert it once
* more, when it receives a frame.)
*/
for (int i = 0; i < len; i++) {
int idx = i * 8;
buf[idx + 7] = tmp[i] & 0x80 ? 0xff : 0x00;
buf[idx + 6] = tmp[i] & 0x40 ? 0xff : 0x00;
buf[idx + 5] = tmp[i] & 0x20 ? 0xff : 0x00;
buf[idx + 4] = tmp[i] & 0x10 ? 0xff : 0x00;
buf[idx + 3] = tmp[i] & 0x08 ? 0xff : 0x00;
buf[idx + 2] = tmp[i] & 0x04 ? 0xff : 0x00;
buf[idx + 1] = tmp[i] & 0x02 ? 0xff : 0x00;
buf[idx + 0] = tmp[i] & 0x01 ? 0xff : 0x00;
}
bitmap.hdr.Format = LGLCD_BMP_FORMAT_160x43x1;
DWORD dwErr =
lgLcdUpdateBitmap(engine->llcContext.device, &bitmap.hdr,
alert ? LGLCD_SYNC_UPDATE(LGLCD_PRIORITY_ALERT) : LGLCD_SYNC_UPDATE(LGLCD_PRIORITY_NORMAL));
}
QString G15LCDDeviceLGLCD::name() const {
return QString::fromLatin1("Logitech Gamepanel");
}
QSize G15LCDDeviceLGLCD::size() const {
return QSize(G15_MAX_WIDTH, G15_MAX_HEIGHT);
}
#undef G15_MAX_DEV
#undef G15_MAX_WIDTH
#undef G15_MAX_HEIGHT
#undef G15_MAX_BPP
#undef G15_MAX_FBMEM
#undef G15_MAX_FBMEM_BITS
#undef G15_WIDGET_NAME