Skip to content

Commit

Permalink
Add support for status details to help in diagnosing issues:
Browse files Browse the repository at this point in the history
- Add bool+string detailed status result type
- Modify API wrappers to return detailed status results
- Add right-click menu to show detailed status results
  • Loading branch information
HunterZ committed Mar 18, 2018
1 parent 052d67b commit f732c0e
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 86 deletions.
50 changes: 8 additions & 42 deletions UniLight/CUEUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "CUEUtil.h"

#include "CUESDK.h"

#include <tchar.h>
#include <vector>

namespace CUEUtil
Expand All @@ -18,7 +18,7 @@ namespace CUEUtil
{
}

bool CUEUtilC::SetCUEColor(unsigned char red, unsigned char green, unsigned char blue)
ResultT CUEUtilC::SetCUEColor(unsigned char red, unsigned char green, unsigned char blue)
{
// scoop up desired LED IDs and associated colors into a vector
std::vector<CorsairLedColor> ledVector;
Expand All @@ -30,47 +30,13 @@ namespace CUEUtil
ledVector.push_back(CorsairLedColor{ static_cast<CorsairLedId>(i), red, green, blue });
}

/*
// get number of Corsair devices
// need to enumerate devices on every call, in case of hot swapping
const int deviceCount(CorsairGetDeviceCount());
// loop over list of devices
for (int i(0); i < deviceCount; ++i)
{
CorsairDeviceInfo* deviceInfoPtr(CorsairGetDeviceInfo(i));
switch (deviceInfoPtr->type)
{
case CDT_Unknown:
// obviously this is unsupported
break;
case CDT_Mouse:
break;
case CDT_Keyboard:
case CDT_MouseMat:
{
// keyboards and mousemats support CorsairGetLedPositionsByDeviceIndex()
CorsairLedPositions* ledPositionsPtr(CorsairGetLedPositionsByDeviceIndex(i));
for (int j(0); j < ledPositionsPtr->numberOfLed; ++j)
{
ledVector.push_back(CorsairLedColor{ ledPositionsPtr->pLedPosition[j].ledId, red, green, blue });
}
}
break;
case CDT_Headset:
break;
case CDT_HeadsetStand:
break;
}
}
*/

if (ledVector.empty()) return false;
if (ledVector.empty())
return ResultT(false, _T("SetCUEColor() found no IDs"));

// don't really care if it fully succeeds, so call async with NULL
return CorsairSetLedsColorsAsync(ledVector.size(), ledVector.data(), 0, 0);
if (!CorsairSetLedsColorsAsync(ledVector.size(), ledVector.data(), 0, 0))
return ResultT(false, _T("CorsairSetLedsColorsAsync() failed"));

return ResultT(true, _T("SetCUEColor() success"));
}
}
4 changes: 3 additions & 1 deletion UniLight/CUEUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#pragma once

#include "UniLight.h"

// utilities for working with Corsair Utility Engine (CUE) API
namespace CUEUtil
{
Expand All @@ -13,6 +15,6 @@ namespace CUEUtil

virtual ~CUEUtilC();

bool SetCUEColor(unsigned char red, unsigned char green, unsigned char blue);
ResultT SetCUEColor(unsigned char red, unsigned char green, unsigned char blue);
};
}
35 changes: 23 additions & 12 deletions UniLight/LFXUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ namespace

bool initialized(false);

