/* * Send some DMX data, allowing finer grained control of parameters. * @param universe the id of the universe to send * @param buffer the DMX data * @param cid the cid to send from * @param sequence_offset used to twiddle the sequence numbers, this doesn't * increment the sequence counter. * @param priority the priority to use * @param preview set to true to turn on the preview bit * @return true if it was sent successfully, false otherwise */ bool E131Node::SendDMXWithSequenceOffset(uint16_t universe, const ola::DmxBuffer &buffer, int8_t sequence_offset, uint8_t priority, bool preview) { map<unsigned int, tx_universe>::iterator iter = m_tx_universes.find(universe); tx_universe *settings; if (iter == m_tx_universes.end()) settings = SetupOutgoingSettings(universe); else settings = &iter->second; const uint8_t *dmp_data; unsigned int dmp_data_length; if (m_use_rev2) { dmp_data = buffer.GetRaw(); dmp_data_length = buffer.Size(); } else { unsigned int data_size = DMX_UNIVERSE_SIZE; buffer.Get(m_send_buffer + 1, &data_size); dmp_data = m_send_buffer; dmp_data_length = data_size + 1; } TwoByteRangeDMPAddress range_addr(0, 1, (uint16_t) dmp_data_length); DMPAddressData<TwoByteRangeDMPAddress> range_chunk(&range_addr, dmp_data, dmp_data_length); vector<DMPAddressData<TwoByteRangeDMPAddress> > ranged_chunks; ranged_chunks.push_back(range_chunk); const DMPPDU *pdu = NewRangeDMPSetProperty<uint16_t>(true, false, ranged_chunks); E131Header header(settings->source, priority, static_cast<uint8_t>(settings->sequence + sequence_offset), universe, preview, // preview false, // terminated m_use_rev2); bool result = m_e131_layer.SendDMP(header, pdu); if (result && !sequence_offset) settings->sequence++; delete pdu; return result; }
/** * set device level */ bool AgoDmx::setDevice_level(Variant::Map device, int level=0) { if (device["level"]) { string channel = device["level"]; ola_setChannel(atoi(channel.c_str()), (int) ( 255.0 * level / 100 )); return ola_send(); } else { string channel_red = device["red"]; string channel_green = device["green"]; string channel_blue = device["blue"]; int red = (int) ( buffer.Get(atoi(channel_red.c_str())) * level / 100); int green = (int) ( buffer.Get(atoi(channel_green.c_str())) * level / 100); int blue = (int) ( buffer.Get(atoi(channel_blue.c_str())) * level / 100); return setDevice_color(device, red, green, blue); } }
// Called when new DMX data arrives. void NewDmx(unsigned int universe, uint8_t priority, const ola::DmxBuffer &data, const std::string &error) { if (error.empty()) { OLA_INFO << "Received " << data.Size() << " channels for universe " << universe << ", priority " << static_cast<int>(priority); } else { OLA_WARN << "Receive failed: " << error; } }
bool FtdiWidget::Write(const ola::DmxBuffer& data) { unsigned char buffer[DMX_UNIVERSE_SIZE + 1]; int unsigned length = DMX_UNIVERSE_SIZE; buffer[0] = 0x00; data.Get(buffer + 1, &length); if (ftdi_write_data(&m_handle, buffer, length + 1) < 0) { OLA_WARN << Name() << " " << ftdi_get_error_string(&m_handle); return false; } else { return true; } }
/** * Write a new frame */ bool ShowSaver::NewFrame(const ola::TimeStamp &arrival_time, unsigned int universe, const ola::DmxBuffer &data) { // TODO(simon): add much better error handling here if (m_last_frame.IsSet()) { // this is not the first frame so write the delay in ms const ola::TimeInterval delta = arrival_time - m_last_frame; m_show_file << delta.InMilliSeconds() << endl; } m_last_frame = arrival_time; m_show_file << universe << " " << data.ToString() << endl; return true; }
/* * Signal termination of this stream for a universe. * @param universe the id of the universe to send * @param priority the priority to use, this doesn't actually make a * difference. */ bool E131Node::StreamTerminated(uint16_t universe, const ola::DmxBuffer &buffer, uint8_t priority) { map<unsigned int, tx_universe>::iterator iter = m_tx_universes.find(universe); string source_name; uint8_t sequence_number; if (iter == m_tx_universes.end()) { source_name = ""; sequence_number = 0; } else { source_name = iter->second.source; sequence_number = iter->second.sequence; } unsigned int data_size = DMX_UNIVERSE_SIZE; buffer.Get(m_send_buffer + 1, &data_size); TwoByteRangeDMPAddress range_addr(0, 1, (uint16_t) data_size); DMPAddressData<TwoByteRangeDMPAddress> range_chunk(&range_addr, m_send_buffer, data_size + 1); vector<DMPAddressData<TwoByteRangeDMPAddress> > ranged_chunks; ranged_chunks.push_back(range_chunk); const DMPPDU *pdu = NewRangeDMPSetProperty<uint16_t>(true, false, ranged_chunks); E131Header header(source_name, priority, sequence_number, universe, false, // preview true, // terminated false); bool result = m_e131_layer.SendDMP(header, pdu); // only update if we were previously tracking this universe if (result && iter != m_tx_universes.end()) iter->second.sequence++; delete pdu; return result; }
void AgoDmx::setupApp() { fs::path channelsFile; std::string ola_server; channelsFile=getConfigOption("channelsfile", getConfigPath("/dmx/channels.xml")); ola_server=getConfigOption("url", "ip:127.0.0.1"); universe = atoi(getConfigOption("universe","0").c_str()); // load xml file into map if (!loadChannels(channelsFile.string(), channelMap)) { AGO_FATAL() << "Can't load channel xml"; throw StartupError(); } // connect to OLA // turn on OLA logging //ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR); AGO_DEBUG() << "Setting up OLA log destination"; agoLogDestination = new AgoLogDestination(); ola::InitLogging(ola::OLA_LOG_WARN, agoLogDestination); // set all channels to 0 AGO_TRACE() << "Blacking out DMX buffer"; buffer.Blackout(); // Setup the client, this connects to the server AGO_DEBUG() << "Setting up OLA client"; if (!ola_client.Setup()) { AGO_FATAL() << "OLA client setup failed"; throw StartupError(); } AGO_TRACE() << "reporting devices"; reportDevices(channelMap); addCommandHandler(); }
/** * set a channel to off */ void AgoDmx::ola_setChannel(int channel, int value) { AGO_DEBUG() << "Setting channel " << channel << " to value " << value; buffer.SetChannel(channel, value); }