diff --git a/NetworkClient.cpp b/NetworkClient.cpp index a25e86d54..ffec82ca7 100644 --- a/NetworkClient.cpp +++ b/NetworkClient.cpp @@ -44,8 +44,8 @@ NetworkClient::NetworkClient(std::vector& control) : controller server_reinitialize = false; change_in_progress = false; - ListenThread = NULL; - ConnectionThread = NULL; + ListenThread = NULL; + ConnectionThread = NULL; } NetworkClient::~NetworkClient() @@ -53,37 +53,22 @@ NetworkClient::~NetworkClient() StopClient(); } -void NetworkClient::ClearCallbacks() +/*---------------------------------------------------------*\ +| Client Information functions | +\*---------------------------------------------------------*/ +bool NetworkClient::GetConnected() { - ClientInfoChangeCallbacks.clear(); - ClientInfoChangeCallbackArgs.clear(); -} - -void NetworkClient::ClientInfoChanged() -{ - ClientInfoChangeMutex.lock(); - ControllerListMutex.lock(); - - /*---------------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*---------------------------------------------------------*/ - for(unsigned int callback_idx = 0; callback_idx < ClientInfoChangeCallbacks.size(); callback_idx++) - { - ClientInfoChangeCallbacks[callback_idx](ClientInfoChangeCallbackArgs[callback_idx]); - } - - ControllerListMutex.unlock(); - ClientInfoChangeMutex.unlock(); + return(server_connected); } std::string NetworkClient::GetIP() { - return port_ip; + return(port_ip); } unsigned short NetworkClient::GetPort() { - return port_num; + return(port_num); } unsigned int NetworkClient::GetProtocolVersion() @@ -102,22 +87,19 @@ unsigned int NetworkClient::GetProtocolVersion() return(protocol_version); } -bool NetworkClient::GetConnected() -{ - return(server_connected); -} - bool NetworkClient::GetOnline() { return(server_connected && client_string_sent && protocol_initialized && server_initialized); } -void NetworkClient::RegisterClientInfoChangeCallback(NetClientCallback new_callback, void * new_callback_arg) +std::string NetworkClient::GetServerName() { - ClientInfoChangeCallbacks.push_back(new_callback); - ClientInfoChangeCallbackArgs.push_back(new_callback_arg); + return(server_name); } +/*---------------------------------------------------------*\ +| Client Control functions | +\*---------------------------------------------------------*/ void NetworkClient::SetIP(std::string new_ip) { if(server_connected == false) @@ -214,6 +196,469 @@ void NetworkClient::StopClient() ClientInfoChanged(); } +void NetworkClient::SendRequest_ControllerData(unsigned int dev_idx) +{ + NetPacketHeader request_hdr; + unsigned int protocol_version; + + controller_data_received = false; + + memcpy(request_hdr.pkt_magic, openrgb_sdk_magic, sizeof(openrgb_sdk_magic)); + + request_hdr.pkt_dev_idx = dev_idx; + request_hdr.pkt_id = NET_PACKET_ID_REQUEST_CONTROLLER_DATA; + + if(server_protocol_version == 0) + { + request_hdr.pkt_size = 0; + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); + } + else + { + request_hdr.pkt_size = sizeof(unsigned int); + + /*-------------------------------------------------------------*\ + | Limit the protocol version to the highest supported by both | + | the client and the server. | + \*-------------------------------------------------------------*/ + if(server_protocol_version > OPENRGB_SDK_PROTOCOL_VERSION) + { + protocol_version = OPENRGB_SDK_PROTOCOL_VERSION; + } + else + { + protocol_version = server_protocol_version; + } + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)&protocol_version, sizeof(unsigned int), MSG_NOSIGNAL); + send_in_progress.unlock(); + } +} + +void NetworkClient::SendRequest_RescanDevices() +{ + if(GetProtocolVersion() >= 5) + { + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_REQUEST_RESCAN_DEVICES, 0); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); + } +} + +/*---------------------------------------------------------*\ +| Client Callback functions | +\*---------------------------------------------------------*/ +void NetworkClient::ClearCallbacks() +{ + ClientInfoChangeCallbacks.clear(); + ClientInfoChangeCallbackArgs.clear(); +} + +void NetworkClient::RegisterClientInfoChangeCallback(NetClientCallback new_callback, void * new_callback_arg) +{ + ClientInfoChangeCallbacks.push_back(new_callback); + ClientInfoChangeCallbackArgs.push_back(new_callback_arg); +} + +/*---------------------------------------------------------*\ +| ProfileManager functions | +\*---------------------------------------------------------*/ +char * NetworkClient::ProfileManager_GetProfileList() +{ + NetPacketHeader reply_hdr; + char * response_data = NULL; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST, 0); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); + + std::unique_lock wait_lock(waiting_on_response_mutex); + waiting_on_response_cv.wait(wait_lock); + + if(response_header.pkt_id == NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST && response_data_ptr != NULL) + { + response_data = response_data_ptr; + response_data_ptr = NULL; + } + + return(response_data); +} + +void NetworkClient::ProfileManager_LoadProfile(std::string profile_name) +{ + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_LOAD_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::ProfileManager_SaveProfile(std::string profile_name) +{ + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_SAVE_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::ProfileManager_DeleteProfile(std::string profile_name) +{ + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_DELETE_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::ProfileManager_UploadProfile(std::string profile_json_str) +{ + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_UPLOAD_PROFILE, (unsigned int)strlen(profile_json_str.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)profile_json_str.c_str(), request_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +std::string NetworkClient::ProfileManager_DownloadProfile(std::string profile_name) +{ + NetPacketHeader request_hdr; + std::string response_string; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_DOWNLOAD_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)profile_name.c_str(), request_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); + + std::unique_lock wait_lock(waiting_on_response_mutex); + waiting_on_response_cv.wait(wait_lock); + + if(response_header.pkt_id == NET_PACKET_ID_PROFILEMANAGER_DOWNLOAD_PROFILE && response_data_ptr != NULL) + { + response_string.assign(response_data_ptr, response_header.pkt_size); + delete[] response_data_ptr; + response_data_ptr = NULL; + } + + return(response_string); +} + +std::string NetworkClient::ProfileManager_GetActiveProfile() +{ + NetPacketHeader request_hdr; + std::string response_string; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_GET_ACTIVE_PROFILE, 0); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); + + std::unique_lock wait_lock(waiting_on_response_mutex); + waiting_on_response_cv.wait(wait_lock); + + if(response_header.pkt_id == NET_PACKET_ID_PROFILEMANAGER_GET_ACTIVE_PROFILE && response_data_ptr != NULL) + { + response_string.assign(response_data_ptr, response_header.pkt_size); + delete[] response_data_ptr; + response_data_ptr = NULL; + } + + return(response_string); +} + +/*---------------------------------------------------------*\ +| SettingsManager functions | +\*---------------------------------------------------------*/ +std::string NetworkClient::SettingsManager_GetSettings(std::string settings_key) +{ + NetPacketHeader request_hdr; + std::string response_string; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_SETTINGSMANAGER_GET_SETTINGS, (unsigned int)strlen(settings_key.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)settings_key.c_str(), request_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); + + std::unique_lock wait_lock(waiting_on_response_mutex); + waiting_on_response_cv.wait(wait_lock); + + if(response_header.pkt_id == NET_PACKET_ID_SETTINGSMANAGER_GET_SETTINGS && response_data_ptr != NULL) + { + response_string.assign(response_data_ptr, response_header.pkt_size); + delete[] response_data_ptr; + response_data_ptr = NULL; + } + + return(response_string); +} + +void NetworkClient::SettingsManager_SaveSettings() +{ + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_SETTINGSMANAGER_SAVE_SETTINGS, 0); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SettingsManager_SetSettings(std::string settings_json_str) +{ + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_SETTINGSMANAGER_SET_SETTINGS, (unsigned int)strlen(settings_json_str.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)settings_json_str.c_str(), request_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +/*---------------------------------------------------------*\ +| RGBController functions | +\*---------------------------------------------------------*/ +void NetworkClient::SendRequest_RGBController_ClearSegments(unsigned int dev_idx, int zone) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + int request_data[1]; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS, sizeof(request_data)); + + request_data[0] = zone; + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)&request_data, sizeof(request_data), MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_AddSegment(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, 0); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_ResizeZone(unsigned int dev_idx, int zone, int new_size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + int request_data[2]; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE, sizeof(request_data)); + + request_data[0] = zone; + request_data[1] = new_size; + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)&request_data, sizeof(request_data), MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_UpdateLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, 0); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_UpdateZoneLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_UpdateSingleLED(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_SetCustomMode(unsigned int dev_idx) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE, 0); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_UpdateMode(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_UpdateZoneMode(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATEZONEMODE, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_SaveMode(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_SAVEMODE, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::WaitOnControllerData() +{ + for(int i = 0; i < 1000; i++) + { + if(controller_data_received) + { + break; + } + std::this_thread::sleep_for(1ms); + } + + return; +} + +/*---------------------------------------------------------*\ +| Client callback signal functions | +\*---------------------------------------------------------*/ +void NetworkClient::ClientInfoChanged() +{ + ClientInfoChangeMutex.lock(); + ControllerListMutex.lock(); + + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ + for(unsigned int callback_idx = 0; callback_idx < ClientInfoChangeCallbacks.size(); callback_idx++) + { + ClientInfoChangeCallbacks[callback_idx](ClientInfoChangeCallbackArgs[callback_idx]); + } + + ControllerListMutex.unlock(); + ClientInfoChangeMutex.unlock(); +} + +/*---------------------------------------------------------*\ +| Client thread functions | +\*---------------------------------------------------------*/ void NetworkClient::ConnectionThreadFunction() { std::unique_lock lock(connection_mutex); @@ -413,37 +858,6 @@ void NetworkClient::ConnectionThreadFunction() } } -int NetworkClient::recv_select(SOCKET s, char *buf, int len, int flags) -{ - fd_set set; - struct timeval timeout; - - while(1) - { - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - FD_ZERO(&set); - FD_SET(s, &set); - - int rv = select((int)s + 1, &set, NULL, NULL, &timeout); - - if(rv == SOCKET_ERROR || server_connected == false) - { - return 0; - } - else if(rv == 0) - { - continue; - } - else - { - return(recv(s, buf, len, flags)); - } - - } -} - void NetworkClient::ListenThreadFunction() { printf("Network client listener started\n"); @@ -456,6 +870,7 @@ void NetworkClient::ListenThreadFunction() NetPacketHeader header; int bytes_read = 0; char * data = NULL; + bool delete_data = true; for(unsigned int i = 0; i < 4; i++) { @@ -540,12 +955,40 @@ void NetworkClient::ListenThreadFunction() ProcessReply_ProtocolVersion(header.pkt_size, data); break; + case NET_PACKET_ID_SET_SERVER_NAME: + if(data == NULL) + { + break; + } + + ProcessRequest_ServerString(header.pkt_size, data); + break; + case NET_PACKET_ID_DEVICE_LIST_UPDATED: ProcessRequest_DeviceListChanged(); break; + + case NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST: + case NET_PACKET_ID_PROFILEMANAGER_DOWNLOAD_PROFILE: + case NET_PACKET_ID_PROFILEMANAGER_GET_ACTIVE_PROFILE: + case NET_PACKET_ID_SETTINGSMANAGER_GET_SETTINGS: + { + std::unique_lock lock(waiting_on_response_mutex); + + response_header = header; + response_data_ptr = data; + delete_data = false; + + lock.unlock(); + waiting_on_response_cv.notify_all(); + } + break; } - delete[] data; + if(delete_data) + { + delete[] data; + } } listen_done: @@ -592,20 +1035,9 @@ listen_done: ClientInfoChanged(); } -void NetworkClient::WaitOnControllerData() -{ - for(int i = 0; i < 1000; i++) - { - if(controller_data_received) - { - break; - } - std::this_thread::sleep_for(1ms); - } - - return; -} - +/*---------------------------------------------------------*\ +| Private Client functions | +\*---------------------------------------------------------*/ void NetworkClient::ProcessReply_ControllerCount(unsigned int data_size, char * data) { if(data_size == sizeof(unsigned int)) @@ -630,7 +1062,7 @@ void NetworkClient::ProcessReply_ControllerData(unsigned int data_size, char * d { RGBController_Network * new_controller = new RGBController_Network(this, dev_idx); - new_controller->ReadDeviceDescription((unsigned char *)data, GetProtocolVersion()); + new_controller->SetDeviceDescription((unsigned char *)data, GetProtocolVersion()); /*-----------------------------------------------------*\ | Mark this controller as remote owned | @@ -730,6 +1162,16 @@ void NetworkClient::ProcessRequest_DeviceListChanged() change_in_progress = false; } +void NetworkClient::ProcessRequest_ServerString(unsigned int data_size, char * data) +{ + server_name.assign(data, data_size); + + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ + ClientInfoChanged(); +} + void NetworkClient::SendData_ClientString() { NetPacketHeader reply_hdr; @@ -753,50 +1195,6 @@ void NetworkClient::SendRequest_ControllerCount() send_in_progress.unlock(); } -void NetworkClient::SendRequest_ControllerData(unsigned int dev_idx) -{ - NetPacketHeader request_hdr; - unsigned int protocol_version; - - controller_data_received = false; - - memcpy(request_hdr.pkt_magic, openrgb_sdk_magic, sizeof(openrgb_sdk_magic)); - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_REQUEST_CONTROLLER_DATA; - - if(server_protocol_version == 0) - { - request_hdr.pkt_size = 0; - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send_in_progress.unlock(); - } - else - { - request_hdr.pkt_size = sizeof(unsigned int); - - /*-------------------------------------------------------------*\ - | Limit the protocol version to the highest supported by both | - | the client and the server. | - \*-------------------------------------------------------------*/ - if(server_protocol_version > OPENRGB_SDK_PROTOCOL_VERSION) - { - protocol_version = OPENRGB_SDK_PROTOCOL_VERSION; - } - else - { - protocol_version = server_protocol_version; - } - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)&protocol_version, sizeof(unsigned int), MSG_NOSIGNAL); - send_in_progress.unlock(); - } -} - void NetworkClient::SendRequest_ProtocolVersion() { NetPacketHeader request_hdr; @@ -812,226 +1210,9 @@ void NetworkClient::SendRequest_ProtocolVersion() send_in_progress.unlock(); } -void NetworkClient::SendRequest_RescanDevices() -{ - if(GetProtocolVersion() >= 5) - { - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_REQUEST_RESCAN_DEVICES, 0); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send_in_progress.unlock(); - } -} - -void NetworkClient::SendRequest_RGBController_ClearSegments(unsigned int dev_idx, int zone) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - int request_data[1]; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS, sizeof(request_data)); - - request_data[0] = zone; - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)&request_data, sizeof(request_data), MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_AddSegment(unsigned int dev_idx, unsigned char * data, unsigned int size) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT, size); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)data, size, 0); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_ResizeZone(unsigned int dev_idx, int zone, int new_size) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - int request_data[2]; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE, sizeof(request_data)); - - request_data[0] = zone; - request_data[1] = new_size; - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)&request_data, sizeof(request_data), MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_UpdateLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS, size); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)data, size, 0); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_UpdateZoneLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS, size); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)data, size, MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_UpdateSingleLED(unsigned int dev_idx, unsigned char * data, unsigned int size) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED, size); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)data, size, MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_SetCustomMode(unsigned int dev_idx) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE, 0); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_UpdateMode(unsigned int dev_idx, unsigned char * data, unsigned int size) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE, size); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)data, size, MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_RGBController_SaveMode(unsigned int dev_idx, unsigned char * data, unsigned int size) -{ - if(change_in_progress) - { - return; - } - - NetPacketHeader request_hdr; - - InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_SAVEMODE, size); - - send_in_progress.lock(); - send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)data, size, MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_LoadProfile(std::string profile_name) -{ - NetPacketHeader reply_hdr; - - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_LOAD_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); - - send_in_progress.lock(); - send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_SaveProfile(std::string profile_name) -{ - NetPacketHeader reply_hdr; - - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_SAVE_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); - - send_in_progress.lock(); - send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_DeleteProfile(std::string profile_name) -{ - NetPacketHeader reply_hdr; - - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_DELETE_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); - - send_in_progress.lock(); - send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); - send_in_progress.unlock(); -} - -void NetworkClient::SendRequest_GetProfileList() -{ - NetPacketHeader reply_hdr; - - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_PROFILE_LIST, 0); - - send_in_progress.lock(); - send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); - send_in_progress.unlock(); -} - +/*---------------------------------------------------------*\ +| Private ProfileManager functions | +\*---------------------------------------------------------*/ std::vector * NetworkClient::ProcessReply_ProfileList(unsigned int data_size, char * data) { std::vector * profile_list; @@ -1071,3 +1252,37 @@ std::vector * NetworkClient::ProcessReply_ProfileList(unsigned int return profile_list; } + +/*---------------------------------------------------------*\ +| Private helper functions | +\*---------------------------------------------------------*/ +int NetworkClient::recv_select(SOCKET s, char *buf, int len, int flags) +{ + fd_set set; + struct timeval timeout; + + while(1) + { + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + FD_ZERO(&set); + FD_SET(s, &set); + + int rv = select((int)s + 1, &set, NULL, NULL, &timeout); + + if(rv == SOCKET_ERROR || server_connected == false) + { + return 0; + } + else if(rv == 0) + { + continue; + } + else + { + return(recv(s, buf, len, flags)); + } + + } +} diff --git a/NetworkClient.h b/NetworkClient.h index c8c7e8764..597cfdcb2 100644 --- a/NetworkClient.h +++ b/NetworkClient.h @@ -11,6 +11,7 @@ #pragma once +#include #include #include #include @@ -26,104 +27,166 @@ public: NetworkClient(std::vector& control); ~NetworkClient(); - void ClientInfoChanged(); + /*-----------------------------------------------------*\ + | Client Information functions | + \*-----------------------------------------------------*/ + bool GetConnected(); + std::string GetIP(); + unsigned short GetPort(); + unsigned int GetProtocolVersion(); + bool GetOnline(); + std::string GetServerName(); - bool GetConnected(); - std::string GetIP(); - unsigned short GetPort(); - unsigned int GetProtocolVersion(); - bool GetOnline(); + /*-----------------------------------------------------*\ + | Client Control functions | + \*-----------------------------------------------------*/ + void SetIP(std::string new_ip); + void SetName(std::string new_name); + void SetPort(unsigned short new_port); - void ClearCallbacks(); - void RegisterClientInfoChangeCallback(NetClientCallback new_callback, void * new_callback_arg); + void StartClient(); + void StopClient(); - void SetIP(std::string new_ip); - void SetName(std::string new_name); - void SetPort(unsigned short new_port); + void SendRequest_ControllerData(unsigned int dev_idx); + void SendRequest_RescanDevices(); - void StartClient(); - void StopClient(); + /*-----------------------------------------------------*\ + | Client Callback functions | + \*-----------------------------------------------------*/ + void ClearCallbacks(); + void RegisterClientInfoChangeCallback(NetClientCallback new_callback, void * new_callback_arg); - void ConnectionThreadFunction(); - void ListenThreadFunction(); + /*-----------------------------------------------------*\ + | ProfileManager functions | + \*-----------------------------------------------------*/ + char * ProfileManager_GetProfileList(); + void ProfileManager_LoadProfile(std::string profile_name); + void ProfileManager_SaveProfile(std::string profile_name); + void ProfileManager_DeleteProfile(std::string profile_name); + void ProfileManager_UploadProfile(std::string profile_json_str); + std::string ProfileManager_DownloadProfile(std::string profile_name); + std::string ProfileManager_GetActiveProfile(); - void WaitOnControllerData(); + /*-----------------------------------------------------*\ + | SettingsManager functions | + \*-----------------------------------------------------*/ + std::string SettingsManager_GetSettings(std::string settings_key); + void SettingsManager_SaveSettings(); + void SettingsManager_SetSettings(std::string settings_json_str); - void ProcessReply_ControllerCount(unsigned int data_size, char * data); - void ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_idx); - void ProcessReply_ProtocolVersion(unsigned int data_size, char * data); + /*-----------------------------------------------------*\ + | RGBController functions | + \*-----------------------------------------------------*/ + void SendRequest_RGBController_ClearSegments(unsigned int dev_idx, int zone); + void SendRequest_RGBController_AddSegment(unsigned int dev_idx, unsigned char * data, unsigned int size); + void SendRequest_RGBController_ResizeZone(unsigned int dev_idx, int zone, int new_size); - void ProcessRequest_DeviceListChanged(); + void SendRequest_RGBController_UpdateLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size); + void SendRequest_RGBController_UpdateZoneLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size); + void SendRequest_RGBController_UpdateSingleLED(unsigned int dev_idx, unsigned char * data, unsigned int size); - void SendData_ClientString(); + void SendRequest_RGBController_SetCustomMode(unsigned int dev_idx); - void SendRequest_ControllerCount(); - void SendRequest_ControllerData(unsigned int dev_idx); - void SendRequest_ProtocolVersion(); + void SendRequest_RGBController_UpdateMode(unsigned int dev_idx, unsigned char * data, unsigned int size); + void SendRequest_RGBController_UpdateZoneMode(unsigned int dev_idx, unsigned char * data, unsigned int size); + void SendRequest_RGBController_SaveMode(unsigned int dev_idx, unsigned char * data, unsigned int size); - void SendRequest_RescanDevices(); - - void SendRequest_RGBController_ClearSegments(unsigned int dev_idx, int zone); - void SendRequest_RGBController_AddSegment(unsigned int dev_idx, unsigned char * data, unsigned int size); - void SendRequest_RGBController_ResizeZone(unsigned int dev_idx, int zone, int new_size); - - void SendRequest_RGBController_UpdateLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size); - void SendRequest_RGBController_UpdateZoneLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size); - void SendRequest_RGBController_UpdateSingleLED(unsigned int dev_idx, unsigned char * data, unsigned int size); - - void SendRequest_RGBController_SetCustomMode(unsigned int dev_idx); - - void SendRequest_RGBController_UpdateMode(unsigned int dev_idx, unsigned char * data, unsigned int size); - void SendRequest_RGBController_SaveMode(unsigned int dev_idx, unsigned char * data, unsigned int size); - - - std::vector * ProcessReply_ProfileList(unsigned int data_size, char * data); - - void SendRequest_GetProfileList(); - void SendRequest_LoadProfile(std::string profile_name); - void SendRequest_SaveProfile(std::string profile_name); - void SendRequest_DeleteProfile(std::string profile_name); - - std::vector server_controllers; - - std::mutex ControllerListMutex; - -protected: - std::vector& controllers; + void WaitOnControllerData(); + std::vector server_controllers; private: - SOCKET client_sock; - std::string client_name; - net_port port; - std::string port_ip; - unsigned short port_num; - std::atomic client_active; - bool client_string_sent; - bool controller_data_received; - bool controller_data_requested; - bool protocol_initialized; - bool server_connected; - bool server_initialized; - bool server_reinitialize; - unsigned int server_controller_count; - bool server_controller_count_requested; - bool server_controller_count_received; - unsigned int server_protocol_version; - bool server_protocol_version_received; - bool change_in_progress; - unsigned int requested_controllers; - std::mutex send_in_progress; + /*-----------------------------------------------------*\ + | Client state variables | + \*-----------------------------------------------------*/ + std::atomic client_active; + bool client_string_sent; + bool controller_data_received; + bool controller_data_requested; + bool protocol_initialized; + bool change_in_progress; + unsigned int requested_controllers; + std::mutex send_in_progress; - std::mutex connection_mutex; - std::condition_variable connection_cv; + NetPacketHeader response_header; + char * response_data_ptr; + std::mutex waiting_on_response_mutex; + std::condition_variable waiting_on_response_cv; - std::thread * ConnectionThread; - std::thread * ListenThread; + /*-----------------------------------------------------*\ + | Client information | + \*-----------------------------------------------------*/ + std::string client_name; + SOCKET client_sock; + net_port port; + std::string port_ip; + unsigned short port_num; + /*-----------------------------------------------------*\ + | Server information | + \*-----------------------------------------------------*/ + std::string server_name; + bool server_connected; + bool server_initialized; + bool server_reinitialize; + unsigned int server_controller_count; + bool server_controller_count_requested; + bool server_controller_count_received; + unsigned int server_protocol_version; + bool server_protocol_version_received; + + /*-----------------------------------------------------*\ + | Client threads | + \*-----------------------------------------------------*/ + std::mutex connection_mutex; + std::condition_variable connection_cv; + std::thread * ConnectionThread; + std::thread * ListenThread; + + /*-----------------------------------------------------*\ + | Callbacks | + \*-----------------------------------------------------*/ std::mutex ClientInfoChangeMutex; std::vector ClientInfoChangeCallbacks; std::vector ClientInfoChangeCallbackArgs; - int recv_select(SOCKET s, char *buf, int len, int flags); + /*-----------------------------------------------------*\ + | Controller list | + \*-----------------------------------------------------*/ + std::mutex ControllerListMutex; + std::vector& controllers; + + /*-----------------------------------------------------*\ + | Client callback signal functions | + \*-----------------------------------------------------*/ + void ClientInfoChanged(); + + /*-----------------------------------------------------*\ + | Client thread functions | + \*-----------------------------------------------------*/ + void ConnectionThreadFunction(); + void ListenThreadFunction(); + + /*-----------------------------------------------------*\ + | Private Client functions | + \*-----------------------------------------------------*/ + void ProcessReply_ControllerCount(unsigned int data_size, char * data); + void ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_idx); + void ProcessReply_ProtocolVersion(unsigned int data_size, char * data); + void ProcessRequest_DeviceListChanged(); + void ProcessRequest_ServerString(unsigned int data_size, char * data); + + void SendData_ClientString(); + void SendRequest_ControllerCount(); + void SendRequest_ProtocolVersion(); + + /*-----------------------------------------------------*\ + | Private ProfileManager functions | + \*-----------------------------------------------------*/ + std::vector * ProcessReply_ProfileList(unsigned int data_size, char * data); + + /*-----------------------------------------------------*\ + | Private helper functions | + \*-----------------------------------------------------*/ + int recv_select(SOCKET s, char *buf, int len, int flags); }; diff --git a/NetworkProtocol.h b/NetworkProtocol.h index b44dfa650..5f9d04e6d 100644 --- a/NetworkProtocol.h +++ b/NetworkProtocol.h @@ -61,33 +61,51 @@ enum NET_PACKET_ID_REQUEST_PROTOCOL_VERSION = 40, /* Request OpenRGB SDK protocol version from server */ NET_PACKET_ID_SET_CLIENT_NAME = 50, /* Send client name string to server */ + NET_PACKET_ID_SET_SERVER_NAME = 51, /* Send server name string to client */ NET_PACKET_ID_DEVICE_LIST_UPDATED = 100, /* Indicate to clients that device list has updated */ NET_PACKET_ID_REQUEST_RESCAN_DEVICES = 140, /* Request rescan of devices */ - NET_PACKET_ID_REQUEST_PROFILE_LIST = 150, /* Request profile list */ - NET_PACKET_ID_REQUEST_SAVE_PROFILE = 151, /* Save current configuration in a new profile */ - NET_PACKET_ID_REQUEST_LOAD_PROFILE = 152, /* Load a given profile */ - NET_PACKET_ID_REQUEST_DELETE_PROFILE = 153, /* Delete a given profile */ - - NET_PACKET_ID_REQUEST_PLUGIN_LIST = 200, /* Request list of plugins */ - NET_PACKET_ID_PLUGIN_SPECIFIC = 201, /* Interact with a plugin */ + /*----------------------------------------------------------------------------------------------------------*\ + | ProfileManager functions | + \*----------------------------------------------------------------------------------------------------------*/ + NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST = 150, /* Get profile list */ + NET_PACKET_ID_PROFILEMANAGER_SAVE_PROFILE = 151, /* Save current configuration in a new profile */ + NET_PACKET_ID_PROFILEMANAGER_LOAD_PROFILE = 152, /* Load a given profile */ + NET_PACKET_ID_PROFILEMANAGER_DELETE_PROFILE = 153, /* Delete a given profile */ + NET_PACKET_ID_PROFILEMANAGER_UPLOAD_PROFILE = 154, /* Upload a profile to the server in JSON format */ + NET_PACKET_ID_PROFILEMANAGER_DOWNLOAD_PROFILE = 155, /* Download a profile from the server in JSON format*/ + NET_PACKET_ID_PROFILEMANAGER_GET_ACTIVE_PROFILE = 156, /* Get the active profile name */ /*----------------------------------------------------------------------------------------------------------*\ - | RGBController class functions | + | PluginManager functions | \*----------------------------------------------------------------------------------------------------------*/ - NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE = 1000, /* RGBController::ResizeZone() */ - NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS = 1001, /* RGBController::ClearSegments() */ - NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT = 1002, /* RGBController::AddSegment() */ + NET_PACKET_ID_PLUGINMANAGER_GET_PLUGIN_LIST = 200, /* Get list of plugins */ + NET_PACKET_ID_PLUGINMANAGER_PLUGIN_SPECIFIC = 201, /* Interact with a plugin */ - NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS = 1050, /* RGBController::UpdateLEDs() */ - NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS = 1051, /* RGBController::UpdateZoneLEDs() */ - NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED = 1052, /* RGBController::UpdateSingleLED() */ + /*----------------------------------------------------------------------------------------------------------*\ + | SettingsManager functions | + \*----------------------------------------------------------------------------------------------------------*/ + NET_PACKET_ID_SETTINGSMANAGER_GET_SETTINGS = 250, /* Get settings for a given key in JSON format */ + NET_PACKET_ID_SETTINGSMANAGER_SET_SETTINGS = 251, /* Set settings for a given key in JSON format */ + NET_PACKET_ID_SETTINGSMANAGER_SAVE_SETTINGS = 252, /* Save settings */ - NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE = 1100, /* RGBController::SetCustomMode() */ - NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE = 1101, /* RGBController::UpdateMode() */ - NET_PACKET_ID_RGBCONTROLLER_SAVEMODE = 1102, /* RGBController::SaveMode() */ + /*----------------------------------------------------------------------------------------------------------*\ + | RGBController functions | + \*----------------------------------------------------------------------------------------------------------*/ + NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE = 1000, /* RGBController::ResizeZone() */ + NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS = 1001, /* RGBController::ClearSegments() */ + NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT = 1002, /* RGBController::AddSegment() */ + + NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS = 1050, /* RGBController::UpdateLEDs() */ + NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS = 1051, /* RGBController::UpdateZoneLEDs() */ + NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED = 1052, /* RGBController::UpdateSingleLED() */ + + NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE = 1100, /* RGBController::SetCustomMode() */ + NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE = 1101, /* RGBController::UpdateMode() */ + NET_PACKET_ID_RGBCONTROLLER_SAVEMODE = 1102, /* RGBController::SaveMode() */ + NET_PACKET_ID_RGBCONTROLLER_UPDATEZONEMODE = 1103, /* RGBController::UpdateZoneMode() */ }; void InitNetPacketHeader diff --git a/NetworkServer.cpp b/NetworkServer.cpp index 456189ee0..2e74485ad 100644 --- a/NetworkServer.cpp +++ b/NetworkServer.cpp @@ -10,10 +10,11 @@ \*---------------------------------------------------------*/ #include +#include #include "NetworkServer.h" #include "LogManager.h" -#ifndef WIN32 +#ifndef _WIN32 #include #include #include @@ -28,8 +29,9 @@ const char yes = 1; -#ifdef WIN32 +#ifdef _WIN32 #include +#define MSG_NOSIGNAL 0 #else #include #endif @@ -71,6 +73,7 @@ NetworkServer::NetworkServer(std::vector& control) : controller plugin_manager = nullptr; profile_manager = nullptr; + settings_manager = nullptr; } NetworkServer::~NetworkServer() @@ -78,48 +81,9 @@ NetworkServer::~NetworkServer() StopServer(); } -void NetworkServer::ClientInfoChanged() -{ - ClientInfoChangeMutex.lock(); - - /*---------------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*---------------------------------------------------------*/ - for(unsigned int callback_idx = 0; callback_idx < ClientInfoChangeCallbacks.size(); callback_idx++) - { - ClientInfoChangeCallbacks[callback_idx](ClientInfoChangeCallbackArgs[callback_idx]); - } - - ClientInfoChangeMutex.unlock(); -} - -void NetworkServer::DeviceListChanged() -{ - /*---------------------------------------------------------*\ - | Indicate to the clients that the controller list has | - | changed | - \*---------------------------------------------------------*/ - for(unsigned int client_idx = 0; client_idx < ServerClients.size(); client_idx++) - { - SendRequest_DeviceListChanged(ServerClients[client_idx]->client_sock); - } -} - -void NetworkServer::ServerListeningChanged() -{ - ServerListeningChangeMutex.lock(); - - /*---------------------------------------------------------*\ - | Server state has changed, call the callbacks | - \*---------------------------------------------------------*/ - for(unsigned int callback_idx = 0; callback_idx < ServerListeningChangeCallbacks.size(); callback_idx++) - { - ServerListeningChangeCallbacks[callback_idx](ServerListeningChangeCallbackArgs[callback_idx]); - } - - ServerListeningChangeMutex.unlock(); -} - +/*---------------------------------------------------------*\ +| Server Information functions | +\*---------------------------------------------------------*/ std::string NetworkServer::GetHost() { return host; @@ -205,6 +169,21 @@ unsigned int NetworkServer::GetClientProtocolVersion(unsigned int client_num) return result; } +/*---------------------------------------------------------*\ +| Callback functions | +\*---------------------------------------------------------*/ +void NetworkServer::DeviceListChanged() +{ + /*-----------------------------------------------------*\ + | Indicate to the clients that the controller list has | + | changed | + \*-----------------------------------------------------*/ + for(unsigned int client_idx = 0; client_idx < ServerClients.size(); client_idx++) + { + SendRequest_DeviceListChanged(ServerClients[client_idx]->client_sock); + } +} + void NetworkServer::RegisterClientInfoChangeCallback(NetServerCallback new_callback, void * new_callback_arg) { ClientInfoChangeCallbacks.push_back(new_callback); @@ -217,6 +196,9 @@ void NetworkServer::RegisterServerListeningChangeCallback(NetServerCallback new_ ServerListeningChangeCallbackArgs.push_back(new_callback_arg); } +/*---------------------------------------------------------*\ +| Server Configuration functions | +\*---------------------------------------------------------*/ void NetworkServer::SetHost(std::string new_host) { if(server_online == false) @@ -230,6 +212,22 @@ void NetworkServer::SetLegacyWorkaroundEnable(bool enable) legacy_workaround_enabled = enable; } +void NetworkServer::SetName(std::string new_name) +{ + /*-----------------------------------------------------*\ + | Store the server name | + \*-----------------------------------------------------*/ + server_name = new_name; + + /*-----------------------------------------------------*\ + | Send server name to all clients | + \*-----------------------------------------------------*/ + for(std::size_t client_idx = 0; client_idx < ServerClients.size(); client_idx++) + { + SendReply_ServerString(ServerClients[client_idx]->client_sock); + } +} + void NetworkServer::SetPort(unsigned short new_port) { if(server_online == false) @@ -238,22 +236,25 @@ void NetworkServer::SetPort(unsigned short new_port) } } +/*---------------------------------------------------------*\ +| Server Control functions | +\*---------------------------------------------------------*/ void NetworkServer::StartServer() { int err; struct addrinfo hints, *res, *result; - /*---------------------------------------------------------*\ - | Start a TCP server and launch threads | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Start a TCP server and launch threads | + \*-----------------------------------------------------*/ char port_str[6]; snprintf(port_str, 6, "%d", port_num); socket_count = 0; - /*---------------------------------------------------------*\ - | Windows requires WSAStartup before using sockets | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Windows requires WSAStartup before using sockets | + \*-----------------------------------------------------*/ #ifdef WIN32 if(WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR) { @@ -275,9 +276,9 @@ void NetworkServer::StartServer() return; } - /*---------------------------------------------------------*\ - | Create a server socket for each address returned. | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Create a server socket for each address returned. | + \*-----------------------------------------------------*/ for(res = result; res && socket_count < MAXSOCK; res = res->ai_next) { server_sock[socket_count] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); @@ -289,14 +290,14 @@ void NetworkServer::StartServer() return; } - /*---------------------------------------------------------*\ - | Set socket options - reuse addr | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Set socket options - reuse addr | + \*-------------------------------------------------*/ setsockopt(server_sock[socket_count], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - /*---------------------------------------------------------*\ - | Bind the server socket | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Bind the server socket | + \*-------------------------------------------------*/ if(bind(server_sock[socket_count], res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) { if(errno == EADDRINUSE) @@ -332,9 +333,9 @@ void NetworkServer::StartServer() return; } - /*---------------------------------------------------------*\ - | Set socket options - no delay | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Set socket options - no delay | + \*-------------------------------------------------*/ setsockopt(server_sock[socket_count], IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); socket_count += 1; @@ -343,9 +344,9 @@ void NetworkServer::StartServer() freeaddrinfo(result); server_online = true; - /*---------------------------------------------------------*\ - | Start the connection thread | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Start the connection thread | + \*-----------------------------------------------------*/ for(int curr_socket = 0; curr_socket < socket_count; curr_socket++) { ConnectionThread[curr_socket] = new std::thread(&NetworkServer::ConnectionThreadFunction, this, curr_socket); @@ -386,24 +387,78 @@ void NetworkServer::StopServer() socket_count = 0; - /*---------------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*-----------------------------------------------------*/ ClientInfoChanged(); } +/*---------------------------------------------------------*\ +| Server Interface functions | +\*---------------------------------------------------------*/ +void NetworkServer::SetPluginManager(PluginManagerInterface* plugin_manager_pointer) +{ + plugin_manager = plugin_manager_pointer; +} + +void NetworkServer::SetProfileManager(ProfileManagerInterface* profile_manager_pointer) +{ + profile_manager = profile_manager_pointer; +} + +void NetworkServer::SetSettingsManager(SettingsManagerInterface* settings_manager_pointer) +{ + settings_manager = settings_manager_pointer; +} + +/*---------------------------------------------------------*\ +| Server callback signal functions | +\*---------------------------------------------------------*/ +void NetworkServer::ClientInfoChanged() +{ + ClientInfoChangeMutex.lock(); + + /*-----------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*-----------------------------------------------------*/ + for(unsigned int callback_idx = 0; callback_idx < ClientInfoChangeCallbacks.size(); callback_idx++) + { + ClientInfoChangeCallbacks[callback_idx](ClientInfoChangeCallbackArgs[callback_idx]); + } + + ClientInfoChangeMutex.unlock(); +} + +void NetworkServer::ServerListeningChanged() +{ + ServerListeningChangeMutex.lock(); + + /*-----------------------------------------------------*\ + | Server state has changed, call the callbacks | + \*-----------------------------------------------------*/ + for(unsigned int callback_idx = 0; callback_idx < ServerListeningChangeCallbacks.size(); callback_idx++) + { + ServerListeningChangeCallbacks[callback_idx](ServerListeningChangeCallbackArgs[callback_idx]); + } + + ServerListeningChangeMutex.unlock(); +} + +/*---------------------------------------------------------*\ +| Server Thread functions | +\*---------------------------------------------------------*/ void NetworkServer::ConnectionThreadFunction(int socket_idx) { - /*---------------------------------------------------------*\ - | This thread handles client connections | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | This thread handles client connections | + \*-----------------------------------------------------*/ LOG_INFO("[NetworkServer] Network connection thread started on port %hu", GetPort()); while(server_online == true) { - /*---------------------------------------------------------*\ - | Create new socket for client connection | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Create new socket for client connection | + \*-------------------------------------------------*/ NetworkClientInfo * client_info = new NetworkClientInfo(); /*---------------------------------------------------------*\ @@ -422,9 +477,9 @@ void NetworkServer::ConnectionThreadFunction(int socket_idx) server_listening = true; ServerListeningChanged(); - /*---------------------------------------------------------*\ - | Accept the client connection | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Accept the client connection | + \*-------------------------------------------------*/ client_info->client_sock = accept_select((int)server_sock[socket_idx]); if(client_info->client_sock < 0) @@ -446,9 +501,9 @@ void NetworkServer::ConnectionThreadFunction(int socket_idx) ioctlsocket(client_info->client_sock, FIONBIO, &arg); setsockopt(client_info->client_sock, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); - /*---------------------------------------------------------*\ - | Discover the remote hosts IP | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Discover the remote hosts IP | + \*-------------------------------------------------*/ struct sockaddr_storage tmp_addr; char ipstr[INET6_ADDRSTRLEN]; socklen_t len; @@ -482,9 +537,9 @@ void NetworkServer::ConnectionThreadFunction(int socket_idx) ServerClients.push_back(client_info); ServerClientsMutex.unlock(); - /*---------------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*-------------------------------------------------*/ ClientInfoChanged(); } @@ -494,62 +549,54 @@ void NetworkServer::ConnectionThreadFunction(int socket_idx) ServerListeningChanged(); } -int NetworkServer::accept_select(int sockfd) +void NetworkServer::ControllerListenThread(NetworkServerControllerThread * this_thread) { - fd_set set; - struct timeval timeout; - - while(1) + while(this_thread->online == true) { - timeout.tv_sec = TCP_TIMEOUT_SECONDS; - timeout.tv_usec = 0; + std::unique_lock start_lock(this_thread->start_mutex); + this_thread->start_cv.wait(start_lock); - FD_ZERO(&set); - FD_SET(sockfd, &set); - - int rv = select(sockfd + 1, &set, NULL, NULL, &timeout); - - if(rv == SOCKET_ERROR || server_online == false) + while(this_thread->queue.size() > 0) { - return -1; - } - else if(rv == 0) - { - continue; - } - else - { - return(accept((int)sockfd, NULL, NULL)); - } - } -} + NetworkServerControllerThreadQueueEntry queue_entry; -int NetworkServer::recv_select(SOCKET s, char *buf, int len, int flags) -{ - fd_set set; - struct timeval timeout; + this_thread->queue_mutex.lock(); + queue_entry = this_thread->queue.front(); + this_thread->queue.pop(); + this_thread->queue_mutex.unlock(); - while(1) - { - timeout.tv_sec = TCP_TIMEOUT_SECONDS; - timeout.tv_usec = 0; + switch(queue_entry.id) + { + case NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS: + ProcessRequest_RGBController_UpdateLEDs(this_thread->index, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); + break; - FD_ZERO(&set); - FD_SET(s, &set); + case NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS: + { + int zone; - int rv = select((int)s + 1, &set, NULL, NULL, &timeout); + memcpy(&zone, &queue_entry.data[sizeof(unsigned int)], sizeof(int)); - if(rv == SOCKET_ERROR || server_online == false) - { - return 0; - } - else if(rv == 0) - { - continue; - } - else - { - return(recv(s, buf, len, flags)); + controllers[this_thread->index]->SetZoneColorDescription((unsigned char *)queue_entry.data); + controllers[this_thread->index]->UpdateZoneLEDs(zone); + } + break; + + case NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE: + ProcessRequest_RGBController_UpdateSaveMode(this_thread->index, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); + controllers[this_thread->index]->UpdateMode(); + break; + + case NET_PACKET_ID_RGBCONTROLLER_SAVEMODE: + ProcessRequest_RGBController_UpdateSaveMode(this_thread->index, (unsigned char *)queue_entry.data, queue_entry.client_protocol_version); + controllers[this_thread->index]->SaveMode(); + break; + + case NET_PACKET_ID_RGBCONTROLLER_UPDATEZONEMODE: + break; + } + + delete[] queue_entry.data; } } } @@ -560,20 +607,21 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) LOG_INFO("[NetworkServer] Network server started"); - /*---------------------------------------------------------*\ - | This thread handles messages received from clients | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | This thread handles messages received from clients | + \*-----------------------------------------------------*/ while(server_online == true) { NetPacketHeader header; int bytes_read = 0; char * data = NULL; + bool delete_data = true; for(unsigned int i = 0; i < 4; i++) { - /*---------------------------------------------------------*\ - | Read byte of magic | - \*---------------------------------------------------------*/ + /*---------------------------------------------*\ + | Read byte of magic | + \*---------------------------------------------*/ bytes_read = recv_select(client_sock, &header.pkt_magic[i], 1, 0); if(bytes_read <= 0) @@ -582,9 +630,9 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) goto listen_done; } - /*---------------------------------------------------------*\ - | Test characters of magic "ORGB" | - \*---------------------------------------------------------*/ + /*---------------------------------------------*\ + | Test characters of magic "ORGB" | + \*---------------------------------------------*/ if(header.pkt_magic[i] != openrgb_sdk_magic[i]) { LOG_ERROR("[NetworkServer] Invalid magic received"); @@ -592,10 +640,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) } } - /*---------------------------------------------------------*\ - | If we get to this point, the magic is correct. Read the | - | rest of the header | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | If we get to this point, the magic is correct. | + | Read the rest of the header | + \*-------------------------------------------------*/ bytes_read = 0; do { @@ -613,9 +661,9 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) } while(bytes_read != sizeof(header) - sizeof(header.pkt_magic)); - /*---------------------------------------------------------*\ - | Header received, now receive the data | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Header received, now receive the data | + \*-------------------------------------------------*/ bytes_read = 0; if(header.pkt_size > 0) { @@ -637,12 +685,15 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) } while ((unsigned int)bytes_read < header.pkt_size); } - /*---------------------------------------------------------*\ - | Entire request received, select functionality based on | - | request ID | - \*---------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Entire request received, select functionality | + | based on request ID | + \*-------------------------------------------------*/ switch(header.pkt_id) { + /*-------------------------------------------------*\ + | Network requests | + \*-------------------------------------------------*/ case NET_PACKET_ID_REQUEST_CONTROLLER_COUNT: SendReply_ControllerCount(client_sock); break; @@ -661,8 +712,9 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; case NET_PACKET_ID_REQUEST_PROTOCOL_VERSION: - SendReply_ProtocolVersion(client_sock); ProcessRequest_ClientProtocolVersion(client_sock, header.pkt_size, data); + SendReply_ProtocolVersion(client_sock); + SendReply_ServerString(client_sock); break; case NET_PACKET_ID_SET_CLIENT_NAME: @@ -678,6 +730,189 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) ProcessRequest_RescanDevices(); break; + /*-------------------------------------------------*\ + | ProfileManager functions | + \*-------------------------------------------------*/ + case NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST: + SendReply_ProfileList(client_sock); + break; + + case NET_PACKET_ID_PROFILEMANAGER_SAVE_PROFILE: + if(data == NULL) + { + break; + } + + if(profile_manager) + { + std::string profile_name; + profile_name.assign(data, header.pkt_size); + + profile_manager->SaveProfile(profile_name); + } + break; + + case NET_PACKET_ID_PROFILEMANAGER_LOAD_PROFILE: + if(data == NULL) + { + break; + } + + if(profile_manager) + { + std::string profile_name; + profile_name.assign(data, header.pkt_size); + + profile_manager->LoadProfile(profile_name); + } + break; + + case NET_PACKET_ID_PROFILEMANAGER_DELETE_PROFILE: + if(data == NULL) + { + break; + } + + if(profile_manager) + { + std::string profile_name; + profile_name.assign(data, header.pkt_size); + + profile_manager->DeleteProfile(profile_name); + } + break; + + case NET_PACKET_ID_PROFILEMANAGER_UPLOAD_PROFILE: + if(data == NULL) + { + break; + } + + if(profile_manager) + { + std::string profile_json_string; + profile_json_string.assign(data, header.pkt_size); + + nlohmann::json profile_json = nlohmann::json::parse(profile_json_string); + + profile_manager->SaveProfileFromJSON(profile_json); + } + break; + + case NET_PACKET_ID_PROFILEMANAGER_DOWNLOAD_PROFILE: + if(data == NULL) + { + break; + } + + if(profile_manager) + { + std::string profile_name; + profile_name.assign(data, header.pkt_size); + + std::string profile_json_string = profile_manager->ReadProfileJSON(profile_name).dump(); + + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_DOWNLOAD_PROFILE, (unsigned int)strlen(profile_json_string.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)profile_json_string.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); + } + break; + + case NET_PACKET_ID_PROFILEMANAGER_GET_ACTIVE_PROFILE: + { + std::string active_profile_name = profile_manager->GetActiveProfile(); + + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_GET_ACTIVE_PROFILE, (unsigned int)strlen(active_profile_name.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)active_profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); + } + break; + + /*-------------------------------------------------*\ + | PluginManager functions | + \*-------------------------------------------------*/ + case NET_PACKET_ID_PLUGINMANAGER_GET_PLUGIN_LIST: + SendReply_PluginList(client_sock); + break; + + case NET_PACKET_ID_PLUGINMANAGER_PLUGIN_SPECIFIC: + if(plugin_manager) + { + unsigned int plugin_pkt_id = *((unsigned int*)(data)); + unsigned int plugin_pkt_size = header.pkt_size - (sizeof(unsigned int)); + unsigned char* plugin_data = (unsigned char*)(data + sizeof(unsigned int)); + unsigned char* output = plugin_manager->OnSDKCommand(header.pkt_dev_idx, plugin_pkt_id, plugin_data, &plugin_pkt_size); + + if(output != nullptr) + { + SendReply_PluginSpecific(client_sock, plugin_pkt_id, output, plugin_pkt_size); + } + } + break; + + /*-------------------------------------------------*\ + | SettingsManager functions | + \*-------------------------------------------------*/ + case NET_PACKET_ID_SETTINGSMANAGER_GET_SETTINGS: + if(data == NULL) + { + break; + } + + if(settings_manager != NULL) + { + std::string settings_key; + settings_key.assign(data, header.pkt_size); + + nlohmann::json settings_json = settings_manager->GetSettings(settings_key); + std::string settings_json_str = settings_json.dump(); + + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_SETTINGSMANAGER_GET_SETTINGS, (unsigned int)strlen(settings_json_str.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)settings_json_str.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); + } + break; + + case NET_PACKET_ID_SETTINGSMANAGER_SET_SETTINGS: + if(data == NULL) + { + break; + } + + if(settings_manager != NULL) + { + std::string settings_json_str; + settings_json_str.assign(data, header.pkt_size); + + settings_manager->SetSettingsFromJsonString(settings_json_str); + } + break; + + case NET_PACKET_ID_SETTINGSMANAGER_SAVE_SETTINGS: + if(settings_manager != NULL) + { + settings_manager->SaveSettings(); + } + break; + + /*-------------------------------------------------*\ + | RGBController functions | + \*-------------------------------------------------*/ case NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE: if(data == NULL) { @@ -698,71 +933,64 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; case NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS: - if(data == NULL) - { - break; - } - - /*---------------------------------------------------------*\ - | Verify the color description size (first 4 bytes of data) | - | matches the packet size in the header | - | | - | If protocol version is 4 or below and the legacy SDK | - | compatibility workaround is enabled, ignore this check. | - | This allows backwards compatibility with old versions of | - | SDK applications that didn't properly implement the size | - | field. | - \*---------------------------------------------------------*/ - if((header.pkt_size == *((unsigned int*)data)) - || ((client_info->client_protocol_version <= 4) - && (legacy_workaround_enabled))) - { - if(header.pkt_dev_idx < controllers.size()) - { - controllers[header.pkt_dev_idx]->SetColorDescription((unsigned char *)data); - controllers[header.pkt_dev_idx]->UpdateLEDs(); - } - } - else - { - LOG_ERROR("[NetworkServer] UpdateLEDs packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, *((unsigned int*)data)); - goto listen_done; - } - break; - case NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS: + case NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE: + case NET_PACKET_ID_RGBCONTROLLER_SAVEMODE: + case NET_PACKET_ID_RGBCONTROLLER_UPDATEZONEMODE: if(data == NULL) { break; } - /*---------------------------------------------------------*\ - | Verify the color description size (first 4 bytes of data) | - | matches the packet size in the header | - | | - | If protocol version is 4 or below and the legacy SDK | - | compatibility workaround is enabled, ignore this check. | - | This allows backwards compatibility with old versions of | - | SDK applications that didn't properly implement the size | - | field. | - \*---------------------------------------------------------*/ + /*-----------------------------------------*\ + | Verify the color description size (first | + | 4 bytes of data) matches the packet size | + | in the header | + | | + | If protocol version is 4 or below and the | + | legacy SDK compatibility workaround is | + | enabled, ignore this check. This allows | + | backwards compatibility with old versions | + | of SDK applications that didn't properly | + | implement the size field. | + \*-----------------------------------------*/ if((header.pkt_size == *((unsigned int*)data)) || ((client_info->client_protocol_version <= 4) && (legacy_workaround_enabled))) { if(header.pkt_dev_idx < controllers.size()) { - int zone; + if(controller_threads.size() < controllers.size()) + { + for(std::size_t controller_idx = controller_threads.size(); controller_idx < controllers.size(); controller_idx++) + { + NetworkServerControllerThread * new_controller_thread = new NetworkServerControllerThread; - memcpy(&zone, &data[sizeof(unsigned int)], sizeof(int)); + new_controller_thread->index = controller_idx; + new_controller_thread->online = true; + new_controller_thread->thread = new std::thread(&NetworkServer::ControllerListenThread, this, new_controller_thread); - controllers[header.pkt_dev_idx]->SetZoneColorDescription((unsigned char *)data); - controllers[header.pkt_dev_idx]->UpdateZoneLEDs(zone); + controller_threads.push_back(new_controller_thread); + } + } + + controller_threads[header.pkt_dev_idx]->queue_mutex.lock(); + NetworkServerControllerThreadQueueEntry new_entry; + new_entry.data = data; + new_entry.id = header.pkt_id; + new_entry.size = header.pkt_size; + new_entry.client_protocol_version = client_info->client_protocol_version; + controller_threads[header.pkt_dev_idx]->queue.push(new_entry); + controller_threads[header.pkt_dev_idx]->queue_mutex.unlock(); + + controller_threads[header.pkt_dev_idx]->start_cv.notify_all(); + + delete_data = false; } } else { - LOG_ERROR("[NetworkServer] UpdateZoneLEDs packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, *((unsigned int*)data)); + LOG_ERROR("[NetworkServer] RGBController packet with ID %d has invalid size. Packet size: %d, Data size: %d", header.pkt_id, header.pkt_size, *((unsigned int*)data)); goto listen_done; } break; @@ -773,10 +1001,11 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; } - /*---------------------------------------------------------*\ - | Verify the single LED color description size (8 bytes) | - | matches the packet size in the header | - \*---------------------------------------------------------*/ + /*-----------------------------------------*\ + | Verify the single LED color description | + | size (8 bytes) matches the packet size in | + | the header | + \*-----------------------------------------*/ if(header.pkt_size == (sizeof(int) + sizeof(RGBColor))) { if(header.pkt_dev_idx < controllers.size()) @@ -803,138 +1032,6 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) } break; - case NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE: - if(data == NULL) - { - break; - } - - /*---------------------------------------------------------*\ - | Verify the mode description size (first 4 bytes of data) | - | matches the packet size in the header | - | | - | If protocol version is 4 or below and the legacy SDK | - | compatibility workaround is enabled, ignore this check. | - | This allows backwards compatibility with old versions of | - | SDK applications that didn't properly implement the size | - | field. | - \*---------------------------------------------------------*/ - if((header.pkt_size == *((unsigned int*)data)) - || ((client_info->client_protocol_version <= 4) - && (legacy_workaround_enabled))) - { - if(header.pkt_dev_idx < controllers.size()) - { - controllers[header.pkt_dev_idx]->SetModeDescription((unsigned char *)data, client_info->client_protocol_version); - controllers[header.pkt_dev_idx]->UpdateMode(); - } - } - else - { - LOG_ERROR("[NetworkServer] UpdateMode packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, *((unsigned int*)data)); - goto listen_done; - } - break; - - case NET_PACKET_ID_RGBCONTROLLER_SAVEMODE: - if(data == NULL) - { - break; - } - - /*---------------------------------------------------------*\ - | Verify the mode description size (first 4 bytes of data) | - | matches the packet size in the header | - | | - | If protocol version is 4 or below and the legacy SDK | - | compatibility workaround is enabled, ignore this check. | - | This allows backwards compatibility with old versions of | - | SDK applications that didn't properly implement the size | - | field. | - \*---------------------------------------------------------*/ - if((header.pkt_size == *((unsigned int*)data)) - || ((client_info->client_protocol_version <= 4) - && (legacy_workaround_enabled))) - { - if(header.pkt_dev_idx < controllers.size()) - { - controllers[header.pkt_dev_idx]->SetModeDescription((unsigned char *)data, client_info->client_protocol_version); - controllers[header.pkt_dev_idx]->SaveMode(); - } - } - break; - - case NET_PACKET_ID_REQUEST_PROFILE_LIST: - SendReply_ProfileList(client_sock); - break; - - case NET_PACKET_ID_REQUEST_SAVE_PROFILE: - if(data == NULL) - { - break; - } - - if(profile_manager) - { - std::string profile_name; - profile_name.assign(data, header.pkt_size); - - profile_manager->SaveProfile(profile_name); - } - - break; - - case NET_PACKET_ID_REQUEST_LOAD_PROFILE: - if(data == NULL) - { - break; - } - - if(profile_manager) - { - std::string profile_name; - profile_name.assign(data, header.pkt_size); - - profile_manager->LoadProfile(profile_name); - } - - break; - - case NET_PACKET_ID_REQUEST_DELETE_PROFILE: - if(data == NULL) - { - break; - } - - if(profile_manager) - { - std::string profile_name; - profile_name.assign(data, header.pkt_size); - - profile_manager->DeleteProfile(profile_name); - } - - break; - - case NET_PACKET_ID_REQUEST_PLUGIN_LIST: - SendReply_PluginList(client_sock); - break; - - case NET_PACKET_ID_PLUGIN_SPECIFIC: - if(plugin_manager) - { - unsigned int plugin_pkt_id = *((unsigned int*)(data)); - unsigned int plugin_pkt_size = header.pkt_size - (sizeof(unsigned int)); - unsigned char* plugin_data = (unsigned char*)(data + sizeof(unsigned int)); - unsigned char* output = plugin_manager->OnSDKCommand(header.pkt_dev_idx, plugin_pkt_id, plugin_data, &plugin_pkt_size); - - if(output != nullptr) - { - SendReply_PluginSpecific(client_sock, plugin_pkt_id, output, plugin_pkt_size); - } - } - break; - case NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS: if(data == NULL) { @@ -954,15 +1051,16 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) case NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT: { - /*---------------------------------------------------------*\ - | Verify the segment description size (first 4 bytes of | - | data) matches the packet size in the header | - \*---------------------------------------------------------*/ + /*-------------------------------------*\ + | Verify the segment description size | + | (first 4 bytes of data) matches the | + | packet size in the header | + \*-------------------------------------*/ if(header.pkt_size == *((unsigned int*)data)) { if(header.pkt_dev_idx < controllers.size()) { - controllers[header.pkt_dev_idx]->SetSegmentDescription((unsigned char *)data); + ProcessRequest_RGBController_AddSegment(header.pkt_dev_idx, (unsigned char *)data, client_info->client_protocol_version); profile_manager->SaveSizes(); } } @@ -970,7 +1068,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; } - delete[] data; + if(delete_data) + { + delete[] data; + } } listen_done: @@ -991,12 +1092,15 @@ listen_done: ServerClientsMutex.unlock(); - /*---------------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*-----------------------------------------------------*/ ClientInfoChanged(); } +/*---------------------------------------------------------*\ +| Server Protocol functions | +\*---------------------------------------------------------*/ void NetworkServer::ProcessRequest_ClientProtocolVersion(SOCKET client_sock, unsigned int data_size, char * data) { unsigned int protocol_version = 0; @@ -1039,6 +1143,7 @@ void NetworkServer::ProcessRequest_ClientString(SOCKET client_sock, unsigned int break; } } + ServerClientsMutex.unlock(); /*---------------------------------------------------------*\ @@ -1052,6 +1157,159 @@ void NetworkServer::ProcessRequest_RescanDevices() ResourceManager::get()->RescanDevices(); } +void NetworkServer::ProcessRequest_RGBController_AddSegment(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Copy in zone index | + \*-----------------------------------------------------*/ + unsigned int zone_idx; + memcpy(&zone_idx, data_ptr, sizeof(zone_idx)); + data_ptr += sizeof(zone_idx); + + /*-----------------------------------------------------*\ + | Add new segment | + \*-----------------------------------------------------*/ + segment new_segment; + + data_ptr = controllers[controller_idx]->SetSegmentDescription(data_ptr, &new_segment, protocol_version); + + controllers[controller_idx]->AddSegment(zone_idx, new_segment); +} + +void NetworkServer::ProcessRequest_RGBController_UpdateLEDs(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Skip over data size | + \*-----------------------------------------------------*/ + data_ptr += sizeof(unsigned int); + + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.lock(); + + /*-----------------------------------------------------*\ + | Update colors | + \*-----------------------------------------------------*/ + controllers[controller_idx]->SetColorDescription(data_ptr, protocol_version); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.unlock(); + + /*-----------------------------------------------------*\ + | Update LEDs | + \*-----------------------------------------------------*/ + controllers[controller_idx]->UpdateLEDs(); +} + +void NetworkServer::ProcessRequest_RGBController_UpdateSaveMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.lock(); + + /*-----------------------------------------------------*\ + | Skip data size | + \*-----------------------------------------------------*/ + data_ptr += sizeof(unsigned int); + + /*-----------------------------------------------------*\ + | Copy in mode index | + \*-----------------------------------------------------*/ + int mode_idx; + memcpy(&mode_idx, data_ptr, sizeof(mode_idx)); + data_ptr += sizeof(mode_idx); + + /*-----------------------------------------------------*\ + | Check if we aren't reading beyond the list of modes. | + \*-----------------------------------------------------*/ + if(((size_t) mode_idx) > controllers[controller_idx]->modes.size()) + { + /*-------------------------------------------------*\ + | Unlock access mutex | + \*-------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.unlock_shared(); + return; + } + + /*-----------------------------------------------------*\ + | Set active mode | + \*-----------------------------------------------------*/ + controllers[controller_idx]->active_mode = mode_idx; + + /*-----------------------------------------------------*\ + | Set mode description | + \*-----------------------------------------------------*/ + data_ptr = controllers[controller_idx]->SetModeDescription(data_ptr, &controllers[controller_idx]->modes[mode_idx], protocol_version); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.unlock(); +} + +void NetworkServer::ProcessRequest_RGBController_UpdateZoneMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.lock(); + + /*-----------------------------------------------------*\ + | Skip data size | + \*-----------------------------------------------------*/ + data_ptr += sizeof(unsigned int); + + /*-----------------------------------------------------*\ + | Copy in mode index | + \*-----------------------------------------------------*/ + int zone_idx; + memcpy(&zone_idx, data_ptr, sizeof(zone_idx)); + data_ptr += sizeof(zone_idx); + + /*-----------------------------------------------------*\ + | Copy in mode index | + \*-----------------------------------------------------*/ + int mode_idx; + memcpy(&mode_idx, data_ptr, sizeof(mode_idx)); + data_ptr += sizeof(mode_idx); + + /*-----------------------------------------------------*\ + | Check if we aren't reading beyond the list of modes. | + \*-----------------------------------------------------*/ + if((((size_t)zone_idx) > controllers[controller_idx]->zones.size()) || (((size_t)mode_idx) > controllers[controller_idx]->zones[zone_idx].modes.size())) + { + /*-------------------------------------------------*\ + | Unlock access mutex | + \*-------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.unlock_shared(); + return; + } + + /*-----------------------------------------------------*\ + | Set active mode | + \*-----------------------------------------------------*/ + controllers[controller_idx]->zones[zone_idx].active_mode = mode_idx; + + /*-----------------------------------------------------*\ + | Set mode description | + \*-----------------------------------------------------*/ + data_ptr = controllers[controller_idx]->SetModeDescription(data_ptr, &controllers[controller_idx]->zones[zone_idx].modes[mode_idx], protocol_version); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + controllers[controller_idx]->AccessMutex.unlock(); + + /*-----------------------------------------------------*\ + | Update zone mode | + \*-----------------------------------------------------*/ + controllers[controller_idx]->UpdateZoneMode(zone_idx); +} + void NetworkServer::SendReply_ControllerCount(SOCKET client_sock) { NetPacketHeader reply_hdr; @@ -1072,18 +1330,57 @@ void NetworkServer::SendReply_ControllerData(SOCKET client_sock, unsigned int de if(dev_idx < controllers.size()) { NetPacketHeader reply_hdr; - unsigned char *reply_data = controllers[dev_idx]->GetDeviceDescription(protocol_version); - unsigned int reply_size; + unsigned char * reply_data; + unsigned int reply_size; - memcpy(&reply_size, reply_data, sizeof(reply_size)); + /*-----------------------------------------------------*\ + | Lock controller's access mutex | + \*-----------------------------------------------------*/ + controllers[dev_idx]->AccessMutex.lock_shared(); + /*-----------------------------------------------------*\ + | Get data size | + \*-----------------------------------------------------*/ + reply_size = controllers[dev_idx]->GetDeviceDescriptionSize(protocol_version); + + /*-----------------------------------------------------*\ + | Create data buffer | + \*-----------------------------------------------------*/ + reply_data = new unsigned char[reply_size]; + unsigned char * data_ptr = reply_data; + + /*-----------------------------------------------------*\ + | Copy in data size | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &reply_size, sizeof(reply_size)); + data_ptr += sizeof(reply_size); + + /*-----------------------------------------------------*\ + | Copy in data | + \*-----------------------------------------------------*/ + data_ptr = controllers[dev_idx]->GetDeviceDescriptionData(data_ptr, protocol_version); + + /*-----------------------------------------------------*\ + | Unlock controller's access mutex | + \*-----------------------------------------------------*/ + controllers[dev_idx]->AccessMutex.unlock_shared(); + + /*-----------------------------------------------------*\ + | Initialize packet header | + \*-----------------------------------------------------*/ InitNetPacketHeader(&reply_hdr, dev_idx, NET_PACKET_ID_REQUEST_CONTROLLER_DATA, reply_size); + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); send(client_sock, (const char *)reply_data, reply_size, 0); send_in_progress.unlock(); + /*-----------------------------------------------------*\ + | Delete data | + \*-----------------------------------------------------*/ delete[] reply_data; } } @@ -1103,6 +1400,33 @@ void NetworkServer::SendReply_ProtocolVersion(SOCKET client_sock) send_in_progress.unlock(); } +void NetworkServer::SendReply_ServerString(SOCKET client_sock) +{ + /*---------------------------------------------------------*\ + | Send server string to client only if protocol is 5 or | + | greater | + \*---------------------------------------------------------*/ + ServerClientsMutex.lock(); + for(unsigned int this_idx = 0; this_idx < ServerClients.size(); this_idx++) + { + if(ServerClients[this_idx]->client_sock == client_sock) + { + if(ServerClients[this_idx]->client_protocol_version >= 5) + { + NetPacketHeader reply_hdr; + + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_SET_SERVER_NAME, (unsigned int)strlen(server_name.c_str()) + 1); + + send_in_progress.lock(); + send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)server_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); + } + } + } + ServerClientsMutex.unlock(); +} + void NetworkServer::SendRequest_DeviceListChanged(SOCKET client_sock) { NetPacketHeader pkt_hdr; @@ -1127,7 +1451,7 @@ void NetworkServer::SendReply_ProfileList(SOCKET client_sock) memcpy(&reply_size, reply_data, sizeof(reply_size)); - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_PROFILE_LIST, reply_size); + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST, reply_size); send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); @@ -1228,7 +1552,7 @@ void NetworkServer::SendReply_PluginList(SOCKET client_sock) memcpy(&reply_size, data_buf, sizeof(reply_size)); - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_PLUGIN_LIST, reply_size); + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PLUGINMANAGER_GET_PLUGIN_LIST, reply_size); send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); @@ -1242,7 +1566,7 @@ void NetworkServer::SendReply_PluginSpecific(SOCKET client_sock, unsigned int pk { NetPacketHeader reply_hdr; - InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PLUGIN_SPECIFIC, data_size + sizeof(pkt_id)); + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PLUGINMANAGER_PLUGIN_SPECIFIC, data_size + sizeof(pkt_id)); send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); @@ -1253,12 +1577,65 @@ void NetworkServer::SendReply_PluginSpecific(SOCKET client_sock, unsigned int pk delete [] data; } -void NetworkServer::SetPluginManager(PluginManagerInterface* plugin_manager_pointer) +/*---------------------------------------------------------*\ +| Private helper functions | +\*---------------------------------------------------------*/ +int NetworkServer::accept_select(int sockfd) { - plugin_manager = plugin_manager_pointer; + fd_set set; + struct timeval timeout; + + while(1) + { + timeout.tv_sec = TCP_TIMEOUT_SECONDS; + timeout.tv_usec = 0; + + FD_ZERO(&set); + FD_SET(sockfd, &set); + + int rv = select(sockfd + 1, &set, NULL, NULL, &timeout); + + if(rv == SOCKET_ERROR || server_online == false) + { + return -1; + } + else if(rv == 0) + { + continue; + } + else + { + return(accept((int)sockfd, NULL, NULL)); + } + } } -void NetworkServer::SetProfileManager(ProfileManagerInterface* profile_manager_pointer) +int NetworkServer::recv_select(SOCKET s, char *buf, int len, int flags) { - profile_manager = profile_manager_pointer; + fd_set set; + struct timeval timeout; + + while(1) + { + timeout.tv_sec = TCP_TIMEOUT_SECONDS; + timeout.tv_usec = 0; + + FD_ZERO(&set); + FD_SET(s, &set); + + int rv = select((int)s + 1, &set, NULL, NULL, &timeout); + + if(rv == SOCKET_ERROR || server_online == false) + { + return 0; + } + else if(rv == 0) + { + continue; + } + else + { + return(recv(s, buf, len, flags)); + } + } } diff --git a/NetworkServer.h b/NetworkServer.h index 96eff12d2..baa03a133 100644 --- a/NetworkServer.h +++ b/NetworkServer.h @@ -11,21 +11,44 @@ #pragma once +#include +#include +#include #include #include -#include +#include #include "RGBController.h" #include "NetworkProtocol.h" #include "net_port.h" #include "PluginManagerInterface.h" #include "ProfileManager.h" #include "ResourceManager.h" +#include "SettingsManager.h" #define MAXSOCK 32 #define TCP_TIMEOUT_SECONDS 5 typedef void (*NetServerCallback)(void *); +typedef struct +{ + char * data; + unsigned int id; + unsigned int size; + unsigned int client_protocol_version; +} NetworkServerControllerThreadQueueEntry; + +typedef struct +{ + unsigned int index; + std::queue queue; + std::mutex queue_mutex; + std::mutex start_mutex; + std::condition_variable start_cv; + std::thread * thread; + std::atomic online; +} NetworkServerControllerThread; + class NetworkClientInfo { public: @@ -45,6 +68,9 @@ public: NetworkServer(std::vector& control); ~NetworkServer(); + /*-----------------------------------------------------*\ + | Server Information functions | + \*-----------------------------------------------------*/ std::string GetHost(); unsigned short GetPort(); bool GetOnline(); @@ -54,73 +80,128 @@ public: const char * GetClientIP(unsigned int client_num); unsigned int GetClientProtocolVersion(unsigned int client_num); - void ClientInfoChanged(); + /*-----------------------------------------------------*\ + | Callback functions | + \*-----------------------------------------------------*/ void DeviceListChanged(); void RegisterClientInfoChangeCallback(NetServerCallback, void * new_callback_arg); - - void ServerListeningChanged(); void RegisterServerListeningChangeCallback(NetServerCallback, void * new_callback_arg); + /*-----------------------------------------------------*\ + | Server Configuration functions | + \*-----------------------------------------------------*/ void SetHost(std::string host); void SetLegacyWorkaroundEnable(bool enable); + void SetName(std::string new_name); void SetPort(unsigned short new_port); + /*-----------------------------------------------------*\ + | Server Control functions | + \*-----------------------------------------------------*/ void StartServer(); void StopServer(); + /*-----------------------------------------------------*\ + | Server Interface functions | + \*-----------------------------------------------------*/ + void SetPluginManager(PluginManagerInterface* plugin_manager_pointer); + void SetProfileManager(ProfileManagerInterface* profile_manager_pointer); + void SetSettingsManager(SettingsManagerInterface* settings_manager_pointer); + +private: + /*-----------------------------------------------------*\ + | Server variables | + \*-----------------------------------------------------*/ + std::string host; + bool legacy_workaround_enabled; + unsigned short port_num; + std::mutex send_in_progress; + std::string server_name; + std::atomic server_online; + std::atomic server_listening; + SOCKET server_sock[MAXSOCK]; + int socket_count; + + /*-----------------------------------------------------*\ + | Server controller list | + \*-----------------------------------------------------*/ + std::vector& controllers; + std::vector controller_threads; + + /*-----------------------------------------------------*\ + | Server clients | + \*-----------------------------------------------------*/ + std::mutex ServerClientsMutex; + std::vector ServerClients; + std::thread * ConnectionThread[MAXSOCK]; + + /*-----------------------------------------------------*\ + | Client information change callbacks | + \*-----------------------------------------------------*/ + std::mutex ClientInfoChangeMutex; + std::vector ClientInfoChangeCallbacks; + std::vector ClientInfoChangeCallbackArgs; + + /*-----------------------------------------------------*\ + | Server listening change callbacks | + \*-----------------------------------------------------*/ + std::mutex ServerListeningChangeMutex; + std::vector ServerListeningChangeCallbacks; + std::vector ServerListeningChangeCallbackArgs; + + /*-----------------------------------------------------*\ + | Pointers to components that integrate with server | + \*-----------------------------------------------------*/ + PluginManagerInterface* plugin_manager; + ProfileManagerInterface* profile_manager; + SettingsManagerInterface* settings_manager; + +private: +#ifdef WIN32 + /*-----------------------------------------------------*\ + | Windows-specific WSA data | + \*-----------------------------------------------------*/ + WSADATA wsa; +#endif + + /*-----------------------------------------------------*\ + | Server callback signal functions | + \*-----------------------------------------------------*/ + void ClientInfoChanged(); + void ServerListeningChanged(); + + /*-----------------------------------------------------*\ + | Server Thread functions | + \*-----------------------------------------------------*/ void ConnectionThreadFunction(int socket_idx); + void ControllerListenThread(NetworkServerControllerThread * this_thread); void ListenThreadFunction(NetworkClientInfo * client_sock); + /*-----------------------------------------------------*\ + | Server Protocol functions | + \*-----------------------------------------------------*/ void ProcessRequest_ClientProtocolVersion(SOCKET client_sock, unsigned int data_size, char * data); void ProcessRequest_ClientString(SOCKET client_sock, unsigned int data_size, char * data); void ProcessRequest_RescanDevices(); + void ProcessRequest_RGBController_AddSegment(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_UpdateLEDs(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_UpdateSaveMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); + void ProcessRequest_RGBController_UpdateZoneMode(std::size_t controller_idx, unsigned char * data_ptr, unsigned int protocol_version); + void SendReply_ControllerCount(SOCKET client_sock); void SendReply_ControllerData(SOCKET client_sock, unsigned int dev_idx, unsigned int protocol_version); void SendReply_ProtocolVersion(SOCKET client_sock); + void SendReply_ServerString(SOCKET client_sock); void SendRequest_DeviceListChanged(SOCKET client_sock); void SendReply_ProfileList(SOCKET client_sock); void SendReply_PluginList(SOCKET client_sock); void SendReply_PluginSpecific(SOCKET client_sock, unsigned int pkt_type, unsigned char* data, unsigned int data_size); - void SetPluginManager(PluginManagerInterface* plugin_manager_pointer); - void SetProfileManager(ProfileManagerInterface* profile_manager_pointer); - -protected: - std::string host; - unsigned short port_num; - std::atomic server_online; - std::atomic server_listening; - - std::vector& controllers; - - std::mutex ServerClientsMutex; - std::vector ServerClients; - std::thread * ConnectionThread[MAXSOCK]; - - std::mutex ClientInfoChangeMutex; - std::vector ClientInfoChangeCallbacks; - std::vector ClientInfoChangeCallbackArgs; - - std::mutex ServerListeningChangeMutex; - std::vector ServerListeningChangeCallbacks; - std::vector ServerListeningChangeCallbackArgs; - - PluginManagerInterface* plugin_manager; - ProfileManagerInterface* profile_manager; - - std::mutex send_in_progress; - -private: -#ifdef WIN32 - WSADATA wsa; -#endif - - bool legacy_workaround_enabled; - int socket_count; - SOCKET server_sock[MAXSOCK]; - - int accept_select(int sockfd); - int recv_select(SOCKET s, char *buf, int len, int flags); + /*-----------------------------------------------------*\ + | Private helper functions | + \*-----------------------------------------------------*/ + int accept_select(int sockfd); + int recv_select(SOCKET s, char *buf, int len, int flags); }; diff --git a/ProfileManager.cpp b/ProfileManager.cpp index 772bbfd22..8eb5f0dd0 100644 --- a/ProfileManager.cpp +++ b/ProfileManager.cpp @@ -97,12 +97,22 @@ ProfileManager::~ProfileManager() void ProfileManager::DeleteProfile(std::string profile_name) { + /*-----------------------------------------------------*\ + | Clean up the profile name | + \*-----------------------------------------------------*/ profile_name = StringUtils::remove_null_terminating_chars(profile_name); - filesystem::path filename = profile_directory / profile_name; - filename.concat(".json"); + if(ResourceManager::get()->IsLocalClient()) + { + ResourceManager::get()->GetLocalClient()->ProfileManager_DeleteProfile(profile_name); + } + else + { + filesystem::path filename = profile_directory / profile_name; + filename.concat(".json"); - filesystem::remove(filename); + filesystem::remove(filename); + } UpdateProfileList(); } @@ -230,22 +240,31 @@ bool ProfileManager::LoadProfile(std::string profile_name) nlohmann::json ProfileManager::ReadProfileJSON(std::string profile_name) { + nlohmann::json profile_json; + /*-----------------------------------------------------*\ | Clean up the profile name | \*-----------------------------------------------------*/ profile_name = StringUtils::remove_null_terminating_chars(profile_name); - /*-----------------------------------------------------*\ - | File extension for v6+ profiles is .json | - \*-----------------------------------------------------*/ - profile_name += ".json"; + if(ResourceManager::get()->IsLocalClient()) + { + profile_json = nlohmann::json::parse(ResourceManager::get()->GetLocalClient()->ProfileManager_DownloadProfile(profile_name)); + } + else + { + /*-------------------------------------------------*\ + | File extension for v6+ profiles is .json | + \*-------------------------------------------------*/ + profile_name += ".json"; - /*-----------------------------------------------------*\ - | Read the profile JSON from the file | - \*-----------------------------------------------------*/ - filesystem::path profile_path = profile_directory / filesystem::u8path(profile_name); + /*-------------------------------------------------*\ + | Read the profile JSON from the file | + \*-------------------------------------------------*/ + filesystem::path profile_path = profile_directory / filesystem::u8path(profile_name); - nlohmann::json profile_json = ReadProfileFileJSON(profile_path); + profile_json = ReadProfileFileJSON(profile_path); + } return(profile_json); } @@ -299,15 +318,25 @@ bool ProfileManager::SaveProfile(std::string profile_name) profile_json["plugins"] = plugin_manager->OnProfileSave(); } - /*-------------------------------------------------*\ - | Save the profile to file from the JSON | - \*-------------------------------------------------*/ - SaveProfileFromJSON(profile_json); + if(ResourceManager::get()->IsLocalClient()) + { + /*---------------------------------------------*\ + | Upload the profile to the server | + \*---------------------------------------------*/ + ResourceManager::get()->GetLocalClient()->ProfileManager_UploadProfile(profile_json.dump()); - /*-------------------------------------------------*\ - | Update the profile list | - \*-------------------------------------------------*/ - UpdateProfileList(); + /*---------------------------------------------*\ + | Update the profile list | + \*---------------------------------------------*/ + UpdateProfileList(); + } + else + { + /*---------------------------------------------*\ + | Save the profile to file from the JSON | + \*---------------------------------------------*/ + SaveProfileFromJSON(profile_json); + } return(true); } @@ -341,6 +370,11 @@ bool ProfileManager::SaveProfileFromJSON(nlohmann::json profile_json) \*-------------------------------------------------*/ profile_file.close(); + /*-------------------------------------------------*\ + | Update the profile list | + \*-------------------------------------------------*/ + UpdateProfileList(); + return(true); } else @@ -447,29 +481,42 @@ void ProfileManager::UpdateProfileList() { profile_list.clear(); - /*-----------------------------------------------------*\ - | Load profiles by looking for .json files in profile | - | directory | - \*-----------------------------------------------------*/ - for(const filesystem::directory_entry &entry : filesystem::directory_iterator(profile_directory)) + if(ResourceManager::get()->IsLocalClient()) { - std::string filename = entry.path().filename().string(); + char * profile_data = ResourceManager::get()->GetLocalClient()->ProfileManager_GetProfileList(); - if(filename.find(".json") != std::string::npos) + if(profile_data != NULL) { - LOG_INFO("[ProfileManager] Found file: %s attempting to validate header", filename.c_str()); + SetProfileListFromDescription(profile_data); + delete[] profile_data; + } + } + else + { + /*-------------------------------------------------*\ + | Load profiles by looking for .json files in | + | profile directory | + \*-------------------------------------------------*/ + for(const filesystem::directory_entry &entry : filesystem::directory_iterator(profile_directory)) + { + std::string filename = entry.path().filename().string(); - /*---------------------------------------------*\ - | Open input file in binary mode | - \*---------------------------------------------*/ - filesystem::path file_path = profile_directory; - file_path.append(filename); - - nlohmann::json profile_json = ReadProfileFileJSON(file_path); - - if(!profile_json.empty()) + if(filename.find(".json") != std::string::npos) { - profile_list.push_back(filename.erase(filename.length() - 5)); + LOG_INFO("[ProfileManager] Found file: %s attempting to validate header", filename.c_str()); + + /*-----------------------------------------*\ + | Open input file in binary mode | + \*-----------------------------------------*/ + filesystem::path file_path = profile_directory; + file_path.append(filename); + + nlohmann::json profile_json = ReadProfileFileJSON(file_path); + + if(!profile_json.empty()) + { + profile_list.push_back(filename.erase(filename.length() - 5)); + } } } } diff --git a/RGBController/RGBController.cpp b/RGBController/RGBController.cpp index dc7f8744a..ba4d04637 100644 --- a/RGBController/RGBController.cpp +++ b/RGBController/RGBController.cpp @@ -1521,207 +1521,77 @@ void RGBController::SetAllZoneColors(int zone, RGBColor color) /*---------------------------------------------------------*\ | Serialized Description Functions | \*---------------------------------------------------------*/ -unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_version) +unsigned char * RGBController::GetColorDescriptionData(unsigned char* data_ptr, unsigned int /*protocol_version*/) { /*-----------------------------------------------------*\ - | Lock access mutex | + | Initialize variables | \*-----------------------------------------------------*/ - AccessMutex.lock_shared(); + unsigned short num_colors = (unsigned short)colors.size(); - unsigned int data_ptr = 0; - unsigned int data_size = 0; + /*-----------------------------------------------------*\ + | Copy in number of colors | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &num_colors, sizeof(num_colors)); + data_ptr += sizeof(num_colors); + + /*-----------------------------------------------------*\ + | Copy in colors | + \*-----------------------------------------------------*/ + for(int color_index = 0; color_index < num_colors; color_index++) + { + memcpy(data_ptr, &colors[color_index], sizeof(colors[color_index])); + data_ptr += sizeof(colors[color_index]); + } + + return(data_ptr); +} + +unsigned int RGBController::GetColorDescriptionSize(unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + unsigned short num_colors = (unsigned short)colors.size(); /*-----------------------------------------------------*\ | Calculate data size | \*-----------------------------------------------------*/ - unsigned short name_len = (unsigned short)strlen(name.c_str()) + 1; - unsigned short vendor_len = (unsigned short)strlen(vendor.c_str()) + 1; - unsigned short description_len = (unsigned short)strlen(description.c_str()) + 1; - unsigned short version_len = (unsigned short)strlen(version.c_str()) + 1; - unsigned short serial_len = (unsigned short)strlen(serial.c_str()) + 1; - unsigned short location_len = (unsigned short)strlen(location.c_str()) + 1; - unsigned short num_modes = (unsigned short)modes.size(); - unsigned short num_zones = (unsigned short)zones.size(); - unsigned short num_leds = (unsigned short)leds.size(); - unsigned short num_colors = (unsigned short)colors.size(); - unsigned short num_led_alt_names= (unsigned short)led_alt_names.size(); + data_size += sizeof(num_colors); + data_size += num_colors * sizeof(RGBColor); - unsigned short *mode_name_len = new unsigned short[num_modes]; - unsigned short *zone_name_len = new unsigned short[num_zones]; - unsigned short *led_name_len = new unsigned short[num_leds]; - - unsigned short *zone_matrix_len = new unsigned short[num_zones]; - unsigned short *mode_num_colors = new unsigned short[num_modes]; - - data_size += sizeof(data_size); - data_size += sizeof(device_type); - data_size += name_len + sizeof(name_len); - - if(protocol_version >= 1) - { - data_size += vendor_len + sizeof(vendor_len); - } - - data_size += description_len + sizeof(description_len); - data_size += version_len + sizeof(version_len); - data_size += serial_len + sizeof(serial_len); - data_size += location_len + sizeof(location_len); - - data_size += sizeof(num_modes); - data_size += sizeof(active_mode); - - for(int mode_index = 0; mode_index < num_modes; mode_index++) - { - mode_name_len[mode_index] = (unsigned short)strlen(modes[mode_index].name.c_str()) + 1; - mode_num_colors[mode_index] = (unsigned short)modes[mode_index].colors.size(); - - data_size += mode_name_len[mode_index] + sizeof(mode_name_len[mode_index]); - data_size += sizeof(modes[mode_index].value); - data_size += sizeof(modes[mode_index].flags); - data_size += sizeof(modes[mode_index].speed_min); - data_size += sizeof(modes[mode_index].speed_max); - if(protocol_version >= 3) - { - data_size += sizeof(modes[mode_index].brightness_min); - data_size += sizeof(modes[mode_index].brightness_max); - } - data_size += sizeof(modes[mode_index].colors_min); - data_size += sizeof(modes[mode_index].colors_max); - data_size += sizeof(modes[mode_index].speed); - if(protocol_version >= 3) - { - data_size += sizeof(modes[mode_index].brightness); - } - data_size += sizeof(modes[mode_index].direction); - data_size += sizeof(modes[mode_index].color_mode); - data_size += sizeof(mode_num_colors[mode_index]); - data_size += (mode_num_colors[mode_index] * sizeof(RGBColor)); - } - - data_size += sizeof(num_zones); - - for(int zone_index = 0; zone_index < num_zones; zone_index++) - { - zone_name_len[zone_index] = (unsigned short)strlen(zones[zone_index].name.c_str()) + 1; - - data_size += zone_name_len[zone_index] + sizeof(zone_name_len[zone_index]); - data_size += sizeof(zones[zone_index].type); - data_size += sizeof(zones[zone_index].leds_min); - data_size += sizeof(zones[zone_index].leds_max); - data_size += sizeof(zones[zone_index].leds_count); - - if(zones[zone_index].matrix_map == NULL) - { - zone_matrix_len[zone_index] = 0; - } - else - { - zone_matrix_len[zone_index] = (unsigned short)((2 * sizeof(unsigned int)) + (zones[zone_index].matrix_map->height * zones[zone_index].matrix_map->width * sizeof(unsigned int))); - } - - data_size += sizeof(zone_matrix_len[zone_index]); - data_size += zone_matrix_len[zone_index]; - - if(protocol_version >= 4) - { - /*---------------------------------------------*\ - | Number of segments in zone | - \*---------------------------------------------*/ - data_size += sizeof(unsigned short); - - for(size_t segment_index = 0; segment_index < zones[zone_index].segments.size(); segment_index++) - { - /*-----------------------------------------*\ - | Length of segment name string | - \*-----------------------------------------*/ - data_size += sizeof(unsigned short); - - /*-----------------------------------------*\ - | Segment name string data | - \*-----------------------------------------*/ - data_size += (unsigned int)strlen(zones[zone_index].segments[segment_index].name.c_str()) + 1; - - data_size += sizeof(zones[zone_index].segments[segment_index].type); - data_size += sizeof(zones[zone_index].segments[segment_index].start_idx); - data_size += sizeof(zones[zone_index].segments[segment_index].leds_count); - } - } - - /*-------------------------------------------------*\ - | Zone flags | - \*-------------------------------------------------*/ - if(protocol_version >= 5) - { - data_size += sizeof(unsigned int); - } - } - - data_size += sizeof(num_leds); - - for(int led_index = 0; led_index < num_leds; led_index++) - { - led_name_len[led_index] = (unsigned short)strlen(leds[led_index].name.c_str()) + 1; - - data_size += led_name_len[led_index] + sizeof(led_name_len[led_index]); - - data_size += sizeof(leds[led_index].value); - } + return(data_size); +} +unsigned char * RGBController::GetDeviceDescriptionData(unsigned char* data_ptr, unsigned int protocol_version) +{ /*-----------------------------------------------------*\ - | LED alternate names | + | Calculate data size | \*-----------------------------------------------------*/ - if(protocol_version >= 5) - { - /*-------------------------------------------------*\ - | Number of LED alternate names | - \*-------------------------------------------------*/ - data_size += sizeof(num_led_alt_names); - - /*-------------------------------------------------*\ - | LED alternate name strings | - \*-------------------------------------------------*/ - for(std::size_t led_idx = 0; led_idx < led_alt_names.size(); led_idx++) - { - data_size += sizeof(unsigned short); - data_size += (unsigned int)strlen(led_alt_names[led_idx].c_str()) + 1; - } - } - - /*-----------------------------------------------------*\ - | Controller flags | - \*-----------------------------------------------------*/ - if(protocol_version >= 5) - { - data_size += sizeof(flags); - } - - data_size += sizeof(num_colors); - data_size += num_colors * sizeof(RGBColor); - - /*-----------------------------------------------------*\ - | Create data buffer | - \*-----------------------------------------------------*/ - unsigned char *data_buf = new unsigned char[data_size]; - - /*-----------------------------------------------------*\ - | Copy in data size | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &data_size, sizeof(data_size)); - data_ptr += sizeof(data_size); + unsigned short name_len = (unsigned short)strlen(name.c_str()) + 1; + unsigned short vendor_len = (unsigned short)strlen(vendor.c_str()) + 1; + unsigned short description_len = (unsigned short)strlen(description.c_str()) + 1; + unsigned short version_len = (unsigned short)strlen(version.c_str()) + 1; + unsigned short serial_len = (unsigned short)strlen(serial.c_str()) + 1; + unsigned short location_len = (unsigned short)strlen(location.c_str()) + 1; + unsigned short num_modes = (unsigned short)modes.size(); + unsigned short num_zones = (unsigned short)zones.size(); + unsigned short num_leds = (unsigned short)leds.size(); + unsigned short num_led_alt_names = (unsigned short)led_alt_names.size(); /*-----------------------------------------------------*\ | Copy in type | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &type, sizeof(device_type)); + memcpy(data_ptr, &type, sizeof(device_type)); data_ptr += sizeof(device_type); /*-----------------------------------------------------*\ | Copy in name (size+data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &name_len, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &name_len, sizeof(name_len)); + data_ptr += sizeof(name_len); - strcpy((char *)&data_buf[data_ptr], name.c_str()); + strcpy((char *)data_ptr, name.c_str()); data_ptr += name_len; /*-----------------------------------------------------*\ @@ -1729,59 +1599,59 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio \*-----------------------------------------------------*/ if(protocol_version >= 1) { - memcpy(&data_buf[data_ptr], &vendor_len, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &vendor_len, sizeof(vendor_len)); + data_ptr += sizeof(vendor_len); - strcpy((char *)&data_buf[data_ptr], vendor.c_str()); + strcpy((char *)data_ptr, vendor.c_str()); data_ptr += vendor_len; } /*-----------------------------------------------------*\ | Copy in description (size+data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &description_len, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &description_len, sizeof(description_len)); + data_ptr += sizeof(description_len); - strcpy((char *)&data_buf[data_ptr], description.c_str()); + strcpy((char *)data_ptr, description.c_str()); data_ptr += description_len; /*-----------------------------------------------------*\ | Copy in version (size+data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &version_len, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &version_len, sizeof(version_len)); + data_ptr += sizeof(version_len); - strcpy((char *)&data_buf[data_ptr], version.c_str()); + strcpy((char *)data_ptr, version.c_str()); data_ptr += version_len; /*-----------------------------------------------------*\ | Copy in serial (size+data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &serial_len, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &serial_len, sizeof(serial_len)); + data_ptr += sizeof(serial_len); - strcpy((char *)&data_buf[data_ptr], serial.c_str()); + strcpy((char *)data_ptr, serial.c_str()); data_ptr += serial_len; /*-----------------------------------------------------*\ | Copy in location (size+data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &location_len, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &location_len, sizeof(location_len)); + data_ptr += sizeof(location_len); - strcpy((char *)&data_buf[data_ptr], location.c_str()); + strcpy((char *)data_ptr, location.c_str()); data_ptr += location_len; /*-----------------------------------------------------*\ - | Copy in number of modes (data) | + | Copy in number of modes | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &num_modes, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &num_modes, sizeof(num_modes)); + data_ptr += sizeof(num_modes); /*-----------------------------------------------------*\ - | Copy in active mode (data) | + | Copy in active mode | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &active_mode, sizeof(active_mode)); + memcpy(data_ptr, &active_mode, sizeof(active_mode)); data_ptr += sizeof(active_mode); /*-----------------------------------------------------*\ @@ -1789,341 +1659,51 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio \*-----------------------------------------------------*/ for(int mode_index = 0; mode_index < num_modes; mode_index++) { - /*-------------------------------------------------*\ - | Copy in mode name (size+data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &mode_name_len[mode_index], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - strcpy((char *)&data_buf[data_ptr], modes[mode_index].name.c_str()); - data_ptr += mode_name_len[mode_index]; - - /*-------------------------------------------------*\ - | Copy in mode value (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].value, sizeof(modes[mode_index].value)); - data_ptr += sizeof(modes[mode_index].value); - - /*-------------------------------------------------*\ - | Copy in mode flags (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].flags, sizeof(modes[mode_index].flags)); - data_ptr += sizeof(modes[mode_index].flags); - - /*-------------------------------------------------*\ - | Copy in mode speed_min (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].speed_min, sizeof(modes[mode_index].speed_min)); - data_ptr += sizeof(modes[mode_index].speed_min); - - /*-------------------------------------------------*\ - | Copy in mode speed_max (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].speed_max, sizeof(modes[mode_index].speed_max)); - data_ptr += sizeof(modes[mode_index].speed_max); - - /*-------------------------------------------------*\ - | Copy in mode brightness_min and brightness_max | - | (data) if protocol 3 or higher | - \*-------------------------------------------------*/ - if(protocol_version >= 3) - { - memcpy(&data_buf[data_ptr], &modes[mode_index].brightness_min, sizeof(modes[mode_index].brightness_min)); - data_ptr += sizeof(modes[mode_index].brightness_min); - - memcpy(&data_buf[data_ptr], &modes[mode_index].brightness_max, sizeof(modes[mode_index].brightness_max)); - data_ptr += sizeof(modes[mode_index].brightness_max); - } - - /*-------------------------------------------------*\ - | Copy in mode colors_min (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].colors_min, sizeof(modes[mode_index].colors_min)); - data_ptr += sizeof(modes[mode_index].colors_min); - - /*-------------------------------------------------*\ - | Copy in mode colors_max (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].colors_max, sizeof(modes[mode_index].colors_max)); - data_ptr += sizeof(modes[mode_index].colors_max); - - /*-------------------------------------------------*\ - | Copy in mode speed (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].speed, sizeof(modes[mode_index].speed)); - data_ptr += sizeof(modes[mode_index].speed); - - /*-------------------------------------------------*\ - | Copy in mode brightness (data) if protocol 3 or | - | higher | - \*-------------------------------------------------*/ - if(protocol_version >= 3) - { - memcpy(&data_buf[data_ptr], &modes[mode_index].brightness, sizeof(modes[mode_index].brightness)); - data_ptr += sizeof(modes[mode_index].brightness); - } - - /*-------------------------------------------------*\ - | Copy in mode direction (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].direction, sizeof(modes[mode_index].direction)); - data_ptr += sizeof(modes[mode_index].direction); - - /*-------------------------------------------------*\ - | Copy in mode color_mode (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].color_mode, sizeof(modes[mode_index].color_mode)); - data_ptr += sizeof(modes[mode_index].color_mode); - - /*-------------------------------------------------*\ - | Copy in mode number of colors | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &mode_num_colors[mode_index], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-------------------------------------------------*\ - | Copy in mode mode colors | - \*-------------------------------------------------*/ - for(int color_index = 0; color_index < mode_num_colors[mode_index]; color_index++) - { - /*---------------------------------------------*\ - | Copy in color (data) | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode_index].colors[color_index], sizeof(modes[mode_index].colors[color_index])); - data_ptr += sizeof(modes[mode_index].colors[color_index]); - } + data_ptr = GetModeDescriptionData(data_ptr, modes[mode_index], protocol_version); } /*-----------------------------------------------------*\ - | Copy in number of zones (data) | + | Copy in number of zones | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &num_zones, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &num_zones, sizeof(num_zones)); + data_ptr += sizeof(num_zones); /*-----------------------------------------------------*\ | Copy in zones | \*-----------------------------------------------------*/ for(int zone_index = 0; zone_index < num_zones; zone_index++) { - /*-------------------------------------------------*\ - | Copy in zone name (size+data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zone_name_len[zone_index], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - strcpy((char *)&data_buf[data_ptr], zones[zone_index].name.c_str()); - data_ptr += zone_name_len[zone_index]; - - /*-------------------------------------------------*\ - | Copy in zone type (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].type, sizeof(zones[zone_index].type)); - data_ptr += sizeof(zones[zone_index].type); - - /*-------------------------------------------------*\ - | Check for resizable effects-only zone. For | - | protocol versions that do not support this | - | feature, we have to overwrite the | - | leds_min/max/count parameters to 1 so that the | - | zone appears a fixed size to older clients. | - \*-------------------------------------------------*/ - if((zones[zone_index].flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY) && (protocol_version < 5)) - { - /*---------------------------------------------*\ - | Create a temporary variable to hold the fixed | - | value of 1 | - \*---------------------------------------------*/ - unsigned int tmp_size = 1; - - /*---------------------------------------------*\ - | Copy in temporary minimum LED count (data) | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &tmp_size, sizeof(tmp_size)); - data_ptr += sizeof(tmp_size); - - /*---------------------------------------------*\ - | Copy in temporary maximum LED count (data) | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &tmp_size, sizeof(tmp_size)); - data_ptr += sizeof(tmp_size); - - /*---------------------------------------------*\ - | Copy in temporary LED count (data) | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &tmp_size, sizeof(tmp_size)); - data_ptr += sizeof(tmp_size); - } - else - { - /*---------------------------------------------*\ - | Copy in zone minimum LED count (data) | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].leds_min, sizeof(zones[zone_index].leds_min)); - data_ptr += sizeof(zones[zone_index].leds_min); - - /*---------------------------------------------*\ - | Copy in zone maximum LED count (data) | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].leds_max, sizeof(zones[zone_index].leds_max)); - data_ptr += sizeof(zones[zone_index].leds_max); - - /*---------------------------------------------*\ - | Copy in zone LED count (data) | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].leds_count, sizeof(zones[zone_index].leds_count)); - data_ptr += sizeof(zones[zone_index].leds_count); - } - - /*-------------------------------------------------*\ - | Copy in size of zone matrix | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zone_matrix_len[zone_index], sizeof(zone_matrix_len[zone_index])); - data_ptr += sizeof(zone_matrix_len[zone_index]); - - /*-------------------------------------------------*\ - | Copy in matrix data if size is nonzero | - \*-------------------------------------------------*/ - if(zone_matrix_len[zone_index] > 0) - { - /*---------------------------------------------*\ - | Copy in matrix height | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].matrix_map->height, sizeof(zones[zone_index].matrix_map->height)); - data_ptr += sizeof(zones[zone_index].matrix_map->height); - - /*---------------------------------------------*\ - | Copy in matrix width | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].matrix_map->width, sizeof(zones[zone_index].matrix_map->width)); - data_ptr += sizeof(zones[zone_index].matrix_map->width); - - /*---------------------------------------------*\ - | Copy in matrix map | - \*---------------------------------------------*/ - for(unsigned int matrix_idx = 0; matrix_idx < (zones[zone_index].matrix_map->height * zones[zone_index].matrix_map->width); matrix_idx++) - { - memcpy(&data_buf[data_ptr], &zones[zone_index].matrix_map->map[matrix_idx], sizeof(zones[zone_index].matrix_map->map[matrix_idx])); - data_ptr += sizeof(zones[zone_index].matrix_map->map[matrix_idx]); - } - } - - /*-------------------------------------------------*\ - | Copy in segments | - \*-------------------------------------------------*/ - if(protocol_version >= 4) - { - unsigned short num_segments = (unsigned short)zones[zone_index].segments.size(); - - /*---------------------------------------------*\ - | Number of segments in zone | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &num_segments, sizeof(num_segments)); - data_ptr += sizeof(num_segments); - - for(int segment_index = 0; segment_index < num_segments; segment_index++) - { - /*-----------------------------------------*\ - | Length of segment name string | - \*-----------------------------------------*/ - unsigned short segment_name_length = (unsigned short)strlen(zones[zone_index].segments[segment_index].name.c_str()) + 1; - - memcpy(&data_buf[data_ptr], &segment_name_length, sizeof(segment_name_length)); - data_ptr += sizeof(segment_name_length); - - /*-----------------------------------------*\ - | Segment name string data | - \*-----------------------------------------*/ - strcpy((char *)&data_buf[data_ptr], zones[zone_index].segments[segment_index].name.c_str()); - data_ptr += segment_name_length; - - /*-----------------------------------------*\ - | Segment type data | - \*-----------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].segments[segment_index].type, sizeof(zones[zone_index].segments[segment_index].type)); - data_ptr += sizeof(zones[zone_index].segments[segment_index].type); - - /*-----------------------------------------*\ - | Segment start index data | - \*-----------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].segments[segment_index].start_idx, sizeof(zones[zone_index].segments[segment_index].start_idx)); - data_ptr += sizeof(zones[zone_index].segments[segment_index].start_idx); - - /*-----------------------------------------*\ - | Segment LED count data | - \*-----------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].segments[segment_index].leds_count, sizeof(zones[zone_index].segments[segment_index].leds_count)); - data_ptr += sizeof(zones[zone_index].segments[segment_index].leds_count); - } - } - - /*-------------------------------------------------*\ - | Copy in zone flags | - \*-------------------------------------------------*/ - if(protocol_version >= 5) - { - /*---------------------------------------------*\ - | Zone flags | - \*---------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].flags, sizeof(zones[zone_index].flags)); - data_ptr += sizeof(zones[zone_index].flags); - } + data_ptr = GetZoneDescriptionData(data_ptr, zones[zone_index], protocol_version); } /*-----------------------------------------------------*\ - | Copy in number of LEDs (data) | + | Copy in number of LEDs | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &num_leds, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); + memcpy(data_ptr, &num_leds, sizeof(num_leds)); + data_ptr += sizeof(num_leds); /*-----------------------------------------------------*\ | Copy in LEDs | \*-----------------------------------------------------*/ for(int led_index = 0; led_index < num_leds; led_index++) { - /*-------------------------------------------------*\ - | Copy in LED name (size+data) | - \*-------------------------------------------------*/ - unsigned short ledname_len = (unsigned short)strlen(leds[led_index].name.c_str()) + 1; - memcpy(&data_buf[data_ptr], &ledname_len, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - strcpy((char *)&data_buf[data_ptr], leds[led_index].name.c_str()); - data_ptr += ledname_len; - - /*-------------------------------------------------*\ - | Copy in LED value (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &leds[led_index].value, sizeof(leds[led_index].value)); - data_ptr += sizeof(leds[led_index].value); + data_ptr = GetLEDDescriptionData(data_ptr, leds[led_index], protocol_version); } - /*-----------------------------------------------------*\ - | Copy in number of colors (data) | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &num_colors, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - /*-----------------------------------------------------*\ | Copy in colors | \*-----------------------------------------------------*/ - for(int color_index = 0; color_index < num_colors; color_index++) - { - /*-------------------------------------------------*\ - | Copy in color (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &colors[color_index], sizeof(colors[color_index])); - data_ptr += sizeof(colors[color_index]); - } + data_ptr = GetColorDescriptionData(data_ptr, protocol_version); /*-----------------------------------------------------*\ - | LED alternate names data | + | Copy in LED alternate names | \*-----------------------------------------------------*/ if(protocol_version >= 5) { /*-------------------------------------------------*\ | Number of LED alternate name strings | \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &num_led_alt_names, sizeof(num_led_alt_names)); + memcpy(data_ptr, &num_led_alt_names, sizeof(num_led_alt_names)); data_ptr += sizeof(num_led_alt_names); for(std::size_t led_idx = 0; led_idx < led_alt_names.size(); led_idx++) @@ -2131,606 +1711,290 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio /*---------------------------------------------*\ | Copy in LED alternate name (size+data) | \*---------------------------------------------*/ - unsigned short string_length = (unsigned short)strlen(led_alt_names[led_idx].c_str()) + 1; + unsigned short string_length = (unsigned short)strlen(led_alt_names[led_idx].c_str()) + 1; - memcpy(&data_buf[data_ptr], &string_length, sizeof(string_length)); + memcpy(data_ptr, &string_length, sizeof(string_length)); data_ptr += sizeof(string_length); - strcpy((char *)&data_buf[data_ptr], led_alt_names[led_idx].c_str()); + strcpy((char *)data_ptr, led_alt_names[led_idx].c_str()); data_ptr += string_length; } } /*-----------------------------------------------------*\ - | Controller flags data | + | Copy in controller flags | \*-----------------------------------------------------*/ if(protocol_version >= 5) { - memcpy(&data_buf[data_ptr], &flags, sizeof(flags)); + memcpy(data_ptr, &flags, sizeof(flags)); data_ptr += sizeof(flags); } - delete[] mode_name_len; - delete[] zone_name_len; - delete[] led_name_len; - - delete[] zone_matrix_len; - delete[] mode_num_colors; - - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock_shared(); - - return(data_buf); + return(data_ptr); } -void RGBController::ReadDeviceDescription(unsigned char* data_buf, unsigned int protocol_version) +unsigned int RGBController::GetDeviceDescriptionSize(unsigned int protocol_version) { /*-----------------------------------------------------*\ - | Lock access mutex | + | Initialize variables | \*-----------------------------------------------------*/ - AccessMutex.lock(); - - unsigned int data_ptr = 0; - - data_ptr += sizeof(unsigned int); - - /*-----------------------------------------------------*\ - | Copy in type | - \*-----------------------------------------------------*/ - memcpy(&type, &data_buf[data_ptr], sizeof(device_type)); - data_ptr += sizeof(device_type); - - /*-----------------------------------------------------*\ - | Copy in name | - \*-----------------------------------------------------*/ - unsigned short name_len; - memcpy(&name_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - name = (char *)&data_buf[data_ptr]; - data_ptr += name_len; - - /*-----------------------------------------------------*\ - | Copy in vendor if protocol version is 1 or higher | - \*-----------------------------------------------------*/ - if(protocol_version >= 1) - { - unsigned short vendor_len; - memcpy(&vendor_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - vendor = (char *)&data_buf[data_ptr]; - data_ptr += vendor_len; - } - - /*-----------------------------------------------------*\ - | Copy in description | - \*-----------------------------------------------------*/ - unsigned short description_len; - memcpy(&description_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - description = (char *)&data_buf[data_ptr]; - data_ptr += description_len; - - /*-----------------------------------------------------*\ - | Copy in version | - \*-----------------------------------------------------*/ - unsigned short version_len; - memcpy(&version_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - version = (char *)&data_buf[data_ptr]; - data_ptr += version_len; - - /*-----------------------------------------------------*\ - | Copy in serial | - \*-----------------------------------------------------*/ - unsigned short serial_len; - memcpy(&serial_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - serial = (char *)&data_buf[data_ptr]; - data_ptr += serial_len; - - /*-----------------------------------------------------*\ - | Copy in location | - \*-----------------------------------------------------*/ - unsigned short location_len; - memcpy(&location_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - location = (char *)&data_buf[data_ptr]; - data_ptr += location_len; - - /*-----------------------------------------------------*\ - | Copy in number of modes (data) | - \*-----------------------------------------------------*/ - unsigned short num_modes; - memcpy(&num_modes, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Copy in active mode (data) | - \*-----------------------------------------------------*/ - memcpy(&active_mode, &data_buf[data_ptr], sizeof(active_mode)); - data_ptr += sizeof(active_mode); - - /*-----------------------------------------------------*\ - | Copy in modes | - \*-----------------------------------------------------*/ - for(int mode_index = 0; mode_index < num_modes; mode_index++) - { - mode new_mode; - - /*-------------------------------------------------*\ - | Copy in mode name (size+data) | - \*-------------------------------------------------*/ - unsigned short modename_len; - memcpy(&modename_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - new_mode.name = (char *)&data_buf[data_ptr]; - data_ptr += modename_len; - - /*-------------------------------------------------*\ - | Copy in mode value (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.value, &data_buf[data_ptr], sizeof(new_mode.value)); - data_ptr += sizeof(new_mode.value); - - /*-------------------------------------------------*\ - | Copy in mode flags (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.flags, &data_buf[data_ptr], sizeof(new_mode.flags)); - data_ptr += sizeof(new_mode.flags); - - /*-------------------------------------------------*\ - | Copy in mode speed_min (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.speed_min, &data_buf[data_ptr], sizeof(new_mode.speed_min)); - data_ptr += sizeof(new_mode.speed_min); - - /*-------------------------------------------------*\ - | Copy in mode speed_max (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.speed_max, &data_buf[data_ptr], sizeof(new_mode.speed_max)); - data_ptr += sizeof(new_mode.speed_max); - - /*-------------------------------------------------*\ - | Copy in mode brightness min and max if protocol | - | version is 3 or higher | - \*-------------------------------------------------*/ - if(protocol_version >= 3) - { - memcpy(&new_mode.brightness_min, &data_buf[data_ptr], sizeof(new_mode.brightness_min)); - data_ptr += sizeof(new_mode.brightness_min); - - memcpy(&new_mode.brightness_max, &data_buf[data_ptr], sizeof(new_mode.brightness_max)); - data_ptr += sizeof(new_mode.brightness_max); - } - - /*-------------------------------------------------*\ - | Copy in mode colors_min (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.colors_min, &data_buf[data_ptr], sizeof(new_mode.colors_min)); - data_ptr += sizeof(new_mode.colors_min); - - /*-------------------------------------------------*\ - | Copy in mode colors_max (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.colors_max, &data_buf[data_ptr], sizeof(new_mode.colors_max)); - data_ptr += sizeof(new_mode.colors_max); - - /*-------------------------------------------------*\ - | Copy in mode speed (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.speed, &data_buf[data_ptr], sizeof(new_mode.speed)); - data_ptr += sizeof(new_mode.speed); - - /*-------------------------------------------------*\ - | Copy in mode brightness if protocol version is 3 | - | or higher | - \*-------------------------------------------------*/ - if(protocol_version >= 3) - { - memcpy(&new_mode.brightness, &data_buf[data_ptr], sizeof(new_mode.brightness)); - data_ptr += sizeof(new_mode.brightness); - } - - /*-------------------------------------------------*\ - | Copy in mode direction (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.direction, &data_buf[data_ptr], sizeof(new_mode.direction)); - data_ptr += sizeof(new_mode.direction); - - /*-------------------------------------------------*\ - | Copy in mode color_mode (data) | - \*-------------------------------------------------*/ - memcpy(&new_mode.color_mode, &data_buf[data_ptr], sizeof(new_mode.color_mode)); - data_ptr += sizeof(new_mode.color_mode); - - /*-------------------------------------------------*\ - | Copy in mode number of colors | - \*-------------------------------------------------*/ - unsigned short mode_num_colors; - memcpy(&mode_num_colors, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-------------------------------------------------*\ - | Copy in mode mode colors | - \*-------------------------------------------------*/ - for(int color_index = 0; color_index < mode_num_colors; color_index++) - { - /*---------------------------------------------*\ - | Copy in color (data) | - \*---------------------------------------------*/ - RGBColor new_color; - memcpy(&new_color, &data_buf[data_ptr], sizeof(RGBColor)); - data_ptr += sizeof(modes[mode_index].colors[color_index]); - - new_mode.colors.push_back(new_color); - } - - modes.push_back(new_mode); - } - - /*-----------------------------------------------------*\ - | Copy in number of zones (data) | - \*-----------------------------------------------------*/ - unsigned short num_zones; - memcpy(&num_zones, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Copy in zones | - \*-----------------------------------------------------*/ - for(int zone_index = 0; zone_index < num_zones; zone_index++) - { - zone new_zone; - - /*-------------------------------------------------*\ - | Copy in zone name (size+data) | - \*-------------------------------------------------*/ - unsigned short zonename_len; - memcpy(&zonename_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - new_zone.name = (char *)&data_buf[data_ptr]; - data_ptr += zonename_len; - - /*-------------------------------------------------*\ - | Copy in zone type (data) | - \*-------------------------------------------------*/ - memcpy(&new_zone.type, &data_buf[data_ptr], sizeof(new_zone.type)); - data_ptr += sizeof(new_zone.type); - - /*-------------------------------------------------*\ - | Copy in zone minimum LED count (data) | - \*-------------------------------------------------*/ - memcpy(&new_zone.leds_min, &data_buf[data_ptr], sizeof(new_zone.leds_min)); - data_ptr += sizeof(new_zone.leds_min); - - /*-------------------------------------------------*\ - | Copy in zone maximum LED count (data) | - \*-------------------------------------------------*/ - memcpy(&new_zone.leds_max, &data_buf[data_ptr], sizeof(new_zone.leds_max)); - data_ptr += sizeof(new_zone.leds_max); - - /*-------------------------------------------------*\ - | Copy in zone LED count (data) | - \*-------------------------------------------------*/ - memcpy(&new_zone.leds_count, &data_buf[data_ptr], sizeof(new_zone.leds_count)); - data_ptr += sizeof(new_zone.leds_count); - - /*-------------------------------------------------*\ - | Copy in size of zone matrix | - \*-------------------------------------------------*/ - unsigned short zone_matrix_len; - memcpy(&zone_matrix_len, &data_buf[data_ptr], sizeof(zone_matrix_len)); - data_ptr += sizeof(zone_matrix_len); - - /*-------------------------------------------------*\ - | Copy in matrix data if size is nonzero | - \*-------------------------------------------------*/ - if(zone_matrix_len > 0) - { - /*---------------------------------------------*\ - | Create a map data structure to fill in and | - | attach it to the new zone | - \*---------------------------------------------*/ - matrix_map_type * new_map = new matrix_map_type; - - new_zone.matrix_map = new_map; - - /*---------------------------------------------*\ - | Copy in matrix height | - \*---------------------------------------------*/ - memcpy(&new_map->height, &data_buf[data_ptr], sizeof(new_map->height)); - data_ptr += sizeof(new_map->height); - - /*---------------------------------------------*\ - | Copy in matrix width | - \*---------------------------------------------*/ - memcpy(&new_map->width, &data_buf[data_ptr], sizeof(new_map->width)); - data_ptr += sizeof(new_map->width); - - /*---------------------------------------------*\ - | Copy in matrix map | - \*---------------------------------------------*/ - new_map->map = new unsigned int[new_map->height * new_map->width]; - - for(unsigned int matrix_idx = 0; matrix_idx < (new_map->height * new_map->width); matrix_idx++) - { - memcpy(&new_map->map[matrix_idx], &data_buf[data_ptr], sizeof(new_map->map[matrix_idx])); - data_ptr += sizeof(new_map->map[matrix_idx]); - } - } - else - { - new_zone.matrix_map = NULL; - } - - /*-------------------------------------------------*\ - | Copy in segments | - \*-------------------------------------------------*/ - if(protocol_version >= 4) - { - unsigned short num_segments = 0; - - /*---------------------------------------------*\ - | Number of segments in zone | - \*---------------------------------------------*/ - memcpy(&num_segments, &data_buf[data_ptr], sizeof(num_segments)); - data_ptr += sizeof(num_segments); - - for(int segment_index = 0; segment_index < num_segments; segment_index++) - { - segment new_segment; - - /*-----------------------------------------*\ - | Copy in segment name (size+data) | - \*-----------------------------------------*/ - unsigned short segmentname_len; - memcpy(&segmentname_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - new_segment.name = (char *)&data_buf[data_ptr]; - data_ptr += segmentname_len; - - /*-----------------------------------------*\ - | Segment type data | - \*-----------------------------------------*/ - memcpy(&new_segment.type, &data_buf[data_ptr], sizeof(new_segment.type)); - data_ptr += sizeof(new_segment.type); - - /*-----------------------------------------*\ - | Segment start index data | - \*-----------------------------------------*/ - memcpy(&new_segment.start_idx, &data_buf[data_ptr], sizeof(new_segment.start_idx)); - data_ptr += sizeof(new_segment.start_idx); - - /*-----------------------------------------*\ - | Segment LED count data | - \*-----------------------------------------*/ - memcpy(&new_segment.leds_count, &data_buf[data_ptr], sizeof(new_segment.leds_count)); - data_ptr += sizeof(new_segment.leds_count); - - new_zone.segments.push_back(new_segment); - } - } - - /*-------------------------------------------------*\ - | Copy in zone flags | - \*-------------------------------------------------*/ - if(protocol_version >= 5) - { - memcpy(&new_zone.flags, &data_buf[data_ptr], sizeof(new_zone.flags)); - data_ptr += sizeof(new_zone.flags); - } - - zones.push_back(new_zone); - } - - /*-----------------------------------------------------*\ - | Copy in number of LEDs (data) | - \*-----------------------------------------------------*/ - unsigned short num_leds; - memcpy(&num_leds, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Copy in LEDs | - \*-----------------------------------------------------*/ - for(int led_index = 0; led_index < num_leds; led_index++) - { - led new_led; - - /*-------------------------------------------------*\ - | Copy in LED name (size+data) | - \*-------------------------------------------------*/ - unsigned short ledname_len; - memcpy(&ledname_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - new_led.name = (char *)&data_buf[data_ptr]; - data_ptr += ledname_len; - - /*-------------------------------------------------*\ - | Copy in LED value (data) | - \*-------------------------------------------------*/ - memcpy(&new_led.value, &data_buf[data_ptr], sizeof(new_led.value)); - data_ptr += sizeof(new_led.value); - - leds.push_back(new_led); - } - - /*-----------------------------------------------------*\ - | Copy in number of colors (data) | - \*-----------------------------------------------------*/ - unsigned short num_colors; - memcpy(&num_colors, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Copy in colors | - \*-----------------------------------------------------*/ - for(int color_index = 0; color_index < num_colors; color_index++) - { - RGBColor new_color; - - /*-------------------------------------------------*\ - | Copy in color (data) | - \*-------------------------------------------------*/ - memcpy(&new_color, &data_buf[data_ptr], sizeof(RGBColor)); - data_ptr += sizeof(RGBColor); - - colors.push_back(new_color); - } - - /*-----------------------------------------------------*\ - | Copy in LED alternate names data | - \*-----------------------------------------------------*/ - if(protocol_version >= 5) - { - /*-------------------------------------------------*\ - | Copy in number of LED alternate names | - \*-------------------------------------------------*/ - unsigned short num_led_alt_names; - - memcpy(&num_led_alt_names, &data_buf[data_ptr], sizeof(num_led_alt_names)); - data_ptr += sizeof(num_led_alt_names); - - for(int led_idx = 0; led_idx < num_led_alt_names; led_idx++) - { - unsigned short string_length = 0; - - /*---------------------------------------------*\ - | Copy in LED alternate name string (size+data) | - \*---------------------------------------------*/ - memcpy(&string_length, &data_buf[data_ptr], sizeof(string_length)); - data_ptr += sizeof(string_length); - - led_alt_names.push_back((char *)&data_buf[data_ptr]); - data_ptr += string_length; - } - } - - /*-----------------------------------------------------*\ - | Copy in controller flags data | - \*-----------------------------------------------------*/ - if(protocol_version >= 5) - { - memcpy(&flags, &data_buf[data_ptr], sizeof(flags)); - data_ptr += sizeof(flags); - } - - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock(); - - /*-----------------------------------------------------*\ - | Setup colors | - \*-----------------------------------------------------*/ - SetupColors(); -} - -unsigned char * RGBController::GetModeDescription(int mode, unsigned int protocol_version) -{ - /*-----------------------------------------------------*\ - | Lock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.lock_shared(); - - unsigned int data_ptr = 0; - unsigned int data_size = 0; - - unsigned short mode_name_len; - unsigned short mode_num_colors; + unsigned int data_size = 0; /*-----------------------------------------------------*\ | Calculate data size | \*-----------------------------------------------------*/ - mode_name_len = (unsigned short)strlen(modes[mode].name.c_str()) + 1; - mode_num_colors = (unsigned short)modes[mode].colors.size(); + unsigned short name_len = (unsigned short)strlen(name.c_str()) + 1; + unsigned short vendor_len = (unsigned short)strlen(vendor.c_str()) + 1; + unsigned short description_len = (unsigned short)strlen(description.c_str()) + 1; + unsigned short version_len = (unsigned short)strlen(version.c_str()) + 1; + unsigned short serial_len = (unsigned short)strlen(serial.c_str()) + 1; + unsigned short location_len = (unsigned short)strlen(location.c_str()) + 1; + unsigned short num_modes = (unsigned short)modes.size(); + unsigned short num_zones = (unsigned short)zones.size(); + unsigned short num_leds = (unsigned short)leds.size(); + unsigned short num_led_alt_names = (unsigned short)led_alt_names.size(); - data_size += sizeof(data_size); - data_size += sizeof(mode); - data_size += sizeof(mode_name_len); - data_size += mode_name_len; - data_size += sizeof(modes[mode].value); - data_size += sizeof(modes[mode].flags); - data_size += sizeof(modes[mode].speed_min); - data_size += sizeof(modes[mode].speed_max); + data_size += sizeof(data_size); + data_size += sizeof(device_type); + data_size += sizeof(name_len); + data_size += name_len; + + if(protocol_version >= 1) + { + data_size += sizeof(vendor_len); + data_size += vendor_len; + } + + data_size += sizeof(description_len); + data_size += description_len; + data_size += sizeof(version_len); + data_size += version_len; + data_size += sizeof(serial_len); + data_size += serial_len; + data_size += sizeof(location_len); + data_size += location_len; + + data_size += sizeof(num_modes); + data_size += sizeof(active_mode); + + for(int mode_index = 0; mode_index < num_modes; mode_index++) + { + data_size += GetModeDescriptionSize(modes[mode_index], protocol_version); + } + + data_size += sizeof(num_zones); + + for(int zone_index = 0; zone_index < num_zones; zone_index++) + { + data_size += GetZoneDescriptionSize(zones[zone_index], protocol_version); + } + + data_size += sizeof(num_leds); + + for(int led_index = 0; led_index < num_leds; led_index++) + { + data_size += GetLEDDescriptionSize(leds[led_index], protocol_version); + } + + data_size += GetColorDescriptionSize(protocol_version); + + if(protocol_version >= 5) + { + data_size += sizeof(num_led_alt_names); + + for(std::size_t led_idx = 0; led_idx < led_alt_names.size(); led_idx++) + { + data_size += sizeof(unsigned short); + data_size += (unsigned int)strlen(led_alt_names[led_idx].c_str()) + 1; + } + } + + if(protocol_version >= 5) + { + data_size += sizeof(flags); + } + + return(data_size); +} + +unsigned char * RGBController::GetLEDDescriptionData(unsigned char* data_ptr, led led, unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Copy in LED name (size+data) | + \*-----------------------------------------------------*/ + unsigned short led_name_len = (unsigned short)strlen(led.name.c_str()) + 1; + + memcpy(data_ptr, &led_name_len, sizeof(led_name_len)); + data_ptr += sizeof(led_name_len); + + strcpy((char *)data_ptr, led.name.c_str()); + data_ptr += led_name_len; + + /*-----------------------------------------------------*\ + | Copy in LED value | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &led.value, sizeof(led.value)); + data_ptr += sizeof(led.value); + + return(data_ptr); +} + +unsigned int RGBController::GetLEDDescriptionSize(led led, unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + + /*-----------------------------------------------------*\ + | Calculate description data size for the given LED | + \*-----------------------------------------------------*/ + unsigned short led_name_len = (unsigned short)strlen(led.name.c_str()) + 1; + + data_size += sizeof(led_name_len); + data_size += led_name_len; + data_size += sizeof(led.value); + + return(data_size); +} + +unsigned char * RGBController::GetMatrixMapDescriptionData(unsigned char* data_ptr, matrix_map_type* matrix_map, unsigned int /*protocol_version*/) +{ + if(matrix_map != NULL) + { + /*-------------------------------------------------*\ + | Copy in matrix height | + \*-------------------------------------------------*/ + memcpy(data_ptr, &matrix_map->height, sizeof(matrix_map->height)); + data_ptr += sizeof(matrix_map->height); + + /*-------------------------------------------------*\ + | Copy in matrix width | + \*-------------------------------------------------*/ + memcpy(data_ptr, &matrix_map->width, sizeof(matrix_map->width)); + data_ptr += sizeof(matrix_map->width); + + /*-------------------------------------------------*\ + | Copy in matrix map | + \*-------------------------------------------------*/ + for(unsigned int matrix_idx = 0; matrix_idx < (matrix_map->height * matrix_map->width); matrix_idx++) + { + memcpy(data_ptr, &matrix_map->map[matrix_idx], sizeof(matrix_map->map[matrix_idx])); + data_ptr += sizeof(matrix_map->map[matrix_idx]); + } + } + + return(data_ptr); +} + +unsigned int RGBController::GetMatrixMapDescriptionSize(matrix_map_type* matrix_map, unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + + /*-----------------------------------------------------*\ + | Calculate description data size for the given matrix | + | map | + \*-----------------------------------------------------*/ + if(matrix_map != NULL) + { + data_size += sizeof(matrix_map->height); + data_size += sizeof(matrix_map->width); + data_size += (matrix_map->height * matrix_map->width) * sizeof(unsigned int); + } + + return(data_size); +} + +unsigned int RGBController::GetModeDescriptionSize(mode mode, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int mode_description_size = 0; + unsigned short mode_name_len = 0; + unsigned short mode_num_colors = 0; + + /*-----------------------------------------------------*\ + | Calculate description data size for the given mode | + \*-----------------------------------------------------*/ + mode_name_len = (unsigned short)strlen(mode.name.c_str()) + 1; + mode_num_colors = (unsigned short)mode.colors.size(); + + mode_description_size += sizeof(mode_name_len); + mode_description_size += mode_name_len; + mode_description_size += sizeof(mode.value); + mode_description_size += sizeof(mode.flags); + mode_description_size += sizeof(mode.speed_min); + mode_description_size += sizeof(mode.speed_max); if(protocol_version >= 3) { - data_size += sizeof(modes[mode].brightness_min); - data_size += sizeof(modes[mode].brightness_max); + mode_description_size += sizeof(mode.brightness_min); + mode_description_size += sizeof(mode.brightness_max); } - data_size += sizeof(modes[mode].colors_min); - data_size += sizeof(modes[mode].colors_max); - data_size += sizeof(modes[mode].speed); + mode_description_size += sizeof(mode.colors_min); + mode_description_size += sizeof(mode.colors_max); + mode_description_size += sizeof(mode.speed); if(protocol_version >= 3) { - data_size += sizeof(modes[mode].brightness); + mode_description_size += sizeof(mode.brightness); } - data_size += sizeof(modes[mode].direction); - data_size += sizeof(modes[mode].color_mode); - data_size += sizeof(mode_num_colors); - data_size += (mode_num_colors * sizeof(RGBColor)); + mode_description_size += sizeof(mode.direction); + mode_description_size += sizeof(mode.color_mode); + mode_description_size += sizeof(mode_num_colors); + mode_description_size += (mode_num_colors * sizeof(RGBColor)); + + return(mode_description_size); +} + +unsigned char * RGBController::GetModeDescriptionData(unsigned char* data_ptr, mode mode, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned short mode_name_len = 0; + unsigned short mode_num_colors = 0; /*-----------------------------------------------------*\ - | Create data buffer | + | Calculate mode sizes | \*-----------------------------------------------------*/ - unsigned char *data_buf = new unsigned char[data_size]; - - /*-----------------------------------------------------*\ - | Copy in data size | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &data_size, sizeof(data_size)); - data_ptr += sizeof(data_size); - - /*-----------------------------------------------------*\ - | Copy in mode index | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &mode, sizeof(int)); - data_ptr += sizeof(int); + mode_name_len = (unsigned short)strlen(mode.name.c_str()) + 1; + mode_num_colors = (unsigned short)mode.colors.size(); /*-----------------------------------------------------*\ | Copy in mode name (size+data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &mode_name_len, sizeof(unsigned short)); + memcpy(data_ptr, &mode_name_len, sizeof(unsigned short)); data_ptr += sizeof(unsigned short); - strcpy((char *)&data_buf[data_ptr], modes[mode].name.c_str()); + strcpy((char *)data_ptr, mode.name.c_str()); data_ptr += mode_name_len; /*-----------------------------------------------------*\ | Copy in mode value (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].value, sizeof(modes[mode].value)); - data_ptr += sizeof(modes[mode].value); + memcpy(data_ptr, &mode.value, sizeof(mode.value)); + data_ptr += sizeof(mode.value); /*-----------------------------------------------------*\ | Copy in mode flags (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].flags, sizeof(modes[mode].flags)); - data_ptr += sizeof(modes[mode].flags); + memcpy(data_ptr, &mode.flags, sizeof(mode.flags)); + data_ptr += sizeof(mode.flags); /*-----------------------------------------------------*\ | Copy in mode speed_min (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].speed_min, sizeof(modes[mode].speed_min)); - data_ptr += sizeof(modes[mode].speed_min); + memcpy(data_ptr, &mode.speed_min, sizeof(mode.speed_min)); + data_ptr += sizeof(mode.speed_min); /*-----------------------------------------------------*\ | Copy in mode speed_max (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].speed_max, sizeof(modes[mode].speed_max)); - data_ptr += sizeof(modes[mode].speed_max); + memcpy(data_ptr, &mode.speed_max, sizeof(mode.speed_max)); + data_ptr += sizeof(mode.speed_max); /*-----------------------------------------------------*\ | Copy in mode brightness min and max if protocol | @@ -2738,30 +2002,30 @@ unsigned char * RGBController::GetModeDescription(int mode, unsigned int protoco \*-----------------------------------------------------*/ if(protocol_version >= 3) { - memcpy(&data_buf[data_ptr], &modes[mode].brightness_min, sizeof(modes[mode].brightness_min)); - data_ptr += sizeof(modes[mode].brightness_min); + memcpy(data_ptr, &mode.brightness_min, sizeof(mode.brightness_min)); + data_ptr += sizeof(mode.brightness_min); - memcpy(&data_buf[data_ptr], &modes[mode].brightness_max, sizeof(modes[mode].brightness_max)); - data_ptr += sizeof(modes[mode].brightness_max); + memcpy(data_ptr, &mode.brightness_max, sizeof(mode.brightness_max)); + data_ptr += sizeof(mode.brightness_max); } /*-----------------------------------------------------*\ | Copy in mode colors_min (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].colors_min, sizeof(modes[mode].colors_min)); - data_ptr += sizeof(modes[mode].colors_min); + memcpy(data_ptr, &mode.colors_min, sizeof(mode.colors_min)); + data_ptr += sizeof(mode.colors_min); /*-----------------------------------------------------*\ | Copy in mode colors_max (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].colors_max, sizeof(modes[mode].colors_max)); - data_ptr += sizeof(modes[mode].colors_max); + memcpy(data_ptr, &mode.colors_max, sizeof(mode.colors_max)); + data_ptr += sizeof(mode.colors_max); /*-----------------------------------------------------*\ | Copy in mode speed (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].speed, sizeof(modes[mode].speed)); - data_ptr += sizeof(modes[mode].speed); + memcpy(data_ptr, &mode.speed, sizeof(mode.speed)); + data_ptr += sizeof(mode.speed); /*-----------------------------------------------------*\ | Copy in mode brightness if protocol version is 3 or | @@ -2769,26 +2033,26 @@ unsigned char * RGBController::GetModeDescription(int mode, unsigned int protoco \*-----------------------------------------------------*/ if(protocol_version >= 3) { - memcpy(&data_buf[data_ptr], &modes[mode].brightness, sizeof(modes[mode].brightness)); - data_ptr += sizeof(modes[mode].brightness); + memcpy(data_ptr, &mode.brightness, sizeof(mode.brightness)); + data_ptr += sizeof(mode.brightness); } /*-----------------------------------------------------*\ | Copy in mode direction (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].direction, sizeof(modes[mode].direction)); - data_ptr += sizeof(modes[mode].direction); + memcpy(data_ptr, &mode.direction, sizeof(mode.direction)); + data_ptr += sizeof(mode.direction); /*-----------------------------------------------------*\ | Copy in mode color_mode (data) | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].color_mode, sizeof(modes[mode].color_mode)); - data_ptr += sizeof(modes[mode].color_mode); + memcpy(data_ptr, &mode.color_mode, sizeof(mode.color_mode)); + data_ptr += sizeof(mode.color_mode); /*-----------------------------------------------------*\ | Copy in mode number of colors | \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &mode_num_colors, sizeof(unsigned short)); + memcpy(data_ptr, &mode_num_colors, sizeof(unsigned short)); data_ptr += sizeof(unsigned short); /*-----------------------------------------------------*\ @@ -2799,218 +2063,93 @@ unsigned char * RGBController::GetModeDescription(int mode, unsigned int protoco /*-------------------------------------------------*\ | Copy in color (data) | \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &modes[mode].colors[color_index], sizeof(modes[mode].colors[color_index])); - data_ptr += sizeof(modes[mode].colors[color_index]); + memcpy(data_ptr, &mode.colors[color_index], sizeof(mode.colors[color_index])); + data_ptr += sizeof(mode.colors[color_index]); } - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock_shared(); - - return(data_buf); + return(data_ptr); } -void RGBController::SetModeDescription(unsigned char* data_buf, unsigned int protocol_version) +unsigned char * RGBController::GetSegmentDescriptionData(unsigned char* data_ptr, segment segment, unsigned int /*protocol_version*/) { /*-----------------------------------------------------*\ - | Lock access mutex | + | Length of segment name string | \*-----------------------------------------------------*/ - AccessMutex.lock(); + unsigned short segment_name_length = (unsigned short)strlen(segment.name.c_str()) + 1; - int mode_idx; - unsigned int data_ptr = sizeof(unsigned int); + memcpy(data_ptr, &segment_name_length, sizeof(segment_name_length)); + data_ptr += sizeof(segment_name_length); /*-----------------------------------------------------*\ - | Copy in mode index | + | Segment name string data | \*-----------------------------------------------------*/ - memcpy(&mode_idx, &data_buf[data_ptr], sizeof(int)); - data_ptr += sizeof(int); + strcpy((char *)data_ptr, segment.name.c_str()); + data_ptr += segment_name_length; /*-----------------------------------------------------*\ - | Check if we aren't reading beyond the list of modes. | + | Segment type data | \*-----------------------------------------------------*/ - if(((size_t) mode_idx) > modes.size()) - { - /*-------------------------------------------------*\ - | Unlock access mutex | - \*-------------------------------------------------*/ - AccessMutex.unlock_shared(); - return; - } + memcpy(data_ptr, &segment.type, sizeof(segment.type)); + data_ptr += sizeof(segment.type); /*-----------------------------------------------------*\ - | Get pointer to target mode | + | Segment start index data | \*-----------------------------------------------------*/ - mode * new_mode = &modes[mode_idx]; + memcpy(data_ptr, &segment.start_idx, sizeof(segment.start_idx)); + data_ptr += sizeof(segment.start_idx); /*-----------------------------------------------------*\ - | Set active mode to the new mode | + | Segment LED count data | \*-----------------------------------------------------*/ - active_mode = mode_idx; + memcpy(data_ptr, &segment.leds_count, sizeof(segment.leds_count)); + data_ptr += sizeof(segment.leds_count); - /*-----------------------------------------------------*\ - | Copy in mode name (size+data) | - \*-----------------------------------------------------*/ - unsigned short modename_len; - memcpy(&modename_len, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - new_mode->name = (char *)&data_buf[data_ptr]; - data_ptr += modename_len; - - /*-----------------------------------------------------*\ - | Copy in mode value (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->value, &data_buf[data_ptr], sizeof(new_mode->value)); - data_ptr += sizeof(new_mode->value); - - /*-----------------------------------------------------*\ - | Copy in mode flags (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->flags, &data_buf[data_ptr], sizeof(new_mode->flags)); - data_ptr += sizeof(new_mode->flags); - - /*-----------------------------------------------------*\ - | Copy in mode speed_min (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->speed_min, &data_buf[data_ptr], sizeof(new_mode->speed_min)); - data_ptr += sizeof(new_mode->speed_min); - - /*-----------------------------------------------------*\ - | Copy in mode speed_max (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->speed_max, &data_buf[data_ptr], sizeof(new_mode->speed_max)); - data_ptr += sizeof(new_mode->speed_max); - - /*-----------------------------------------------------*\ - | Copy in mode brightness_min and brightness_max (data) | - | if protocol 3 or higher | - \*-----------------------------------------------------*/ - if(protocol_version >= 3) - { - memcpy(&new_mode->brightness_min, &data_buf[data_ptr], sizeof(new_mode->brightness_min)); - data_ptr += sizeof(new_mode->brightness_min); - - memcpy(&new_mode->brightness_max, &data_buf[data_ptr], sizeof(new_mode->brightness_max)); - data_ptr += sizeof(new_mode->brightness_max); - } - - /*-----------------------------------------------------*\ - | Copy in mode colors_min (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->colors_min, &data_buf[data_ptr], sizeof(new_mode->colors_min)); - data_ptr += sizeof(new_mode->colors_min); - - /*-----------------------------------------------------*\ - | Copy in mode colors_max (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->colors_max, &data_buf[data_ptr], sizeof(new_mode->colors_max)); - data_ptr += sizeof(new_mode->colors_max); - - /*-----------------------------------------------------*\ - | Copy in mode speed (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->speed, &data_buf[data_ptr], sizeof(new_mode->speed)); - data_ptr += sizeof(new_mode->speed); - - /*-----------------------------------------------------*\ - | Copy in mode brightness (data) if protocol 3 or higher| - \*-----------------------------------------------------*/ - if(protocol_version >= 3) - { - memcpy(&new_mode->brightness, &data_buf[data_ptr], sizeof(new_mode->brightness)); - data_ptr += sizeof(new_mode->brightness); - } - - /*-----------------------------------------------------*\ - | Copy in mode direction (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->direction, &data_buf[data_ptr], sizeof(new_mode->direction)); - data_ptr += sizeof(new_mode->direction); - - /*-----------------------------------------------------*\ - | Copy in mode color_mode (data) | - \*-----------------------------------------------------*/ - memcpy(&new_mode->color_mode, &data_buf[data_ptr], sizeof(new_mode->color_mode)); - data_ptr += sizeof(new_mode->color_mode); - - /*-----------------------------------------------------*\ - | Copy in mode number of colors | - \*-----------------------------------------------------*/ - unsigned short mode_num_colors; - memcpy(&mode_num_colors, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Copy in mode mode colors | - \*-----------------------------------------------------*/ - new_mode->colors.clear(); - for(int color_index = 0; color_index < mode_num_colors; color_index++) - { - /*-------------------------------------------------*\ - | Copy in color (data) | - \*-------------------------------------------------*/ - RGBColor new_color; - memcpy(&new_color, &data_buf[data_ptr], sizeof(RGBColor)); - data_ptr += sizeof(RGBColor); - - new_mode->colors.push_back(new_color); - } - - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock(); + return(data_ptr); } -unsigned char * RGBController::GetColorDescription() +unsigned int RGBController::GetSegmentDescriptionSize(segment segment, unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + + /*-----------------------------------------------------*\ + | Calculate description data size for the given segment | + \*-----------------------------------------------------*/ + data_size += sizeof(unsigned short); + data_size += (unsigned int)strlen(segment.name.c_str()) + 1; + + data_size += sizeof(segment.type); + data_size += sizeof(segment.start_idx); + data_size += sizeof(segment.leds_count); + + return(data_size); +} + +unsigned char * RGBController::GetSingleLEDColorDescription(int led) { /*-----------------------------------------------------*\ | Lock access mutex | \*-----------------------------------------------------*/ AccessMutex.lock_shared(); - unsigned int data_ptr = 0; - unsigned int data_size = 0; - - unsigned short num_colors = (unsigned short)colors.size(); + /*-----------------------------------------------------*\ + | Fixed size descrption: | + | int: LED index | + | RGBColor: LED color | + \*-----------------------------------------------------*/ + unsigned char *data_buf = new unsigned char[sizeof(int) + sizeof(RGBColor)]; /*-----------------------------------------------------*\ - | Calculate data size | + | Copy in LED index | \*-----------------------------------------------------*/ - data_size += sizeof(data_size); - data_size += sizeof(num_colors); - data_size += num_colors * sizeof(RGBColor); + memcpy(&data_buf[0], &led, sizeof(int)); /*-----------------------------------------------------*\ - | Create data buffer | + | Copy in LED color | \*-----------------------------------------------------*/ - unsigned char *data_buf = new unsigned char[data_size]; - - /*-----------------------------------------------------*\ - | Copy in data size | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &data_size, sizeof(data_size)); - data_ptr += sizeof(data_size); - - /*-----------------------------------------------------*\ - | Copy in number of colors (data) | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &num_colors, sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Copy in colors | - \*-----------------------------------------------------*/ - for(int color_index = 0; color_index < num_colors; color_index++) - { - /*-------------------------------------------------*\ - | Copy in color (data) | - \*-------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &colors[color_index], sizeof(colors[color_index])); - data_ptr += sizeof(colors[color_index]); - } + memcpy(&data_buf[sizeof(led)], &colors[led], sizeof(RGBColor)); /*-----------------------------------------------------*\ | Unlock access mutex | @@ -3020,56 +2159,6 @@ unsigned char * RGBController::GetColorDescription() return(data_buf); } -void RGBController::SetColorDescription(unsigned char* data_buf) -{ - /*-----------------------------------------------------*\ - | Lock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.lock(); - - unsigned int data_ptr = sizeof(unsigned int); - - /*-----------------------------------------------------*\ - | Copy in number of colors (data) | - \*-----------------------------------------------------*/ - unsigned short num_colors; - memcpy(&num_colors, &data_buf[data_ptr], sizeof(unsigned short)); - data_ptr += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Check if we aren't reading beyond the list of colors. | - \*-----------------------------------------------------*/ - if(((size_t)num_colors) > colors.size()) - { - /*-------------------------------------------------*\ - | Unlock access mutex | - \*-------------------------------------------------*/ - AccessMutex.unlock(); - return; - } - - /*-----------------------------------------------------*\ - | Copy in colors | - \*-----------------------------------------------------*/ - for(int color_index = 0; color_index < num_colors; color_index++) - { - RGBColor new_color; - - /*-------------------------------------------------*\ - | Copy in color (data) | - \*-------------------------------------------------*/ - memcpy(&new_color, &data_buf[data_ptr], sizeof(RGBColor)); - data_ptr += sizeof(RGBColor); - - colors[color_index] = new_color; - } - - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock(); -} - unsigned char * RGBController::GetZoneColorDescription(int zone) { /*-----------------------------------------------------*\ @@ -3133,6 +2222,732 @@ unsigned char * RGBController::GetZoneColorDescription(int zone) return(data_buf); } +unsigned char * RGBController::GetZoneDescriptionData(unsigned char* data_ptr, zone zone, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned short zone_name_len = (unsigned short)strlen(zone.name.c_str()) + 1; + + /*-----------------------------------------------------*\ + | Copy in zone name (size+data) | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &zone_name_len, sizeof(zone_name_len)); + data_ptr += sizeof(unsigned short); + + strcpy((char *)data_ptr, zone.name.c_str()); + data_ptr += zone_name_len; + + /*-----------------------------------------------------*\ + | Copy in zone type | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &zone.type, sizeof(zone.type)); + data_ptr += sizeof(zone.type); + + /*-----------------------------------------------------*\ + | Check for resizable effects-only zone. For protocol | + | versions that do not support this feature, we have to | + | overwrite the leds_min/max/count parameters to 1 so | + | that the zone appears a fixed size to older clients. | + \*-----------------------------------------------------*/ + if((zone.flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY) && (protocol_version < 5)) + { + /*-------------------------------------------------*\ + | Create a temporary variable to hold the fixed | + | value of 1 | + \*-------------------------------------------------*/ + unsigned int tmp_size = 1; + + /*-------------------------------------------------*\ + | Copy in temporary minimum LED count | + \*-------------------------------------------------*/ + memcpy(data_ptr, &tmp_size, sizeof(tmp_size)); + data_ptr += sizeof(tmp_size); + + /*-------------------------------------------------*\ + | Copy in temporary maximum LED count | + \*-------------------------------------------------*/ + memcpy(data_ptr, &tmp_size, sizeof(tmp_size)); + data_ptr += sizeof(tmp_size); + + /*-------------------------------------------------*\ + | Copy in temporary LED count | + \*-------------------------------------------------*/ + memcpy(data_ptr, &tmp_size, sizeof(tmp_size)); + data_ptr += sizeof(tmp_size); + } + else + { + /*-------------------------------------------------*\ + | Copy in zone minimum LED count | + \*-------------------------------------------------*/ + memcpy(data_ptr, &zone.leds_min, sizeof(zone.leds_min)); + data_ptr += sizeof(zone.leds_min); + + /*-------------------------------------------------*\ + | Copy in zone maximum LED count | + \*-------------------------------------------------*/ + memcpy(data_ptr, &zone.leds_max, sizeof(zone.leds_max)); + data_ptr += sizeof(zone.leds_max); + + /*-------------------------------------------------*\ + | Copy in zone LED count | + \*-------------------------------------------------*/ + memcpy(data_ptr, &zone.leds_count, sizeof(zone.leds_count)); + data_ptr += sizeof(zone.leds_count); + } + + /*-----------------------------------------------------*\ + | Copy in matrix map | + \*-----------------------------------------------------*/ + unsigned short matrix_map_size = GetMatrixMapDescriptionSize(zone.matrix_map, protocol_version); + + memcpy(data_ptr, &matrix_map_size, sizeof(matrix_map_size)); + data_ptr += sizeof(matrix_map_size); + + data_ptr = GetMatrixMapDescriptionData(data_ptr, zone.matrix_map, protocol_version); + + /*-----------------------------------------------------*\ + | Copy in segments | + \*-----------------------------------------------------*/ + if(protocol_version >= 4) + { + /*-------------------------------------------------*\ + | Number of segments in zone | + \*-------------------------------------------------*/ + unsigned short num_segments = (unsigned short)zone.segments.size(); + + memcpy(data_ptr, &num_segments, sizeof(num_segments)); + data_ptr += sizeof(num_segments); + + for(int segment_index = 0; segment_index < num_segments; segment_index++) + { + data_ptr = GetSegmentDescriptionData(data_ptr, zone.segments[segment_index], protocol_version); + } + } + + /*-----------------------------------------------------*\ + | Copy in zone flags | + \*-----------------------------------------------------*/ + if(protocol_version >= 5) + { + memcpy(data_ptr, &zone.flags, sizeof(zone.flags)); + data_ptr += sizeof(zone.flags); + } + + return(data_ptr); +} + +unsigned int RGBController::GetZoneDescriptionSize(zone zone, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + + /*-----------------------------------------------------*\ + | Calculate description data size for the given segment | + \*-----------------------------------------------------*/ + data_size += sizeof(unsigned short); + data_size += (unsigned short)strlen(zone.name.c_str()) + 1; + + data_size += sizeof(zone.type); + data_size += sizeof(zone.leds_min); + data_size += sizeof(zone.leds_max); + data_size += sizeof(zone.leds_count); + + /*-----------------------------------------------------*\ + | Matrix map size | + \*-----------------------------------------------------*/ + data_size += sizeof(unsigned short); + data_size += GetMatrixMapDescriptionSize(zone.matrix_map, protocol_version); + + if(protocol_version >= 4) + { + /*-------------------------------------------------*\ + | Number of segments in zone | + \*-------------------------------------------------*/ + data_size += sizeof(unsigned short); + + for(size_t segment_index = 0; segment_index < zone.segments.size(); segment_index++) + { + data_size += GetSegmentDescriptionSize(zone.segments[segment_index], protocol_version); + } + } + + /*-----------------------------------------------------*\ + | Zone flags | + \*-----------------------------------------------------*/ + if(protocol_version >= 5) + { + data_size += sizeof(zone.flags); + } + + return(data_size); +} + +unsigned char* RGBController::SetDeviceDescription(unsigned char* data_ptr, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.lock(); + + /*-----------------------------------------------------*\ + | Skip packet size | + \*-----------------------------------------------------*/ + data_ptr += sizeof(unsigned int); + + /*-----------------------------------------------------*\ + | Copy in type | + \*-----------------------------------------------------*/ + memcpy(&type, data_ptr, sizeof(device_type)); + data_ptr += sizeof(device_type); + + /*-----------------------------------------------------*\ + | Copy in name | + \*-----------------------------------------------------*/ + unsigned short name_len; + memcpy(&name_len, data_ptr, sizeof(name_len)); + data_ptr += sizeof(name_len); + + name = (char *)data_ptr; + data_ptr += name_len; + + /*-----------------------------------------------------*\ + | Copy in vendor if protocol version is 1 or higher | + \*-----------------------------------------------------*/ + if(protocol_version >= 1) + { + unsigned short vendor_len; + memcpy(&vendor_len, data_ptr, sizeof(vendor_len)); + data_ptr += sizeof(vendor_len); + + vendor = (char *)data_ptr; + data_ptr += vendor_len; + } + + /*-----------------------------------------------------*\ + | Copy in description | + \*-----------------------------------------------------*/ + unsigned short description_len; + memcpy(&description_len, data_ptr, sizeof(description_len)); + data_ptr += sizeof(description_len); + + description = (char *)data_ptr; + data_ptr += description_len; + + /*-----------------------------------------------------*\ + | Copy in version | + \*-----------------------------------------------------*/ + unsigned short version_len; + memcpy(&version_len, data_ptr, sizeof(version_len)); + data_ptr += sizeof(version_len); + + version = (char *)data_ptr; + data_ptr += version_len; + + /*-----------------------------------------------------*\ + | Copy in serial | + \*-----------------------------------------------------*/ + unsigned short serial_len; + memcpy(&serial_len, data_ptr, sizeof(serial_len)); + data_ptr += sizeof(serial_len); + + serial = (char *)data_ptr; + data_ptr += serial_len; + + /*-----------------------------------------------------*\ + | Copy in location | + \*-----------------------------------------------------*/ + unsigned short location_len; + memcpy(&location_len, data_ptr, sizeof(location_len)); + data_ptr += sizeof(location_len); + + location = (char *)data_ptr; + data_ptr += location_len; + + /*-----------------------------------------------------*\ + | Copy in number of modes | + \*-----------------------------------------------------*/ + unsigned short num_modes; + memcpy(&num_modes, data_ptr, sizeof(num_modes)); + data_ptr += sizeof(num_modes); + + /*-----------------------------------------------------*\ + | Copy in active mode | + \*-----------------------------------------------------*/ + memcpy(&active_mode, data_ptr, sizeof(active_mode)); + data_ptr += sizeof(active_mode); + + /*-----------------------------------------------------*\ + | Copy in modes | + \*-----------------------------------------------------*/ + modes.resize(num_modes); + + for(int mode_index = 0; mode_index < num_modes; mode_index++) + { + data_ptr = SetModeDescription(data_ptr, &modes[mode_index], protocol_version); + } + + /*-----------------------------------------------------*\ + | Copy in number of zones | + \*-----------------------------------------------------*/ + unsigned short num_zones; + memcpy(&num_zones, data_ptr, sizeof(num_zones)); + data_ptr += sizeof(num_zones); + + /*-----------------------------------------------------*\ + | Copy in zones | + \*-----------------------------------------------------*/ + zones.resize(num_zones); + + for(int zone_index = 0; zone_index < num_zones; zone_index++) + { + data_ptr = SetZoneDescription(data_ptr, &zones[zone_index], protocol_version); + } + + /*-----------------------------------------------------*\ + | Copy in number of LEDs | + \*-----------------------------------------------------*/ + unsigned short num_leds; + memcpy(&num_leds, data_ptr, sizeof(unsigned short)); + data_ptr += sizeof(unsigned short); + + /*-----------------------------------------------------*\ + | Copy in LEDs | + \*-----------------------------------------------------*/ + leds.resize(num_leds); + + for(int led_index = 0; led_index < num_leds; led_index++) + { + data_ptr = SetLEDDescription(data_ptr, &leds[led_index], protocol_version); + } + + /*-----------------------------------------------------*\ + | Copy in colors | + \*-----------------------------------------------------*/ + data_ptr = SetColorDescription(data_ptr, protocol_version, true); + + /*-----------------------------------------------------*\ + | Copy in LED alternate names data | + \*-----------------------------------------------------*/ + if(protocol_version >= 5) + { + /*-------------------------------------------------*\ + | Copy in number of LED alternate names | + \*-------------------------------------------------*/ + unsigned short num_led_alt_names; + + memcpy(&num_led_alt_names, data_ptr, sizeof(num_led_alt_names)); + data_ptr += sizeof(num_led_alt_names); + + for(int led_idx = 0; led_idx < num_led_alt_names; led_idx++) + { + unsigned short string_length = 0; + + /*---------------------------------------------*\ + | Copy in LED alternate name string (size+data) | + \*---------------------------------------------*/ + memcpy(&string_length, data_ptr, sizeof(string_length)); + data_ptr += sizeof(string_length); + + led_alt_names.push_back((char *)data_ptr); + data_ptr += string_length; + } + } + + /*-----------------------------------------------------*\ + | Copy in controller flags data | + \*-----------------------------------------------------*/ + if(protocol_version >= 5) + { + memcpy(&flags, data_ptr, sizeof(flags)); + data_ptr += sizeof(flags); + } + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.unlock(); + + /*-----------------------------------------------------*\ + | Setup colors | + \*-----------------------------------------------------*/ + SetupColors(); + + return(data_ptr); +} + +unsigned char* RGBController::SetColorDescription(unsigned char* data_ptr, unsigned int protocol_version, bool resize) +{ + /*-----------------------------------------------------*\ + | Copy in number of colors (data) | + \*-----------------------------------------------------*/ + unsigned short num_colors; + memcpy(&num_colors, data_ptr, sizeof(unsigned short)); + data_ptr += sizeof(unsigned short); + + if(resize) + { + colors.resize(num_colors); + } + else + { + /*-------------------------------------------------*\ + | Check if we aren't reading beyond the list of | + | colors. | + \*-------------------------------------------------*/ + if(((size_t)num_colors) > colors.size()) + { + data_ptr += (num_colors * sizeof(RGBColor)); + return(data_ptr); + } + } + + /*-----------------------------------------------------*\ + | Copy in colors | + \*-----------------------------------------------------*/ + for(int color_index = 0; color_index < num_colors; color_index++) + { + memcpy(&colors[color_index], data_ptr, sizeof(colors[color_index])); + data_ptr += sizeof(colors[color_index]); + } + + return(data_ptr); +} + +unsigned char* RGBController::SetLEDDescription(unsigned char* data_ptr, led* led, unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Copy in LED name (size+data) | + \*-----------------------------------------------------*/ + unsigned short ledname_len; + memcpy(&ledname_len, data_ptr, sizeof(ledname_len)); + data_ptr += sizeof(ledname_len); + + led->name = (char *)data_ptr; + data_ptr += ledname_len; + + /*-----------------------------------------------------*\ + | Copy in LED value | + \*-----------------------------------------------------*/ + memcpy(&led->value, data_ptr, sizeof(led->value)); + data_ptr += sizeof(led->value); + + return(data_ptr); +} + +unsigned char* RGBController::SetModeDescription(unsigned char* data_ptr, mode* mode, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Copy in mode name (size+data) | + \*-----------------------------------------------------*/ + unsigned short modename_len; + memcpy(&modename_len, data_ptr, sizeof(unsigned short)); + data_ptr += sizeof(unsigned short); + + mode->name = (char *)data_ptr; + data_ptr += modename_len; + + /*-----------------------------------------------------*\ + | Copy in mode value | + \*-----------------------------------------------------*/ + memcpy(&mode->value, data_ptr, sizeof(mode->value)); + data_ptr += sizeof(mode->value); + + /*-----------------------------------------------------*\ + | Copy in mode flags | + \*-----------------------------------------------------*/ + memcpy(&mode->flags, data_ptr, sizeof(mode->flags)); + data_ptr += sizeof(mode->flags); + + /*-----------------------------------------------------*\ + | Copy in mode speed_min | + \*-----------------------------------------------------*/ + memcpy(&mode->speed_min, data_ptr, sizeof(mode->speed_min)); + data_ptr += sizeof(mode->speed_min); + + /*-----------------------------------------------------*\ + | Copy in mode speed_max | + \*-----------------------------------------------------*/ + memcpy(&mode->speed_max, data_ptr, sizeof(mode->speed_max)); + data_ptr += sizeof(mode->speed_max); + + /*-----------------------------------------------------*\ + | Copy in mode brightness_min and brightness_max (data) | + | if protocol 3 or higher | + \*-----------------------------------------------------*/ + if(protocol_version >= 3) + { + memcpy(&mode->brightness_min, data_ptr, sizeof(mode->brightness_min)); + data_ptr += sizeof(mode->brightness_min); + + memcpy(&mode->brightness_max, data_ptr, sizeof(mode->brightness_max)); + data_ptr += sizeof(mode->brightness_max); + } + + /*-----------------------------------------------------*\ + | Copy in mode colors_min | + \*-----------------------------------------------------*/ + memcpy(&mode->colors_min, data_ptr, sizeof(mode->colors_min)); + data_ptr += sizeof(mode->colors_min); + + /*-----------------------------------------------------*\ + | Copy in mode colors_max | + \*-----------------------------------------------------*/ + memcpy(&mode->colors_max, data_ptr, sizeof(mode->colors_max)); + data_ptr += sizeof(mode->colors_max); + + /*-----------------------------------------------------*\ + | Copy in mode speed | + \*-----------------------------------------------------*/ + memcpy(&mode->speed, data_ptr, sizeof(mode->speed)); + data_ptr += sizeof(mode->speed); + + /*-----------------------------------------------------*\ + | Copy in mode brightness (data) if protocol 3 or higher| + \*-----------------------------------------------------*/ + if(protocol_version >= 3) + { + memcpy(&mode->brightness, data_ptr, sizeof(mode->brightness)); + data_ptr += sizeof(mode->brightness); + } + + /*-----------------------------------------------------*\ + | Copy in mode direction | + \*-----------------------------------------------------*/ + memcpy(&mode->direction, data_ptr, sizeof(mode->direction)); + data_ptr += sizeof(mode->direction); + + /*-----------------------------------------------------*\ + | Copy in mode color_mode | + \*-----------------------------------------------------*/ + memcpy(&mode->color_mode, data_ptr, sizeof(mode->color_mode)); + data_ptr += sizeof(mode->color_mode); + + /*-----------------------------------------------------*\ + | Copy in mode number of colors | + \*-----------------------------------------------------*/ + unsigned short mode_num_colors; + memcpy(&mode_num_colors, data_ptr, sizeof(unsigned short)); + data_ptr += sizeof(unsigned short); + + /*-----------------------------------------------------*\ + | Copy in mode mode colors | + \*-----------------------------------------------------*/ + mode->colors.clear(); + for(int color_index = 0; color_index < mode_num_colors; color_index++) + { + /*-------------------------------------------------*\ + | Copy in color | + \*-------------------------------------------------*/ + RGBColor new_color; + memcpy(&new_color, data_ptr, sizeof(RGBColor)); + data_ptr += sizeof(RGBColor); + + mode->colors.push_back(new_color); + } + + return(data_ptr); +} + +unsigned char* RGBController::SetSegmentDescription(unsigned char* data_ptr, segment* segment, unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Copy in segment name (size+data) | + \*-----------------------------------------------------*/ + unsigned short segmentname_len; + memcpy(&segmentname_len, data_ptr, sizeof(segmentname_len)); + data_ptr += sizeof(segmentname_len); + + segment->name = (char *)data_ptr; + data_ptr += segmentname_len; + + /*-----------------------------------------------------*\ + | Copy in segment type | + \*-----------------------------------------------------*/ + memcpy(&segment->type, data_ptr, sizeof(segment->type)); + data_ptr += sizeof(segment->type); + + /*-----------------------------------------------------*\ + | Copy in segment start index | + \*-----------------------------------------------------*/ + memcpy(&segment->start_idx, data_ptr, sizeof(segment->start_idx)); + data_ptr += sizeof(segment->start_idx); + + /*-----------------------------------------------------*\ + | Copy in segment LED count | + \*-----------------------------------------------------*/ + memcpy(&segment->leds_count, data_ptr, sizeof(segment->leds_count)); + data_ptr += sizeof(segment->leds_count); + + return(data_ptr); +} + +void RGBController::SetSingleLEDColorDescription(unsigned char* data_buf) +{ + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.lock(); + + /*-----------------------------------------------------*\ + | Fixed size descrption: | + | int: LED index | + | RGBColor: LED color | + \*-----------------------------------------------------*/ + int led_idx; + + /*-----------------------------------------------------*\ + | Copy in LED index | + \*-----------------------------------------------------*/ + memcpy(&led_idx, &data_buf[0], sizeof(led_idx)); + + /*-----------------------------------------------------*\ + | Check if we aren't reading beyond the list of leds. | + \*-----------------------------------------------------*/ + if(((size_t)led_idx) > leds.size()) + { + /*-------------------------------------------------*\ + | Unlock access mutex | + \*-------------------------------------------------*/ + AccessMutex.unlock(); + return; + } + + /*-----------------------------------------------------*\ + | Copy in LED color | + \*-----------------------------------------------------*/ + memcpy(&colors[led_idx], &data_buf[sizeof(led_idx)], sizeof(RGBColor)); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.unlock(); +} + +unsigned char* RGBController::SetMatrixMapDescription(unsigned char* data_ptr, matrix_map_type* matrix_map, unsigned int /*protocol_version*/) +{ + /*-----------------------------------------------------*\ + | Copy in matrix height | + \*-----------------------------------------------------*/ + memcpy(&matrix_map->height, data_ptr, sizeof(matrix_map->height)); + data_ptr += sizeof(matrix_map->height); + + /*-----------------------------------------------------*\ + | Copy in matrix width | + \*-----------------------------------------------------*/ + memcpy(&matrix_map->width, data_ptr, sizeof(matrix_map->width)); + data_ptr += sizeof(matrix_map->width); + + /*-----------------------------------------------------*\ + | Copy in matrix map | + \*-----------------------------------------------------*/ + matrix_map->map = new unsigned int[matrix_map->height * matrix_map->width]; + + for(unsigned int matrix_idx = 0; matrix_idx < (matrix_map->height * matrix_map->width); matrix_idx++) + { + memcpy(&matrix_map->map[matrix_idx], data_ptr, sizeof(matrix_map->map[matrix_idx])); + data_ptr += sizeof(matrix_map->map[matrix_idx]); + } + + return(data_ptr); +} + +unsigned char* RGBController::SetZoneDescription(unsigned char* data_ptr, zone* zone, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Copy in zone name (size+data) | + \*-----------------------------------------------------*/ + unsigned short zonename_len; + memcpy(&zonename_len, data_ptr, sizeof(zonename_len)); + data_ptr += sizeof(zonename_len); + + zone->name = (char *)data_ptr; + data_ptr += zonename_len; + + /*-----------------------------------------------------*\ + | Copy in zone type | + \*-----------------------------------------------------*/ + memcpy(&zone->type, data_ptr, sizeof(zone->type)); + data_ptr += sizeof(zone->type); + + /*-----------------------------------------------------*\ + | Copy in zone minimum LED count | + \*-----------------------------------------------------*/ + memcpy(&zone->leds_min, data_ptr, sizeof(zone->leds_min)); + data_ptr += sizeof(zone->leds_min); + + /*-----------------------------------------------------*\ + | Copy in zone maximum LED count | + \*-----------------------------------------------------*/ + memcpy(&zone->leds_max, data_ptr, sizeof(zone->leds_max)); + data_ptr += sizeof(zone->leds_max); + + /*-----------------------------------------------------*\ + | Copy in zone LED count | + \*-----------------------------------------------------*/ + memcpy(&zone->leds_count, data_ptr, sizeof(zone->leds_count)); + data_ptr += sizeof(zone->leds_count); + + /*-----------------------------------------------------*\ + | Copy in size of matrix map | + \*-----------------------------------------------------*/ + unsigned short matrix_map_len; + memcpy(&matrix_map_len, data_ptr, sizeof(matrix_map_len)); + data_ptr += sizeof(matrix_map_len); + + /*-----------------------------------------------------*\ + | Copy in matrix data if size is nonzero | + \*-----------------------------------------------------*/ + if(matrix_map_len > 0) + { + /*-------------------------------------------------*\ + | Create a map data structure to fill in | + \*-------------------------------------------------*/ + zone->matrix_map = new matrix_map_type; + + data_ptr = SetMatrixMapDescription(data_ptr, zone->matrix_map, protocol_version); + } + else + { + zone->matrix_map = NULL; + } + + /*-----------------------------------------------------*\ + | Copy in segments | + \*-----------------------------------------------------*/ + if(protocol_version >= 4) + { + unsigned short num_segments = 0; + + /*-------------------------------------------------*\ + | Number of segments in zone | + \*-------------------------------------------------*/ + memcpy(&num_segments, data_ptr, sizeof(num_segments)); + data_ptr += sizeof(num_segments); + + zone->segments.resize(num_segments); + + for(int segment_index = 0; segment_index < num_segments; segment_index++) + { + data_ptr = SetSegmentDescription(data_ptr, &zone->segments[segment_index], protocol_version); + } + } + + /*-----------------------------------------------------*\ + | Copy in zone flags | + \*-----------------------------------------------------*/ + if(protocol_version >= 5) + { + memcpy(&zone->flags, data_ptr, sizeof(zone->flags)); + data_ptr += sizeof(zone->flags); + } + + return(data_ptr); +} + void RGBController::SetZoneColorDescription(unsigned char* data_buf) { /*-----------------------------------------------------*\ @@ -3190,232 +3005,6 @@ void RGBController::SetZoneColorDescription(unsigned char* data_buf) AccessMutex.unlock(); } -unsigned char * RGBController::GetSingleLEDColorDescription(int led) -{ - /*-----------------------------------------------------*\ - | Lock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.lock_shared(); - - /*-----------------------------------------------------*\ - | Fixed size descrption: | - | int: LED index | - | RGBColor: LED color | - \*-----------------------------------------------------*/ - unsigned char *data_buf = new unsigned char[sizeof(int) + sizeof(RGBColor)]; - - /*-----------------------------------------------------*\ - | Copy in LED index | - \*-----------------------------------------------------*/ - memcpy(&data_buf[0], &led, sizeof(int)); - - /*-----------------------------------------------------*\ - | Copy in LED color | - \*-----------------------------------------------------*/ - memcpy(&data_buf[sizeof(led)], &colors[led], sizeof(RGBColor)); - - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock_shared(); - - return(data_buf); -} - -void RGBController::SetSingleLEDColorDescription(unsigned char* data_buf) -{ - /*-----------------------------------------------------*\ - | Lock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.lock(); - - /*-----------------------------------------------------*\ - | Fixed size descrption: | - | int: LED index | - | RGBColor: LED color | - \*-----------------------------------------------------*/ - int led_idx; - - /*-----------------------------------------------------*\ - | Copy in LED index | - \*-----------------------------------------------------*/ - memcpy(&led_idx, &data_buf[0], sizeof(led_idx)); - - /*-----------------------------------------------------*\ - | Check if we aren't reading beyond the list of leds. | - \*-----------------------------------------------------*/ - if(((size_t)led_idx) > leds.size()) - { - /*-------------------------------------------------*\ - | Unlock access mutex | - \*-------------------------------------------------*/ - AccessMutex.unlock(); - return; - } - - /*-----------------------------------------------------*\ - | Copy in LED color | - \*-----------------------------------------------------*/ - memcpy(&colors[led_idx], &data_buf[sizeof(led_idx)], sizeof(RGBColor)); - - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock(); -} - -unsigned char * RGBController::GetSegmentDescription(int zone, segment new_segment) -{ - unsigned int data_ptr = 0; - unsigned int data_size = 0; - - /*-----------------------------------------------------*\ - | Lock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.lock_shared(); - - /*-----------------------------------------------------*\ - | Length of data size | - \*-----------------------------------------------------*/ - data_size += sizeof(data_size); - - /*-----------------------------------------------------*\ - | Length of zone index | - \*-----------------------------------------------------*/ - data_size += sizeof(zone); - - /*-----------------------------------------------------*\ - | Length of segment name string | - \*-----------------------------------------------------*/ - data_size += sizeof(unsigned short); - - /*-----------------------------------------------------*\ - | Segment name string data | - \*-----------------------------------------------------*/ - data_size += (unsigned int)strlen(new_segment.name.c_str()) + 1; - - data_size += sizeof(new_segment.type); - data_size += sizeof(new_segment.start_idx); - data_size += sizeof(new_segment.leds_count); - - /*-----------------------------------------------------*\ - | Create data buffer | - \*-----------------------------------------------------*/ - unsigned char *data_buf = new unsigned char[data_size]; - - /*-----------------------------------------------------*\ - | Copy in data size | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &data_size, sizeof(data_size)); - data_ptr += sizeof(data_size); - - /*-----------------------------------------------------*\ - | Copy in zone index | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zone, sizeof(zone)); - data_ptr += sizeof(zone); - - /*-----------------------------------------------------*\ - | Length of segment name string | - \*-----------------------------------------------------*/ - unsigned short segment_name_length = (unsigned short)strlen(new_segment.name.c_str()) + 1; - - memcpy(&data_buf[data_ptr], &segment_name_length, sizeof(segment_name_length)); - data_ptr += sizeof(segment_name_length); - - /*-----------------------------------------------------*\ - | Segment name string data | - \*-----------------------------------------------------*/ - strcpy((char *)&data_buf[data_ptr], new_segment.name.c_str()); - data_ptr += segment_name_length; - - /*-----------------------------------------------------*\ - | Segment type data | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &new_segment.type, sizeof(new_segment.type)); - data_ptr += sizeof(new_segment.type); - - /*-----------------------------------------------------*\ - | Segment start index data | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &new_segment.start_idx, sizeof(new_segment.start_idx)); - data_ptr += sizeof(new_segment.start_idx); - - /*-----------------------------------------------------*\ - | Segment LED count data | - \*-----------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &new_segment.leds_count, sizeof(new_segment.leds_count)); - data_ptr += sizeof(new_segment.leds_count); - - /*-----------------------------------------------------*\ - | Unlock access mutex | - \*-----------------------------------------------------*/ - AccessMutex.unlock_shared(); - - return(data_buf); -} - -void RGBController::SetSegmentDescription(unsigned char* data_buf) -{ - unsigned int data_ptr = sizeof(unsigned int); - - /*-----------------------------------------------------*\ - | Copy in zone index | - \*-----------------------------------------------------*/ - unsigned int zone_idx; - memcpy(&zone_idx, &data_buf[data_ptr], sizeof(zone_idx)); - data_ptr += sizeof(zone_idx); - - /*-----------------------------------------------------*\ - | Length of segment name string | - \*-----------------------------------------------------*/ - unsigned short segment_name_length; - memcpy(&segment_name_length, &data_buf[data_ptr], sizeof(segment_name_length)); - data_ptr += sizeof(segment_name_length); - - /*-----------------------------------------------------*\ - | Segment name string data | - \*-----------------------------------------------------*/ - char * segment_name = new char[segment_name_length]; - memcpy(segment_name, &data_buf[data_ptr], segment_name_length); - data_ptr += segment_name_length; - - /*-----------------------------------------------------*\ - | Segment type data | - \*-----------------------------------------------------*/ - zone_type segment_type; - memcpy(&segment_type, &data_buf[data_ptr], sizeof(segment_type)); - data_ptr += sizeof(segment_type); - - /*-----------------------------------------------------*\ - | Segment start index data | - \*-----------------------------------------------------*/ - unsigned int segment_start_idx; - memcpy(&segment_start_idx, &data_buf[data_ptr], sizeof(segment_start_idx)); - data_ptr += sizeof(segment_start_idx); - - /*-----------------------------------------------------*\ - | Segment LED count data | - \*-----------------------------------------------------*/ - unsigned int segment_leds_count; - memcpy(&segment_leds_count, &data_buf[data_ptr], sizeof(segment_leds_count)); - data_ptr += sizeof(segment_leds_count); - - /*-----------------------------------------------------*\ - | Add new segment | - \*-----------------------------------------------------*/ - segment new_segment; - - new_segment.name = segment_name; - new_segment.type = segment_type; - new_segment.start_idx = segment_start_idx; - new_segment.leds_count = segment_leds_count; - - AddSegment(zone_idx, new_segment); - - delete[] segment_name; -} - /*---------------------------------------------------------*\ | JSON Description Functions | \*---------------------------------------------------------*/ diff --git a/RGBController/RGBController.h b/RGBController/RGBController.h index 31f6c4bdf..2ff2290af 100644 --- a/RGBController/RGBController.h +++ b/RGBController/RGBController.h @@ -284,189 +284,200 @@ public: /*-----------------------------------------------------*\ | Controller Information | \*-----------------------------------------------------*/ - virtual std::string GetName() = 0; - virtual std::string GetVendor() = 0; - virtual std::string GetDescription() = 0; - virtual std::string GetVersion() = 0; - virtual std::string GetSerial() = 0; - virtual std::string GetLocation() = 0; + virtual std::string GetName() = 0; + virtual std::string GetVendor() = 0; + virtual std::string GetDescription() = 0; + virtual std::string GetVersion() = 0; + virtual std::string GetSerial() = 0; + virtual std::string GetLocation() = 0; - virtual device_type GetDeviceType() = 0; - virtual unsigned int GetFlags() = 0; + virtual device_type GetDeviceType() = 0; + virtual unsigned int GetFlags() = 0; /*-----------------------------------------------------*\ | Hidden Flag Functions | \*-----------------------------------------------------*/ - virtual bool GetHidden() = 0; - virtual void SetHidden(bool hidden) = 0; + virtual bool GetHidden() = 0; + virtual void SetHidden(bool hidden) = 0; /*-----------------------------------------------------*\ | Zone Functions | \*-----------------------------------------------------*/ - virtual int GetZoneActiveMode(unsigned int zone) = 0; - virtual RGBColor GetZoneColor(unsigned int zone, unsigned int color_index) = 0; - virtual RGBColor* GetZoneColorsPointer(unsigned int zone) = 0; - virtual std::size_t GetZoneCount() = 0; - virtual unsigned int GetZoneFlags(unsigned int zone) = 0; - virtual unsigned int GetZoneLEDsCount(unsigned int zone) = 0; - virtual unsigned int GetZoneLEDsMax(unsigned int zone) = 0; - virtual unsigned int GetZoneLEDsMin(unsigned int zone) = 0; - virtual bool GetZoneMatrixMapAvailable(unsigned int zone) = 0; - virtual unsigned int GetZoneMatrixMapHeight(unsigned int zone) = 0; - virtual const unsigned int * GetZoneMatrixMap(unsigned int zone) = 0; - virtual unsigned int GetZoneMatrixMapWidth(unsigned int zone) = 0; - virtual std::size_t GetZoneModeCount(unsigned int zone) = 0; - virtual unsigned int GetZoneModeBrightness(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeBrightnessMax(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeBrightnessMin(unsigned int zone, unsigned int mode) = 0; - virtual RGBColor GetZoneModeColor(unsigned int zone, unsigned int mode, unsigned int color_index) = 0; - virtual unsigned int GetZoneModeColorMode(unsigned int zone, unsigned int mode) = 0; - virtual std::size_t GetZoneModeColorsCount(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeColorsMax(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeColorsMin(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeDirection(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeFlags(unsigned int zone, unsigned int mode) = 0; - virtual std::string GetZoneModeName(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeSpeed(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeSpeedMax(unsigned int zone, unsigned int mode) = 0; - virtual unsigned int GetZoneModeSpeedMin(unsigned int zone, unsigned int mode) = 0; - virtual int GetZoneModeValue(unsigned int zone, unsigned int mode) = 0; - virtual std::string GetZoneName(unsigned int zone) = 0; - virtual std::size_t GetZoneSegmentCount(unsigned int zone) = 0; - virtual unsigned int GetZoneSegmentLEDsCount(unsigned int zone, unsigned int segment) = 0; - virtual bool GetZoneSegmentMatrixMapAvailable(unsigned int zone, unsigned int segment) = 0; - virtual unsigned int GetZoneSegmentMatrixMapHeight(unsigned int zone, unsigned int segment) = 0; - virtual const unsigned int * GetZoneSegmentMatrixMap(unsigned int zone, unsigned int segment) = 0; - virtual unsigned int GetZoneSegmentMatrixMapWidth(unsigned int zone, unsigned int segment) = 0; - virtual std::string GetZoneSegmentName(unsigned int zone, unsigned int segment) = 0; - virtual unsigned int GetZoneSegmentStartIndex(unsigned int zone, unsigned int segment) = 0; - virtual unsigned int GetZoneSegmentType(unsigned int zone, unsigned int segment) = 0; - virtual unsigned int GetZoneStartIndex(unsigned int zone) = 0; - virtual zone_type GetZoneType(unsigned int zone) = 0; + virtual int GetZoneActiveMode(unsigned int zone) = 0; + virtual RGBColor GetZoneColor(unsigned int zone, unsigned int color_index) = 0; + virtual RGBColor* GetZoneColorsPointer(unsigned int zone) = 0; + virtual std::size_t GetZoneCount() = 0; + virtual unsigned int GetZoneFlags(unsigned int zone) = 0; + virtual unsigned int GetZoneLEDsCount(unsigned int zone) = 0; + virtual unsigned int GetZoneLEDsMax(unsigned int zone) = 0; + virtual unsigned int GetZoneLEDsMin(unsigned int zone) = 0; + virtual bool GetZoneMatrixMapAvailable(unsigned int zone) = 0; + virtual unsigned int GetZoneMatrixMapHeight(unsigned int zone) = 0; + virtual const unsigned int * GetZoneMatrixMap(unsigned int zone) = 0; + virtual unsigned int GetZoneMatrixMapWidth(unsigned int zone) = 0; + virtual std::size_t GetZoneModeCount(unsigned int zone) = 0; + virtual unsigned int GetZoneModeBrightness(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeBrightnessMax(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeBrightnessMin(unsigned int zone, unsigned int mode) = 0; + virtual RGBColor GetZoneModeColor(unsigned int zone, unsigned int mode, unsigned int color_index) = 0; + virtual unsigned int GetZoneModeColorMode(unsigned int zone, unsigned int mode) = 0; + virtual std::size_t GetZoneModeColorsCount(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeColorsMax(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeColorsMin(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeDirection(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeFlags(unsigned int zone, unsigned int mode) = 0; + virtual std::string GetZoneModeName(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeSpeed(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeSpeedMax(unsigned int zone, unsigned int mode) = 0; + virtual unsigned int GetZoneModeSpeedMin(unsigned int zone, unsigned int mode) = 0; + virtual int GetZoneModeValue(unsigned int zone, unsigned int mode) = 0; + virtual std::string GetZoneName(unsigned int zone) = 0; + virtual std::size_t GetZoneSegmentCount(unsigned int zone) = 0; + virtual unsigned int GetZoneSegmentLEDsCount(unsigned int zone, unsigned int segment) = 0; + virtual bool GetZoneSegmentMatrixMapAvailable(unsigned int zone, unsigned int segment) = 0; + virtual unsigned int GetZoneSegmentMatrixMapHeight(unsigned int zone, unsigned int segment) = 0; + virtual const unsigned int * GetZoneSegmentMatrixMap(unsigned int zone, unsigned int segment) = 0; + virtual unsigned int GetZoneSegmentMatrixMapWidth(unsigned int zone, unsigned int segment) = 0; + virtual std::string GetZoneSegmentName(unsigned int zone, unsigned int segment) = 0; + virtual unsigned int GetZoneSegmentStartIndex(unsigned int zone, unsigned int segment) = 0; + virtual unsigned int GetZoneSegmentType(unsigned int zone, unsigned int segment) = 0; + virtual unsigned int GetZoneStartIndex(unsigned int zone) = 0; + virtual zone_type GetZoneType(unsigned int zone) = 0; - virtual unsigned int GetLEDsInZone(unsigned int zone) = 0; + virtual unsigned int GetLEDsInZone(unsigned int zone) = 0; - virtual void SetZoneActiveMode(unsigned int zone, int mode) = 0; - virtual void SetZoneModeBrightness(unsigned int zone, unsigned int mode, unsigned int brightness) = 0; - virtual void SetZoneModeColor(unsigned int zone, unsigned int mode, unsigned int color_index, RGBColor color) = 0; - virtual void SetZoneModeColorMode(unsigned int zone, unsigned int mode, unsigned int color_mode) = 0; - virtual void SetZoneModeColorsCount(unsigned int zone, unsigned int mode, std::size_t count) = 0; - virtual void SetZoneModeDirection(unsigned int zone, unsigned int mode, unsigned int direction) = 0; - virtual void SetZoneModeSpeed(unsigned int zone, unsigned int mode, unsigned int speed) = 0; + virtual void SetZoneActiveMode(unsigned int zone, int mode) = 0; + virtual void SetZoneModeBrightness(unsigned int zone, unsigned int mode, unsigned int brightness) = 0; + virtual void SetZoneModeColor(unsigned int zone, unsigned int mode, unsigned int color_index, RGBColor color) = 0; + virtual void SetZoneModeColorMode(unsigned int zone, unsigned int mode, unsigned int color_mode) = 0; + virtual void SetZoneModeColorsCount(unsigned int zone, unsigned int mode, std::size_t count) = 0; + virtual void SetZoneModeDirection(unsigned int zone, unsigned int mode, unsigned int direction) = 0; + virtual void SetZoneModeSpeed(unsigned int zone, unsigned int mode, unsigned int speed) = 0; - virtual bool SupportsPerZoneModes() = 0; + virtual bool SupportsPerZoneModes() = 0; /*-----------------------------------------------------*\ | Mode Functions | \*-----------------------------------------------------*/ - virtual std::size_t GetModeCount() = 0; - virtual unsigned int GetModeBrightness(unsigned int mode) = 0; - virtual unsigned int GetModeBrightnessMax(unsigned int mode) = 0; - virtual unsigned int GetModeBrightnessMin(unsigned int mode) = 0; - virtual RGBColor GetModeColor(unsigned int mode, unsigned int color_index) = 0; - virtual unsigned int GetModeColorMode(unsigned int mode) = 0; - virtual std::size_t GetModeColorsCount(unsigned int mode) = 0; - virtual unsigned int GetModeColorsMax(unsigned int mode) = 0; - virtual unsigned int GetModeColorsMin(unsigned int mode) = 0; - virtual unsigned int GetModeDirection(unsigned int mode) = 0; - virtual unsigned int GetModeFlags(unsigned int mode) = 0; - virtual std::string GetModeName(unsigned int mode) = 0; - virtual unsigned int GetModeSpeed(unsigned int mode) = 0; - virtual unsigned int GetModeSpeedMax(unsigned int mode) = 0; - virtual unsigned int GetModeSpeedMin(unsigned int mode) = 0; - virtual int GetModeValue(unsigned int mode) = 0; + virtual std::size_t GetModeCount() = 0; + virtual unsigned int GetModeBrightness(unsigned int mode) = 0; + virtual unsigned int GetModeBrightnessMax(unsigned int mode) = 0; + virtual unsigned int GetModeBrightnessMin(unsigned int mode) = 0; + virtual RGBColor GetModeColor(unsigned int mode, unsigned int color_index) = 0; + virtual unsigned int GetModeColorMode(unsigned int mode) = 0; + virtual std::size_t GetModeColorsCount(unsigned int mode) = 0; + virtual unsigned int GetModeColorsMax(unsigned int mode) = 0; + virtual unsigned int GetModeColorsMin(unsigned int mode) = 0; + virtual unsigned int GetModeDirection(unsigned int mode) = 0; + virtual unsigned int GetModeFlags(unsigned int mode) = 0; + virtual std::string GetModeName(unsigned int mode) = 0; + virtual unsigned int GetModeSpeed(unsigned int mode) = 0; + virtual unsigned int GetModeSpeedMax(unsigned int mode) = 0; + virtual unsigned int GetModeSpeedMin(unsigned int mode) = 0; + virtual int GetModeValue(unsigned int mode) = 0; - virtual void SetModeBrightness(unsigned int mode, unsigned int brightness) = 0; - virtual void SetModeColor(unsigned int mode, unsigned int color_index, RGBColor color) = 0; - virtual void SetModeColorMode(unsigned int mode, unsigned int color_mode) = 0; - virtual void SetModeColorsCount(unsigned int mode, std::size_t count) = 0; - virtual void SetModeDirection(unsigned int mode, unsigned int direction) = 0; - virtual void SetModeSpeed(unsigned int mode, unsigned int speed) = 0; + virtual void SetModeBrightness(unsigned int mode, unsigned int brightness) = 0; + virtual void SetModeColor(unsigned int mode, unsigned int color_index, RGBColor color) = 0; + virtual void SetModeColorMode(unsigned int mode, unsigned int color_mode) = 0; + virtual void SetModeColorsCount(unsigned int mode, std::size_t count) = 0; + virtual void SetModeDirection(unsigned int mode, unsigned int direction) = 0; + virtual void SetModeSpeed(unsigned int mode, unsigned int speed) = 0; - virtual int GetActiveMode() = 0; - virtual void SetActiveMode(int mode) = 0; - virtual void SetCustomMode() = 0; + virtual int GetActiveMode() = 0; + virtual void SetActiveMode(int mode) = 0; + virtual void SetCustomMode() = 0; /*-----------------------------------------------------*\ | LED Functions | \*-----------------------------------------------------*/ - virtual std::size_t GetLEDCount() = 0; - virtual std::string GetLEDName(unsigned int led) = 0; - virtual unsigned int GetLEDValue(unsigned int led) = 0; + virtual std::size_t GetLEDCount() = 0; + virtual std::string GetLEDName(unsigned int led) = 0; + virtual unsigned int GetLEDValue(unsigned int led) = 0; - virtual std::string GetLEDDisplayName(unsigned int led) = 0; + virtual std::string GetLEDDisplayName(unsigned int led) = 0; /*-----------------------------------------------------*\ | Color Functions | \*-----------------------------------------------------*/ - virtual RGBColor GetColor(unsigned int led) = 0; - virtual RGBColor* GetColorsPointer() = 0; - virtual void SetColor(unsigned int led, RGBColor color) = 0; + virtual RGBColor GetColor(unsigned int led) = 0; + virtual RGBColor* GetColorsPointer() = 0; + virtual void SetColor(unsigned int led, RGBColor color) = 0; - virtual void SetAllColors(RGBColor color) = 0; - virtual void SetAllZoneColors(int zone, RGBColor color) = 0; + virtual void SetAllColors(RGBColor color) = 0; + virtual void SetAllZoneColors(int zone, RGBColor color) = 0; + + virtual unsigned char * GetSingleLEDColorDescription(int led) = 0; + virtual unsigned char * GetZoneColorDescription(int zone) = 0; + + virtual void SetSingleLEDColorDescription(unsigned char* data_buf) = 0; + virtual void SetZoneColorDescription(unsigned char* data_buf) = 0; /*-----------------------------------------------------*\ | Serialized Description Functions | \*-----------------------------------------------------*/ - virtual unsigned char * GetDeviceDescription(unsigned int protocol_version) = 0; - virtual void ReadDeviceDescription(unsigned char* data_buf, unsigned int protocol_version) = 0; + virtual unsigned char * GetColorDescriptionData(unsigned char* data_ptr, unsigned int protocol_version) = 0; + virtual unsigned int GetColorDescriptionSize(unsigned int protocol_version) = 0; + virtual unsigned char * GetDeviceDescriptionData(unsigned char* data_ptr, unsigned int protocol_version) = 0; + virtual unsigned int GetDeviceDescriptionSize(unsigned int protocol_version) = 0; + virtual unsigned char * GetLEDDescriptionData(unsigned char* data_ptr, led led, unsigned int protocol_version) = 0; + virtual unsigned int GetLEDDescriptionSize(led led, unsigned int protocol_version) = 0; + virtual unsigned char * GetMatrixMapDescriptionData(unsigned char* data_ptr, matrix_map_type* matrix_map, unsigned int protocol_version) = 0; + virtual unsigned int GetMatrixMapDescriptionSize(matrix_map_type* matrix_map, unsigned int protocol_version) = 0; + virtual unsigned char * GetModeDescriptionData(unsigned char* data_ptr, mode mode, unsigned int protocol_version) = 0; + virtual unsigned int GetModeDescriptionSize(mode mode, unsigned int protocol_version) = 0; + virtual unsigned char * GetSegmentDescriptionData(unsigned char* data_ptr, segment segment, unsigned int protocol_version) = 0; + virtual unsigned int GetSegmentDescriptionSize(segment segment, unsigned int protocol_version) = 0; + virtual unsigned char * GetZoneDescriptionData(unsigned char* data_ptr, zone zone, unsigned int protocol_version) = 0; + virtual unsigned int GetZoneDescriptionSize(zone zone, unsigned int protocol_version) = 0; - virtual unsigned char * GetModeDescription(int mode, unsigned int protocol_version) = 0; - virtual void SetModeDescription(unsigned char* data_buf, unsigned int protocol_version) = 0; - - virtual unsigned char * GetColorDescription() = 0; - virtual void SetColorDescription(unsigned char* data_buf) = 0; - - virtual unsigned char * GetZoneColorDescription(int zone) = 0; - virtual void SetZoneColorDescription(unsigned char* data_buf) = 0; - - virtual unsigned char * GetSingleLEDColorDescription(int led) = 0; - virtual void SetSingleLEDColorDescription(unsigned char* data_buf) = 0; - - virtual unsigned char * GetSegmentDescription(int zone, segment new_segment) = 0; - virtual void SetSegmentDescription(unsigned char* data_buf) = 0; + virtual unsigned char* SetColorDescription(unsigned char* data_ptr, unsigned int protocol_version, bool resize = false) = 0; + virtual unsigned char* SetDeviceDescription(unsigned char* data_ptr, unsigned int protocol_version) = 0; + virtual unsigned char* SetLEDDescription(unsigned char* data_ptr, led* led, unsigned int protocol_version) = 0; + virtual unsigned char* SetMatrixMapDescription(unsigned char* data_ptr, matrix_map_type* matrix_map, unsigned int protocol_version) = 0; + virtual unsigned char* SetModeDescription(unsigned char* data_ptr, mode* mode, unsigned int protocol_version) = 0; + virtual unsigned char* SetSegmentDescription(unsigned char* data_ptr, segment* segment, unsigned int protocol_version) = 0; + virtual unsigned char* SetZoneDescription(unsigned char* data_ptr, zone* zone, unsigned int protocol_version) = 0; /*-----------------------------------------------------*\ | JSON Description Functions | \*-----------------------------------------------------*/ - virtual nlohmann::json GetDeviceDescriptionJSON() = 0; - virtual nlohmann::json GetLEDDescriptionJSON(led led) = 0; - virtual nlohmann::json GetMatrixMapDescriptionJSON(matrix_map_type* matrix_map) = 0; - virtual nlohmann::json GetModeDescriptionJSON(mode mode) = 0; - virtual nlohmann::json GetSegmentDescriptionJSON(segment segment) = 0; - virtual nlohmann::json GetZoneDescriptionJSON(zone zone) = 0; + virtual nlohmann::json GetDeviceDescriptionJSON() = 0; + virtual nlohmann::json GetLEDDescriptionJSON(led led) = 0; + virtual nlohmann::json GetMatrixMapDescriptionJSON(matrix_map_type* matrix_map) = 0; + virtual nlohmann::json GetModeDescriptionJSON(mode mode) = 0; + virtual nlohmann::json GetSegmentDescriptionJSON(segment segment) = 0; + virtual nlohmann::json GetZoneDescriptionJSON(zone zone) = 0; - virtual void SetDeviceDescriptionJSON(nlohmann::json controller_json) = 0; - virtual led SetLEDDescriptionJSON(nlohmann::json led_json) = 0; - virtual matrix_map_type* SetMatrixMapDescriptionJSON(nlohmann::json matrix_map_json) = 0; - virtual mode SetModeDescriptionJSON(nlohmann::json mode_json) = 0; - virtual segment SetSegmentDescriptionJSON(nlohmann::json segment_json) = 0; - virtual zone SetZoneDescriptionJSON(nlohmann::json zone_json) = 0; + virtual void SetDeviceDescriptionJSON(nlohmann::json controller_json) = 0; + virtual led SetLEDDescriptionJSON(nlohmann::json led_json) = 0; + virtual matrix_map_type* SetMatrixMapDescriptionJSON(nlohmann::json matrix_map_json) = 0; + virtual mode SetModeDescriptionJSON(nlohmann::json mode_json) = 0; + virtual segment SetSegmentDescriptionJSON(nlohmann::json segment_json) = 0; + virtual zone SetZoneDescriptionJSON(nlohmann::json zone_json) = 0; /*-----------------------------------------------------*\ | Update Callback Functions | \*-----------------------------------------------------*/ - virtual void RegisterUpdateCallback(RGBControllerCallback new_callback, void * new_callback_arg) = 0; - virtual void UnregisterUpdateCallback(void * callback_arg) = 0; - virtual void ClearCallbacks() = 0; - virtual void SignalUpdate(unsigned int update_reason) = 0; + virtual void RegisterUpdateCallback(RGBControllerCallback new_callback, void * new_callback_arg) = 0; + virtual void UnregisterUpdateCallback(void * callback_arg) = 0; + virtual void ClearCallbacks() = 0; + virtual void SignalUpdate(unsigned int update_reason) = 0; /*-----------------------------------------------------*\ | Device Update Functions | \*-----------------------------------------------------*/ - virtual void UpdateLEDs() = 0; - virtual void UpdateZoneLEDs(int zone) = 0; - virtual void UpdateSingleLED(int led) = 0; + virtual void UpdateLEDs() = 0; + virtual void UpdateZoneLEDs(int zone) = 0; + virtual void UpdateSingleLED(int led) = 0; - virtual void UpdateMode() = 0; - virtual void UpdateZoneMode(int zone) = 0; - virtual void SaveMode() = 0; + virtual void UpdateMode() = 0; + virtual void UpdateZoneMode(int zone) = 0; + virtual void SaveMode() = 0; - virtual void ClearSegments(int zone) = 0; - virtual void AddSegment(int zone, segment new_segment) = 0; + virtual void ClearSegments(int zone) = 0; + virtual void AddSegment(int zone, segment new_segment) = 0; - virtual void ResizeZone(int zone, int new_size) = 0; + virtual void ResizeZone(int zone, int new_size) = 0; }; class RGBController : public RGBControllerInterface @@ -602,26 +613,37 @@ public: void SetAllColors(RGBColor color); void SetAllZoneColors(int zone, RGBColor color); + unsigned char * GetSingleLEDColorDescription(int led); + unsigned char * GetZoneColorDescription(int zone); + + void SetSingleLEDColorDescription(unsigned char* data_buf); + void SetZoneColorDescription(unsigned char* data_buf); + /*-----------------------------------------------------*\ | Serialized Description Functions | \*-----------------------------------------------------*/ - unsigned char * GetDeviceDescription(unsigned int protocol_version); - void ReadDeviceDescription(unsigned char* data_buf, unsigned int protocol_version); + unsigned char * GetColorDescriptionData(unsigned char* data_ptr, unsigned int protocol_version); + unsigned int GetColorDescriptionSize(unsigned int protocol_version); + unsigned char * GetDeviceDescriptionData(unsigned char* data_ptr, unsigned int protocol_version); + unsigned int GetDeviceDescriptionSize(unsigned int protocol_version); + unsigned char * GetLEDDescriptionData(unsigned char* data_ptr, led led, unsigned int protocol_version); + unsigned int GetLEDDescriptionSize(led led, unsigned int protocol_version); + unsigned char * GetMatrixMapDescriptionData(unsigned char* data_ptr, matrix_map_type* matrix_map, unsigned int protocol_version); + unsigned int GetMatrixMapDescriptionSize(matrix_map_type* matrix_map, unsigned int protocol_version); + unsigned char * GetModeDescriptionData(unsigned char* data_ptr, mode mode, unsigned int protocol_version); + unsigned int GetModeDescriptionSize(mode mode, unsigned int protocol_version); + unsigned char * GetSegmentDescriptionData(unsigned char* data_ptr, segment segment, unsigned int protocol_version); + unsigned int GetSegmentDescriptionSize(segment segment, unsigned int protocol_version); + unsigned char * GetZoneDescriptionData(unsigned char* data_ptr, zone zone, unsigned int protocol_version); + unsigned int GetZoneDescriptionSize(zone zone, unsigned int protocol_version); - unsigned char * GetModeDescription(int mode, unsigned int protocol_version); - void SetModeDescription(unsigned char* data_buf, unsigned int protocol_version); - - unsigned char * GetColorDescription(); - void SetColorDescription(unsigned char* data_buf); - - unsigned char * GetZoneColorDescription(int zone); - void SetZoneColorDescription(unsigned char* data_buf); - - unsigned char * GetSingleLEDColorDescription(int led); - void SetSingleLEDColorDescription(unsigned char* data_buf); - - unsigned char * GetSegmentDescription(int zone, segment new_segment); - void SetSegmentDescription(unsigned char* data_buf); + unsigned char* SetColorDescription(unsigned char* data_ptr, unsigned int protocol_version, bool resize = false); + unsigned char* SetDeviceDescription(unsigned char* data_ptr, unsigned int protocol_version); + unsigned char* SetLEDDescription(unsigned char* data_ptr, led* led, unsigned int protocol_version); + unsigned char* SetMatrixMapDescription(unsigned char* data_ptr, matrix_map_type* matrix_map, unsigned int protocol_version); + unsigned char* SetModeDescription(unsigned char* data_ptr, mode* mode, unsigned int protocol_version); + unsigned char* SetSegmentDescription(unsigned char* data_ptr, segment* segment, unsigned int protocol_version); + unsigned char* SetZoneDescription(unsigned char* data_ptr, zone* zone, unsigned int protocol_version); /*-----------------------------------------------------*\ | JSON Description Functions | @@ -707,6 +729,11 @@ protected: std::vector modes; /* Modes */ std::vector zones; /* Zones */ + /*-----------------------------------------------------*\ + | Access mutex variables | + \*-----------------------------------------------------*/ + std::shared_mutex AccessMutex; + /*-----------------------------------------------------*\ | Functions not part of interface for internal use only | \*-----------------------------------------------------*/ @@ -729,16 +756,12 @@ private: std::vector UpdateCallbacks; std::vector UpdateCallbackArgs; - /*-----------------------------------------------------*\ - | Access mutex variables | - \*-----------------------------------------------------*/ - std::shared_mutex AccessMutex; - /*-----------------------------------------------------*\ | Certain internal OpenRGB framework classes can modify | | protected members | \*-----------------------------------------------------*/ friend class NetworkClient; + friend class NetworkServer; friend class ProfileManager; friend class ResourceManager; }; diff --git a/RGBController/RGBController_Network.cpp b/RGBController/RGBController_Network.cpp index de2207ba0..fd1532453 100644 --- a/RGBController/RGBController_Network.cpp +++ b/RGBController/RGBController_Network.cpp @@ -20,11 +20,6 @@ RGBController_Network::RGBController_Network(NetworkClient * client_ptr, unsigne dev_idx = dev_idx_val; } -void RGBController_Network::SetupZones() -{ - //Don't send anything, this function should only process on host -} - void RGBController_Network::ClearSegments(int zone) { client->SendRequest_RGBController_ClearSegments(dev_idx, zone); @@ -35,14 +30,54 @@ void RGBController_Network::ClearSegments(int zone) void RGBController_Network::AddSegment(int zone, segment new_segment) { - unsigned char * data = GetSegmentDescription(zone, new_segment); - unsigned int size; + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.lock_shared(); - memcpy(&size, &data[0], sizeof(unsigned int)); + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; - client->SendRequest_RGBController_AddSegment(dev_idx, data, size); + /*-----------------------------------------------------*\ + | Calculate data size | + \*-----------------------------------------------------*/ + data_size += sizeof(data_size); + data_size += sizeof(zone); + data_size += GetSegmentDescriptionSize(new_segment, client->GetProtocolVersion()); - delete[] data; + /*-----------------------------------------------------*\ + | Create data buffer | + \*-----------------------------------------------------*/ + unsigned char * data_buf = new unsigned char[data_size]; + unsigned char * data_ptr = data_buf; + + /*-----------------------------------------------------*\ + | Copy in data size | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &data_size, sizeof(data_size)); + data_ptr += sizeof(data_size); + + /*-----------------------------------------------------*\ + | Copy in zone index | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &zone, sizeof(zone)); + data_ptr += sizeof(zone); + + /*-----------------------------------------------------*\ + | Copy in segment description | + \*-----------------------------------------------------*/ + data_ptr = GetSegmentDescriptionData(data_ptr, new_segment, client->GetProtocolVersion()); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.unlock_shared(); + + client->SendRequest_RGBController_AddSegment(dev_idx, data_buf, data_size); + + delete[] data_buf; client->SendRequest_ControllerData(dev_idx); client->WaitOnControllerData(); @@ -58,7 +93,7 @@ void RGBController_Network::ResizeZone(int zone, int new_size) void RGBController_Network::DeviceUpdateLEDs() { - unsigned char * data = GetColorDescription(); + unsigned char * data = CreateUpdateLEDsPacket(client->GetProtocolVersion()); unsigned int size; memcpy(&size, &data[0], sizeof(unsigned int)); @@ -99,22 +134,34 @@ void RGBController_Network::SetCustomMode() void RGBController_Network::DeviceUpdateMode() { - unsigned char * data = GetModeDescription(active_mode, client->GetProtocolVersion()); - unsigned int size; + unsigned char * data; + unsigned int size; - memcpy(&size, &data[0], sizeof(unsigned int)); + data = CreateUpdateModePacket(active_mode, &size, client->GetProtocolVersion()); client->SendRequest_RGBController_UpdateMode(dev_idx, data, size); delete[] data; } +void RGBController_Network::DeviceUpdateZoneMode(int zone) +{ + unsigned char * data; + unsigned int size; + + data = CreateUpdateZoneModePacket(zone, zones[zone].active_mode, &size, client->GetProtocolVersion()); + + client->SendRequest_RGBController_UpdateZoneMode(dev_idx, data, size); + + delete[] data; +} + void RGBController_Network::DeviceSaveMode() { - unsigned char * data = GetModeDescription(active_mode, client->GetProtocolVersion()); - unsigned int size; + unsigned char * data; + unsigned int size; - memcpy(&size, &data[0], sizeof(unsigned int)); + data = CreateUpdateModePacket(active_mode, &size, client->GetProtocolVersion()); client->SendRequest_RGBController_SaveMode(dev_idx, data, size); @@ -134,3 +181,157 @@ void RGBController_Network::UpdateLEDs() { DeviceUpdateLEDs(); } + +unsigned char * RGBController_Network::CreateUpdateLEDsPacket(unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.lock_shared(); + + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + + /*-----------------------------------------------------*\ + | Calculate data size | + \*-----------------------------------------------------*/ + data_size += sizeof(data_size); + data_size += GetColorDescriptionSize(protocol_version); + + /*-----------------------------------------------------*\ + | Create data buffer | + \*-----------------------------------------------------*/ + unsigned char * data_buf = new unsigned char[data_size]; + unsigned char * data_ptr = data_buf; + + /*-----------------------------------------------------*\ + | Copy in data size | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &data_size, sizeof(data_size)); + data_ptr += sizeof(data_size); + + /*-----------------------------------------------------*\ + | Copy in color data | + \*-----------------------------------------------------*/ + data_ptr = GetColorDescriptionData(data_ptr, protocol_version); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.unlock_shared(); + + return(data_buf); +} + +unsigned char * RGBController_Network::CreateUpdateModePacket(int mode_idx, unsigned int* size, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.lock_shared(); + + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + + /*-----------------------------------------------------*\ + | Calculate data size | + \*-----------------------------------------------------*/ + data_size += sizeof(data_size); + data_size += sizeof(mode_idx); + data_size += GetModeDescriptionSize(modes[mode_idx], protocol_version); + + /*-----------------------------------------------------*\ + | Create data buffer | + \*-----------------------------------------------------*/ + unsigned char* data_buf = new unsigned char[data_size]; + unsigned char* data_ptr = data_buf; + + /*-----------------------------------------------------*\ + | Copy in data size | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &data_size, sizeof(data_size)); + data_ptr += sizeof(data_size); + + /*-----------------------------------------------------*\ + | Copy in mode index | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &mode_idx, sizeof(mode_idx)); + data_ptr += sizeof(mode_idx); + + /*-----------------------------------------------------*\ + | Copy in mode description | + \*-----------------------------------------------------*/ + data_ptr = GetModeDescriptionData(data_ptr, modes[mode_idx], protocol_version); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.unlock_shared(); + + *size = data_size; + + return(data_buf); +} + +unsigned char * RGBController_Network::CreateUpdateZoneModePacket(int zone_idx, int mode_idx, unsigned int* size, unsigned int protocol_version) +{ + /*-----------------------------------------------------*\ + | Lock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.lock_shared(); + + /*-----------------------------------------------------*\ + | Initialize variables | + \*-----------------------------------------------------*/ + unsigned int data_size = 0; + + /*-----------------------------------------------------*\ + | Calculate data size | + \*-----------------------------------------------------*/ + data_size += sizeof(data_size); + data_size += sizeof(zone_idx); + data_size += sizeof(mode_idx); + data_size += GetModeDescriptionSize(zones[zone_idx].modes[mode_idx], protocol_version); + + /*-----------------------------------------------------*\ + | Create data buffer | + \*-----------------------------------------------------*/ + unsigned char* data_buf = new unsigned char[data_size]; + unsigned char* data_ptr = data_buf; + + /*-----------------------------------------------------*\ + | Copy in data size | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &data_size, sizeof(data_size)); + data_ptr += sizeof(data_size); + + /*-----------------------------------------------------*\ + | Copy in zone index | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &zone_idx, sizeof(zone_idx)); + data_ptr += sizeof(zone_idx); + + /*-----------------------------------------------------*\ + | Copy in mode index | + \*-----------------------------------------------------*/ + memcpy(data_ptr, &mode_idx, sizeof(mode_idx)); + data_ptr += sizeof(mode_idx); + + /*-----------------------------------------------------*\ + | Copy in mode description | + \*-----------------------------------------------------*/ + data_ptr = GetModeDescriptionData(data_ptr, zones[zone_idx].modes[mode_idx], protocol_version); + + /*-----------------------------------------------------*\ + | Unlock access mutex | + \*-----------------------------------------------------*/ + AccessMutex.unlock_shared(); + + *size = data_size; + + return(data_buf); +} diff --git a/RGBController/RGBController_Network.h b/RGBController/RGBController_Network.h index 703af601a..47d9bcaa1 100644 --- a/RGBController/RGBController_Network.h +++ b/RGBController/RGBController_Network.h @@ -20,8 +20,6 @@ class RGBController_Network : public RGBController public: RGBController_Network(NetworkClient * client_ptr, unsigned int dev_idx_val); - void SetupZones(); - void ClearSegments(int zone); void AddSegment(int zone, segment new_segment); void ResizeZone(int zone, int new_size); @@ -32,6 +30,7 @@ public: void SetCustomMode(); void DeviceUpdateMode(); + void DeviceUpdateZoneMode(int zone); void DeviceSaveMode(); void UpdateLEDs(); @@ -39,4 +38,8 @@ public: private: NetworkClient * client; unsigned int dev_idx; + + unsigned char * CreateUpdateLEDsPacket(unsigned int protocol_version); + unsigned char * CreateUpdateModePacket(int mode_idx, unsigned int* size, unsigned int protocol_version); + unsigned char * CreateUpdateZoneModePacket(int zone_idx, int mode_idx, unsigned int* size, unsigned int protocol_version); }; diff --git a/ResourceManager.cpp b/ResourceManager.cpp index f2b09e3ed..e1626cb0b 100644 --- a/ResourceManager.cpp +++ b/ResourceManager.cpp @@ -194,6 +194,15 @@ ResourceManager::ResourceManager() server = new NetworkServer(rgb_controllers_hw); } + /*-----------------------------------------------------*\ + | Set server name | + \*-----------------------------------------------------*/ + std::string titleString = "OpenRGB "; + titleString.append(VERSION_STRING); + + server->SetName(titleString); + server->SetSettingsManager(settings_manager); + /*-----------------------------------------------------*\ | Enable legacy SDK workaround in server if configured | \*-----------------------------------------------------*/ @@ -1797,6 +1806,7 @@ void ResourceManager::InitCoroutine() | detection if the local server was connected | \*---------------------------------------------*/ auto_connection_active = true; + profile_manager->UpdateProfileList(); DisableDetection(); } @@ -2123,3 +2133,13 @@ bool ResourceManager::IsAnyDimmDetectorEnabled(json &detector_settings) } return false; } + +bool ResourceManager::IsLocalClient() +{ + return(auto_connection_active); +} + +NetworkClient* ResourceManager::GetLocalClient() +{ + return(auto_connection_client); +} diff --git a/ResourceManager.h b/ResourceManager.h index 208e1b5d4..43b5cbf04 100644 --- a/ResourceManager.h +++ b/ResourceManager.h @@ -199,6 +199,9 @@ public: void WaitForInitialization(); void WaitForDeviceDetection(); + bool IsLocalClient(); + NetworkClient* GetLocalClient(); + private: void UpdateDetectorSettings(); void SetupConfigurationDirectory(); diff --git a/SettingsManager.cpp b/SettingsManager.cpp index 640302b95..ba086618e 100644 --- a/SettingsManager.cpp +++ b/SettingsManager.cpp @@ -13,8 +13,22 @@ #include #include -#include "SettingsManager.h" #include "LogManager.h" +#include "NetworkClient.h" +#include "ResourceManager.h" +#include "SettingsManager.h" +#include "StringUtils.h" + +static const std::string ui_settings_keys[7] = +{ + "UserInterface", + "AutoStart", + "Theme", + "Plugins", + "Client", + "LogManager", + "Server" +}; SettingsManager::SettingsManager() { @@ -28,31 +42,113 @@ SettingsManager::~SettingsManager() json SettingsManager::GetSettings(std::string settings_key) { - /*-----------------------------------------------------*\ - | Check to see if the key exists in the settings store | - | and return the settings associated with the key if it | - | exists. We lock the mutex to protect the value from | - | changing while data is being read and copy before | - | unlocking. | - \*-----------------------------------------------------*/ json result; + bool ui_settings_key = false; - mutex.lock(); - if(settings_data.contains(settings_key)) + /*-----------------------------------------------------*\ + | Remove any excess null termination from settings key | + \*-----------------------------------------------------*/ + settings_key = StringUtils::remove_null_terminating_chars(settings_key); + + for(std::size_t settings_key_idx = 0; settings_key_idx < 7; settings_key_idx++) { - result = settings_data[settings_key]; + if(settings_key == ui_settings_keys[settings_key_idx]) + { + ui_settings_key = true; + break; + } } - mutex.unlock(); + if(!ui_settings_key && ResourceManager::get()->IsLocalClient()) + { + /*-------------------------------------------------*\ + | If this is a local client, request the settings | + | from the server | + \*-------------------------------------------------*/ + try + { + result = nlohmann::json::parse(ResourceManager::get()->GetLocalClient()->SettingsManager_GetSettings(settings_key)); + } + catch(...) + { + + } + } + else + { + /*-------------------------------------------------*\ + | Check to see if the key exists in the settings | + | store and return the settings associated with the | + | key if it exists. We lock the mutex to protect | + | the value from changing while data is being read | + | and copy before unlocking. | + \*-------------------------------------------------*/ + mutex.lock(); + if(settings_data.contains(settings_key)) + { + result = settings_data[settings_key]; + } + mutex.unlock(); + } return result; } void SettingsManager::SetSettings(std::string settings_key, json new_settings) { - mutex.lock(); - settings_data[settings_key] = new_settings; - mutex.unlock(); + bool ui_settings_key = false; + + /*-----------------------------------------------------*\ + | Remove any excess null termination from settings key | + \*-----------------------------------------------------*/ + settings_key = StringUtils::remove_null_terminating_chars(settings_key); + + for(std::size_t settings_key_idx = 0; settings_key_idx < 7; settings_key_idx++) + { + if(settings_key == ui_settings_keys[settings_key_idx]) + { + ui_settings_key = true; + break; + } + } + + if(!ui_settings_key && ResourceManager::get()->IsLocalClient()) + { + /*-------------------------------------------------*\ + | If this is a local client, request the settings | + | from the server | + \*-------------------------------------------------*/ + nlohmann::json settings_json; + + settings_json[settings_key] = new_settings; + + ResourceManager::get()->GetLocalClient()->SettingsManager_SetSettings(settings_json.dump()); + } + else + { + mutex.lock(); + settings_data[settings_key] = new_settings; + mutex.unlock(); + } +} + +void SettingsManager::SetSettingsFromJsonString(std::string settings_json_str) +{ + /*-----------------------------------------------------*\ + | Parse the JSON string | + \*-----------------------------------------------------*/ + nlohmann::json settings_json = nlohmann::json::parse(settings_json_str); + + /*-----------------------------------------------------*\ + | Get key/value pairs from JSON, call SetSettings for | + | each key. This use of `auto` is acceptable due to | + | how the JSON library implements iterators, the type | + | would change based on the library version. | + \*-----------------------------------------------------*/ + for(auto& element : settings_json.items()) + { + SetSettings(element.key(), element.value()); + } } void SettingsManager::LoadSettings(const filesystem::path& filename) @@ -109,6 +205,15 @@ void SettingsManager::LoadSettings(const filesystem::path& filename) void SettingsManager::SaveSettings() { + if(ResourceManager::get()->IsLocalClient()) + { + /*-------------------------------------------------*\ + | If this is a local client, save the settings on | + | the server | + \*-------------------------------------------------*/ + ResourceManager::get()->GetLocalClient()->SettingsManager_SaveSettings(); + } + mutex.lock(); std::ofstream settings_file(settings_filename, std::ios::out | std::ios::binary); diff --git a/SettingsManager.h b/SettingsManager.h index 0f4b991f7..db48af344 100644 --- a/SettingsManager.h +++ b/SettingsManager.h @@ -24,6 +24,7 @@ class SettingsManagerInterface public: virtual json GetSettings(std::string settings_key) = 0; virtual void SetSettings(std::string settings_key, json new_settings) = 0; + virtual void SetSettingsFromJsonString(std::string settings_json_str) = 0; virtual void LoadSettings(const filesystem::path& filename) = 0; virtual void SaveSettings() = 0; @@ -40,6 +41,7 @@ public: json GetSettings(std::string settings_key) override; void SetSettings(std::string settings_key, json new_settings) override; + void SetSettingsFromJsonString(std::string settings_json_str) override; void LoadSettings(const filesystem::path& filename) override; void SaveSettings() override; diff --git a/qt/OpenRGBClientInfoPage/OpenRGBClientInfoPage.cpp b/qt/OpenRGBClientInfoPage/OpenRGBClientInfoPage.cpp index c7a45940e..2ad42176e 100644 --- a/qt/OpenRGBClientInfoPage/OpenRGBClientInfoPage.cpp +++ b/qt/OpenRGBClientInfoPage/OpenRGBClientInfoPage.cpp @@ -131,11 +131,29 @@ void OpenRGBClientInfoPage::UpdateInfo() } /*-----------------------------------------------------*\ - | Create the top level tree widget items and display the| - | client IP addresses and protocol versions in them | + | Create the top level tree widget items | \*-----------------------------------------------------*/ QTreeWidgetItem* new_top_item = new QTreeWidgetItem(ui->ClientTree); - new_top_item->setText(0, QString::fromStdString(ResourceManager::get()->GetClients()[client_idx]->GetIP())); + + /*-----------------------------------------------------*\ + | First column, display the server IP and optionally | + | the server name if it exists | + \*-----------------------------------------------------*/ + std::string server_name = ResourceManager::get()->GetClients()[client_idx]->GetServerName(); + std::string ip = ResourceManager::get()->GetClients()[client_idx]->GetIP(); + + if(server_name == "") + { + new_top_item->setText(0, QString::fromStdString(ip)); + } + else + { + new_top_item->setText(0, QString::fromStdString(ip + ": " + server_name)); + } + + /*-----------------------------------------------------*\ + | Second column, display the protocol version | + \*-----------------------------------------------------*/ new_top_item->setText(1, QString::number(ResourceManager::get()->GetClients()[client_idx]->GetProtocolVersion())); /*-----------------------------------------------------*\ diff --git a/startup/startup.cpp b/startup/startup.cpp index 46f48af50..000d2c14a 100644 --- a/startup/startup.cpp +++ b/startup/startup.cpp @@ -52,6 +52,12 @@ int startup(int argc, char* argv[], unsigned int ret_flags) \*-----------------------------------------------------*/ int exitval = EXIT_SUCCESS; + /*-----------------------------------------------------*\ + | Before opening GUI, wait for automatic connection so | + | that settings and profiles can be updated from server | + \*-----------------------------------------------------*/ + ResourceManager::get()->WaitForInitialization(); + /*-----------------------------------------------------*\ | If the command line parser indicates that the GUI | | should run, or if there were no command line |