/* * Check that the string set/get methods work */ void DmxBufferTest::testStringGetSet() { const string data = "abcdefg"; DmxBuffer buffer; uint8_t *result = new uint8_t[data.length()]; unsigned int size = data.length(); // Check that setting works OLA_ASSERT_TRUE(buffer.Set(data)); OLA_ASSERT_EQ(data.length(), (size_t) buffer.Size()); OLA_ASSERT_EQ(data, buffer.Get()); buffer.Get(result, &size); OLA_ASSERT_EQ(data.length(), (size_t) size); OLA_ASSERT_EQ(0, memcmp(data.data(), result, size)); // Check the string constructor DmxBuffer string_buffer(data); OLA_ASSERT_TRUE(buffer == string_buffer); // Set with an empty string string data2; size = data.length(); OLA_ASSERT_TRUE(buffer.Set(data2)); OLA_ASSERT_EQ(data2.length(), (size_t) buffer.Size()); OLA_ASSERT_EQ(data2, buffer.Get()); buffer.Get(result, &size); OLA_ASSERT_EQ(data2.length(), (size_t) size); OLA_ASSERT_EQ(0, memcmp(data2.data(), result, size)); delete[] result; }
/* * Send 112 channels worth of data * @param buf a DmxBuffer with the data */ int MilInstWidget1463::Send112(const DmxBuffer &buffer) const { unsigned int channels = std::min((unsigned int) DMX_MAX_TRANSMIT_CHANNELS, buffer.Size()); uint8_t msg[channels * 2]; for (unsigned int i = 0; i <= channels; i++) { msg[i * 2] = i + 1; msg[(i * 2) + 1] = buffer.Get(i); OLA_DEBUG << "Setting " << (i + 1) << " to " << static_cast<int>(buffer.Get(i)); } return m_socket->Send(msg, (channels * 2)); }
/** * Send individual messages (one slot per message) to a set of targets. * @param dmx_data the DmxBuffer to send * @param group the OSCOutputGroup with the targets. * @param osc_type the type of OSC message, either "i" or "f" */ bool OSCNode::SendIndividualMessages(const DmxBuffer &dmx_data, OSCOutputGroup *group, const string &osc_type) { bool ok = true; const OSCTargetVector &targets = group->targets; vector<SlotMessage> messages; // We only send the slots that have changed. for (unsigned int i = 0; i < dmx_data.Size(); ++i) { if (i > group->dmx.Size() || dmx_data.Get(i) != group->dmx.Get(i)) { SlotMessage message = {i, lo_message_new()}; if (osc_type == "i") { lo_message_add_int32(message.message, dmx_data.Get(i)); } else { lo_message_add_float(message.message, dmx_data.Get(i) / 255.0f); } messages.push_back(message); } } group->dmx.Set(dmx_data); // Send all messages to each target. OSCTargetVector::const_iterator target_iter = targets.begin(); for (; target_iter != targets.end(); ++target_iter) { OLA_DEBUG << "Sending to " << (*target_iter)->socket_address; vector<SlotMessage>::const_iterator message_iter = messages.begin(); for (; message_iter != messages.end(); ++message_iter) { std::stringstream path; path << (*target_iter)->osc_address << "/" << message_iter->slot + 1; int ret = lo_send_message_from((*target_iter)->liblo_address, m_osc_server, path.str().c_str(), message_iter->message); ok &= (ret > 0); } } // Clean up the messages. vector<SlotMessage>::iterator message_iter = messages.begin(); for (; message_iter != messages.end(); ++message_iter) { lo_message_free(message_iter->message); } return ok; }
bool StreamingClient::SendDmx(unsigned int universe, const DmxBuffer &data) { if (!m_stub || !m_socket->ValidReadDescriptor()) return false; // We select() on the fd here to see if the remove end has closed the // connection. We could skip this and rely on the EPIPE delivered by the // write() below, but that introduces a race condition in the unittests. m_socket_closed = false; m_ss->RunOnce(0, 0); if (m_socket_closed) { Stop(); return false; } ola::proto::DmxData request; request.set_universe(universe); request.set_data(data.Get()); m_stub->StreamDmxData(NULL, &request, NULL, NULL); if (m_socket_closed) { Stop(); return false; } return true; }
bool SendDMX(unsigned int universe_id, uint8_t priority, const DmxBuffer &buffer) { OLA_ASSERT_EQ(TEST_UNIVERSE, universe_id); OLA_ASSERT_EQ(ola::dmx::SOURCE_PRIORITY_MIN, priority); OLA_ASSERT_EQ(string(TEST_DATA), buffer.Get()); m_dmx_set = true; return true; }
/** * Send DMX * @param buffer the DMX data */ bool RobeWidgetImpl::SendDMX(const DmxBuffer &buffer) { // the data is 512 + an extra 4 bytes uint8_t output_data[DMX_FRAME_DATA_SIZE]; memset(output_data, 0, DMX_FRAME_DATA_SIZE); unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(output_data, &length); return SendMessage(CHANNEL_A_OUT, reinterpret_cast<uint8_t*>(&output_data), length + 4); }
/** * @brief Called when new DMX arrives. */ void DMXTrigger::NewDMX(const DmxBuffer &data) { SlotVector::iterator iter = m_slots.begin(); for (; iter != m_slots.end(); iter++) { uint16_t slot_number = (*iter)->SlotOffset(); if (slot_number >= data.Size()) { // the DMX frame was too small break; } (*iter)->TakeAction(m_context, data.Get(slot_number)); } }
/* * Send data * @param buffer a DmxBuffer with the data */ int MilInstWidget1553::Send(const DmxBuffer &buffer) const { unsigned int channels = std::min(static_cast<unsigned int>(m_channels), buffer.Size()); uint8_t msg[3 + channels]; msg[0] = MILINST_1553_LOAD_COMMAND; ola::utils::SplitUInt16(1, &msg[1], &msg[2]); buffer.Get(msg + 3, &channels); return m_socket->Send(msg, sizeof(msg)); }
/** * Send the DmxBuffer as an array of normalized floats. */ bool OSCNode::SendFloatArray(const DmxBuffer &dmx_data, const OSCTargetVector &targets) { lo_message message = lo_message_new(); for (size_t i = 0; i < dmx_data.Size(); ++i) { lo_message_add_float(message, dmx_data.Get(i) / 255.0f); } bool ok = SendMessageToTargets(message, targets); lo_message_free(message); return ok; }
/* * Update the screen with new values */ void DmxMonitor::Values() { int i = 0, x, y, z = first_channel; /* values */ for (y = 2; y < LINES && z < DMX_UNIVERSE_SIZE && i < channels_per_screen; y+=2) { move(y, 0); for (x = 0; x < channels_per_line && z < DMX_UNIVERSE_SIZE && i < channels_per_screen; x++, z++, i++) { const int d = m_buffer.Get(z); switch (d) { case 0: (void) attrset(palette[ZERO]); break; case 255: (void) attrset(palette[FULL]); break; default: (void) attrset(palette[NORM]); } if (z == current_channel) attron(A_REVERSE); switch (display_mode) { case DISP_MODE_HEX: if (d == 0) addstr(" "); else printw(" %02x ", d); break; case DISP_MODE_DEC: if (d == 0) addstr(" "); else if (d < 100) printw(" %02d ", d); else printw("%03d ", d); break; case DISP_MODE_DMX: default: switch (d) { case 0: addstr(" "); break; case 255: addstr(" FL "); break; default: printw(" %02d ", (d * 100) / 255); } } } } }
bool DummyPort::WriteDMX(const DmxBuffer &buffer, uint8_t priority) { (void) priority; m_buffer = buffer; ostringstream str; string data = buffer.Get(); str << "Dummy port: got " << buffer.Size() << " bytes: "; for (unsigned int i = 0; i < 10 && i < data.size(); i++) str << "0x" << std::hex << 0 + (uint8_t) data.at(i) << " "; OLA_INFO << str.str(); return true; }
void OPCServerTest::SendDataAndCheck(uint8_t channel, const DmxBuffer &buffer) { unsigned int dmx_size = buffer.Size(); uint8_t data[dmx_size + 4]; data[0] = channel; data[1] = SET_PIXELS_COMMAND; ola::utils::SplitUInt16(static_cast<uint16_t>(dmx_size), &data[2], &data[3]); buffer.Get(data + 4, &dmx_size); m_client_socket->Send(data, dmx_size + 4); m_ss.Run(); OLA_ASSERT_EQ(m_received_data, buffer); }
bool UltraDMXProWidget::SendDMXWithLabel(uint8_t label, const DmxBuffer &data) { struct { uint8_t start_code; uint8_t dmx[DMX_UNIVERSE_SIZE]; } widget_dmx; widget_dmx.start_code = DMX512_START_CODE; unsigned int length = DMX_UNIVERSE_SIZE; data.Get(widget_dmx.dmx, &length); return SendMessage(label, reinterpret_cast<uint8_t*>(&widget_dmx), length + 1); }
/* * Returns the current DMX values for a particular universe */ void OlaServerServiceImpl::GetDmx( RpcController* controller, const UniverseRequest* request, DmxData* response, ola::rpc::RpcService::CompletionCallback* done) { ClosureRunner runner(done); Universe *universe = m_universe_store->GetUniverse(request->universe()); if (!universe) return MissingUniverseError(controller); const DmxBuffer buffer = universe->GetDMX(); response->set_data(buffer.Get()); response->set_universe(request->universe()); }
/* * Send an EspNet data packet */ bool EspNetNode::SendEspData(const IPV4Address &dst, uint8_t universe, const DmxBuffer &buffer) { espnet_packet_union_t packet; memset(&packet.dmx, 0, sizeof(packet.dmx)); packet.dmx.head = HostToNetwork((uint32_t) ESPNET_DMX); packet.dmx.universe = universe; packet.dmx.start = START_CODE; packet.dmx.type = DATA_RAW; unsigned int size = DMX_UNIVERSE_SIZE; buffer.Get(packet.dmx.data, &size); packet.dmx.size = HostToNetwork((uint16_t) size); return SendPacket(dst, packet, sizeof(packet.dmx)); }
/* * Send an uncompressed DMX packet */ bool SandNetNode::SendUncompressedDMX(uint8_t port_id, const DmxBuffer &buffer) { sandnet_packet packet; sandnet_dmx *dmx_packet = &packet.contents.dmx; packet.opcode = HostToNetwork(static_cast<uint16_t>(SANDNET_DMX)); dmx_packet->group = m_ports[port_id].group; dmx_packet->universe = m_ports[port_id].universe; dmx_packet->port = port_id; unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(dmx_packet->dmx, &length); unsigned int header_size = sizeof(sandnet_dmx) - sizeof(dmx_packet->dmx); return SendPacket(packet, sizeof(packet.opcode) + header_size + length); }
/* * Test that Blackout() works */ void DmxBufferTest::testBlackout() { DmxBuffer buffer; OLA_ASSERT_TRUE(buffer.Blackout()); uint8_t *result = new uint8_t[DMX_UNIVERSE_SIZE]; uint8_t *zero = new uint8_t[DMX_UNIVERSE_SIZE]; unsigned int result_length = DMX_UNIVERSE_SIZE; memset(zero, 0, DMX_UNIVERSE_SIZE); buffer.Get(result, &result_length); OLA_ASSERT_EQ((unsigned int) DMX_UNIVERSE_SIZE, result_length); OLA_ASSERT_EQ(0, memcmp(zero, result, result_length)); delete[] result; delete[] zero; buffer.Reset(); OLA_ASSERT_EQ(0u, buffer.Size()); }
bool PerformTransfer(const DmxBuffer &buffer) { m_adaptor->FillControlSetup( m_control_setup_buffer, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, // bmRequestType UDMX_SET_CHANNEL_RANGE, // bRequest buffer.Size(), // wValue 0, // wIndex buffer.Size()); // wLength unsigned int length = DMX_UNIVERSE_SIZE; buffer.Get(m_control_setup_buffer + LIBUSB_CONTROL_SETUP_SIZE, &length); FillControlTransfer(m_control_setup_buffer, URB_TIMEOUT_MS); return (SubmitTransfer() == 0); }
/* * Send DMX to the widget */ bool SunliteOutputPort::SendDMX(const DmxBuffer &buffer) { for (unsigned int i = 0; i < buffer.Size(); i++) m_packet[(i / CHANNELS_PER_CHUNK) * CHUNK_SIZE + ((i / 4) % 5) * 6 + 3 + (i % 4)] = buffer.Get(i); int transferred; int r = libusb_bulk_transfer( m_usb_handle, ENDPOINT, (unsigned char*) m_packet, SUNLITE_PACKET_SIZE, &transferred, TIMEOUT); if (transferred != SUNLITE_PACKET_SIZE) // not sure if this is fatal or not OLA_WARN << "Sunlite driver failed to transfer all data"; return r == 0; }
/* * Send a DMX Update to this client * @param universe the universe_id for this data * @param buffer the DmxBuffer with the data * @return true if the update was sent, false otherwise */ bool Client::SendDMX(unsigned int universe, const DmxBuffer &buffer) { if (!m_client_stub) { OLA_FATAL << "client_stub is null"; return false; } SimpleRpcController *controller = new SimpleRpcController(); ola::proto::DmxData dmx_data; ola::proto::Ack *ack = new ola::proto::Ack(); dmx_data.set_universe(universe); dmx_data.set_data(buffer.Get()); m_client_stub->UpdateDmxData( controller, &dmx_data, ack, NewCallback(this, &ola::Client::SendDMXCallback, controller, ack)); return true; }
/* * Call the UpdateDmxDataCheck method * @param impl the OlaServerServiceImpl to use * @param universe_id the universe_id in the request * @param data the DmxBuffer to use as data * @param check the SetUniverseNameCheck to use for the callback check */ void OlaServerServiceImplTest::CallUpdateDmxData( OlaClientService *service, int universe_id, const DmxBuffer &data, UpdateDmxDataCheck &check) { SimpleRpcController *controller = new SimpleRpcController(); ola::proto::DmxData *request = new ola::proto::DmxData(); ola::proto::Ack *response = new ola::proto::Ack(); Closure *closure = NewCallback( &check, &UpdateDmxDataCheck::Check, controller, response); request->set_universe(universe_id); request->set_data(data.Get()); service->UpdateDmxData(controller, request, response, closure); delete controller; delete request; delete response; }
/* * Send some DMX data * @param buffer the DMX data * @return true if it was send successfully, false otherwise */ bool PathportNode::SendDMX(unsigned int universe, const DmxBuffer &buffer) { if (!m_running) return false; if (universe > MAX_UNIVERSES) { OLA_WARN << "attempt to send to universe " << universe; return false; } pathport_packet_s packet; // pad to a multiple of 4 bytes unsigned int padded_size = (buffer.Size() + 3) & ~3; PopulateHeader(&packet.header, PATHPORT_DATA_GROUP); pathport_packet_pdu *pdu = &packet.d.pdu; pdu->head.type = HostToNetwork((uint16_t) PATHPORT_DATA); pdu->head.len = HostToNetwork( (uint16_t) (padded_size + sizeof(pathport_pdu_data))); pdu->d.data.type = HostToNetwork((uint16_t) XDMX_DATA_FLAT); pdu->d.data.channel_count = HostToNetwork((uint16_t) buffer.Size()); pdu->d.data.universe = 0; pdu->d.data.start_code = 0; pdu->d.data.offset = HostToNetwork( (uint16_t) (DMX_UNIVERSE_SIZE * universe)); unsigned int length = padded_size; buffer.Get(pdu->d.data.data, &length); // pad data to multiple of 4 bytes length = sizeof(pathport_packet_header) + sizeof(pathport_pdu_header) + sizeof(pathport_pdu_data) + padded_size; return SendPacket(packet, length, m_data_addr); }
/* * Check that Get/Set works correctly */ void DmxBufferTest::testGetSet() { unsigned int fudge_factor = 10; unsigned int result_length = sizeof(TEST_DATA2) + fudge_factor; uint8_t *result = new uint8_t[result_length]; unsigned int size = result_length; DmxBuffer buffer; string str_result; OLA_ASSERT_EQ((uint8_t) 0, buffer.Get(0)); OLA_ASSERT_EQ((uint8_t) 0, buffer.Get(1)); OLA_ASSERT_FALSE(buffer.Set(NULL, sizeof(TEST_DATA))); OLA_ASSERT_TRUE(buffer.Set(TEST_DATA, sizeof(TEST_DATA))); OLA_ASSERT_EQ((uint8_t) 1, buffer.Get(0)); OLA_ASSERT_EQ((uint8_t) 2, buffer.Get(1)); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), buffer.Size()); buffer.Get(result, &size); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA), size); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, result, size)); str_result = buffer.Get(); OLA_ASSERT_EQ((size_t) sizeof(TEST_DATA), str_result.length()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA, str_result.data(), str_result.length())); size = result_length; OLA_ASSERT_TRUE(buffer.Set(TEST_DATA2, sizeof(TEST_DATA2))); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA2), buffer.Size()); buffer.Get(result, &size); OLA_ASSERT_EQ((unsigned int) sizeof(TEST_DATA2), size); OLA_ASSERT_EQ(0, memcmp(TEST_DATA2, result, size)); str_result = buffer.Get(); OLA_ASSERT_EQ((size_t) sizeof(TEST_DATA2), str_result.length()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA2, str_result.data(), str_result.length())); // now check that Set() with another buffer works DmxBuffer buffer2; buffer2.Set(buffer); str_result = buffer2.Get(); OLA_ASSERT_EQ((size_t) sizeof(TEST_DATA2), str_result.length()); OLA_ASSERT_EQ(0, memcmp(TEST_DATA2, str_result.data(), str_result.length())); delete[] result; }
/* * Take a DMXBuffer and RunLengthEncode the data * @param src the DmxBuffer with the DMX data * @param data where to store the RLE data * @param size the size of the data segment, set to the amount of data encoded * @return true if we encoded all data, false if we ran out of space */ bool RunLengthEncoder::Encode(const DmxBuffer &src, uint8_t *data, unsigned int &data_size) { unsigned int src_size = src.Size(); unsigned int dst_size = data_size; unsigned int &dst_index = data_size; dst_index = 0; unsigned int i; for (i = 0; i < src_size && dst_index < dst_size;) { // j points to the first non-repeating value unsigned int j = i + 1; while (j < src_size && src.Get(i) == src.Get(j) && j - i < 0x7f) { j++; } // if the number of repeats is more than 2 // don't encode only two repeats, if (j - i > 2) { // if room left in dst buffer if (dst_size - dst_index > 1) { data[dst_index++] = (REPEAT_FLAG | (j - i)); data[dst_index++] = src.Get(i); } else { // else return what we have done so far return false; } i = j; } else { // this value doesn't repeat more than twice // find out where the next repeat starts // postcondition: j is one more than the last value we want to send for (j = i + 1; j < src_size - 2 && j - i < 0x7f; j++) { // at the end of the array if (j == src_size - 2) { j = src_size; break; } // if we're found a repeat of 3 or more stop here if (src.Get(j) == src.Get(j+1) && src.Get(j) == src.Get(j+2)) break; } if (j >= src_size - 2) j = src_size; // if we have enough room left for all the values if (dst_index + j - i < dst_size) { data[dst_index++] = j - i; memcpy(&data[dst_index], src.GetRaw() + i, j-i); dst_index += j - i; i = j; // see how much data we can get in } else if (dst_size - dst_index > 1) { unsigned int l = dst_size - dst_index -1; data[dst_index++] = l; memcpy(&data[dst_index], src.GetRaw() + i, l); dst_index += l; return false; } else { return false; } } } if (i < src_size) return false; else return true; }
/* * Send a DMX msg. */ bool RenardWidget::SendDmx(const DmxBuffer &buffer) { unsigned int channels = std::max((unsigned int)0, std::min((unsigned int) m_channels + m_dmxOffset, buffer.Size()) - m_dmxOffset); OLA_DEBUG << "Sending " << static_cast<int>(channels) << " channels"; // Max buffer size for worst case scenario (escaping + padding) unsigned int bufferSize = channels * 2 + 10; uint8_t msg[bufferSize]; int dataToSend = 0; for (unsigned int i = 0; i < channels; i++) { if ((i % RENARD_CHANNELS_IN_BANK) == 0) { if (m_byteCounter >= RENARD_BYTES_BETWEEN_PADDING) { // Send PAD every 100 (or so) bytes. Note that the counter is per // device, so the counter should span multiple calls to SendDMX. msg[dataToSend++] = RENARD_COMMAND_PAD; m_byteCounter = 0; } // Send address msg[dataToSend++] = RENARD_COMMAND_START_PACKET; msg[dataToSend++] = m_startAddress + (i / RENARD_CHANNELS_IN_BANK); m_byteCounter += 2; } uint8_t b = buffer.Get(m_dmxOffset + i); // Escaping magic bytes switch (b) { case RENARD_COMMAND_PAD: msg[dataToSend++] = RENARD_COMMAND_ESCAPE; msg[dataToSend++] = RENARD_ESCAPE_PAD; m_byteCounter += 2; break; case RENARD_COMMAND_START_PACKET: msg[dataToSend++] = RENARD_COMMAND_ESCAPE; msg[dataToSend++] = RENARD_ESCAPE_START_PACKET; m_byteCounter += 2; break; case RENARD_COMMAND_ESCAPE: msg[dataToSend++] = RENARD_COMMAND_ESCAPE; msg[dataToSend++] = RENARD_ESCAPE_ESCAPE; m_byteCounter += 2; break; default: msg[dataToSend++] = b; m_byteCounter++; break; } OLA_DEBUG << "Setting Renard " << m_startAddress + (i / RENARD_CHANNELS_IN_BANK) << "/" << ((i % RENARD_CHANNELS_IN_BANK) + 1) << " to " << static_cast<int>(b); } int bytes_sent = m_socket->Send(msg, dataToSend); OLA_DEBUG << "Sending DMX, sent " << bytes_sent << " bytes"; return true; }
/* * Update the screen with new values */ void DmxMonitor::Values() { int i = 0, x, y, z = first_channel; /* values */ for (y = ROWS_PER_CHANNEL_ROW; y < LINES && z < DMX_UNIVERSE_SIZE && i < static_cast<int>(channels_per_screen); y += ROWS_PER_CHANNEL_ROW) { move(y, 0); for (x = 0; x < static_cast<int>(channels_per_line) && z < DMX_UNIVERSE_SIZE && i < static_cast<int>(channels_per_screen); x++, z++, i++) { const int d = m_buffer.Get(z); switch (d) { case DMX_MIN_CHANNEL_VALUE: (void) attrset(palette[ZERO]); break; case DMX_MAX_CHANNEL_VALUE: (void) attrset(palette[FULL]); break; default: (void) attrset(palette[NORM]); } if (static_cast<int>(z) == current_channel) attron(A_REVERSE); switch (display_mode) { case DISP_MODE_HEX: if (d == 0) { if (static_cast<int>(m_buffer.Size()) <= z) { addstr("--- "); } else { addstr(" "); } } else { printw(" %02x ", d); } break; case DISP_MODE_DEC: if (d == 0) { if (static_cast<int>(m_buffer.Size()) <= z) { addstr("--- "); } else { addstr(" "); } } else if (d < 100) { printw(" %02d ", d); } else { printw("%03d ", d); } break; case DISP_MODE_DMX: default: switch (d) { case DMX_MIN_CHANNEL_VALUE: if (static_cast<int>(m_buffer.Size()) <= z) { addstr("--- "); } else { addstr(" "); } break; case DMX_MAX_CHANNEL_VALUE: addstr(" FL "); break; default: printw(" %02d ", (d * 100) / DMX_MAX_CHANNEL_VALUE); } } } } }