diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..8ec3771
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,242 @@
+# Remove the line below if you want to inherit .editorconfig settings from higher directories
+root = true
+
+# C# files
+[*.cs]
+
+#### Core EditorConfig Options ####
+
+# Indentation and spacing
+indent_size = 4
+indent_style = space
+tab_width = 4
+
+# New line preferences
+end_of_line = crlf
+insert_final_newline = false
+
+#### .NET Coding Conventions ####
+
+# Organize usings
+dotnet_separate_import_directive_groups = true
+dotnet_sort_system_directives_first = true
+
+# this. and Me. preferences
+dotnet_style_qualification_for_event = true:warning
+dotnet_style_qualification_for_field = true:warning
+dotnet_style_qualification_for_method = true:warning
+dotnet_style_qualification_for_property = true:warning
+
+# Language keywords vs BCL types preferences
+dotnet_style_predefined_type_for_locals_parameters_members = false:warning
+dotnet_style_predefined_type_for_member_access = false:warning
+
+# Parentheses preferences
+dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:warning
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
+
+# Modifier preferences
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+
+# Expression-level preferences
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_style_inlined_variable_declaration = true:warning
+csharp_style_throw_expression = true:warning
+dotnet_style_coalesce_expression = true:warning
+dotnet_style_collection_initializer = true:warning
+dotnet_style_explicit_tuple_names = true:warning
+dotnet_style_null_propagation = true:warning
+dotnet_style_object_initializer = false:suggestion
+dotnet_style_prefer_auto_properties = true:warning
+dotnet_style_prefer_compound_assignment = true:warning
+dotnet_style_prefer_conditional_expression_over_assignment = true:warning
+dotnet_style_prefer_conditional_expression_over_return = true:warning
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
+
+# Field preferences
+dotnet_style_readonly_field = true:warning
+
+# Parameter preferences
+dotnet_code_quality_unused_parameters = all:warning
+
+#### C# Coding Conventions ####
+
+# var preferences
+csharp_style_var_elsewhere = true:silent
+csharp_style_var_for_built_in_types = true:warning
+csharp_style_var_when_type_is_apparent = true:warning
+
+# Expression-bodied members
+csharp_style_expression_bodied_accessors = when_on_single_line:suggestion
+csharp_style_expression_bodied_constructors = when_on_single_line:suggestion
+csharp_style_expression_bodied_indexers = when_on_single_line:suggestion
+csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion
+csharp_style_expression_bodied_local_functions = when_on_single_line:suggestion
+csharp_style_expression_bodied_methods = when_on_single_line:suggestion
+csharp_style_expression_bodied_operators = when_on_single_line:suggestion
+csharp_style_expression_bodied_properties = when_on_single_line:suggestion
+
+# Pattern matching preferences
+csharp_style_pattern_matching_over_as_with_null_check = true:warning
+csharp_style_pattern_matching_over_is_with_cast_check = true:warning
+
+# Null-checking preferences
+csharp_style_conditional_delegate_call = true:warning
+
+# Modifier preferences
+csharp_prefer_static_local_function = false:warning
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
+
+# Code-block preferences
+csharp_prefer_braces = true:warning
+csharp_prefer_simple_using_statement = false:warning
+
+# Expression-level preferences
+csharp_prefer_simple_default_expression = true:warning
+csharp_style_pattern_local_over_anonymous_function = true:warning
+csharp_style_prefer_index_operator = true:suggestion
+csharp_style_prefer_range_operator = true:suggestion
+csharp_style_unused_value_assignment_preference = discard_variable:suggestion
+csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
+
+# 'using' directive preferences
+csharp_using_directive_placement = inside_namespace:warning
+
+#### C# Formatting Rules ####
+
+# New line preferences
+csharp_new_line_before_catch = true
+csharp_new_line_before_else = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_open_brace = all
+csharp_new_line_between_query_expression_clauses = true
+
+# Indentation preferences
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_case_contents_when_block = false
+csharp_indent_labels = one_less_than_current
+csharp_indent_switch_labels = true
+
+# Space preferences
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_between_square_brackets = false
+
+# Wrapping preferences
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = false
+
+#### Naming styles ####
+
+# Naming rules
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Symbol specifications
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Naming styles
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+#### Diagnostic configuration ####
+
+dotnet_diagnostic.CA1028.severity = none
+dotnet_diagnostic.CA1031.severity = none
+dotnet_diagnostic.CA1054.severity = none
+dotnet_diagnostic.CA1056.severity = none
+dotnet_diagnostic.CA1060.severity = none
+dotnet_diagnostic.CA1303.severity = none
+dotnet_diagnostic.CA1308.severity = none
+dotnet_diagnostic.CA1716.severity = none
+dotnet_diagnostic.CA1720.severity = none
+dotnet_diagnostic.CA2101.severity = none
+dotnet_diagnostic.CA2234.severity = none
+dotnet_diagnostic.CA5350.severity = none
+dotnet_diagnostic.CA9998.severity = none
+
+dotnet_diagnostic.CS1591.severity = none
+
+dotnet_diagnostic.IDE0002.severity = none
+dotnet_diagnostic.IDE0021.severity = warning
+dotnet_diagnostic.IDE0022.severity = warning
+dotnet_diagnostic.IDE0058.severity = none
+dotnet_diagnostic.IDE0059.severity = none
+
+dotnet_diagnostic.SA1108.severity = none
+dotnet_diagnostic.SA1117.severity = none
+dotnet_diagnostic.SA1121.severity = none
+dotnet_diagnostic.SA1122.severity = none
+dotnet_diagnostic.SA1131.severity = none
+dotnet_diagnostic.SA1201.severity = none
+dotnet_diagnostic.SA1202.severity = none
+dotnet_diagnostic.SA1203.severity = none
+dotnet_diagnostic.SA1204.severity = none
+dotnet_diagnostic.SA1214.severity = none
+dotnet_diagnostic.SA1309.severity = none
+dotnet_diagnostic.SA1512.severity = none
+dotnet_diagnostic.SA1513.severity = none
+dotnet_diagnostic.SA1600.severity = none
+dotnet_diagnostic.SA1601.severity = none
+dotnet_diagnostic.SA1602.severity = none
+dotnet_diagnostic.SA1629.severity = none
+dotnet_diagnostic.SA1633.severity = none
+
+dotnet_diagnostic.SX1309.severity = warning
+dotnet_diagnostic.SX1309S.severity = warning
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..51879ab
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,5 @@
+
+
+ 7.3
+
+
diff --git a/VoCPUPlugin.sln b/VoCPUPlugin.sln
new file mode 100644
index 0000000..03bf758
--- /dev/null
+++ b/VoCPUPlugin.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30128.74
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VoCPUPlugin", "VoCPUPlugin\VoCPUPlugin.csproj", "{03022F04-C091-4614-9CBC-7579C1FCA3EE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {03022F04-C091-4614-9CBC-7579C1FCA3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {03022F04-C091-4614-9CBC-7579C1FCA3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {03022F04-C091-4614-9CBC-7579C1FCA3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {03022F04-C091-4614-9CBC-7579C1FCA3EE}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C024C357-17B4-49BD-8871-658BC4148938}
+ EndGlobalSection
+EndGlobal
diff --git a/VoCPUPlugin/Actions/DisplayCPU.cs b/VoCPUPlugin/Actions/DisplayCPU.cs
new file mode 100644
index 0000000..f638179
--- /dev/null
+++ b/VoCPUPlugin/Actions/DisplayCPU.cs
@@ -0,0 +1,59 @@
+namespace Loupedeck.VoCPUPlugin.Actions
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Linq;
+ using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ internal class DisplayCPU: PluginDynamicCommand{
+ private readonly System.Timers.Timer _timer;
+ private readonly PerformanceCounter _perfCounter = new System.Diagnostics.PerformanceCounter();
+ private readonly Queue _cpuavg = new Queue();
+ private readonly BitmapImage _background;
+
+ public DisplayCPU()
+ : base(displayName: "Display CPU %", description: "Displays the CPU utilization.", groupName: "")
+ {
+ this._background = BitmapImage.FromFile("assets\\CPU-xxsmallc.png");
+ this._timer = new System.Timers.Timer(1000);
+ this._timer.Elapsed += (sender, e) =>
+ {
+ this.ActionImageChanged();
+ };
+ this._timer.AutoReset = true;
+ this._timer.Start();
+ }
+
+ protected override String GetCommandDisplayName(String actionParameter, PluginImageSize imageSize)
+ {
+ this._perfCounter.CategoryName = "Processor";
+ this._perfCounter.CounterName = "% Processor Time";
+ this._perfCounter.InstanceName = "_Total";
+ var cpuval = this._perfCounter.NextValue();
+ Thread.Sleep(100);
+
+ this._cpuavg.Enqueue(cpuval);
+ if (this._cpuavg.Count < 10)
+ {
+ return "CPU\n\n" + cpuval.ToString("F2") + "%";
+ }
+ else
+ {
+ this._cpuavg.Dequeue();
+ return "CPU\n\n" + (_cpuavg.Sum(x => x) / 10).ToString("F2") + "%";
+ }
+ }
+
+ protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize)
+ {
+ var bitmap = new BitmapBuilder(imageSize);
+ bitmap.FillRectangle(0, 0, 90, 90, BitmapColor.Black);
+ bitmap.DrawImage(this._background, 0, 0);
+ bitmap.DrawText(this.GetCommandDisplayName(actionParameter, imageSize), BitmapColor.White, 16);
+ return bitmap.ToImage();
+ }
+ }
+}
diff --git a/VoCPUPlugin/App.config b/VoCPUPlugin/App.config
new file mode 100644
index 0000000..25b52c3
--- /dev/null
+++ b/VoCPUPlugin/App.config
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VoCPUPlugin/BuildEvents/postbuild b/VoCPUPlugin/BuildEvents/postbuild
new file mode 100644
index 0000000..1fb4724
--- /dev/null
+++ b/VoCPUPlugin/BuildEvents/postbuild
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Project post-build event for macOS
+
+PROJECT_DIR=$1
+TARGET_DIR=$2
+
+assert() {
+ if eval $1 ; then
+ echo "$0: Error: $2"
+ exit 1
+ fi
+}
+
+assert "[ -z \"$PROJECT_DIR\" ]" "Project directory was not given"
+assert "[ -z \"$TARGET_DIR\" ]" "Target directory was not given"
+assert "[ ! -d \"$TARGET_DIR\" ]" "Target directory does not exist: '$TARGET_DIR'"
+
+METADATA_DIR=${PROJECT_DIR}metadata
+assert "[ ! -d \"$METADATA_DIR\" ]" "metadata directory does not exist: '$METADATA_DIR'"
+
+echo Copying "$METADATA_DIR" to "${TARGET_DIR}../metadata"
+cp -R "$METADATA_DIR" "${TARGET_DIR}../metadata"
+assert "[ $? -ne 0 ]" "Copying metadata failed"
+
+exit 0
diff --git a/VoCPUPlugin/BuildEvents/postbuild.cmd b/VoCPUPlugin/BuildEvents/postbuild.cmd
new file mode 100644
index 0000000..29ebf46
--- /dev/null
+++ b/VoCPUPlugin/BuildEvents/postbuild.cmd
@@ -0,0 +1,31 @@
+@echo off
+
+:: Project post-build event for Windows
+
+set PROJECT_DIR=%~1
+set TARGET_DIR=%~2
+
+if "%PROJECT_DIR%" == "" (
+ echo %~0: Error: Project directory was not given
+ exit /b 1
+)
+
+if "%TARGET_DIR%" == "" (
+ echo %~0: Error: Target directory was not given
+ exit /b 1
+)
+
+if not exist "%TARGET_DIR%" (
+ echo %~0: Error: Target directory does not exist: '%TARGET_DIR%'"
+ exit /b 1
+)
+
+set METADATA_DIR=%PROJECT_DIR%metadata\
+
+if not exist "%METADATA_DIR%" (
+ echo %~0: "Error: metadata directory does not exist: '%METADATA_DIR%'"
+ exit /b 1
+)
+
+echo Copying "%METADATA_DIR%" to "%TARGET_DIR%..\metadata\"
+xcopy /s /y "%METADATA_DIR%" "%TARGET_DIR%..\metadata\"
diff --git a/VoCPUPlugin/Properties/AssemblyInfo.cs b/VoCPUPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1bf8bfa
--- /dev/null
+++ b/VoCPUPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("VoCPU plugin for Loupedeck")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("LoupeDeck Oy")]
+[assembly: AssemblyProduct("Loupedeck2")]
+[assembly: AssemblyCopyright("Copyright (c) 2018 LoupeDeck Oy. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("03022F04-C091-4614-9CBC-7579C1FCA3EE")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("5.3.1.14222")]
+[assembly: AssemblyVersion("5.3.1.14222")]
diff --git a/VoCPUPlugin/VoCPUApplication.cs b/VoCPUPlugin/VoCPUApplication.cs
new file mode 100644
index 0000000..ca48de5
--- /dev/null
+++ b/VoCPUPlugin/VoCPUApplication.cs
@@ -0,0 +1,22 @@
+namespace Loupedeck.VoCPUPlugin
+{
+ using System;
+
+ // This class can be used to connect the Loupedeck plugin to an application.
+
+ public class VoCPUApplication : ClientApplication
+ {
+ public VoCPUApplication()
+ {
+ }
+
+ // This method can be used to link the plugin to a Windows application.
+ protected override String GetProcessName() => "";
+
+ // This method can be used to link the plugin to a macOS application.
+ protected override String GetBundleName() => "";
+
+ // This method can be used to check whether the application is installed or not.
+ public override ClientApplicationStatus GetApplicationStatus() => ClientApplicationStatus.Unknown;
+ }
+}
diff --git a/VoCPUPlugin/VoCPUPlugin.cs b/VoCPUPlugin/VoCPUPlugin.cs
new file mode 100644
index 0000000..799d5f7
--- /dev/null
+++ b/VoCPUPlugin/VoCPUPlugin.cs
@@ -0,0 +1,25 @@
+namespace Loupedeck.VoCPUPlugin
+{
+ using System;
+
+ // This class contains the plugin-level logic of the Loupedeck plugin.
+
+ public class VoCPUPlugin : Plugin
+ {
+ // Gets a value indicating whether this is an Universal plugin or an Application plugin.
+ public override Boolean UsesApplicationApiOnly => true;
+
+ // Gets a value indicating whether this is an API-only plugin.
+ public override Boolean HasNoApplication => true;
+
+ // This method is called when the plugin is loaded during the Loupedeck service start-up.
+ public override void Load()
+ {
+ }
+
+ // This method is called when the plugin is unloaded during the Loupedeck service shutdown.
+ public override void Unload()
+ {
+ }
+ }
+}
diff --git a/VoCPUPlugin/VoCPUPlugin.csproj b/VoCPUPlugin/VoCPUPlugin.csproj
new file mode 100644
index 0000000..4010410
--- /dev/null
+++ b/VoCPUPlugin/VoCPUPlugin.csproj
@@ -0,0 +1,85 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {03022F04-C091-4614-9CBC-7579C1FCA3EE}
+ Library
+ Properties
+ Loupedeck.VoCPUPlugin
+ VoCPUPlugin
+ v4.7.2
+ 512
+
+
+ $(SolutionDir)..\obj\
+ $(SolutionDir)..\bin\
+
+
+ true
+ full
+ false
+ $(LocalAppData)\Loupedeck\Plugins\VoCPU\win\
+ $(HOME)/.local/share/Loupedeck/Plugins/VoCPU/mac/
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ $(BaseOutputPath)$(Configuration)\win\
+ $(BaseOutputPath)$(Configuration)/mac/
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ C:\Program Files (x86)\Loupedeck\Loupedeck2\PluginApi.dll
+ /Applications/Loupedeck.app/Contents/MonoBundle/PluginApi.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+ call "$(ProjectDir)BuildEvents\postbuild.cmd" "$(ProjectDir)" "$(TargetDir)"
+ sh "$(ProjectDir)BuildEvents\postbuild" "$(ProjectDir)" "$(TargetDir)"
+
+
\ No newline at end of file
diff --git a/VoCPUPlugin/assets/CPU-big.png b/VoCPUPlugin/assets/CPU-big.png
new file mode 100644
index 0000000..ddc6323
Binary files /dev/null and b/VoCPUPlugin/assets/CPU-big.png differ
diff --git a/VoCPUPlugin/assets/CPU-xxsmall.png b/VoCPUPlugin/assets/CPU-xxsmall.png
new file mode 100644
index 0000000..11c8684
Binary files /dev/null and b/VoCPUPlugin/assets/CPU-xxsmall.png differ
diff --git a/VoCPUPlugin/assets/CPU-xxsmallb.png b/VoCPUPlugin/assets/CPU-xxsmallb.png
new file mode 100644
index 0000000..940e043
Binary files /dev/null and b/VoCPUPlugin/assets/CPU-xxsmallb.png differ
diff --git a/VoCPUPlugin/assets/CPU-xxsmallc.png b/VoCPUPlugin/assets/CPU-xxsmallc.png
new file mode 100644
index 0000000..2ae86d1
Binary files /dev/null and b/VoCPUPlugin/assets/CPU-xxsmallc.png differ
diff --git a/VoCPUPlugin/metadata/Icon16x16.png b/VoCPUPlugin/metadata/Icon16x16.png
new file mode 100644
index 0000000..ce2c8ba
Binary files /dev/null and b/VoCPUPlugin/metadata/Icon16x16.png differ
diff --git a/VoCPUPlugin/metadata/Icon256x256.png b/VoCPUPlugin/metadata/Icon256x256.png
new file mode 100644
index 0000000..ee29c2c
Binary files /dev/null and b/VoCPUPlugin/metadata/Icon256x256.png differ
diff --git a/VoCPUPlugin/metadata/Icon32x32.png b/VoCPUPlugin/metadata/Icon32x32.png
new file mode 100644
index 0000000..9e908ce
Binary files /dev/null and b/VoCPUPlugin/metadata/Icon32x32.png differ
diff --git a/VoCPUPlugin/metadata/Icon48x48.png b/VoCPUPlugin/metadata/Icon48x48.png
new file mode 100644
index 0000000..3db13a4
Binary files /dev/null and b/VoCPUPlugin/metadata/Icon48x48.png differ
diff --git a/VoCPUPlugin/metadata/LoupedeckPackage.yaml b/VoCPUPlugin/metadata/LoupedeckPackage.yaml
new file mode 100644
index 0000000..434ed59
--- /dev/null
+++ b/VoCPUPlugin/metadata/LoupedeckPackage.yaml
@@ -0,0 +1,73 @@
+# ==================================================================================================
+# GENERAL SETTINGS
+# ==================================================================================================
+
+# Package type. Must be plugin4 for plugins.
+type: plugin4
+
+# Name of the plugin.
+name: VoCPU
+
+# Name that is displayed in the Loupedeck configuration application.
+displayName: VoCPU
+
+# Name of the plugin library file.
+pluginFileName: VoCPUPlugin.dll
+
+# Plugin version.
+version: 1.0.0
+
+# Author of the plugin. The author can be a company or an individual developer.
+author: VoSs2o0o
+
+# Copyright information.
+copyright: Copyright © 2022 VoSs2o0o. All rights reserved.
+
+
+# ==================================================================================================
+# PLUGIN PROPERTIES
+# ==================================================================================================
+
+# Location of plugin files on Windows (relative to the plugin base directory).
+# This parameter is required to support Windows.
+pluginFolderWin: win
+
+# Location of plugin files on macOS (relative to the plugin base directory).
+# This parameter is required to support Mac.
+#pluginFolderMac: mac
+
+# List of supported devices.
+supportedDevices:
+ # LoupedeckCtFamily covers the following devices: Loupedeck CT, Live and Live S, and Razer Stream Controller.
+ - LoupedeckCtFamily
+
+ # LoupedeckPlusFamily covers Loupedeck+ device. Uncomment the following line to support Loupedeck+.
+ #- LoupedeckPlusFamily
+
+# List of plugin capabilities.
+pluginCapabilities:
+ # Uncomment the following line if this plugin is an application plugin.
+ #- HasApplication
+
+ # Uncomment the following line if the plugin sends keyboard shortcuts to the target application.
+ #- ActivatesApplication
+
+
+# ==================================================================================================
+# LOUPEDECK MARKETPLACE SETTINGS
+# ==================================================================================================
+
+# Name of the license that the plugin is licensed under. Select the one that you prefer.
+# NOTE: GPL license is not compatible with Loupedeck Marketplace.
+license: MIT
+
+# URL of the plugin license.
+licenseUrl: https://opensource.org/licenses/MIT
+
+# URL of the support page where the users can send improvement suggestions and report bugs.
+# The URL is shown in Loupedeck Marketplace. The page can be for example a GitHub issues page.
+# NOTE: This setting is recommended when publishing the plugin in Loupedeck Marketplace.
+#supportPageUrl: https://github.com/myusername/myplugin/issues
+
+# URL of the plugin homepage. The URL is shown in Loupedeck Marketplace.
+#homePageUrl: https://github.com/myusername/myplugin