Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c28f1c7
Autogenerated conversion of .sln to cmake using cmake_converter
charlestytler Jan 14, 2026
26c0ca8
Update gitignore for Cmake and cleanup old VS+Nuget options
charlestytler Jan 14, 2026
6300f5a
Include json, lua-5.4.8, google test as vendored/fetched code instead…
charlestytler Jan 15, 2026
5bc56c6
Add root CMakeLists.txt with placeholders for subdirectories
charlestytler Jan 15, 2026
5e0d114
CMakeLists.txt added for ElgatoSD static library
charlestytler Jan 15, 2026
51a7db4
CMakeLists.txt added for Utilities static library
charlestytler Jan 15, 2026
7d4d03f
CMakeLists.txt added for SimulatorInterface static library
charlestytler Jan 15, 2026
7a329a9
CMakeLists.txt added for StreamdeckContext static library
charlestytler Jan 15, 2026
7d822ce
Cleanup static library CMake files to common style
charlestytler Jan 15, 2026
30f99cf
Add executable StreamdeckInterface to CMake files
charlestytler Jan 15, 2026
a31e5cf
Include google test in CMake project with one library's tests - Utilties
charlestytler Jan 15, 2026
27355fb
Update gitignore for ctest outputs
charlestytler Jan 16, 2026
97f132b
Test CMakeLists.txt files for all other library test directories
charlestytler Jan 16, 2026
2b21c32
Create MockESDConnectionManager test cmake target
charlestytler Jan 16, 2026
2c6333f
Format cmake files with gersemi
charlestytler Jan 16, 2026
649949a
Use CMAKE_SOURCE_DIR (backend-cpp/) as include root in cmake libraries
charlestytler Jan 17, 2026
9bdd4a7
Cleanup autogen files and undo include changes (save for later PR)
charlestytler Jan 17, 2026
e09378e
Specify exe output dir and copy necessary runtime DLLs to same location
charlestytler Jan 17, 2026
a0fafba
Update gitignore
charlestytler Jan 17, 2026
dec586f
Update build scripts to use cmake
charlestytler Jan 17, 2026
621149b
Update outdated codecov.yml
charlestytler Jan 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions .github/workflows/cpp-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,25 @@ on:
workflow_dispatch:

env:
# Path to the solution file relative to the root of the project.
SOLUTION_FILE_PATH: ./Sources/backend-cpp/Windows/com.ctytler.dcs.sdPlugin.sln

# Configuration type to build.
# You can convert this to a build matrix if you need coverage of multiple configuration types.
# https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
BUILD_CONFIGURATION: Release
SOURCE_DIR: ./Sources/backend-cpp
BUILD_DIR: ./Sources/backend-cpp/build

jobs:
build:
runs-on: windows-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2

- name: Restore NuGet packages
working-directory: ${{env.GITHUB_WORKSPACE}}
run: nuget restore ${{env.SOLUTION_FILE_PATH}}
- name: CMake
run: cmake -S ${{env.SOURCE_DIR}} -B ${{env.BUILD_DIR}} -A x64 -DBUILD_TESTING=ON

- name: Build
working-directory: ${{env.GITHUB_WORKSPACE}}
# Add additional options to the MSBuild command line here (like platform or verbosity level).
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}}
run: cmake --build ${{env.BUILD_DIR}} --config RelWithDebInfo

- name: Setup OpenCppCoverage and add to PATH
id: setup_opencppcoverage
Expand All @@ -50,11 +41,22 @@ jobs:
- name: Run C++ Unit Tests and Generate Coverage Report
id: generate_test_report
shell: cmd
run: OpenCppCoverage.exe --sources Sources\backend-cpp --excluded_sources Vendor --excluded_sources Windows --export_type cobertura:StreamdeckDcsInterfaceCov.xml .\Sources\backend-cpp\Windows\x64\Release\Test.exe
run: |
OpenCppCoverage.exe ^
--quiet ^
--sources Sources\backend-cpp ^
--excluded_sources Vendor ^
--excluded_sources Windows ^
--excluded_sources Tools ^
--export_type cobertura:StreamdeckDcsInterfaceCov.xml ^
--cover_children ^
-- ctest --test-dir ./${{env.BUILD_DIR}} -C RelWithDebInfo --output-on-failure

- name: Upload Report to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./StreamdeckDcsInterfaceCov.xml
flags: Cpp
disable_search: true

66 changes: 47 additions & 19 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,25 +1,53 @@
# Project-specific Ignore List
settingsUI/

