summaryrefslogtreecommitdiffstats
path: root/tools/EventClients/lib/c++/xbmcclient.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
commitc04dcc2e7d834218ef2d4194331e383402495ae1 (patch)
tree7333e38d10d75386e60f336b80c2443c1166031d /tools/EventClients/lib/c++/xbmcclient.h
parentInitial commit. (diff)
downloadkodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz
kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/EventClients/lib/c++/xbmcclient.h')
-rw-r--r--tools/EventClients/lib/c++/xbmcclient.h823
1 files changed, 823 insertions, 0 deletions
diff --git a/tools/EventClients/lib/c++/xbmcclient.h b/tools/EventClients/lib/c++/xbmcclient.h
new file mode 100644
index 0000000..ef9afc5
--- /dev/null
+++ b/tools/EventClients/lib/c++/xbmcclient.h
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2008-2015 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kodi; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#endif
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <time.h>
+
+#define STD_PORT 9777
+
+#define MS_ABSOLUTE 0x01
+//#define MS_RELATIVE 0x02
+
+#define BTN_USE_NAME 0x01
+#define BTN_DOWN 0x02
+#define BTN_UP 0x04
+#define BTN_USE_AMOUNT 0x08
+#define BTN_QUEUE 0x10
+#define BTN_NO_REPEAT 0x20
+#define BTN_VKEY 0x40
+#define BTN_AXIS 0x80
+
+#define PT_HELO 0x01
+#define PT_BYE 0x02
+#define PT_BUTTON 0x03
+#define PT_MOUSE 0x04
+#define PT_PING 0x05
+#define PT_BROADCAST 0x06
+#define PT_NOTIFICATION 0x07
+#define PT_BLOB 0x08
+#define PT_LOG 0x09
+#define PT_ACTION 0x0A
+#define PT_DEBUG 0xFF
+
+#define ICON_NONE 0x00
+#define ICON_JPEG 0x01
+#define ICON_PNG 0x02
+#define ICON_GIF 0x03
+
+#define MAX_PACKET_SIZE 1024
+#define HEADER_SIZE 32
+#define MAX_PAYLOAD_SIZE (MAX_PACKET_SIZE - HEADER_SIZE)
+
+#define MAJOR_VERSION 2
+#define MINOR_VERSION 0
+
+#define LOGDEBUG 0
+#define LOGINFO 1
+#define LOGNOTICE 2
+#define LOGWARNING 3
+#define LOGERROR 4
+#define LOGSEVERE 5
+#define LOGFATAL 6
+#define LOGNONE 7
+
+#define ACTION_EXECBUILTIN 0x01
+#define ACTION_BUTTON 0x02
+
+class CAddress
+{
+private:
+ struct sockaddr_in m_Addr;
+public:
+ CAddress(int Port = STD_PORT)
+ {
+ m_Addr.sin_family = AF_INET;
+ m_Addr.sin_port = htons(Port);
+ m_Addr.sin_addr.s_addr = INADDR_ANY;
+ memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero);
+ }
+
+ CAddress(const char *Address, int Port = STD_PORT)
+ {
+ m_Addr.sin_port = htons(Port);
+
+ struct hostent *h;
+ if (Address == NULL || (h=gethostbyname(Address)) == NULL)
+ {
+ if (Address != NULL)
+ printf("Error: Get host by name\n");
+
+ m_Addr.sin_addr.s_addr = INADDR_ANY;
+ m_Addr.sin_family = AF_INET;
+ }
+ else
+ {
+ m_Addr.sin_family = h->h_addrtype;
+ m_Addr.sin_addr = *((struct in_addr *)h->h_addr);
+ }
+ memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero);
+ }
+
+ void SetPort(int port)
+ {
+ m_Addr.sin_port = htons(port);
+ }
+
+ const sockaddr *GetAddress()
+ {
+ return ((struct sockaddr *)&m_Addr);
+ }
+
+ bool Bind(int Sockfd)
+ {
+ return (bind(Sockfd, (struct sockaddr *)&m_Addr, sizeof m_Addr) == 0);
+ }
+};
+
+class XBMCClientUtils
+{
+public:
+ XBMCClientUtils() = default;
+ ~XBMCClientUtils() = default;
+ static unsigned int GetUniqueIdentifier()
+ {
+ static time_t id = time(NULL);
+ return id;
+ }
+
+ static void Clean()
+ {
+ #ifdef _WIN32
+ WSACleanup();
+ #endif
+ }
+
+ static bool Initialize()
+ {
+ #ifdef _WIN32
+ WSADATA wsaData;
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData))
+ return false;
+ #endif
+ return true;
+ }
+};
+
+class CPacket
+{
+/* Base class that implements a single event packet.
+
+ - Generic packet structure (maximum 1024 bytes per packet)
+ - Header is 32 bytes long, so 992 bytes available for payload
+ - large payloads can be split into multiple packets using H4 and H5
+ H5 should contain total no. of packets in such a case
+ - H6 contains length of P1, which is limited to 992 bytes
+ - if H5 is 0 or 1, then H4 will be ignored (single packet msg)
+ - H7 must be set to zeros for now
+
+ -----------------------------
+ | -H1 Signature ("XBMC") | - 4 x CHAR 4B
+ | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B
+ | -H3 PacketType | - 1 x UNSIGNED SHORT 2B
+ | -H4 Sequence number | - 1 x UNSIGNED LONG 4B
+ | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B
+ | -H6 Payload size | - 1 x UNSIGNED SHORT 2B
+ | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B
+ | -H8 Reserved | - 10 x UNSIGNED CHAR 10B
+ |---------------------------|
+ | -P1 payload | -
+ -----------------------------
+*/
+public:
+ CPacket()
+ {
+ m_PacketType = 0;
+ }
+ virtual ~CPacket() = default;
+
+ bool Send(int Socket, CAddress &Addr, unsigned int UID = XBMCClientUtils::GetUniqueIdentifier())
+ {
+ if (m_Payload.empty())
+ ConstructPayload();
+ bool SendSuccessful = true;
+ int NbrOfPackages = (m_Payload.size() / MAX_PAYLOAD_SIZE) + 1;
+ int Send = 0;
+ int Sent = 0;
+ int Left = m_Payload.size();
+ for (int Package = 1; Package <= NbrOfPackages; Package++)
+ {
+ if (Left > MAX_PAYLOAD_SIZE)
+ {
+ Send = MAX_PAYLOAD_SIZE;
+ Left -= Send;
+ }
+ else
+ {
+ Send = Left;
+ Left = 0;
+ }
+
+ ConstructHeader(m_PacketType, NbrOfPackages, Package, Send, UID, m_Header);
+ char t[MAX_PACKET_SIZE];
+ int i, j;
+ for (i = 0; i < 32; i++)
+ t[i] = m_Header[i];
+
+ for (j = 0; j < Send; j++)
+ t[(32 + j)] = m_Payload[j + Sent];
+
+ int rtn = sendto(Socket, t, (32 + Send), 0, Addr.GetAddress(), sizeof(struct sockaddr));
+
+ if (rtn != (32 + Send))
+ SendSuccessful = false;
+
+ Sent += Send;
+ }
+ return SendSuccessful;
+ }
+protected:
+ char m_Header[HEADER_SIZE];
+ unsigned short m_PacketType;
+
+ std::vector<char> m_Payload;
+
+ static void ConstructHeader(int PacketType, int NumberOfPackets, int CurrentPacket, unsigned short PayloadSize, unsigned int UniqueToken, char *Header)
+ {
+ sprintf(Header, "XBMC");
+ for (int i = 4; i < HEADER_SIZE; i++)
+ Header[i] = 0;
+ Header[4] = MAJOR_VERSION;
+ Header[5] = MINOR_VERSION;
+ if (CurrentPacket == 1)
+ {
+ Header[6] = ((PacketType & 0xff00) >> 8);
+ Header[7] = (PacketType & 0x00ff);
+ }
+ else
+ {
+ Header[6] = ((PT_BLOB & 0xff00) >> 8);
+ Header[7] = (PT_BLOB & 0x00ff);
+ }
+ Header[8] = ((CurrentPacket & 0xff000000) >> 24);
+ Header[9] = ((CurrentPacket & 0x00ff0000) >> 16);
+ Header[10] = ((CurrentPacket & 0x0000ff00) >> 8);
+ Header[11] = (CurrentPacket & 0x000000ff);
+
+ Header[12] = ((NumberOfPackets & 0xff000000) >> 24);
+ Header[13] = ((NumberOfPackets & 0x00ff0000) >> 16);
+ Header[14] = ((NumberOfPackets & 0x0000ff00) >> 8);
+ Header[15] = (NumberOfPackets & 0x000000ff);
+
+ Header[16] = ((PayloadSize & 0xff00) >> 8);
+ Header[17] = (PayloadSize & 0x00ff);
+
+ Header[18] = ((UniqueToken & 0xff000000) >> 24);
+ Header[19] = ((UniqueToken & 0x00ff0000) >> 16);
+ Header[20] = ((UniqueToken & 0x0000ff00) >> 8);
+ Header[21] = (UniqueToken & 0x000000ff);
+ }
+
+ virtual void ConstructPayload()
+ { }
+};
+
+class CPacketHELO : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %s - device name (max 128 chars) */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %s - my port ( 0=>not listening ) */
+ /* %d - reserved1 ( 0 ) */
+ /* %d - reserved2 ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+private:
+ std::vector<char> m_DeviceName;
+ unsigned short m_IconType;
+ char *m_IconData;
+ unsigned short m_IconSize;
+public:
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ for (unsigned int i = 0; i < m_DeviceName.size(); i++)
+ m_Payload.push_back(m_DeviceName[i]);
+
+ m_Payload.push_back('\0');
+
+ m_Payload.push_back(m_IconType);
+
+ m_Payload.push_back(0);
+ m_Payload.push_back('\0');
+
+ for (int j = 0; j < 8; j++)
+ m_Payload.push_back(0);
+
+ for (int ico = 0; ico < m_IconSize; ico++)
+ m_Payload.push_back(m_IconData[ico]);
+ }
+
+ CPacketHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL) : CPacket()
+ {
+ m_PacketType = PT_HELO;
+
+ unsigned int len = strlen(DevName);
+ for (unsigned int i = 0; i < len; i++)
+ m_DeviceName.push_back(DevName[i]);
+
+ m_IconType = IconType;
+
+ if (IconType == ICON_NONE || IconFile == NULL)
+ {
+ m_IconData = NULL;
+ m_IconSize = 0;
+ return;
+ }
+
+ std::ifstream::pos_type size;
+
+ std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (file.is_open())
+ {
+ size = file.tellg();
+ m_IconData = new char [size];
+ file.seekg (0, std::ios::beg);
+ file.read (m_IconData, size);
+ file.close();
+ m_IconSize = size;
+ }
+ else
+ {
+ m_IconType = ICON_NONE;
+ m_IconSize = 0;
+ }
+ }
+
+ ~CPacketHELO() override
+ {
+ m_DeviceName.clear();
+ delete[] m_IconData;
+ }
+};
+
+class CPacketNOTIFICATION : public CPacket
+{
+ /************************************************************************/
+ /* Payload format: */
+ /* %s - caption */
+ /* %s - message */
+ /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */
+ /* %d - reserved ( 0 ) */
+ /* XX - imagedata ( can span multiple packets ) */
+ /************************************************************************/
+private:
+ std::vector<char> m_Title;
+ std::vector<char> m_Message;
+ unsigned short m_IconType;
+ char *m_IconData;
+ unsigned short m_IconSize;
+public:
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ for (unsigned int i = 0; i < m_Title.size(); i++)
+ m_Payload.push_back(m_Title[i]);
+
+ m_Payload.push_back('\0');
+
+ for (unsigned int i = 0; i < m_Message.size(); i++)
+ m_Payload.push_back(m_Message[i]);
+
+ m_Payload.push_back('\0');
+
+ m_Payload.push_back(m_IconType);
+
+ for (int i = 0; i < 4; i++)
+ m_Payload.push_back(0);
+
+ for (int ico = 0; ico < m_IconSize; ico++)
+ m_Payload.push_back(m_IconData[ico]);
+ }
+
+ CPacketNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL) : CPacket()
+ {
+ m_PacketType = PT_NOTIFICATION;
+ m_IconData = NULL;
+ m_IconSize = 0;
+ unsigned int len = 0;
+ if (Title != NULL)
+ {
+ len = strlen(Title);
+ for (unsigned int i = 0; i < len; i++)
+ m_Title.push_back(Title[i]);
+ }
+
+ if (Message != NULL)
+ {
+ len = strlen(Message);
+ for (unsigned int i = 0; i < len; i++)
+ m_Message.push_back(Message[i]);
+ }
+ m_IconType = IconType;
+
+ if (IconType == ICON_NONE || IconFile == NULL)
+ return;
+
+ std::ifstream::pos_type size;
+
+ std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate);
+ if (file.is_open())
+ {
+ size = file.tellg();
+ m_IconData = new char [size];
+ file.seekg (0, std::ios::beg);
+ file.read (m_IconData, size);
+ file.close();
+ m_IconSize = size;
+ }
+ else
+ m_IconType = ICON_NONE;
+ }
+
+ ~CPacketNOTIFICATION() override
+ {
+ m_Title.clear();
+ m_Message.clear();
+ delete[] m_IconData;
+ }
+};
+
+class CPacketBUTTON : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %i - button code */
+ /* %i - flags 0x01 => use button map/name instead of code */
+ /* 0x02 => btn down */
+ /* 0x04 => btn up */
+ /* 0x08 => use amount */
+ /* 0x10 => queue event */
+ /* 0x20 => do not repeat */
+ /* 0x40 => virtual key */
+ /* 0x40 => axis key */
+ /* %i - amount ( 0 => 65k maps to -1 => 1 ) */
+ /* %s - device map (case sensitive and required if flags & 0x01) */
+ /* "KB" - Standard keyboard map */
+ /* "XG" - Xbox Gamepad */
+ /* "R1" - Xbox Remote */
+ /* "R2" - Xbox Universal Remote */
+ /* "LI:devicename" - valid LIRC device map where 'devicename' */
+ /* is the actual name of the LIRC device */
+ /* "JS<num>:joyname" - valid Joystick device map where */
+ /* 'joyname' is the name specified in */
+ /* the keymap. JS only supports button code */
+ /* and not button name currently (!0x01). */
+ /* %s - button name (required if flags & 0x01) */
+ /************************************************************************/
+private:
+ std::vector<char> m_DeviceMap;
+ std::vector<char> m_Button;
+ unsigned short m_ButtonCode;
+ unsigned short m_Amount;
+ unsigned short m_Flags;
+public:
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ if (m_Button.size() != 0)
+ {
+ if (!(m_Flags & BTN_USE_NAME)) // If the BTN_USE_NAME isn't flagged for some reason
+ m_Flags |= BTN_USE_NAME;
+ m_ButtonCode = 0;
+ }
+ else
+ m_Button.clear();
+
+ if (m_Amount > 0)
+ {
+ if (!(m_Flags & BTN_USE_AMOUNT))
+ m_Flags |= BTN_USE_AMOUNT;
+ }
+ if (!((m_Flags & BTN_DOWN) || (m_Flags & BTN_UP))) //If none of them are tagged.
+ m_Flags |= BTN_DOWN;
+
+ m_Payload.push_back(((m_ButtonCode & 0xff00) >> 8));
+ m_Payload.push_back( (m_ButtonCode & 0x00ff));
+
+ m_Payload.push_back(((m_Flags & 0xff00) >> 8) );
+ m_Payload.push_back( (m_Flags & 0x00ff));
+
+ m_Payload.push_back(((m_Amount & 0xff00) >> 8) );
+ m_Payload.push_back( (m_Amount & 0x00ff));
+
+
+ for (unsigned int i = 0; i < m_DeviceMap.size(); i++)
+ m_Payload.push_back(m_DeviceMap[i]);
+
+ m_Payload.push_back('\0');
+
+ for (unsigned int i = 0; i < m_Button.size(); i++)
+ m_Payload.push_back(m_Button[i]);
+
+ m_Payload.push_back('\0');
+ }
+
+ CPacketBUTTON(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = Flags;
+ m_ButtonCode = 0;
+ m_Amount = Amount;
+
+ unsigned int len = strlen(DeviceMap);
+ for (unsigned int i = 0; i < len; i++)
+ m_DeviceMap.push_back(DeviceMap[i]);
+
+ len = strlen(Button);
+ for (unsigned int i = 0; i < len; i++)
+ m_Button.push_back(Button[i]);
+ }
+
+ CPacketBUTTON(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = Flags;
+ m_ButtonCode = ButtonCode;
+ m_Amount = Amount;
+
+ unsigned int len = strlen(DeviceMap);
+ for (unsigned int i = 0; i < len; i++)
+ m_DeviceMap.push_back(DeviceMap[i]);
+ }
+
+ CPacketBUTTON(unsigned short ButtonCode, unsigned short Flags, unsigned short Amount = 0) : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = Flags;
+ m_ButtonCode = ButtonCode;
+ m_Amount = Amount;
+ }
+
+ // Used to send a release event
+ CPacketBUTTON() : CPacket()
+ {
+ m_PacketType = PT_BUTTON;
+ m_Flags = BTN_UP;
+ m_Amount = 0;
+ m_ButtonCode = 0;
+ }
+
+ ~CPacketBUTTON() override
+ {
+ m_DeviceMap.clear();
+ m_Button.clear();
+ }
+
+ inline unsigned short GetFlags() { return m_Flags; }
+ inline unsigned short GetButtonCode() { return m_ButtonCode; }
+};
+
+class CPacketPING : public CPacket
+{
+ /************************************************************************/
+ /* no payload */
+ /************************************************************************/
+public:
+ CPacketPING() : CPacket()
+ {
+ m_PacketType = PT_PING;
+ }
+ ~CPacketPING() override = default;
+};
+
+class CPacketBYE : public CPacket
+{
+ /************************************************************************/
+ /* no payload */
+ /************************************************************************/
+public:
+ CPacketBYE() : CPacket()
+ {
+ m_PacketType = PT_BYE;
+ }
+ ~CPacketBYE() override = default;
+};
+
+class CPacketMOUSE : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %c - flags */
+ /* - 0x01 absolute position */
+ /* %i - mousex (0-65535 => maps to screen width) */
+ /* %i - mousey (0-65535 => maps to screen height) */
+ /************************************************************************/
+private:
+ unsigned short m_X;
+ unsigned short m_Y;
+ unsigned char m_Flag;
+public:
+ CPacketMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE)
+ {
+ m_PacketType = PT_MOUSE;
+ m_Flag = Flag;
+ m_X = X;
+ m_Y = Y;
+ }
+
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ m_Payload.push_back(m_Flag);
+
+ m_Payload.push_back(((m_X & 0xff00) >> 8));
+ m_Payload.push_back( (m_X & 0x00ff));
+
+ m_Payload.push_back(((m_Y & 0xff00) >> 8));
+ m_Payload.push_back( (m_Y & 0x00ff));
+ }
+
+ ~CPacketMOUSE() override = default;
+};
+
+class CPacketLOG : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %c - log type */
+ /* %s - message */
+ /************************************************************************/
+private:
+ std::vector<char> m_Message;
+ unsigned char m_LogLevel;
+ bool m_AutoPrintf;
+public:
+ CPacketLOG(int LogLevel, const char *Message, bool AutoPrintf = true)
+ {
+ m_PacketType = PT_LOG;
+
+ unsigned int len = strlen(Message);
+ for (unsigned int i = 0; i < len; i++)
+ m_Message.push_back(Message[i]);
+
+ m_LogLevel = LogLevel;
+ m_AutoPrintf = AutoPrintf;
+ }
+
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ m_Payload.push_back( (m_LogLevel & 0x00ff) );
+
+ if (m_AutoPrintf)
+ {
+ char* str=&m_Message[0];
+ printf("%s\n", str);
+ }
+ for (unsigned int i = 0; i < m_Message.size(); i++)
+ m_Payload.push_back(m_Message[i]);
+
+ m_Payload.push_back('\0');
+ }
+
+ ~CPacketLOG() override = default;
+};
+
+class CPacketACTION : public CPacket
+{
+ /************************************************************************/
+ /* Payload format */
+ /* %c - action type */
+ /* %s - action message */
+ /************************************************************************/
+private:
+ unsigned char m_ActionType;
+ std::vector<char> m_Action;
+public:
+ CPacketACTION(const char *Action, unsigned char ActionType = ACTION_EXECBUILTIN)
+ {
+ m_PacketType = PT_ACTION;
+
+ m_ActionType = ActionType;
+ unsigned int len = strlen(Action);
+ for (unsigned int i = 0; i < len; i++)
+ m_Action.push_back(Action[i]);
+ }
+
+ void ConstructPayload() override
+ {
+ m_Payload.clear();
+
+ m_Payload.push_back(m_ActionType);
+ for (unsigned int i = 0; i < m_Action.size(); i++)
+ m_Payload.push_back(m_Action[i]);
+
+ m_Payload.push_back('\0');
+ }
+
+ ~CPacketACTION() override = default;
+};
+
+class CXBMCClient
+{
+private:
+ CAddress m_Addr;
+ int m_Socket;
+ unsigned int m_UID;
+public:
+ CXBMCClient(const char *IP = "127.0.0.1", int Port = 9777, int Socket = -1, unsigned int UID = 0)
+ {
+ m_Addr = CAddress(IP, Port);
+ if (Socket == -1)
+ m_Socket = socket(AF_INET, SOCK_DGRAM, 0);
+ else
+ m_Socket = Socket;
+
+ if (UID)
+ m_UID = UID;
+ else
+ m_UID = XBMCClientUtils::GetUniqueIdentifier();
+ }
+
+ void SendNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketNOTIFICATION notification(Title, Message, IconType, IconFile);
+ notification.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketHELO helo(DevName, IconType, IconFile);
+ helo.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendButton(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketBUTTON button(Button, DeviceMap, Flags, Amount);
+ button.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendButton(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketBUTTON button(ButtonCode, DeviceMap, Flags, Amount);
+ button.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendButton(unsigned short ButtonCode, unsigned Flags, unsigned short Amount = 0)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketBUTTON button(ButtonCode, Flags, Amount);
+ button.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketMOUSE mouse(X, Y, Flag);
+ mouse.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendLOG(int LogLevel, const char *Message, bool AutoPrintf = true)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketLOG log(LogLevel, Message, AutoPrintf);
+ log.Send(m_Socket, m_Addr, m_UID);
+ }
+
+ void SendACTION(const char *ActionMessage, int ActionType = ACTION_EXECBUILTIN)
+ {
+ if (m_Socket < 0)
+ return;
+
+ CPacketACTION action(ActionMessage, ActionType);
+ action.Send(m_Socket, m_Addr, m_UID);
+ }
+};
+