// Copyright 2005-2019 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 . #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 registrar(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 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); }