示例#1
0
/**
 * @brief Handle the set DMX command
 * @param request the HTTPRequest
 * @param response the HTTPResponse
 * @returns MHD_NO or MHD_YES
 */
int OladHTTPServer::HandleSetDmx(const HTTPRequest *request,
                                 HTTPResponse *response) {
  if (request->CheckParameterExists(HELP_PARAMETER)) {
    return ServeUsage(response,
        "POST u=[universe], d=[DMX data (a comma separated list of values)]");
  }
  string dmx_data_str = request->GetPostParameter("d");
  string uni_id = request->GetPostParameter("u");
  unsigned int universe_id;
  if (!StringToInt(uni_id, &universe_id)) {
    return ServeHelpRedirect(response);
  }

  DmxBuffer buffer;
  buffer.SetFromString(dmx_data_str);
  if (!buffer.Size()) {
    return m_server.ServeError(response, "Invalid DMX string");
  }

  ola::client::SendDMXArgs args(
      NewSingleCallback(this, &OladHTTPServer::HandleBoolResponse, response));
  m_client.SendDMX(universe_id, buffer, args);
  return MHD_YES;
}
示例#2
0
/*
 * Send the dmx out the widget
 * @return true on success, false on failure
 */
bool VellemanOutputPort::SendDMX(const DmxBuffer &buffer) {
  unsigned char usb_data[m_chunk_size];
  unsigned int size = buffer.Size();
  const uint8_t *data = buffer.GetRaw();
  unsigned int i = 0;
  unsigned int n;

  // this could be up to 254 for the standard interface but then the shutdown
  // process gets wacky. Limit it to 100 for the standard and 255 for the
  // extended.
  unsigned int max_compressed_channels = m_chunk_size == UPGRADED_CHUNK_SIZE ?
    254 : 100;
  unsigned int compressed_channel_count = m_chunk_size - 2;
  unsigned int channel_count = m_chunk_size - 1;

  memset(usb_data, 0, sizeof(usb_data));

  if (m_chunk_size == UPGRADED_CHUNK_SIZE && size <= m_chunk_size - 2) {
    // if the upgrade is present and we can fit the data in a single packet
    // use the 7 message type
    usb_data[0] = 7;
    usb_data[1] = size;  // number of channels in packet
    memcpy(usb_data + 2, data, std::min(size, m_chunk_size - 2));
  } else {
    // otherwise use 4 to signal the start of frame
    for (n = 0;
         n < max_compressed_channels && n < size - compressed_channel_count
         && !data[n];
         n++) {
    }
    usb_data[0] = 4;
    usb_data[1] = n + 1;  // include start code
    memcpy(usb_data + 2, data + n, compressed_channel_count);
    i += n + compressed_channel_count;
  }

  if (!SendDataChunk(usb_data))
    return false;

  while (i < size - channel_count) {
    for (n = 0;
         n < max_compressed_channels && n + i < size - compressed_channel_count
           && !data[i + n];
         n++) {
    }
    if (n) {
      // we have leading zeros
      usb_data[0] = 5;
      usb_data[1] = n;
      memcpy(usb_data + 2, data + i + n, compressed_channel_count);
      i += n + compressed_channel_count;
    } else {
      usb_data[0] = 2;
      memcpy(usb_data + 1, data + i, channel_count);
      i += channel_count;
    }
    if (!SendDataChunk(usb_data))
      return false;
  }

  // send the last channels
  if (m_chunk_size == UPGRADED_CHUNK_SIZE) {
    // if running in extended mode we can use the 6 message type to send
    // everything at once.
    usb_data[0] = 6;
    usb_data[1] = size - i;
    memcpy(usb_data + 2, data + i, size - i);
    if (!SendDataChunk(usb_data))
      return false;

  } else {
    // else we use the 3 message type to send one at a time
    for (;i != size; i++) {
      usb_data[0] = 3;
      usb_data[1] = data[i];
      if (!SendDataChunk(usb_data))
        return false;
    }
  }
  return true;
}
示例#3
0
/*
 * 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;
}
示例#4
0
/*
 * 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);
          }
      }
    }
  }
}
示例#5
0
/**
 * Check that we receive OSC messages correctly.
 */