# --- CMake Artifacts ---
# Ignore the entire build directory (assuming you name it 'build' or 'out')
build/
out/
Testing/

# If you accidentally build in the root directory (In-Source Build),
# these lines will catch the mess:
CMakeFiles/
CMakeCache.txt
CMakeScripts/
cmake_install.cmake
install_manifest.txt
compile_commands.json
_deps/
*.cmake

# --- CMake Presets ---
# CMakePresets.json IS usually committed (it shares build configs with the team)
# CMakeUserPresets.json is NOT committed (it contains your personal paths)
CMakeUserPresets.json

# --- IDE Specifics ---
# Visual Studio
.vs/
*.sln
*.vcxproj
*.vcxproj.filters
*.user
*.suo
packages/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
settingsUI/

# VS Code
.vscode/
!.vscode/extensions.json # Keep this if you want to suggest extensions

# --- Output Binaries ---
*.exe
*.dll
*.pdb
*.lib
*.obj
*.ilk
*.exp

# --- Log Files ---
*.log
.vs/
.vscode
*.user

# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
60 changes: 60 additions & 0 deletions Sources/backend-cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
cmake_minimum_required(VERSION 3.23)

# Note: C is included because of the Vendor/lua-5.4.8 C library
project(StreamdeckPluginBackend LANGUAGES C CXX)

# Force the use of the Dynamic Runtime (/MD and /MDd) across the whole project
# This is added to align with the Vendored websocketpp library
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")

# Global C++ Settings
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

if(MSVC)
add_compile_options(
/W3 # Warning Level 3
/WX # Treat Warning As Error
/sdl # Enable Security Checks
/MP # Multi-processor compilation
/Zc:__cplusplus # Correct __cplusplus macro
)
endif()

add_compile_definitions(UNICODE _UNICODE _CONSOLE)
# TODO: If you are using _CONSOLE, you might see a black command prompt
# window pop up when your plugin starts. If you eventually want your
# plugin to run silently in the background without that window,
# you would change your project type to a Windows Application and use
# _WINDOWS instead of _CONSOLE, but for development and debugging,
# using _CONSOLE is much easier because you can see your log output.

# Testing
include(CTest)

if(BUILD_TESTING)
include(FetchContent)

FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest
GIT_TAG v1.17.0
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)

# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(googletest)
endif()

# Libraries
add_subdirectory(Vendor)
add_subdirectory(Utilities)
add_subdirectory(ElgatoSD)
add_subdirectory(SimulatorInterface)
add_subdirectory(StreamdeckContext)

# Executable
add_subdirectory(StreamdeckInterface)
29 changes: 29 additions & 0 deletions Sources/backend-cpp/ElgatoSD/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
add_library(ElgatoSD STATIC)

target_sources(
ElgatoSD
PRIVATE
ESDConnectionManager.cpp
ESDLocalizer.cpp
ESDUtilitiesWindows.cpp
pch.cpp
PUBLIC
FILE_SET HEADERS
BASE_DIRS ${CMAKE_SOURCE_DIR}
FILES
EPLJSONUtils.h
ESDBasePlugin.h
ESDConnectionManager.h
ESDLocalizer.h
ESDSDKDefines.h
ESDUtilities.h
pch.h
# TODO: Consider deleting the pch.* files,
# as they are not used as precompiled headers
)

target_link_libraries(ElgatoSD PUBLIC nlohmann_json websocketpp)

if(BUILD_TESTING)
add_subdirectory(test)
endif()
10 changes: 6 additions & 4 deletions Sources/backend-cpp/ElgatoSD/ESDConnectionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
#include "ESDBasePlugin.h"
#include "ESDSDKDefines.h"

#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE
#include <Vendor/websocketpp/websocketpp/client.hpp>
#include <Vendor/websocketpp/websocketpp/common/memory.hpp>
#include <Vendor/websocketpp/websocketpp/common/thread.hpp>
#include <Vendor/websocketpp/websocketpp/config/asio_no_tls_client.hpp>
#endif
#include <websocketpp/client.hpp>
#include <websocketpp/common/memory.hpp>
#include <websocketpp/common/thread.hpp>
#include <websocketpp/config/asio_no_tls_client.hpp>

typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
typedef websocketpp::client<websocketpp::config::asio_client> WebsocketClient;
Expand Down
8 changes: 8 additions & 0 deletions Sources/backend-cpp/ElgatoSD/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
add_library(MockESDConnectionManager INTERFACE)

