Skip to content

Commit

Permalink
External api and ipc improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
JPersson77 committed Apr 20, 2023
1 parent 027885e commit 5d7d1e0
Show file tree
Hide file tree
Showing 14 changed files with 2,094 additions and 453 deletions.
783 changes: 781 additions & 2 deletions Common/Common.cpp

Large diffs are not rendered by default.

105 changes: 102 additions & 3 deletions Common/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@
#include <sstream>
#include <iostream>
#include <iomanip>
#include <thread>
//#include <mutex>
#include <fstream>
#include <sstream>
#include <nlohmann/json.hpp>

// common general application definitions
#define APPNAME L"LGTV Companion"
#define APP_VERSION L"2.1.6"
#define APP_VERSION L"2.2.0"
#define CONFIG_FILE L"config.json"
#define LOG_FILE L"Log.txt"
#define WINDOW_CLASS_UNIQUE L"YOLOx0x0x0181818"
#define PIPENAME TEXT("\\\\.\\pipe\\LGTVyolo")
#define NEWRELEASELINK L"https://github.com/JPersson77/LGTVCompanion/releases"
#define VERSIONCHECKLINK L"https://api.github.com/repos/JPersson77/LGTVCompanion/releases"
#define DONATELINK L"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=jorgen.persson@gmail.com&lc=US&item_name=Friendly+gift+for+the+development+of+LGTV+Companion&no_note=0&cn=&currency_code=EUR&bn=PP-DonationsBF:btn_donateCC_LG.gif:NonHosted"
#define DISCORDLINK L"https://discord.gg/7KkTPrP3fq"
#define MUTEX_WAIT 10 // thread wait in ms

// common preferences definitions
#define JSON_PREFS_NODE "LGTV Companion"
Expand All @@ -34,8 +40,12 @@
#define JSON_IDLEWHITELIST "IdleWhiteListEnabled"
#define JSON_IDLEFULLSCREEN "IdleFullscreen"
#define JSON_WHITELIST "IdleWhiteList"
#define JSON_IDLE_FS_EXCLUSIONS_ENABLE "IdleFsExclusionsEnabled"
#define JSON_IDLE_FS_EXCLUSIONS "IdleFsExclusions"
#define JSON_REMOTESTREAM "RemoteStream"
#define JSON_TOPOLOGYMODE "TopologyPreferPowerEfficient"
#define JSON_EXTERNAL_API "ExternalAPI"
#define JSON_MUTE_SPEAKERS "MuteSpeakers"
#define JSON_DEVICE_NAME "Name"
#define JSON_DEVICE_IP "IP"
#define JSON_DEVICE_UNIQUEKEY "UniqueDeviceKey"
Expand All @@ -56,6 +66,7 @@
#define WOL_SUBNETBROADCAST 3
#define WOL_DEFAULTSUBNET L"255.255.255.0"

// commandline events
#define APP_CMDLINE_ON 1
#define APP_CMDLINE_OFF 2
#define APP_CMDLINE_AUTOENABLE 3
Expand All @@ -67,11 +78,25 @@
#define APP_CMDLINE_SETHDMI2 9
#define APP_CMDLINE_SETHDMI3 10
#define APP_CMDLINE_SETHDMI4 11
#define APP_CMDLINE_MUTE 12
#define APP_CMDLINE_UNMUTE 13

// WOL types
#define WOL_NETWORKBROADCAST 1
#define WOL_IPSEND 2
#define WOL_SUBNETBROADCAST 3

//IPC
#define PIPE_BUF_SIZE 1024
#define PIPE_INSTANCES 5
#define PIPE_NOT_RUNNING 99
#define PIPE_EVENT_ERROR 100
#define PIPE_EVENT_READ 101 // Data was read
#define PIPE_EVENT_SEND 102 // Write data
#define PIPE_RUNNING 103 // Server is running
#define PIPE_EVENT_TERMINATE 120 // Terminate


