<commit_before> 

#include "cinder/app/AppBasic.h"
#include "cinder/Utilities.h"
#include <iostream>
#include "DMXPro.h"

using namespace ci;
using namespace ci::app;
using namespace std;


DMXPro::DMXPro( const string &serialDevicePath ) : mDMXPacket(NULL), mSerialDevicePath(serialDevicePath), mSerial(NULL)
{	
	mThreadSleepFor = 1000 / DMXPRO_FRAME_RATE;
    
	init();
	
	setZeros();
}


DMXPro::~DMXPro()
{
    setZeros();
    
    ci::sleep(50);	
    
    mRunSendDataThread = false;
    if ( mSendDataThread.joinable() )
        mSendDataThread.join();
    
    if ( mSerial )
    {
        mSerial->flush();
        delete mSerial;
        mSerial = NULL;
    }
    
    
    delete []mDMXPacket;
    
    console() << "shutdown DMXPro" << endl;
}

void DMXPro::shutdown(bool send_zeros)
{
	if ( mSerial )
	{
		if (send_zeros)
			setZeros();					// send zeros to all channels
		
		ci::sleep( mThreadSleepFor*2 );
		mSerial->flush();	
		delete mSerial;
		mSerial = NULL;
		ci::sleep(50);	
	}
    console() << "DMXPro > shutdown!" << endl;
}


void DMXPro::init(bool initWithZeros) 
{
    console() << "DMXPro > Initializing device" << endl;

	initDMX();
	initSerial(initWithZeros);
}


void DMXPro::initSerial(bool initWithZeros)
{
	if ( mSerial )
	{
		if (initWithZeros)
		{
			setZeros();					// send zeros to all channels
            console() << "DMXPro > Init serial with zeros() before disconnect" << endl;
			ci::sleep(100);	
		}
		mSerial->flush();	
		delete mSerial;
		mSerial = NULL;
		ci::sleep(50);	
	}
	
	try 
    {
		Serial::Device dev = findDeviceByPathContains(mSerialDevicePath);
		mSerial = new Serial(dev, DMXPRO_BAUD_RATE);
        console() << "DMXPro > Connected to usb DMX interface: " << dev.getName() << endl;
	}
	catch( ... ) 
    {
        console() << "DMXPro > There was an error initializing the usb DMX device" << endl;
		mSerial = NULL;
	}
    
    mSendDataThread = std::thread( &DMXPro::sendDMXData, this );
}


void DMXPro::initDMX()
{
	delete []mDMXPacket;
	mDMXPacket	= NULL;
	mDMXPacket	= new unsigned char[DMXPRO_PACKET_SIZE];
    
    // LAST 4 dmx channels seem not to be working, 508-511 !!!
    
    for (int i=0; i < DMXPRO_PACKET_SIZE; i++)                      // initialize all channels with zeros, data starts from [5]
		mDMXPacket[i] = 0;
    
    mDMXPacket[0] = DMXPRO_START_MSG;								// DMX start delimiter 0x7E
	mDMXPacket[1] = DMXPRO_SEND_LABEL;								// set message type
    mDMXPacket[2] = (int)DMXPRO_DATA_SIZE & 0xFF;					// Data Length LSB
    mDMXPacket[3] = ((int)DMXPRO_DATA_SIZE >> 8) & 0xFF;            // Data Length MSB
	mDMXPacket[4] = 0;                                              // NO IDEA what this is for!
	mDMXPacket[DMXPRO_PACKET_SIZE-1] = DMXPRO_END_MSG;              // DMX start delimiter 0xE7
}


void DMXPro::sendDMXData() 
{
    mRunSendDataThread = true;
    
	while( mRunSendDataThread )
    {
		std::unique_lock<std::mutex> dataLock(mDMXDataMutex);                           // get DMX packet UNIQUE lock
		mSerial->writeBytes( mDMXPacket, DMXPRO_PACKET_SIZE );                          // send data
		dataLock.unlock();                                                              // unlock data
        std::this_thread::sleep_for( std::chrono::milliseconds( mThreadSleepFor ) );
	}
    console() << "DMXPro > sendDMXData() thread exited!" << endl;
}


Serial::Device DMXPro::findDeviceByPathContains( const string &searchString) 
{
	const std::vector<Serial::Device> &devices = Serial::getDevices();
	for( std::vector<Serial::Device>::const_iterator deviceIt = devices.begin(); deviceIt != devices.end(); ++deviceIt ) {
		if( deviceIt->getPath().find( searchString ) != std::string::npos )
			return *deviceIt;
	}
	return Serial::Device();
}