bool InitLFX()
ResultT InitLFX()
{
if (initialized) return true;
if (initialized)
return ResultT(true, _T("Already initialized"));

// Dell is stupid and forces us to manually load the DLL and bind its functions
hLibrary = LoadLibrary(_T(LFX_DLL_NAME));
if (!hLibrary) return false;
if (!hLibrary)
return ResultT(false, _T("LoadLibrary() failed"));

_LFX_Initialize = (LFX2INITIALIZE)GetProcAddress(hLibrary, LFX_DLL_INITIALIZE);
_LFX_Release = (LFX2RELEASE)GetProcAddress(hLibrary, LFX_DLL_RELEASE);
Expand All @@ -73,9 +75,11 @@ namespace
_LFX_SetTiming = (LFX2SETTIMING)GetProcAddress(hLibrary, LFX_DLL_SETTIMING);
_LFX_GetVersion = (LFX2GETVERSION)GetProcAddress(hLibrary, LFX_DLL_GETVERSION);

LFX_RESULT result(_LFX_Initialize());
initialized = (result == LFX_SUCCESS);
return initialized;
if (_LFX_Initialize() != LFX_SUCCESS)
return ResultT(false, _T("_LFX_Initialize() failed"));

initialized = true;
return ResultT(true, _T("InitFX() success"));
}
}

Expand All @@ -91,25 +95,32 @@ namespace LFXUtil
}
}

bool LFXUtilC::SetLFXColor(unsigned char red, unsigned char green, unsigned char blue)
ResultT LFXUtilC::SetLFXColor(unsigned char red, unsigned char green, unsigned char blue)
{
// perform lazy initialization
// this should support a device being plugged in after the program has already started running
// abort if initialization fails
if (!initialized && !InitLFX()) return false;
const ResultT& result(InitLFX());
if (!result.first)
return result;

// Reset the state machine and await light settings
if (_LFX_Reset() != LFX_SUCCESS) return false;
if (_LFX_Reset() != LFX_SUCCESS)
return ResultT(false, _T("_LFX_Reset() failed"));

// Set all lights to color
static ColorU color;
color.cs.red = red;
color.cs.green = green;
color.cs.blue = blue;
color.cs.brightness = 0xFF;
if (_LFX_Light(LFX_ALL, color.ci) != LFX_SUCCESS) return false;
if (_LFX_Light(LFX_ALL, color.ci) != LFX_SUCCESS)
return ResultT(false, _T("_LFX_Light() failed"));

// Update the state machine, which causes the physical color change
if (_LFX_Update() != LFX_SUCCESS) return false;
if (_LFX_Update() != LFX_SUCCESS)
return ResultT(false, _T("_LFX_Update() failed"));

return true;
return ResultT(true, _T("SetLFXColor() success"));
}
}
4 changes: 3 additions & 1 deletion UniLight/LFXUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#pragma once

#include "UniLight.h"

// utilities for working with Dell LightFX/AlienFX API
namespace LFXUtil
{
Expand All @@ -16,6 +18,6 @@ namespace LFXUtil

// set LFX color to given RGB value
// returns true on success, false on failure
bool SetLFXColor(unsigned char red, unsigned char green, unsigned char blue);
ResultT SetLFXColor(unsigned char red, unsigned char green, unsigned char blue);
};
}
42 changes: 26 additions & 16 deletions UniLight/LLEDUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "LLEDUtil.h"

#include "LogitechLEDLib.h"
#include <tchar.h>

namespace
{
Expand All @@ -15,17 +16,19 @@ namespace

bool initialized(false);

bool initLLED()
ResultT initLLED()
{
if (initialized) return true;
if (initialized)
return ResultT(true, _T("Already initialized"));

if (LogiLedInit())
{
LogiLedSaveCurrentLighting();
initialized = true;
}
if (!LogiLedInit())
return ResultT(false, _T("LogiLedInit() failed"));

return initialized;
// save previous lighting state as courtesy to user
// don't care if this succeeds though
LogiLedSaveCurrentLighting();
initialized = true;
return ResultT(true, _T("initLLED() success"));
}
}

Expand All @@ -39,18 +42,25 @@ namespace LLEDUtil

LLEDUtilC::~LLEDUtilC()
{
// attempt to restore original state
// don't care if these succeed
LogiLedRestoreLighting();

LogiLedShutdown();
initialized = false;
}