// common forward function declarations
namespace jpersson77 {
namespace common {
Expand All @@ -94,6 +119,7 @@ namespace jpersson77 {
bool bRemoteCurrentStatusRDP = false;
bool bRemoteCurrentStatusSunshine = false;
std::wstring sCurrentlyRunningWhitelistedProcess = L"";
std::wstring sCurrentlyRunningFsExcludedProcess = L"";
std::string Sunshine_Log_File = "";
uintmax_t Sunshine_Log_Size = 0;

Expand All @@ -104,7 +130,7 @@ namespace jpersson77 {
L"usb#vid_0955&pid_b4f0" //nvidia
};
};
struct WHITELIST { // whitelist info
struct PROCESSLIST { // whitelist info
std::wstring Name;
std::wstring Application;
};
Expand All @@ -125,6 +151,7 @@ namespace jpersson77 {
bool SetHDMIInputOnResume = false;
int SetHDMIInputOnResumeToNumber = 1;
bool SSL = true;
bool MuteSpeakers = false;

//service.h
int BlankScreenWhenIdleDelay = 10;
Expand All @@ -148,9 +175,13 @@ namespace jpersson77 {
bool AdhereTopology = false;
bool bIdleWhitelistEnabled = false;
bool bFullscreenCheckEnabled = false;
std::vector<WHITELIST> WhiteList;
std::vector<PROCESSLIST> WhiteList;
bool bIdleFsExclusionsEnabled = false;
std::vector<PROCESSLIST> FsExclusions;
bool RemoteStreamingCheck = false;
bool TopologyPreferPowerEfficiency = true;
bool ExternalAPI = false;
bool MuteSpeakers = false;
std::wstring DataPath;
std::vector <DEVICE> Devices;

Expand All @@ -162,4 +193,72 @@ namespace jpersson77 {
REMOTE_STREAM Remote;
};
}
namespace ipc
{
class PipeServer
{
public:
PipeServer(std::wstring, void (*fcnPtr)(std::wstring));
~PipeServer(void);
bool Send(std::wstring sData, int iPipe = -1);
bool Terminate();
bool isRunning();

//DEBUG
void Log(std::wstring);
std::atomic_int bLock2 = false;;

private:
void OnEvent(int, std::wstring sData = L"", int iPipe = -1);
void WorkerThread();
bool DisconnectAndReconnect(int);
bool Write(std::wstring&, int);

HANDLE hPipeHandles[PIPE_INSTANCES] = {};
DWORD dwBytesTransferred;
TCHAR Buffer[PIPE_INSTANCES][PIPE_BUF_SIZE+1];
OVERLAPPED Ovlap[PIPE_INSTANCES];
HANDLE hEvents[PIPE_INSTANCES + 2] = {}; // include termination and termination confirm events
std::atomic_bool bWriteData[PIPE_INSTANCES] = {};
void (*FunctionPtr)(std::wstring);
std::wstring sPipeName;
std::atomic_int iState = PIPE_NOT_RUNNING;

};

class PipeClient
{
public:
PipeClient(std::wstring, void (*fcnPtr)(std::wstring));
~PipeClient(void);
bool Init();
bool Send(std::wstring);
bool Terminate();
bool isRunning();


//DEBUG
void Log(std::wstring);
std::atomic_int bLock = false;

private:
void OnEvent(int, std::wstring sData = L"");
void WorkerThread();
bool DisconnectAndReconnect();
bool Write(std::wstring&);

HANDLE hFile = NULL;

HANDLE hPipeHandle = {};
DWORD dwBytesTransferred;
TCHAR Buffer[PIPE_BUF_SIZE+1];
OVERLAPPED Ovlap;
HANDLE hEvents[3] = {}; // overlapped event, terminate event, terminate accept event
void (*FunctionPtr)(std::wstring);
std::wstring sPipeName;
std::atomic_int iState = PIPE_NOT_RUNNING;
std::atomic_bool bWriteData = {};

};
}
}
121 changes: 121 additions & 0 deletions Example scripts/Named pipe client - Read Events Example v2.ahk
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
Version 1.1
This is a sample script using AutoHotKey (AHK) v2 for accessing the API for LGTV Companion. This sample script
illustrate how to listen to events sent from LGTV Companion. Note that bi-directional communication is
supported and sending commands/events to LGTV Companion is covered in another example script.
Please install AHK by downloading the installer from here: https://www.autohotkey.com/ and then install.
AutoHotkey is a free, open-source scripting language for Windows that allows users to easily create small
to complex scripts for all kinds of tasks such as: form fillers, auto-clicking, macros, etc.
PLEASE NOTE that the LGTV Companion API is using named pipes for its intra-process communication so any
scripting or programming language which can access named pipes (which is surely the vast majority) can be used
to communicate with LGTV Companion.
Remember to enable the "External API" option in LGTV Companion.
For discussions, tips and tricks etc please use Discord: https://discord.gg/7KkTPrP3fq
*/

; SCRIPT STARTS HERE

; This script will run under v2 of AHK
#Requires AutoHotkey v2.0

;Only one instance of the script can run
#SingleInstance Ignore

; The following DllCall() is optional: it tells the OS to shut down this script last (after all other applications).
DllCall("kernel32.dll\SetProcessShutdownParameters", "UInt", 0x101, "UInt", 0)

; The name of the named pipe to connect to
PipeName := "\\.\pipe\LGTVyolo"

; Connect to the Named Pipe using CreateFile() https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
Pipe := DllCall("CreateFile", "Str", PipeName, "UInt", 0x80000000 | 0x40000000, "UInt", 0, "Ptr", 0, "UInt", 0x00000003, "UInt", 0x00000080, "Ptr", 0)

; Set the max message length to 1024 bytes (maximum supported currently)
VarSetStrCapacity(&Buff , 1024)
Bytes := 0

;read messages in an infinite loop
Go := true
while (Go = true)
{
if (Pipe != -1)
{
; Read synchronously (i.e. blocking) using ReadFile() https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile
if (DllCall("ReadFile", "Ptr", Pipe, "Str", Buff, "UInt", 512, "UInt*", Bytes, "Ptr", 0))
{
Log(Buff)

Switch Buff
{
Case "SYSTEM_DISPLAYS_OFF": ; System signals displays OFF
{
; Do stuff here
}
Case "SYSTEM_DISPLAYS_OFF_DIMMED": ; System signals displays OFF, BUT DIMMED (usually occurs in laptops)
{
; Do stuff here
}
Case "SYSTEM_DISPLAYS_ON": ; System signals displays ON
{
; Do stuff here
}
Case "SYSTEM_USER_BUSY": ; System is busy / user away mode is inactive
{
; Do stuff here
}
Case "SYSTEM_USER_IDLE": ; System is idle / user away mode is active
{
; Do stuff here
}
Case "SYSTEM_REBOOT": ; System is about to reboot
{
; Do stuff here
}
Case "SYSTEM_SHUTDOWN": ; System is about to shutdown
{
; Do stuff here
}
Case "SYSTEM_RESUME": ; System is resuming from sleep/hibernate
{
; Do stuff here
}
Case "SYSTEM_SUSPEND": ; System is suspending to sleep/hibernate
{
; Do stuff here
}
Default:
{
}
}
}
else
{
Log("ERROR, Failed to ReadFile(). Script will Terminate!")
Go := false
}
}
else
{
Log("ERROR, Pipe handle is invalid. Script will Terminate!")
Go := false
}
}

; Close the handle
DllCall("CloseHandle", "Ptr", Pipe)

ExitApp

; This function will write 'message' to log.txt in the same directory as the script
Log(message)
{
FileAppend a_hour . ":" . a_min . ":" . a_sec . " > " . message "`n", "log.txt"
}

70 changes: 70 additions & 0 deletions Example scripts/Named pipe client - Write Event Example v2.ahk
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Version 1.0
This is a sample script using AutoHotKey (AHK) for accessing the API for LGTV Companion. This sample script
illustrate how to send events to LGTV Companion. Note that bi-directional communication is
supported and receiving commands/events to LGTV Companion is covered in another example script.
Please install AHK by downloading the installer from here: https://www.autohotkey.com/ and then install.
AutoHotkey is a free, open-source scripting language for Windows that allows users to easily create small
to complex scripts for all kinds of tasks such as: form fillers, auto-clicking, macros, etc.
PLEASE NOTE that the LGTV Companion API is using named pipes for its intra-process communication so any scripting or programming language which can access named pipes (which is surely the vast majority) can be used
to communicate with LGTV Companion.
Remember to enable the "External API" option in LGTV Companion.
For discussions, tips and tricks etc please use Discord: https://discord.gg/7KkTPrP3fq
*/

; SCRIPT STARTS HERE

; This script will run under v2 of AHK
#Requires AutoHotkey v2.0

;Only one instance of the script can run
#SingleInstance Ignore

; Set keyboard shortcut CTRL+SHIFT+M to mute TV-speaker (Device1)
^+m::
{
Send_LGTV_Message("-mute device1")
return
}

; Set keyboard shortcut CTRL+SHIFT+U to unmute TV-speaker (Device1)
^+u::
{
Send_LGTV_Message("-unmute device1")
return
}

; This function will send 'message' to the LGTV Companion service (currently the messages that can be sent correspond to the command line parameters)
Send_LGTV_Message(message)
{
; The name of the named pipe to connect to
PipeName := "\\.\pipe\LGTVyolo"

; Connect to the Named Pipe using CreateFile() https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
Pipe := DllCall("CreateFile", "Str", PipeName, "UInt", 0x80000000 | 0x40000000, "UInt", 0x00000001 | 0x00000002, "Ptr", 0, "UInt", 0x00000003, "UInt", 0, "Ptr", 0)
if(Pipe = -1)
{
MsgBox "Could not connect to the LGTV Companion service. Check that the service is running!"
Return
}

;Write to the named pipe using WriteFile() https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
If !DllCall("WriteFile", "Ptr", Pipe, "Str", message, "UInt", (StrLen(message)+1)*2, "UInt*", 0, "Ptr", 0)
MsgBox "WriteFile failed: %ErrorLevel%/%A_LastError%"

;Tiny bit of delay so that closing the handle doesn't abort the (overlapped) read by the LGTV Companion Service
Sleep 100

;Close the handle
DllCall("CloseHandle", "Ptr", Pipe)

Return
}

Expand Down
Loading

0 comments on commit 5d7d1e0

Please sign in to comment.