target_sources(MockESDConnectionManager INTERFACE MockESDConnectionManager.h)

target_include_directories(
MockESDConnectionManager
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
109 changes: 109 additions & 0 deletions Sources/backend-cpp/ElgatoSD/test/MockESDConnectionManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2021 Charles Tytler
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file was copied from a top level Test directory, backend-cpp/Test/MockESDConnectionManager.h. Original file will be deleted later.


/***
*
* This file holds Mock classes of Elgato Streamdeck code that can be passed to plugin code for unit testing Streamdeck
* context management. The mocked ESDConnectionManager prevents actual websockets to the Streamdeck from being opened in
* the unit tests and instead allows output commands to be inspected.
*
***/

#pragma once

#include "ElgatoSD/ESDBasePlugin.h"
#include "ElgatoSD/ESDConnectionManager.h"

class MockPlugin : public ESDBasePlugin
{
public:
MockPlugin() {}
virtual ~MockPlugin() {}

void SetConnectionManager(ESDConnectionManager *inConnectionManager) { mConnectionManager = inConnectionManager; }

virtual void KeyDownForAction(const std::string &inAction,
const std::string &inContext,
const json &inPayload,
const std::string &inDeviceID)
{
}
virtual void KeyUpForAction(const std::string &inAction,
const std::string &inContext,
const json &inPayload,
const std::string &inDeviceID)
{
}

virtual void WillAppearForAction(const std::string &inAction,
const std::string &inContext,
const json &inPayload,
const std::string &inDeviceID)
{
}
virtual void WillDisappearForAction(const std::string &inAction,
const std::string &inContext,
const json &inPayload,
const std::string &inDeviceID)
{
}

virtual void DeviceDidConnect(const std::string &inDeviceID, const json &inDeviceInfo) {}
virtual void DeviceDidDisconnect(const std::string &inDeviceID) {}

virtual void DidReceiveGlobalSettings(const json &inPayload) {}

virtual void SendToPlugin(const std::string &inAction,
const std::string &inContext,
const json &inPayload,
const std::string &inDeviceID)
{
}
};

class MockESDConnectionManager : public ESDConnectionManager
{
public:
// MOCK_METHOD(void, SetState, (int state, std::string context), (override));
// MOCK_METHOD(void, SetTitle, (std::string title, std::string context, int flag), (override));
MockESDConnectionManager() : ESDConnectionManager(0, "", "", "", &plugin_) {}
// ESDBasePlugin *inPlugin) {}

void SetState(int inState, const std::string &inContext)
{
context_ = inContext;
state_ = inState;
num_calls_to_SetState++;
}

void SetImage(const std::string &inBase64ImageString, const std::string &inContext, ESDSDKTarget inTarget)
{
context_ = inContext;
base64_image_string_ = inBase64ImageString;
num_calls_to_SetImage++;
}

void SetTitle(const std::string &inTitle, const std::string &inContext, ESDSDKTarget inTarget)
{
context_ = inContext;
title_ = inTitle;
num_calls_to_SetTitle++;
}

// Only in mock class:
void clear_buffer()
{
context_ = "";
state_ = 0;
title_ = "";
}

MockPlugin plugin_;
std::string context_ = "";
int state_ = 0;
std::string base64_image_string_ = "";
std::string title_ = "";

int num_calls_to_SetState = 0;
int num_calls_to_SetImage = 0;
int num_calls_to_SetTitle = 0;
};
29 changes: 29 additions & 0 deletions Sources/backend-cpp/SimulatorInterface/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
add_library(SimulatorInterface STATIC)

target_sources(
SimulatorInterface
PRIVATE
SimConnectionManager.cpp
SimulatorInterface.cpp
Protocols/DcsBiosProtocol.cpp
Protocols/DcsBiosProtocol.h
Protocols/DcsBiosStreamParser.cpp
Protocols/DcsBiosStreamParser.h
Protocols/DcsExportScriptProtocol.cpp
Protocols/DcsExportScriptProtocol.h
PUBLIC
FILE_SET HEADERS
BASE_DIRS ${CMAKE_SOURCE_DIR}
FILES
SimConnectionManager.h
SimulatorInterface.h
SimulatorInterfaceParameters.h
SimulatorProtocolTypes.h
)

target_link_libraries(SimulatorInterface PUBLIC Utilities)

if(BUILD_TESTING)
add_subdirectory(test)
add_subdirectory(Protocols/test)
endif()
Loading