bool LLEDUtilC::SetLLEDColor(unsigned char red, unsigned char green, unsigned char blue)
ResultT LLEDUtilC::SetLLEDColor(unsigned char red, unsigned char green, unsigned char blue)
{
return
(
initLLED() &&
LogiLedSetTargetDevice(LOGI_DEVICETYPE_PERKEY_RGB | LOGI_DEVICETYPE_RGB) &&
LogiLedSetLighting(b2p(red), b2p(green), b2p(blue))
);
const ResultT& result(initLLED());
if (!result.first)
return result;

if (!LogiLedSetTargetDevice(LOGI_DEVICETYPE_PERKEY_RGB | LOGI_DEVICETYPE_RGB))
return ResultT(false, _T("LogiLedSetTargetDevice() failed"));

if (!LogiLedSetLighting(b2p(red), b2p(green), b2p(blue)))
return ResultT(false, _T("LogiLedSetLighting() failed"));

return ResultT(true, _T("SetLLEDColor() success"));
}
}
4 changes: 3 additions & 1 deletion UniLight/LLEDUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#pragma once

#include "UniLight.h"

// utilities for working with Logitech Gaming LED API
namespace LLEDUtil
{
Expand All @@ -13,6 +15,6 @@ namespace LLEDUtil

virtual ~LLEDUtilC();

bool SetLLEDColor(unsigned char red, unsigned char green, unsigned char blue);
ResultT SetLLEDColor(unsigned char red, unsigned char green, unsigned char blue);
};
}
57 changes: 44 additions & 13 deletions UniLight/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ typedef struct _iobuf FILE;
#include "LFXUtil.h"
#include "LLEDUtil.h"
#include "resource.h"
#include "UniLight.h"

#include <iomanip>
#include <sstream>
Expand All @@ -34,21 +35,33 @@ typedef struct _iobuf FILE;
*/
#define ID_TRAY_APP_ICON 1001
#define ID_TRAY_SYNC 1002
#define ID_TRAY_ABOUT 1003
#define ID_TRAY_EXIT 1004
#define ID_TRAY_STATUS 1003
#define ID_TRAY_ABOUT 1004
#define ID_TRAY_EXIT 1005
#define WM_SYSICON (WM_USER + 1)

