1 /* 2 * Copyright (C) 2008-2015 Team Kodi 3 * http://kodi.tv 4 * 5 * This Program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2, or (at your option) 8 * any later version. 9 * 10 * This Program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with Kodi; see the file COPYING. If not, see 17 * <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #pragma once 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <sys/types.h> 27 #ifdef _WIN32 28 #include <winsock.h> 29 #else 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 #include <netdb.h> 33 #include <arpa/inet.h> 34 #endif 35 #include <vector> 36 #include <iostream> 37 #include <fstream> 38 #include <time.h> 39 40 #define STD_PORT 9777 41 42 #define MS_ABSOLUTE 0x01 43 //#define MS_RELATIVE 0x02 44 45 #define BTN_USE_NAME 0x01 46 #define BTN_DOWN 0x02 47 #define BTN_UP 0x04 48 #define BTN_USE_AMOUNT 0x08 49 #define BTN_QUEUE 0x10 50 #define BTN_NO_REPEAT 0x20 51 #define BTN_VKEY 0x40 52 #define BTN_AXIS 0x80 53 54 #define PT_HELO 0x01 55 #define PT_BYE 0x02 56 #define PT_BUTTON 0x03 57 #define PT_MOUSE 0x04 58 #define PT_PING 0x05 59 #define PT_BROADCAST 0x06 60 #define PT_NOTIFICATION 0x07 61 #define PT_BLOB 0x08 62 #define PT_LOG 0x09 63 #define PT_ACTION 0x0A 64 #define PT_DEBUG 0xFF 65 66 #define ICON_NONE 0x00 67 #define ICON_JPEG 0x01 68 #define ICON_PNG 0x02 69 #define ICON_GIF 0x03 70 71 #define MAX_PACKET_SIZE 1024 72 #define HEADER_SIZE 32 73 #define MAX_PAYLOAD_SIZE (MAX_PACKET_SIZE - HEADER_SIZE) 74 75 #define MAJOR_VERSION 2 76 #define MINOR_VERSION 0 77 78 #define LOGDEBUG 0 79 #define LOGINFO 1 80 #define LOGNOTICE 2 81 #define LOGWARNING 3 82 #define LOGERROR 4 83 #define LOGSEVERE 5 84 #define LOGFATAL 6 85 #define LOGNONE 7 86 87 #define ACTION_EXECBUILTIN 0x01 88 #define ACTION_BUTTON 0x02 89 90 class CAddress 91 { 92 private: 93 struct sockaddr_in m_Addr; 94 public: 95 CAddress(int Port = STD_PORT) 96 { 97 m_Addr.sin_family = AF_INET; 98 m_Addr.sin_port = htons(Port); 99 m_Addr.sin_addr.s_addr = INADDR_ANY; 100 memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero); 101 } 102 103 CAddress(const char *Address, int Port = STD_PORT) 104 { 105 m_Addr.sin_port = htons(Port); 106 107 struct hostent *h; 108 if (Address == NULL || (h=gethostbyname(Address)) == NULL) 109 { 110 if (Address != NULL) 111 printf("Error: Get host by name\n"); 112 113 m_Addr.sin_addr.s_addr = INADDR_ANY; 114 m_Addr.sin_family = AF_INET; 115 } 116 else 117 { 118 m_Addr.sin_family = h->h_addrtype; 119 m_Addr.sin_addr = *((struct in_addr *)h->h_addr); 120 } 121 memset(m_Addr.sin_zero, '\0', sizeof m_Addr.sin_zero); 122 } 123 SetPort(int port)124 void SetPort(int port) 125 { 126 m_Addr.sin_port = htons(port); 127 } 128 GetAddress()129 const sockaddr *GetAddress() 130 { 131 return ((struct sockaddr *)&m_Addr); 132 } 133 Bind(int Sockfd)134 bool Bind(int Sockfd) 135 { 136 return (bind(Sockfd, (struct sockaddr *)&m_Addr, sizeof m_Addr) == 0); 137 } 138 }; 139 140 class XBMCClientUtils 141 { 142 public: 143 XBMCClientUtils() = default; 144 ~XBMCClientUtils() = default; GetUniqueIdentifier()145 static unsigned int GetUniqueIdentifier() 146 { 147 static time_t id = time(NULL); 148 return id; 149 } 150 Clean()151 static void Clean() 152 { 153 #ifdef _WIN32 154 WSACleanup(); 155 #endif 156 } 157 Initialize()158 static bool Initialize() 159 { 160 #ifdef _WIN32 161 WSADATA wsaData; 162 if (WSAStartup(MAKEWORD(1, 1), &wsaData)) 163 return false; 164 #endif 165 return true; 166 } 167 }; 168 169 class CPacket 170 { 171 /* Base class that implements a single event packet. 172 173 - Generic packet structure (maximum 1024 bytes per packet) 174 - Header is 32 bytes long, so 992 bytes available for payload 175 - large payloads can be split into multiple packets using H4 and H5 176 H5 should contain total no. of packets in such a case 177 - H6 contains length of P1, which is limited to 992 bytes 178 - if H5 is 0 or 1, then H4 will be ignored (single packet msg) 179 - H7 must be set to zeros for now 180 181 ----------------------------- 182 | -H1 Signature ("XBMC") | - 4 x CHAR 4B 183 | -H2 Version (eg. 2.0) | - 2 x UNSIGNED CHAR 2B 184 | -H3 PacketType | - 1 x UNSIGNED SHORT 2B 185 | -H4 Sequence number | - 1 x UNSIGNED LONG 4B 186 | -H5 No. of packets in msg | - 1 x UNSIGNED LONG 4B 187 | -H6 Payload size | - 1 x UNSIGNED SHORT 2B 188 | -H7 Client's unique token | - 1 x UNSIGNED LONG 4B 189 | -H8 Reserved | - 10 x UNSIGNED CHAR 10B 190 |---------------------------| 191 | -P1 payload | - 192 ----------------------------- 193 */ 194 public: CPacket()195 CPacket() 196 { 197 m_PacketType = 0; 198 } 199 virtual ~CPacket() = default; 200 201 bool Send(int Socket, CAddress &Addr, unsigned int UID = XBMCClientUtils::GetUniqueIdentifier()) 202 { 203 if (m_Payload.empty()) 204 ConstructPayload(); 205 bool SendSuccessful = true; 206 int NbrOfPackages = (m_Payload.size() / MAX_PAYLOAD_SIZE) + 1; 207 int Send = 0; 208 int Sent = 0; 209 int Left = m_Payload.size(); 210 for (int Package = 1; Package <= NbrOfPackages; Package++) 211 { 212 if (Left > MAX_PAYLOAD_SIZE) 213 { 214 Send = MAX_PAYLOAD_SIZE; 215 Left -= Send; 216 } 217 else 218 { 219 Send = Left; 220 Left = 0; 221 } 222 223 ConstructHeader(m_PacketType, NbrOfPackages, Package, Send, UID, m_Header); 224 char t[MAX_PACKET_SIZE]; 225 int i, j; 226 for (i = 0; i < 32; i++) 227 t[i] = m_Header[i]; 228 229 for (j = 0; j < Send; j++) 230 t[(32 + j)] = m_Payload[j + Sent]; 231 232 int rtn = sendto(Socket, t, (32 + Send), 0, Addr.GetAddress(), sizeof(struct sockaddr)); 233 234 if (rtn != (32 + Send)) 235 SendSuccessful = false; 236 237 Sent += Send; 238 } 239 return SendSuccessful; 240 } 241 protected: 242 char m_Header[HEADER_SIZE]; 243 unsigned short m_PacketType; 244 245 std::vector<char> m_Payload; 246 ConstructHeader(int PacketType,int NumberOfPackets,int CurrentPacket,unsigned short PayloadSize,unsigned int UniqueToken,char * Header)247 static void ConstructHeader(int PacketType, int NumberOfPackets, int CurrentPacket, unsigned short PayloadSize, unsigned int UniqueToken, char *Header) 248 { 249 sprintf(Header, "XBMC"); 250 for (int i = 4; i < HEADER_SIZE; i++) 251 Header[i] = 0; 252 Header[4] = MAJOR_VERSION; 253 Header[5] = MINOR_VERSION; 254 if (CurrentPacket == 1) 255 { 256 Header[6] = ((PacketType & 0xff00) >> 8); 257 Header[7] = (PacketType & 0x00ff); 258 } 259 else 260 { 261 Header[6] = ((PT_BLOB & 0xff00) >> 8); 262 Header[7] = (PT_BLOB & 0x00ff); 263 } 264 Header[8] = ((CurrentPacket & 0xff000000) >> 24); 265 Header[9] = ((CurrentPacket & 0x00ff0000) >> 16); 266 Header[10] = ((CurrentPacket & 0x0000ff00) >> 8); 267 Header[11] = (CurrentPacket & 0x000000ff); 268 269 Header[12] = ((NumberOfPackets & 0xff000000) >> 24); 270 Header[13] = ((NumberOfPackets & 0x00ff0000) >> 16); 271 Header[14] = ((NumberOfPackets & 0x0000ff00) >> 8); 272 Header[15] = (NumberOfPackets & 0x000000ff); 273 274 Header[16] = ((PayloadSize & 0xff00) >> 8); 275 Header[17] = (PayloadSize & 0x00ff); 276 277 Header[18] = ((UniqueToken & 0xff000000) >> 24); 278 Header[19] = ((UniqueToken & 0x00ff0000) >> 16); 279 Header[20] = ((UniqueToken & 0x0000ff00) >> 8); 280 Header[21] = (UniqueToken & 0x000000ff); 281 } 282 ConstructPayload()283 virtual void ConstructPayload() 284 { } 285 }; 286 287 class CPacketHELO : public CPacket 288 { 289 /************************************************************************/ 290 /* Payload format */ 291 /* %s - device name (max 128 chars) */ 292 /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */ 293 /* %s - my port ( 0=>not listening ) */ 294 /* %d - reserved1 ( 0 ) */ 295 /* %d - reserved2 ( 0 ) */ 296 /* XX - imagedata ( can span multiple packets ) */ 297 /************************************************************************/ 298 private: 299 std::vector<char> m_DeviceName; 300 unsigned short m_IconType; 301 char *m_IconData; 302 unsigned short m_IconSize; 303 public: ConstructPayload()304 void ConstructPayload() override 305 { 306 m_Payload.clear(); 307 308 for (unsigned int i = 0; i < m_DeviceName.size(); i++) 309 m_Payload.push_back(m_DeviceName[i]); 310 311 m_Payload.push_back('\0'); 312 313 m_Payload.push_back(m_IconType); 314 315 m_Payload.push_back(0); 316 m_Payload.push_back('\0'); 317 318 for (int j = 0; j < 8; j++) 319 m_Payload.push_back(0); 320 321 for (int ico = 0; ico < m_IconSize; ico++) 322 m_Payload.push_back(m_IconData[ico]); 323 } 324 CPacket()325 CPacketHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL) : CPacket() 326 { 327 m_PacketType = PT_HELO; 328 329 unsigned int len = strlen(DevName); 330 for (unsigned int i = 0; i < len; i++) 331 m_DeviceName.push_back(DevName[i]); 332 333 m_IconType = IconType; 334 335 if (IconType == ICON_NONE || IconFile == NULL) 336 { 337 m_IconData = NULL; 338 m_IconSize = 0; 339 return; 340 } 341 342 std::ifstream::pos_type size; 343 344 std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate); 345 if (file.is_open()) 346 { 347 size = file.tellg(); 348 m_IconData = new char [size]; 349 file.seekg (0, std::ios::beg); 350 file.read (m_IconData, size); 351 file.close(); 352 m_IconSize = size; 353 } 354 else 355 { 356 m_IconType = ICON_NONE; 357 m_IconSize = 0; 358 } 359 } 360 ~CPacketHELO()361 ~CPacketHELO() override 362 { 363 m_DeviceName.clear(); 364 delete[] m_IconData; 365 } 366 }; 367 368 class CPacketNOTIFICATION : public CPacket 369 { 370 /************************************************************************/ 371 /* Payload format: */ 372 /* %s - caption */ 373 /* %s - message */ 374 /* %c - icontype ( 0=>NOICON, 1=>JPEG , 2=>PNG , 3=>GIF ) */ 375 /* %d - reserved ( 0 ) */ 376 /* XX - imagedata ( can span multiple packets ) */ 377 /************************************************************************/ 378 private: 379 std::vector<char> m_Title; 380 std::vector<char> m_Message; 381 unsigned short m_IconType; 382 char *m_IconData; 383 unsigned short m_IconSize; 384 public: ConstructPayload()385 void ConstructPayload() override 386 { 387 m_Payload.clear(); 388 389 for (unsigned int i = 0; i < m_Title.size(); i++) 390 m_Payload.push_back(m_Title[i]); 391 392 m_Payload.push_back('\0'); 393 394 for (unsigned int i = 0; i < m_Message.size(); i++) 395 m_Payload.push_back(m_Message[i]); 396 397 m_Payload.push_back('\0'); 398 399 m_Payload.push_back(m_IconType); 400 401 for (int i = 0; i < 4; i++) 402 m_Payload.push_back(0); 403 404 for (int ico = 0; ico < m_IconSize; ico++) 405 m_Payload.push_back(m_IconData[ico]); 406 } 407 CPacket()408 CPacketNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL) : CPacket() 409 { 410 m_PacketType = PT_NOTIFICATION; 411 m_IconData = NULL; 412 m_IconSize = 0; 413 unsigned int len = 0; 414 if (Title != NULL) 415 { 416 len = strlen(Title); 417 for (unsigned int i = 0; i < len; i++) 418 m_Title.push_back(Title[i]); 419 } 420 421 if (Message != NULL) 422 { 423 len = strlen(Message); 424 for (unsigned int i = 0; i < len; i++) 425 m_Message.push_back(Message[i]); 426 } 427 m_IconType = IconType; 428 429 if (IconType == ICON_NONE || IconFile == NULL) 430 return; 431 432 std::ifstream::pos_type size; 433 434 std::ifstream file (IconFile, std::ios::in|std::ios::binary|std::ios::ate); 435 if (file.is_open()) 436 { 437 size = file.tellg(); 438 m_IconData = new char [size]; 439 file.seekg (0, std::ios::beg); 440 file.read (m_IconData, size); 441 file.close(); 442 m_IconSize = size; 443 } 444 else 445 m_IconType = ICON_NONE; 446 } 447 ~CPacketNOTIFICATION()448 ~CPacketNOTIFICATION() override 449 { 450 m_Title.clear(); 451 m_Message.clear(); 452 delete[] m_IconData; 453 } 454 }; 455 456 class CPacketBUTTON : public CPacket 457 { 458 /************************************************************************/ 459 /* Payload format */ 460 /* %i - button code */ 461 /* %i - flags 0x01 => use button map/name instead of code */ 462 /* 0x02 => btn down */ 463 /* 0x04 => btn up */ 464 /* 0x08 => use amount */ 465 /* 0x10 => queue event */ 466 /* 0x20 => do not repeat */ 467 /* 0x40 => virtual key */ 468 /* 0x40 => axis key */ 469 /* %i - amount ( 0 => 65k maps to -1 => 1 ) */ 470 /* %s - device map (case sensitive and required if flags & 0x01) */ 471 /* "KB" - Standard keyboard map */ 472 /* "XG" - Xbox Gamepad */ 473 /* "R1" - Xbox Remote */ 474 /* "R2" - Xbox Universal Remote */ 475 /* "LI:devicename" - valid LIRC device map where 'devicename' */ 476 /* is the actual name of the LIRC device */ 477 /* "JS<num>:joyname" - valid Joystick device map where */ 478 /* 'joyname' is the name specified in */ 479 /* the keymap. JS only supports button code */ 480 /* and not button name currently (!0x01). */ 481 /* %s - button name (required if flags & 0x01) */ 482 /************************************************************************/ 483 private: 484 std::vector<char> m_DeviceMap; 485 std::vector<char> m_Button; 486 unsigned short m_ButtonCode; 487 unsigned short m_Amount; 488 unsigned short m_Flags; 489 public: ConstructPayload()490 void ConstructPayload() override 491 { 492 m_Payload.clear(); 493 494 if (m_Button.size() != 0) 495 { 496 if (!(m_Flags & BTN_USE_NAME)) // If the BTN_USE_NAME isn't flagged for some reason 497 m_Flags |= BTN_USE_NAME; 498 m_ButtonCode = 0; 499 } 500 else 501 m_Button.clear(); 502 503 if (m_Amount > 0) 504 { 505 if (!(m_Flags & BTN_USE_AMOUNT)) 506 m_Flags |= BTN_USE_AMOUNT; 507 } 508 if (!((m_Flags & BTN_DOWN) || (m_Flags & BTN_UP))) //If none of them are tagged. 509 m_Flags |= BTN_DOWN; 510 511 m_Payload.push_back(((m_ButtonCode & 0xff00) >> 8)); 512 m_Payload.push_back( (m_ButtonCode & 0x00ff)); 513 514 m_Payload.push_back(((m_Flags & 0xff00) >> 8) ); 515 m_Payload.push_back( (m_Flags & 0x00ff)); 516 517 m_Payload.push_back(((m_Amount & 0xff00) >> 8) ); 518 m_Payload.push_back( (m_Amount & 0x00ff)); 519 520 521 for (unsigned int i = 0; i < m_DeviceMap.size(); i++) 522 m_Payload.push_back(m_DeviceMap[i]); 523 524 m_Payload.push_back('\0'); 525 526 for (unsigned int i = 0; i < m_Button.size(); i++) 527 m_Payload.push_back(m_Button[i]); 528 529 m_Payload.push_back('\0'); 530 } 531 CPacket()532 CPacketBUTTON(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket() 533 { 534 m_PacketType = PT_BUTTON; 535 m_Flags = Flags; 536 m_ButtonCode = 0; 537 m_Amount = Amount; 538 539 unsigned int len = strlen(DeviceMap); 540 for (unsigned int i = 0; i < len; i++) 541 m_DeviceMap.push_back(DeviceMap[i]); 542 543 len = strlen(Button); 544 for (unsigned int i = 0; i < len; i++) 545 m_Button.push_back(Button[i]); 546 } 547 CPacket()548 CPacketBUTTON(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) : CPacket() 549 { 550 m_PacketType = PT_BUTTON; 551 m_Flags = Flags; 552 m_ButtonCode = ButtonCode; 553 m_Amount = Amount; 554 555 unsigned int len = strlen(DeviceMap); 556 for (unsigned int i = 0; i < len; i++) 557 m_DeviceMap.push_back(DeviceMap[i]); 558 } 559 CPacket()560 CPacketBUTTON(unsigned short ButtonCode, unsigned short Flags, unsigned short Amount = 0) : CPacket() 561 { 562 m_PacketType = PT_BUTTON; 563 m_Flags = Flags; 564 m_ButtonCode = ButtonCode; 565 m_Amount = Amount; 566 } 567 568 // Used to send a release event CPacketBUTTON()569 CPacketBUTTON() : CPacket() 570 { 571 m_PacketType = PT_BUTTON; 572 m_Flags = BTN_UP; 573 m_Amount = 0; 574 m_ButtonCode = 0; 575 } 576 ~CPacketBUTTON()577 ~CPacketBUTTON() override 578 { 579 m_DeviceMap.clear(); 580 m_Button.clear(); 581 } 582 GetFlags()583 inline unsigned short GetFlags() { return m_Flags; } GetButtonCode()584 inline unsigned short GetButtonCode() { return m_ButtonCode; } 585 }; 586 587 class CPacketPING : public CPacket 588 { 589 /************************************************************************/ 590 /* no payload */ 591 /************************************************************************/ 592 public: CPacketPING()593 CPacketPING() : CPacket() 594 { 595 m_PacketType = PT_PING; 596 } 597 ~CPacketPING() override = default; 598 }; 599 600 class CPacketBYE : public CPacket 601 { 602 /************************************************************************/ 603 /* no payload */ 604 /************************************************************************/ 605 public: CPacketBYE()606 CPacketBYE() : CPacket() 607 { 608 m_PacketType = PT_BYE; 609 } 610 ~CPacketBYE() override = default; 611 }; 612 613 class CPacketMOUSE : public CPacket 614 { 615 /************************************************************************/ 616 /* Payload format */ 617 /* %c - flags */ 618 /* - 0x01 absolute position */ 619 /* %i - mousex (0-65535 => maps to screen width) */ 620 /* %i - mousey (0-65535 => maps to screen height) */ 621 /************************************************************************/ 622 private: 623 unsigned short m_X; 624 unsigned short m_Y; 625 unsigned char m_Flag; 626 public: 627 CPacketMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE) 628 { 629 m_PacketType = PT_MOUSE; 630 m_Flag = Flag; 631 m_X = X; 632 m_Y = Y; 633 } 634 ConstructPayload()635 void ConstructPayload() override 636 { 637 m_Payload.clear(); 638 639 m_Payload.push_back(m_Flag); 640 641 m_Payload.push_back(((m_X & 0xff00) >> 8)); 642 m_Payload.push_back( (m_X & 0x00ff)); 643 644 m_Payload.push_back(((m_Y & 0xff00) >> 8)); 645 m_Payload.push_back( (m_Y & 0x00ff)); 646 } 647 648 ~CPacketMOUSE() override = default; 649 }; 650 651 class CPacketLOG : public CPacket 652 { 653 /************************************************************************/ 654 /* Payload format */ 655 /* %c - log type */ 656 /* %s - message */ 657 /************************************************************************/ 658 private: 659 std::vector<char> m_Message; 660 unsigned char m_LogLevel; 661 bool m_AutoPrintf; 662 public: 663 CPacketLOG(int LogLevel, const char *Message, bool AutoPrintf = true) 664 { 665 m_PacketType = PT_LOG; 666 667 unsigned int len = strlen(Message); 668 for (unsigned int i = 0; i < len; i++) 669 m_Message.push_back(Message[i]); 670 671 m_LogLevel = LogLevel; 672 m_AutoPrintf = AutoPrintf; 673 } 674 ConstructPayload()675 void ConstructPayload() override 676 { 677 m_Payload.clear(); 678 679 m_Payload.push_back( (m_LogLevel & 0x00ff) ); 680 681 if (m_AutoPrintf) 682 { 683 char* str=&m_Message[0]; 684 printf("%s\n", str); 685 } 686 for (unsigned int i = 0; i < m_Message.size(); i++) 687 m_Payload.push_back(m_Message[i]); 688 689 m_Payload.push_back('\0'); 690 } 691 692 ~CPacketLOG() override = default; 693 }; 694 695 class CPacketACTION : public CPacket 696 { 697 /************************************************************************/ 698 /* Payload format */ 699 /* %c - action type */ 700 /* %s - action message */ 701 /************************************************************************/ 702 private: 703 unsigned char m_ActionType; 704 std::vector<char> m_Action; 705 public: 706 CPacketACTION(const char *Action, unsigned char ActionType = ACTION_EXECBUILTIN) 707 { 708 m_PacketType = PT_ACTION; 709 710 m_ActionType = ActionType; 711 unsigned int len = strlen(Action); 712 for (unsigned int i = 0; i < len; i++) 713 m_Action.push_back(Action[i]); 714 } 715 ConstructPayload()716 void ConstructPayload() override 717 { 718 m_Payload.clear(); 719 720 m_Payload.push_back(m_ActionType); 721 for (unsigned int i = 0; i < m_Action.size(); i++) 722 m_Payload.push_back(m_Action[i]); 723 724 m_Payload.push_back('\0'); 725 } 726 727 ~CPacketACTION() override = default; 728 }; 729 730 class CXBMCClient 731 { 732 private: 733 CAddress m_Addr; 734 int m_Socket; 735 unsigned int m_UID; 736 public: 737 CXBMCClient(const char *IP = "127.0.0.1", int Port = 9777, int Socket = -1, unsigned int UID = 0) 738 { 739 m_Addr = CAddress(IP, Port); 740 if (Socket == -1) 741 m_Socket = socket(AF_INET, SOCK_DGRAM, 0); 742 else 743 m_Socket = Socket; 744 745 if (UID) 746 m_UID = UID; 747 else 748 m_UID = XBMCClientUtils::GetUniqueIdentifier(); 749 } 750 751 void SendNOTIFICATION(const char *Title, const char *Message, unsigned short IconType, const char *IconFile = NULL) 752 { 753 if (m_Socket < 0) 754 return; 755 756 CPacketNOTIFICATION notification(Title, Message, IconType, IconFile); 757 notification.Send(m_Socket, m_Addr, m_UID); 758 } 759 760 void SendHELO(const char *DevName, unsigned short IconType, const char *IconFile = NULL) 761 { 762 if (m_Socket < 0) 763 return; 764 765 CPacketHELO helo(DevName, IconType, IconFile); 766 helo.Send(m_Socket, m_Addr, m_UID); 767 } 768 769 void SendButton(const char *Button, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) 770 { 771 if (m_Socket < 0) 772 return; 773 774 CPacketBUTTON button(Button, DeviceMap, Flags, Amount); 775 button.Send(m_Socket, m_Addr, m_UID); 776 } 777 778 void SendButton(unsigned short ButtonCode, const char *DeviceMap, unsigned short Flags, unsigned short Amount = 0) 779 { 780 if (m_Socket < 0) 781 return; 782 783 CPacketBUTTON button(ButtonCode, DeviceMap, Flags, Amount); 784 button.Send(m_Socket, m_Addr, m_UID); 785 } 786 787 void SendButton(unsigned short ButtonCode, unsigned Flags, unsigned short Amount = 0) 788 { 789 if (m_Socket < 0) 790 return; 791 792 CPacketBUTTON button(ButtonCode, Flags, Amount); 793 button.Send(m_Socket, m_Addr, m_UID); 794 } 795 796 void SendMOUSE(int X, int Y, unsigned char Flag = MS_ABSOLUTE) 797 { 798 if (m_Socket < 0) 799 return; 800 801 CPacketMOUSE mouse(X, Y, Flag); 802 mouse.Send(m_Socket, m_Addr, m_UID); 803 } 804 805 void SendLOG(int LogLevel, const char *Message, bool AutoPrintf = true) 806 { 807 if (m_Socket < 0) 808 return; 809 810 CPacketLOG log(LogLevel, Message, AutoPrintf); 811 log.Send(m_Socket, m_Addr, m_UID); 812 } 813 814 void SendACTION(const char *ActionMessage, int ActionType = ACTION_EXECBUILTIN) 815 { 816 if (m_Socket < 0) 817 return; 818 819 CPacketACTION action(ActionMessage, ActionType); 820 action.Send(m_Socket, m_Addr, m_UID); 821 } 822 }; 823 824