void DMXPro::setValue(int value, int channel) 
{    
	if ( channel < 0 || channel > DMXPRO_PACKET_SIZE-2 )
	{
        console() << "DMXPro > invalid DMX channel: " << channel << endl;<commit_msg>fix bug send data thread<commit_after> 

#include "cinder/app/AppBasic.h"
#include "cinder/Utilities.h"
#include <iostream>
#include "DMXPro.h"

using namespace ci;
using namespace ci::app;
using namespace std;


DMXPro::DMXPro( const string &serialDevicePath ) : mDMXPacket(NULL), mSerialDevicePath(serialDevicePath), mSerial(NULL)
{	
	mThreadSleepFor = 1000 / DMXPRO_FRAME_RATE;
    
	init();
	
	setZeros();
}


DMXPro::~DMXPro()
{
    setZeros();
    
    ci::sleep(50);	
    
    mRunSendDataThread = false;
    if ( mSendDataThread.joinable() )
        mSendDataThread.join();
    
    if ( mSerial )
    {
        mSerial->flush();
        delete mSerial;
        mSerial = NULL;
    }
    
    
    delete []mDMXPacket;
    
    console() << "shutdown DMXPro" << endl;
}

void DMXPro::shutdown(bool send_zeros)
{
	if ( mSerial )
	{
		if (send_zeros)
			setZeros();					// send zeros to all channels
		
		ci::sleep( mThreadSleepFor*2 );
		mSerial->flush();	
		delete mSerial;
		mSerial = NULL;
		ci::sleep(50);	
	}
    console() << "DMXPro > shutdown!" << endl;
}


void DMXPro::init(bool initWithZeros) 
{
    console() << "DMXPro > Initializing device" << endl;

	initDMX();
	initSerial(initWithZeros);
}


void DMXPro::initSerial(bool initWithZeros)
{
	if ( mSerial )
	{
		if (initWithZeros)
		{
			setZeros();					// send zeros to all channels
            console() << "DMXPro > Init serial with zeros() before disconnect" << endl;
			ci::sleep(100);	
		}
		mSerial->flush();	
		delete mSerial;
		mSerial = NULL;
		ci::sleep(50);	
	}
	
	try 
    {
		Serial::Device dev = findDeviceByPathContains(mSerialDevicePath);
		mSerial = new Serial(dev, DMXPRO_BAUD_RATE);
        console() << "DMXPro > Connected to usb DMX interface: " << dev.getName() << endl;
	}
	catch( ... ) 
    {
        console() << "DMXPro > There was an error initializing the usb DMX device" << endl;
		mSerial = NULL;
	}
    
    mSendDataThread = std::thread( &DMXPro::sendDMXData, this );
}


void DMXPro::initDMX()
{
	delete []mDMXPacket;
	mDMXPacket	= NULL;
	mDMXPacket	= new unsigned char[DMXPRO_PACKET_SIZE];
    
    // LAST 4 dmx channels seem not to be working, 508-511 !!!
    
    for (int i=0; i < DMXPRO_PACKET_SIZE; i++)                      // initialize all channels with zeros, data starts from [5]
		mDMXPacket[i] = 0;
    
    mDMXPacket[0] = DMXPRO_START_MSG;								// DMX start delimiter 0x7E
	mDMXPacket[1] = DMXPRO_SEND_LABEL;								// set message type
    mDMXPacket[2] = (int)DMXPRO_DATA_SIZE & 0xFF;					// Data Length LSB
    mDMXPacket[3] = ((int)DMXPRO_DATA_SIZE >> 8) & 0xFF;            // Data Length MSB
	mDMXPacket[4] = 0;                                              // NO IDEA what this is for!
	mDMXPacket[DMXPRO_PACKET_SIZE-1] = DMXPRO_END_MSG;              // DMX start delimiter 0xE7
}


void DMXPro::sendDMXData() 
{
    mRunSendDataThread = true;
    
	while( mSerial && mRunSendDataThread )
    {
		std::unique_lock<std::mutex> dataLock(mDMXDataMutex);                           // get DMX packet UNIQUE lock
		mSerial->writeBytes( mDMXPacket, DMXPRO_PACKET_SIZE );                          // send data
		dataLock.unlock();                                                              // unlock data
        std::this_thread::sleep_for( std::chrono::milliseconds( mThreadSleepFor ) );
	}
    console() << "DMXPro > sendDMXData() thread exited!" << endl;
}


Serial::Device DMXPro::findDeviceByPathContains( const string &searchString) 
{
	const std::vector<Serial::Device> &devices = Serial::getDevices();
	for( std::vector<Serial::Device>::const_iterator deviceIt = devices.begin(); deviceIt != devices.end(); ++deviceIt ) {
		if( deviceIt->getPath().find( searchString ) != std::string::npos )
			return *deviceIt;
	}
	return Serial::Device();
}


void DMXPro::setValue(int value, int channel) 
{    
	if ( channel < 0 || channel > DMXPRO_PACKET_SIZE-2 )
	{
        console() << "DMXPro > invalid DMX channel: " << channel << endl;
{'fraction_non_alphanumeric': 0.13275905751203446, 'fraction_numerical': 0.010134279199391943, 'mean_word_length': 2.725814063237376, 'pattern_counts': {'":': 0, '<': 87, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5061705', 'n_tokens_mistral': 2924, 'n_tokens_neox': 2724, 'n_words': 598}