├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── Sources ├── CMakeLists.txt ├── MyStreamDeckPlugin.cpp ├── MyStreamDeckPlugin.h ├── StreamDeckSDK.cmake ├── Windows │ ├── CpuUsageHelper.cpp │ └── CpuUsageHelper.h ├── com.elgato.cpu.sdPlugin │ ├── de.json │ ├── defaultImage.png │ ├── defaultImage@2x.png │ ├── en.json │ ├── es.json │ ├── fr.json │ ├── icon.png │ ├── icon@2x.png │ ├── ja.json │ ├── ko.json │ ├── manifest.json │ ├── pluginIcon.png │ ├── pluginIcon@2x.png │ └── zh_CN.json ├── macOS │ ├── CpuUsageHelper.h │ └── CpuUsageHelper.mm └── main.cpp └── screenshot.png /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | on: [push, pull_request] 3 | jobs: 4 | build: 5 | name: ${{matrix.os}}/${{matrix.build-type}} 6 | runs-on: ${{matrix.os}}-latest 7 | steps: 8 | - uses: actions/checkout@v4 9 | - name: Make build directory 10 | run: cmake -E make_directory build 11 | - name: Configure 12 | working-directory: build 13 | run: | 14 | cmake ../Sources \ 15 | -DCMAKE_BUILD_TYPE=${{matrix.build-type}} 16 | shell: bash 17 | - name: Compile 18 | working-directory: build 19 | run: cmake --build . --config ${{matrix.build-type}} 20 | - name: Upload binary (Mac) 21 | if: matrix.os == 'macos' 22 | uses: actions/upload-artifact@v4 23 | with: 24 | name: cpu-${{matrix.build-type}} 25 | path: build/cpu 26 | - name: Upload binary (Windows) 27 | if: matrix.os == 'windows' 28 | uses: actions/upload-artifact@v4 29 | with: 30 | name: cpu-${{matrix.build-type}}.exe 31 | path: build/${{matrix.build-type}}/cpu.exe 32 | strategy: 33 | matrix: 34 | os: [windows, macos] 35 | build-type: [Release, Debug] 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode 3 | *.swp 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2018 Corsair Memory, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | `CPU` is a sample plugin demonstrating the [Stream Deck SDK](https://developer.elgato.com/documentation/stream-deck/). 3 | 4 | 5 | # Description 6 | 7 | `CPU` is a plugin that displays the CPU usage on a key. 8 | 9 | 10 | # Features 11 | 12 | - code written in C++ 13 | - cross-platform (macOS, Windows) 14 | - localized 15 | 16 | 17 | ![](screenshot.png) 18 | 19 | 20 | # Installation 21 | 22 | In the Release folder, you can find the file `com.elgato.cpu.streamDeckPlugin`. If you double-click this file on your machine, Stream Deck will install the plugin. 23 | 24 | 25 | # Source code 26 | 27 | The Sources folder contains the source code of the plugin. 28 | -------------------------------------------------------------------------------- /Sources/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(com.elgato.cpu VERSION 1.4.2) 4 | 5 | if (APPLE) 6 | set( 7 | STREAMDECK_PLUGIN_DIR 8 | "$ENV{HOME}/Library/ApplicationSupport/com.elgato.StreamDeck/Plugins" 9 | ) 10 | find_library(APPKIT_LIBRARY AppKit) 11 | set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64") 12 | endif() 13 | set( 14 | CMAKE_INSTALL_PREFIX 15 | "${STREAMDECK_PLUGIN_DIR}/${CMAKE_PROJECT_NAME}" 16 | CACHE STRING "See cmake documentation" 17 | ) 18 | 19 | set(CMAKE_CXX_STANDARD 23) 20 | set(CXX_STANDARD_REQUIRED true) 21 | if (MSVC) 22 | add_definitions("/Zc:__cplusplus" -DUNICODE=1) 23 | endif() 24 | include_directories("${CMAKE_SOURCE_DIR}") 25 | 26 | include("StreamDeckSDK.cmake") 27 | 28 | set( 29 | SOURCES 30 | MyStreamDeckPlugin.cpp 31 | main.cpp 32 | ) 33 | set( 34 | EXTRA_LIBS 35 | StreamDeckSDK 36 | ) 37 | if (APPLE) 38 | list(APPEND SOURCES macOS/CpuUsageHelper.mm) 39 | list(APPEND EXTRA_LIBS ${APPKIT_LIBRARY}) 40 | elseif (WIN32) 41 | list(APPEND SOURCES Windows/CpuUsageHelper.cpp) 42 | endif() 43 | add_executable( 44 | cpu 45 | ${SOURCES} 46 | ) 47 | target_link_libraries(cpu ${EXTRA_LIBS}) 48 | -------------------------------------------------------------------------------- /Sources/MyStreamDeckPlugin.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | /** 3 | @file MyStreamDeckPlugin.cpp 4 | 5 | @brief CPU plugin 6 | 7 | @copyright (c) 2018, Corsair Memory, Inc. 8 | This source code is licensed under the MIT-style license found in the LICENSE file. 9 | 10 | **/ 11 | //============================================================================== 12 | 13 | #include "MyStreamDeckPlugin.h" 14 | #include 15 | 16 | #ifdef __APPLE__ 17 | #include "macOS/CpuUsageHelper.h" 18 | #else 19 | #include "Windows/CpuUsageHelper.h" 20 | #endif 21 | 22 | #include 23 | 24 | class CallBackTimer 25 | { 26 | public: 27 | CallBackTimer() :_execute(false) { } 28 | 29 | ~CallBackTimer() 30 | { 31 | if( _execute.load(std::memory_order_acquire) ) 32 | { 33 | stop(); 34 | }; 35 | } 36 | 37 | void stop() 38 | { 39 | _execute.store(false, std::memory_order_release); 40 | if(_thd.joinable()) 41 | _thd.join(); 42 | } 43 | 44 | void start(int interval, std::function func) 45 | { 46 | if(_execute.load(std::memory_order_acquire)) 47 | { 48 | stop(); 49 | }; 50 | _execute.store(true, std::memory_order_release); 51 | _thd = std::thread([this, interval, func]() 52 | { 53 | while (_execute.load(std::memory_order_acquire)) 54 | { 55 | func(); 56 | std::this_thread::sleep_for(std::chrono::milliseconds(interval)); 57 | } 58 | }); 59 | } 60 | 61 | bool is_running() const noexcept 62 | { 63 | return (_execute.load(std::memory_order_acquire) && _thd.joinable()); 64 | } 65 | 66 | private: 67 | std::atomic _execute; 68 | std::thread _thd; 69 | }; 70 | 71 | MyStreamDeckPlugin::MyStreamDeckPlugin() 72 | { 73 | mCpuUsageHelper = new CpuUsageHelper(); 74 | mTimer = new CallBackTimer(); 75 | mTimer->start(1000, [this]() 76 | { 77 | this->UpdateTimer(); 78 | }); 79 | } 80 | 81 | MyStreamDeckPlugin::~MyStreamDeckPlugin() 82 | { 83 | if(mTimer != nullptr) 84 | { 85 | mTimer->stop(); 86 | 87 | delete mTimer; 88 | mTimer = nullptr; 89 | } 90 | 91 | if(mCpuUsageHelper != nullptr) 92 | { 93 | delete mCpuUsageHelper; 94 | mCpuUsageHelper = nullptr; 95 | } 96 | } 97 | 98 | void MyStreamDeckPlugin::UpdateTimer() 99 | { 100 | // 101 | // Warning: UpdateTimer() is running in the timer thread 102 | // 103 | if(mConnectionManager != nullptr) 104 | { 105 | mVisibleContextsMutex.lock(); 106 | int currentValue = mCpuUsageHelper->GetCurrentCPUValue(); 107 | for (const std::string& context : mVisibleContexts) 108 | { 109 | mConnectionManager->SetTitle(std::to_string(currentValue) + "%", context, kESDSDKTarget_HardwareAndSoftware); 110 | } 111 | mVisibleContextsMutex.unlock(); 112 | } 113 | } 114 | 115 | void MyStreamDeckPlugin::KeyDownForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) 116 | { 117 | // Nothing to do 118 | } 119 | 120 | void MyStreamDeckPlugin::KeyUpForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) 121 | { 122 | mCpuUsageHelper->OpenSystemMonitor(); 123 | } 124 | 125 | void MyStreamDeckPlugin::WillAppearForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) 126 | { 127 | // Remember the context 128 | mVisibleContextsMutex.lock(); 129 | mVisibleContexts.insert(inContext); 130 | mVisibleContextsMutex.unlock(); 131 | } 132 | 133 | void MyStreamDeckPlugin::WillDisappearForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) 134 | { 135 | // Remove the context 136 | mVisibleContextsMutex.lock(); 137 | mVisibleContexts.erase(inContext); 138 | mVisibleContextsMutex.unlock(); 139 | } 140 | 141 | void MyStreamDeckPlugin::DeviceDidConnect(const std::string& inDeviceID, const json &inDeviceInfo) 142 | { 143 | // Nothing to do 144 | } 145 | 146 | void MyStreamDeckPlugin::DeviceDidDisconnect(const std::string& inDeviceID) 147 | { 148 | // Nothing to do 149 | } 150 | 151 | void MyStreamDeckPlugin::SendToPlugin(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) 152 | { 153 | // Nothing to do 154 | } 155 | -------------------------------------------------------------------------------- /Sources/MyStreamDeckPlugin.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | /** 3 | @file MyStreamDeckPlugin.h 4 | 5 | @brief CPU plugin 6 | 7 | @copyright (c) 2018, Corsair Memory, Inc. 8 | This source code is licensed under the MIT-style license found in the LICENSE file. 9 | 10 | **/ 11 | //============================================================================== 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | using json = nlohmann::json; 19 | 20 | class CpuUsageHelper; 21 | class CallBackTimer; 22 | 23 | class MyStreamDeckPlugin : public ESDBasePlugin 24 | { 25 | public: 26 | 27 | MyStreamDeckPlugin(); 28 | virtual ~MyStreamDeckPlugin(); 29 | 30 | void KeyDownForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) override; 31 | void KeyUpForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) override; 32 | 33 | void WillAppearForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) override; 34 | void WillDisappearForAction(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) override; 35 | 36 | void DeviceDidConnect(const std::string& inDeviceID, const json &inDeviceInfo) override; 37 | void DeviceDidDisconnect(const std::string& inDeviceID) override; 38 | 39 | void SendToPlugin(const std::string& inAction, const std::string& inContext, const json &inPayload, const std::string& inDeviceID) override; 40 | 41 | private: 42 | 43 | void UpdateTimer(); 44 | 45 | std::mutex mVisibleContextsMutex; 46 | std::set mVisibleContexts; 47 | 48 | CpuUsageHelper *mCpuUsageHelper = nullptr; 49 | CallBackTimer *mTimer; 50 | }; 51 | -------------------------------------------------------------------------------- /Sources/StreamDeckSDK.cmake: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | 3 | FetchContent_Declare( 4 | StreamDeckSDK 5 | URL https://github.com/fredemmott/StreamDeck-CPPSDK/releases/download/v3.0.3/StreamDeckSDK-v3.0.3.zip 6 | URL_HASH SHA512=b0d1a3e11ba6c0fbffbf875cd608015596e27efdc7839557adfb86183572c6827fccbd693d5f6e7d6af53f2d4e325ea69aa0b74225d85846d9939f65fadfaa7c 7 | ) 8 | 9 | FetchContent_GetProperties(StreamDeckSDK) 10 | if(NOT streamdecksdk_POPULATED) 11 | FetchContent_Populate(StreamDeckSDK) 12 | add_subdirectory("${streamdecksdk_SOURCE_DIR}" "${streamdecksdk_BINARY_DIR}" EXCLUDE_FROM_ALL) 13 | endif() 14 | 15 | if(APPLE) 16 | set( 17 | STREAMDECK_PLUGIN_DIR 18 | "$ENV{HOME}/Library/Application Support/com.elgato.StreamDeck/Plugins" 19 | ) 20 | elseif(WIN32) 21 | string( 22 | REPLACE 23 | "\\" 24 | "/" 25 | STREAMDECK_PLUGIN_DIR 26 | "$ENV{appdata}/Elgato/StreamDeck/Plugins" 27 | ) 28 | endif() 29 | 30 | set( 31 | STREAMDECK_PLUGIN_DIR 32 | ${STREAMDECK_PLUGIN_DIR} 33 | CACHE PATH "Path to this system's streamdeck plugin directory" 34 | ) 35 | 36 | function(set_default_install_dir_to_streamdeck_plugin_dir) 37 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 38 | set( 39 | CMAKE_INSTALL_PREFIX 40 | "${STREAMDECK_PLUGIN_DIR}/${CMAKE_PROJECT_NAME}" 41 | CACHE PATH "See cmake documentation" 42 | FORCE 43 | ) 44 | endif() 45 | endfunction() 46 | -------------------------------------------------------------------------------- /Sources/Windows/CpuUsageHelper.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | /** 3 | @file CpuUsageHelper.cpp 4 | 5 | @brief Calculate the current CPU percentage 6 | 7 | @copyright (c) 2018, Corsair Memory, Inc. 8 | This source code is licensed under the MIT-style license found in the LICENSE file. 9 | 10 | **/ 11 | //============================================================================== 12 | 13 | #include "CpuUsageHelper.h" 14 | #include 15 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 16 | 17 | CpuUsageHelper::CpuUsageHelper() 18 | { 19 | PdhOpenQuery(nullptr, NULL, &mCpuQuery); 20 | PdhAddEnglishCounter(mCpuQuery, L"\\Processor Information(_Total)\\% Processor Utility", NULL, &mCpuTotal); 21 | PdhCollectQueryData(mCpuQuery); 22 | GetCurrentCPUValue(); 23 | } 24 | 25 | int CpuUsageHelper::GetCurrentCPUValue() 26 | { 27 | PDH_FMT_COUNTERVALUE counterVal; 28 | 29 | PdhCollectQueryData(mCpuQuery); 30 | PdhGetFormattedCounterValue(mCpuTotal, PDH_FMT_LONG, NULL, &counterVal); 31 | return (int)(MIN(counterVal.longValue, 100L)); 32 | } 33 | 34 | // Open Windows Task Manager 35 | void CpuUsageHelper::OpenSystemMonitor() 36 | { 37 | char buffer[MAX_PATH]; 38 | int length = GetSystemDirectoryA(buffer, MAX_PATH); 39 | 40 | if (length > 0 && length <= MAX_PATH) { 41 | ShellExecuteA(NULL, "open", (std::string(buffer) + "\\Taskmgr.exe").c_str(), NULL, NULL, SW_SHOWDEFAULT); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/Windows/CpuUsageHelper.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | /** 3 | @file CpuUsageHelper.h 4 | 5 | @brief Calculate the current CPU percentage 6 | 7 | @copyright (c) 2018, Corsair Memory, Inc. 8 | This source code is licensed under the MIT-style license found in the LICENSE file. 9 | 10 | **/ 11 | //============================================================================== 12 | 13 | #pragma once 14 | #pragma comment(lib, "Pdh.lib") 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | class CpuUsageHelper 21 | { 22 | public: 23 | CpuUsageHelper(); 24 | ~CpuUsageHelper() {}; 25 | 26 | int GetCurrentCPUValue(); 27 | void OpenSystemMonitor(); 28 | 29 | private: 30 | PDH_HQUERY mCpuQuery; 31 | PDH_HCOUNTER mCpuTotal; 32 | }; 33 | -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "Zeigt die aktuelle CPU-Auslastung an.", 3 | "Name": "CPU", 4 | "com.elgato.cpu.cpu": { 5 | "Name": "CPU", 6 | "Tooltip": "Diese Aktion zeigt die CPU-Auslastung an" 7 | } 8 | } -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/defaultImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elgatosf/streamdeck-cpu/f942745cdbc54f208d5bbad61f143344be27ca40/Sources/com.elgato.cpu.sdPlugin/defaultImage.png -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/defaultImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elgatosf/streamdeck-cpu/f942745cdbc54f208d5bbad61f143344be27ca40/Sources/com.elgato.cpu.sdPlugin/defaultImage@2x.png -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "Displays the current CPU usage.", 3 | "Name": "CPU", 4 | "com.elgato.cpu.cpu": { 5 | "Name": "CPU", 6 | "Tooltip": "This action displays the CPU usage" 7 | } 8 | } -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "Muestra el uso actual del procesador.", 3 | "Name": "Procesador", 4 | "com.elgato.cpu.cpu": { 5 | "Name": "Procesador", 6 | "Tooltip": "Esta acción muestra el uso del procesador" 7 | } 8 | } -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "Affiche la consommation actuelle de ressources processeur.", 3 | "Name": "Processeur", 4 | "com.elgato.cpu.cpu": { 5 | "Name": "Processeur", 6 | "Tooltip": "Cette action affiche la consommation de ressources processeur" 7 | } 8 | } -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elgatosf/streamdeck-cpu/f942745cdbc54f208d5bbad61f143344be27ca40/Sources/com.elgato.cpu.sdPlugin/icon.png -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elgatosf/streamdeck-cpu/f942745cdbc54f208d5bbad61f143344be27ca40/Sources/com.elgato.cpu.sdPlugin/icon@2x.png -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "現在のCPUの使用状況を表示します。", 3 | "Name": "CPU", 4 | "com.elgato.cpu.cpu": { 5 | "Name": "CPU", 6 | "Tooltip": "このアクションはCPUの使用状況を表示します" 7 | } 8 | } -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/ko.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "현재 CPU 사용량을 표시합니다.", 3 | "Name": "CPU", 4 | "com.elgato.cpu.cpu": { 5 | "Name": "CPU", 6 | "Tooltip": "이 동작은 CPU 사용량을 표시합니다" 7 | } 8 | } -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "Actions": [ 3 | { 4 | "Icon": "icon", 5 | "Name": "CPU", 6 | "States": [ 7 | { 8 | "Image": "defaultImage", 9 | "TitleAlignment": "middle", 10 | "FontSize": "17" 11 | } 12 | ], 13 | "SupportedInMultiActions": false, 14 | "Tooltip": "This action displays the CPU usage", 15 | "UUID": "com.elgato.cpu.cpu" 16 | } 17 | ], 18 | "SDKVersion": 2, 19 | "Author": "Elgato", 20 | "CodePathWin": "cpu.exe", 21 | "CodePathMac": "cpu", 22 | "Description": "Displays the current CPU usage.", 23 | "Name": "CPU", 24 | "Icon": "pluginIcon", 25 | "URL": "https://www.elgato.com/gaming/stream-deck", 26 | "Version": "1.4.2", 27 | "OS": [ 28 | { 29 | "Platform": "mac", 30 | "MinimumVersion" : "10.11" 31 | }, 32 | { 33 | "Platform": "windows", 34 | "MinimumVersion" : "10" 35 | } 36 | ], 37 | "Software": 38 | { 39 | "MinimumVersion" : "4.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/pluginIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elgatosf/streamdeck-cpu/f942745cdbc54f208d5bbad61f143344be27ca40/Sources/com.elgato.cpu.sdPlugin/pluginIcon.png -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/pluginIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elgatosf/streamdeck-cpu/f942745cdbc54f208d5bbad61f143344be27ca40/Sources/com.elgato.cpu.sdPlugin/pluginIcon@2x.png -------------------------------------------------------------------------------- /Sources/com.elgato.cpu.sdPlugin/zh_CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "显示当前的 CPU使用率。", 3 | "Name": "CPU", 4 | "com.elgato.cpu.cpu": { 5 | "Name": "CPU", 6 | "Tooltip": "该操作可显示 CPU 使用率" 7 | } 8 | } -------------------------------------------------------------------------------- /Sources/macOS/CpuUsageHelper.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | /** 3 | @file CpuUsageHelper.h 4 | 5 | @brief Calculate the current CPU percentage 6 | 7 | @copyright (c) 2018, Corsair Memory, Inc. 8 | This source code is licensed under the MIT-style license found in the LICENSE file. 9 | 10 | **/ 11 | //============================================================================== 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | class CpuUsageHelper 22 | { 23 | public: 24 | CpuUsageHelper(); 25 | ~CpuUsageHelper() {}; 26 | 27 | int GetCurrentCPUValue(); 28 | void OpenSystemMonitor(); 29 | 30 | private: 31 | 32 | processor_info_array_t mProcessorInfo = nullptr; 33 | mach_msg_type_number_t mProcessorInfoCnt = 0; 34 | 35 | processor_info_array_t mOldProcessorInfo = nullptr; 36 | mach_msg_type_number_t mOldProcessorInfoCnt = 0; 37 | 38 | unsigned mNumberOfCPUs = 0; 39 | }; 40 | -------------------------------------------------------------------------------- /Sources/macOS/CpuUsageHelper.mm: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | /** 3 | @file CpuUsageHelper.mm 4 | 5 | @brief Calculate the current CPU percentage 6 | 7 | @copyright (c) 2018, Corsair Memory, Inc. 8 | This source code is licensed under the MIT-style license found in the LICENSE file. 9 | 10 | **/ 11 | //============================================================================== 12 | 13 | #include "CpuUsageHelper.h" 14 | #include 15 | 16 | CpuUsageHelper::CpuUsageHelper() 17 | { 18 | int mib[2U] = { CTL_HW, HW_NCPU }; 19 | size_t sizeOfNumCPUs = sizeof(mNumberOfCPUs); 20 | int status = sysctl(mib, 2U, &mNumberOfCPUs, &sizeOfNumCPUs, NULL, 0U); 21 | if(status) 22 | { 23 | mNumberOfCPUs = 1; 24 | } 25 | } 26 | 27 | int CpuUsageHelper::GetCurrentCPUValue() 28 | { 29 | if(mNumberOfCPUs <= 0) 30 | return 0; 31 | 32 | double cpuPercentage = 0; 33 | 34 | natural_t processorCount = 0; 35 | kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &processorCount, &mProcessorInfo, &mProcessorInfoCnt); 36 | if(err == KERN_SUCCESS) 37 | { 38 | for(unsigned int cpuIndex = 0 ; cpuIndex < mNumberOfCPUs; cpuIndex++) 39 | { 40 | double inUse = 0.0; 41 | double total = 0.0; 42 | 43 | if(mOldProcessorInfo != NULL) 44 | { 45 | inUse = ( 46 | (mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_USER] - mOldProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_USER]) 47 | + (mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_SYSTEM] - mOldProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_SYSTEM]) 48 | + (mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_NICE] - mOldProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_NICE]) 49 | ); 50 | total = inUse + (mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_IDLE] - mOldProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_IDLE]); 51 | } 52 | else 53 | { 54 | inUse = mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_USER] + mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_SYSTEM] + mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_NICE]; 55 | total = inUse + mProcessorInfo[(CPU_STATE_MAX * cpuIndex) + CPU_STATE_IDLE]; 56 | } 57 | 58 | cpuPercentage += inUse / total; 59 | } 60 | 61 | if(mOldProcessorInfo) 62 | { 63 | size_t prevCpuInfoSize = sizeof(integer_t) * mOldProcessorInfoCnt; 64 | vm_deallocate(mach_task_self(), (vm_address_t)mOldProcessorInfo, prevCpuInfoSize); 65 | } 66 | 67 | mOldProcessorInfo = mProcessorInfo; 68 | mOldProcessorInfoCnt = mProcessorInfoCnt; 69 | 70 | mProcessorInfo = NULL; 71 | mProcessorInfoCnt = 0; 72 | } 73 | 74 | return (int)lround(100.0 * cpuPercentage / mNumberOfCPUs); 75 | } 76 | 77 | // Open macOS Activity Monitor 78 | void CpuUsageHelper::OpenSystemMonitor() 79 | { 80 | NSURL* url = [[NSWorkspace sharedWorkspace] URLForApplicationWithBundleIdentifier:@"com.apple.ActivityMonitor"]; 81 | NSString* path = [[url.absoluteString componentsSeparatedByString:@"//"][1] stringByRemovingPercentEncoding]; 82 | [[NSWorkspace sharedWorkspace] launchApplication:path]; 83 | } 84 | -------------------------------------------------------------------------------- /Sources/main.cpp: -------------------------------------------------------------------------------- 1 | #include "MyStreamDeckPlugin.h" 2 | 3 | #include 4 | #include 5 | 6 | int main(int argc, const char** argv) { 7 | return esd_main(argc, argv, new MyStreamDeckPlugin()); 8 | } 9 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elgatosf/streamdeck-cpu/f942745cdbc54f208d5bbad61f143344be27ca40/screenshot.png --------------------------------------------------------------------------------