namespace
{
UINT WM_TASKBARCREATED(0);
HMENU Hmenu;
NOTIFYICONDATA notifyIconData;
const LPCWSTR szTIP(_T("UniLight"));
const LPCWSTR szTIP(_T("UniLight status:\n...initializing..."));
const LPCWSTR szClassName(_T("UniLight"));
CUEUtil::CUEUtilC cueUtil;
LFXUtil::LFXUtilC lfxUtil;
LLEDUtil::LLEDUtilC llledUtil;
COLORREF lastColor(0);
ResultT cueStatus(false, _T("Not yet initialized"));
ResultT lfxStatus(false, _T("Not yet initialized"));
ResultT lledStatus(false, _T("Not yet initialized"));
const std::wstring sSuccess(_T("SUCCESS"));
const std::wstring sFailure(_T("FAILURE"));
const std::wstring sIndent2(_T("\n\t\t"));
const std::wstring sCUEStatus(_T("\n\n\tCorsair CUE:"));
const std::wstring sLFXStatus(_T("\n\n\tDell/Alienware AlienFX/LightFX:"));
const std::wstring sLLEDStatus(_T("\n\n\tLogitech LED:"));
const wchar_t cSuccess(0x2714); // check mark
const wchar_t cFailure(0x2716); // cross mark
}
/*
// maximum mumber of lines the output console should have
Expand Down Expand Up @@ -82,30 +95,46 @@ void ShowAbout(HWND hwnd)
active = false;
}

void ShowStatus(HWND hwnd)
{
SetForegroundWindow(hwnd);
std::wstring status(_T("Snapshot of status details from most recent synchronization:\n"));
status += sCUEStatus
+ sIndent2 + (cueStatus.first ? sSuccess : sFailure)
+ sIndent2 + cueStatus.second;
status += sLFXStatus
+ sIndent2 + (lfxStatus.first ? sSuccess : sFailure)
+ sIndent2 + lfxStatus.second;
status += sLLEDStatus
+ sIndent2 + (lledStatus.first ? sSuccess : sFailure)
+ sIndent2 + lledStatus.second;
MessageBox(hwnd, status.c_str(), _T("UniLight detailed status"), NULL);
}

void UpdateColor(const COLORREF curColor)
{
const unsigned char red(GetRValue(curColor));
const unsigned char green(GetGValue(curColor));
const unsigned char blue(GetBValue(curColor));

// set Corsair CUE color
const bool cueStatus(cueUtil.SetCUEColor(red, green, blue));
cueStatus = cueUtil.SetCUEColor(red, green, blue);

// set AlienFX/LightFX color
const bool lfxStatus(lfxUtil.SetLFXColor(red, green, blue));
lfxStatus = lfxUtil.SetLFXColor(red, green, blue);

// set Logitech LED color
const bool lledStatus(llledUtil.SetLLEDColor(red, green, blue));
lledStatus = llledUtil.SetLLEDColor(red, green, blue);

// set tooltip
std::wstringstream s;
s << "UniLight status:";
s << "\nCurrent color: 0x" << std::setfill(L'0') << std::setw(8) << std::hex << curColor;
s << "\nPrevious color: 0x" << std::setfill(L'0') << std::setw(8) << std::hex << lastColor;
s << "\nCorsCUE: " << (cueStatus ? "active" : "inactive");
s << "\nLightFX: " << (lfxStatus ? "active" : "inactive");
s << "\nLogiLED: " << (lledStatus ? "active" : "inactive");
StringCchCopy(notifyIconData.szTip, 128, s.str().c_str());
s << "\nCorsCUE: " << (cueStatus.first ? cSuccess : cFailure);
s << "\nLightFX: " << (lfxStatus.first ? cSuccess : cFailure);
s << "\nLogiLED: " << (lledStatus.first ? cSuccess : cFailure);
StringCchCopy(notifyIconData.szTip, sizeof(notifyIconData.szTip), s.str().c_str());
Shell_NotifyIcon(NIM_MODIFY, &notifyIconData);

// update last-seen color to new value
Expand Down Expand Up @@ -158,9 +187,10 @@ LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM
const UINT clicked(TrackPopupMenu(Hmenu, TPM_RETURNCMD | TPM_NONOTIFY, curPoint.x, curPoint.y, 0, hwnd, NULL));
switch (clicked)
{
case ID_TRAY_SYNC: GetAndUpdateColor(); break; // manual color sync
case ID_TRAY_ABOUT: ShowAbout(hwnd); break; // show about menu
case ID_TRAY_EXIT: PostQuitMessage(0); break; // quit the application
case ID_TRAY_SYNC: GetAndUpdateColor(); break; // manual color sync
case ID_TRAY_ABOUT: ShowAbout(hwnd); break; // show about menu
case ID_TRAY_STATUS: ShowStatus(hwnd); break; // show detailed status
case ID_TRAY_EXIT: PostQuitMessage(0); break; // quit the application
}
}
}
Expand Down Expand Up @@ -199,6 +229,7 @@ int WINAPI WinMain(HINSTANCE hThisInstance,
Hmenu = CreatePopupMenu();
AppendMenu(Hmenu, MF_STRING, ID_TRAY_SYNC, TEXT("Synchronize manually"));
SetMenuDefaultItem(Hmenu, ID_TRAY_SYNC, FALSE);
AppendMenu(Hmenu, MF_STRING, ID_TRAY_STATUS, TEXT("Detailed status..."));
AppendMenu(Hmenu, MF_STRING, ID_TRAY_ABOUT, TEXT("About UniLight..."));
AppendMenu(Hmenu, MF_STRING, ID_TRAY_EXIT, TEXT("Exit"));

Expand Down
Loading

0 comments on commit f732c0e

Please sign in to comment.