void OSCNodeTest::testReceive() {
  DmxBuffer expected_data;

  // Register the test OSC Address with the OSCNode using the DMXHandler as the
  // callback.
  OLA_ASSERT_TRUE(m_osc_node->RegisterAddress(
      TEST_OSC_ADDRESS, NewCallback(this, &OSCNodeTest::DMXHandler)));

  // Attempt to register the same address with a different path, this should
  // return false
  OLA_ASSERT_FALSE(m_osc_node->RegisterAddress(
      TEST_OSC_ADDRESS,
      NewCallback(this, &OSCNodeTest::DMXHandler)));

  // Using our test UDP socket, send the OSC_BLOB_DATA to the default OSC
  // port. The OSCNode should receive the packet and call DMXHandler.
  IPV4SocketAddress dest_address(IPV4Address::Loopback(),
                                 m_osc_node->ListeningPort());

  // send a single float update
  m_udp_socket.SendTo(OSC_SINGLE_FLOAT_DATA, sizeof(OSC_SINGLE_FLOAT_DATA),
                      dest_address);
  m_ss.Run();
  OLA_ASSERT_EQ(512u, m_received_data.Size());
  expected_data.SetChannel(0, 127);
  OLA_ASSERT_EQ(expected_data, m_received_data);

  // now send a blob update
  m_udp_socket.SendTo(OSC_BLOB_DATA, sizeof(OSC_BLOB_DATA),
                      dest_address);
  // Run the SelectServer, this will return either when DMXHandler
  // completes, or the abort timeout triggers.
  m_ss.Run();

  OLA_ASSERT_EQ(11u, m_received_data.Size());
  expected_data.SetFromString("0,1,2,3,4,5,6,7,8,9,10");
  OLA_ASSERT_EQ(expected_data, m_received_data);

  // Now try sending a float update.
  m_udp_socket.SendTo(OSC_SINGLE_FLOAT_DATA, sizeof(OSC_SINGLE_FLOAT_DATA),
                      dest_address);
  m_ss.Run();
  OLA_ASSERT_EQ(11u, m_received_data.Size());
  expected_data.SetChannel(0, 127);
  OLA_ASSERT_EQ(expected_data, m_received_data);

  // Now try sending an int update.
  m_udp_socket.SendTo(OSC_SINGLE_INT_DATA, sizeof(OSC_SINGLE_INT_DATA),
                      dest_address);
  m_ss.Run();
  OLA_ASSERT_EQ(11u, m_received_data.Size());
  expected_data.SetChannel(5, 140);
  OLA_ASSERT_EQ(expected_data, m_received_data);

  // An 'ii' update
  m_udp_socket.SendTo(OSC_INT_TUPLE_DATA, sizeof(OSC_INT_TUPLE_DATA),
                      dest_address);
  m_ss.Run();
  OLA_ASSERT_EQ(11u, m_received_data.Size());
  expected_data.SetChannel(7, 90);
  OLA_ASSERT_EQ(expected_data, m_received_data);

  // An 'if' update
  m_udp_socket.SendTo(OSC_FLOAT_TUPLE_DATA, sizeof(OSC_FLOAT_TUPLE_DATA),
                      dest_address);
  m_ss.Run();
  OLA_ASSERT_EQ(11u, m_received_data.Size());
  expected_data.SetChannel(8, 127);
  OLA_ASSERT_EQ(expected_data, m_received_data);

  // De-regsiter
  OLA_ASSERT_TRUE(m_osc_node->RegisterAddress(TEST_OSC_ADDRESS, NULL));
  // De-register a second time
  OLA_ASSERT_TRUE(m_osc_node->RegisterAddress(TEST_OSC_ADDRESS, NULL));
}
示例#6
0
/*
 * 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;
}