<commit_before>#include "client.h"
#include "config.h"
#include "curses.h"
#include "log.h"
#include "queue.h"

#include <cstdlib>
#include <experimental/filesystem>
#include <iostream>
#include <memory>
#include <queue>
#include <thread>

void client_runner(Client& client) {
  client.run();
}

void client_reader(Client& client, std::queue<std::string>& read_q, queue<bool>& end_signal) {
  while (true) {
    const auto line = client.read();
    if (line != "") {
      read_q.push(line);
    }
    if (!end_signal.empty()) {
      end_signal.pop();
      break;
    }
  }
}

int main(int argc, char** argv) {
  fs::path config_path;
  if (argc > 1) {
    config_path = argv[1];
  } else {
    config_path = fs::path(getenv("HOME")) / ".config/courier/courier.conf";
  }

  Config config(config_path);
  if (!config.okay) {
    return 1;
  }

  const auto host = config.get("host");
  const auto port = config.get("port");

  if (!host) {
    std::cerr << "IMAP host not found in config" << std::endl;
    return 1;
  }

  if (!port) {
    std::cerr << "IMAP port not found in config" << std::endl;
    return 1;
  }

  const auto user = config.get("user");
  const auto pass = config.get("pass");

  if (!user || !pass) {
    std::cerr << "IMAP user or password not found in config" << std::endl;
    return 1;
  }

  Client client(*host, *port);
  Log logfile("courier.log");

  if (!client.connect()) {
    return 1;
  } else {
    logfile.info("Connected to " + *host + ":" + *port);
  }

  std::queue<std::string> read_q;
  queue<bool> end_signal;
  std::thread client_thread([&client]() {
    client_runner(client);
  });
  std::thread client_reader_thread([&client, &read_q, &end_signal]() {
    client_reader(client, read_q, end_signal);
  });

  curses::init();

  const auto dim = curses::dimensions();

  curses::Window input(0, std::get<1>(dim) - 5, std::get<0>(dim), 5);
  input.add_border();
  input.write_string(1, 1, "> ");
  input.disable_delay();

  client.login(*user, *pass);

  bool running = true;
  std::string buf;
  buf.reserve(256);
  while (running) {
    while (!read_q.empty()) {
      logfile.info("< " + read_q.front());
      read_q.pop();
      input.move_cursor(3 + buf.length(), 1);
    }

    char c = input.get_char();
    if (c < 0) {
      continue;
    } else if (c == 27) { // Escape
      client.stop();
      end_signal.push(true);
      running = false;
    } else if (c == 13) { // Enter
      if (buf == "") {
        continue;
      }
      const auto line = client.next_id() + " " + buf;
      client.write(line);
      logfile.info("> " + line);
      buf.clear();
      input.clear_line(1);
      input.write_string(1, 1, "> ");
    } else if (c == 8 || c == 127) { // Backspace
      buf = buf.substr(0, buf.length() - 1);
      input.delete_char(3 + buf.length(), 1);
    } else {
      buf += c;
      // "|> "
      input.write_char(2 + buf.length(), 1, c);
    }
  }

  client_thread.join();
  client_reader_thread.join();

  curses::cleanup();

  return 0;
}
<commit_msg>Fix end signal<commit_after>#include "client.h"
#include "config.h"
#include "curses.h"
#include "log.h"
#include "queue.h"

#include <atomic>
#include <cstdlib>
#include <experimental/filesystem>
#include <iostream>
#include <memory>
#include <queue>
#include <thread>

void client_reader(Client& client, std::queue<std::string>& read_q, std::atomic<bool>& running) {
  while (true) {
    const auto line = client.read();
    if (!line.empty()) {
      read_q.push(line);
    }
    if (!running) {
      break;
    }
  }
}

int main(int argc, char** argv) {
  fs::path config_path;
  if (argc > 1) {
    config_path = argv[1];
  } else {
    config_path = fs::path(getenv("HOME")) / ".config/courier/courier.conf";
  }

  Config config(config_path);
  if (!config.okay) {
    return 1;
  }

  const auto host = config.get("host");
  const auto port = config.get("port");

  if (!host) {
    std::cerr << "IMAP host not found in config" << std::endl;
    return 1;
  }

  if (!port) {
    std::cerr << "IMAP port not found in config" << std::endl;
    return 1;
  }

  const auto user = config.get("user");
  const auto pass = config.get("pass");

  if (!user || !pass) {
    std::cerr << "IMAP user or password not found in config" << std::endl;
    return 1;
  }

  Client client(*host, *port);
  Log logfile("courier.log");

  if (!client.connect()) {
    return 1;
  } else {
    logfile.info("Connected to " + *host + ":" + *port);
  }

  std::atomic<bool> running;
  running.store(true);
  std::queue<std::string> read_q;
  std::thread client_thread([&client]() {
    client.run();
  });
  std::thread client_reader_thread([&client, &read_q, &running]() {
    client_reader(client, read_q, running);
  });

  curses::init();

  const auto dim = curses::dimensions();

  curses::Window input(0, std::get<1>(dim) - 5, std::get<0>(dim), 5);
  input.add_border();
  input.write_string(1, 1, "> ");
  input.disable_delay();

  client.login(*user, *pass);

  std::string buf;
  buf.reserve(256);
  while (running) {
    while (!read_q.empty()) {
      logfile.info("< " + read_q.front());
      read_q.pop();
      input.move_cursor(3 + buf.length(), 1);
    }

    char c = input.get_char();
    if (c < 0) {
      continue;
    } else if (c == 27) { // Escape
      client.stop();
      running.store(false);
    } else if (c == 13) { // Enter
      if (buf.empty()) {
        continue;
      }
      const auto line = client.next_id() + " " + buf;
      client.write(line);
      logfile.info("> " + line);
      buf.clear();
      input.clear_line(1);
      input.write_string(1, 1, "> ");
    } else if (c == 8 || c == 127) { // Backspace
      buf = buf.substr(0, buf.length() - 1);
      input.delete_char(3 + buf.length(), 1);
    } else {
      buf += c;
      // "|> "
      input.write_char(2 + buf.length(), 1, c);
    }
  }

  client_thread.join();
  client_reader_thread.join();

  curses::cleanup();

  return 0;
}
<|endoftext|>


<commit_before>#include <cstdlib>

#include <iostream>
#include <memory>

#include "UI/console.hpp"
#include "pawn.hpp"

int main()
{
    Quoridor::UI::Console console(2);
    console.run();

    return EXIT_SUCCESS;
}
<commit_msg>Parse cmd with boost program_options.<commit_after>#include <cstdlib>

#include <iostream>
#include <memory>

#include <boost/program_options.hpp>

#include "UI/console.hpp"
#include "pawn.hpp"

namespace po = boost::program_options;

int main(int argc, char **argv)
{
    po::options_description options("Options");
    options.add_options()
        ("players,p", po::value<int>(), "number of players")
        ("help,h", "show help message")
        ;
    po::variables_map vm;

    try {
        po::store(po::parse_command_line(argc, argv, options), vm);
    }
    catch (po::error &e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    po::notify(vm);

    if (vm.count("help")) {
        std::cout << options << std::endl;
        return EXIT_FAILURE;
    }

    int players = 2;
    if (vm.count("players")) {
        players = vm["players"].as<int>();
    }

    Quoridor::UI::Console console(players);
    console.run();

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
	Optimal Read Normalization Algorithm:
	Developed by : Dilip A Durai and Marcel H Schulz
	ORNA uses GATB library for graph building and k-mer counting. We are thankful for their support
*/

#include <gatb/gatb_core.hpp>
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>

typedef Kmer<>::Type bloom;
static const char* STR_BASE = "-base";
static const char* STR_INPUT = "-input";
static const char* STR_OUTPUT = "-output";
static const char* STR_KMER = "-kmer";
static const char* STR_PAIR1 = "-pair1";
static const char* STR_PAIR2 = "-pair2";

int readacceptance(Graph graph, Kmer<>::ModelCanonical::Iterator itKmer, Kmer<>::ModelCanonical model, unsigned short *counter, double base){
	int acceptance=0;
	for (itKmer.first(); !itKmer.isDone(); itKmer.next())
	{
		std::string s = model.toString (itKmer->value());
		const char* sq = s.c_str();
		Node node = graph.buildNode(sq);
		double threshold=0;
		//Checking whether the node exists.
		auto index = graph.nodeMPHFIndex(node);
		auto abund = graph.queryAbundance(node);
		threshold = ceil((log(abund)/log(base)));
		if(threshold>abund)
		{
			threshold=abund;
		}
		if(threshold<1)
		{
			threshold=1;
		}
		if(counter[index] < threshold)
		{
			acceptance=acceptance+1;
			break;
			//__sync_fetch_and_add (&counter[index], 1);
	       	}
	}
	return acceptance;
}

void singleend(const char* filename, const char* out_file, double base, unsigned short kmer, int nbCores)
{
	int count=0;

	//Multithreading functionality provided by GATB library
	Dispatcher dispatcher(nbCores) ;
	ISynchronizer* sync = System::thread().newSynchronizer();	//Locking a section

	//Variables required for GATB
	IBank* InputDataset = Bank::open (filename);
	ProgressIterator<Sequence> itSeq (*InputDataset);
	IBank* OutDataset = new BankFasta (out_file);

	//Creating a graph and an iterator. from the parameters. The threshold value is kept as the minimum abundance parameter of the graph. kmer size is the actual kmer+1
	Graph graph = Graph::create (Bank::open(filename), "-kmer-size %d -abundance-min 1", kmer);
	GraphIterator<Node> it = graph.iterator();

	long node_size= it.size();
	unsigned short *counter = new unsigned short[node_size];

	//Initializing the counter for each node in the de Bruijn graph
	for(int i=0;i<node_size;i++)
	{
	    counter[i]=0;
	}

	//Iterating over sequences the GATB way
	dispatcher.iterate (itSeq, [&] (Sequence& seq)
	{
		int length = seq.getDataSize();
		int flag=1;
		int gb = 1;
		int acceptance=0;

		Kmer<>::ModelCanonical model (kmer);
		Kmer<>::ModelCanonical::Iterator itKmer (model);
		itKmer.setData (seq.getData());
		char* data = seq.getDataBuffer();

		//checking the thresholding
		if(flag==1){
			acceptance=readacceptance(graph, itKmer, model, counter, base);
		}
		if(acceptance > 0)
		{
			for (itKmer.first(); !itKmer.isDone(); itKmer.next())
			{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				//Checking whether the node exists.
				if(graph.contains(node))
	       			{
					auto index = graph.nodeMPHFIndex(node);
					__sync_fetch_and_add (&counter[index], 1);
				}
			}
			sync->lock();
			OutDataset->insert(seq);
			count++;
			sync->unlock();
		}

	});
	std::cout << "Kept " << count << " reads" <<  std::endl;

	//Free the memory
	std::string filename1 = string(filename).substr(string(filename).find_last_of("/\\") + 1);
	size_t lindex = filename1.find_last_of(".");
	filename1 = (filename1.substr(0,lindex)) + string(".h5");
	remove(filename1.c_str());

	delete [] counter;
	InputDataset->flush();
	OutDataset->flush();
}

void pairedend(const char* read1, const char* read2, const char* out_file, double base, unsigned short kmer )
{
	IBank* InputDataset1 = Bank::open (read1);
	LOCAL (InputDataset1);
        IBank* InputDataset2 = Bank::open (read2);
	LOCAL (InputDataset2);

	IBank* OutDataset = new BankFasta (out_file);

	Graph graph = Graph::create ("-in %s,%s -kmer-size %d -abundance-min 1", read1, read2, kmer);
	GraphIterator<Node> NodeIterator = graph.iterator();
	long node_size= NodeIterator.size();
	unsigned short *counter = new unsigned short[node_size];

	for(int i=0;i<node_size;i++)
        {
            counter[i]=0;
        }

	int cnt=0;
	int count=0;
	int num_sequence=0;
	int *pos;
	int size;
	int index;
	unsigned short length;
	int tmp=0;

	//Iterating paired end sequences using GATB's paired end iterator
        PairedIterator<Sequence> itPair (InputDataset1->iterator(), InputDataset2->iterator());
        for(itPair.first(); !itPair.isDone(); itPair.next())
        {
        	num_sequence++;
        }
        std::vector<int> tempBank;

	Kmer<>::ModelCanonical model (kmer);
	Kmer<>::ModelCanonical::Iterator itKmer (model);
	Kmer<>::ModelCanonical::Iterator itKmer1 (model);

	//Iteration 1

	for (itPair.first(); !itPair.isDone(); itPair.next())
        {
            Sequence& s1 = itPair.item().first;
            Sequence& s2 = itPair.item().second;

	    int acceptance1=0;
	    int acceptance2=0;

	    itKmer.setData (s1.getData());
	    itKmer1.setData (s2.getData());

	    //checking the threshold
	    acceptance1 = readacceptance(graph, itKmer, model, counter, base);
	    acceptance2 = readacceptance(graph, itKmer1, model, counter, base);
	    if(acceptance1 > 0 && acceptance2>0)
	    {
		for (itKmer.first(); !itKmer.isDone(); itKmer.next())
	    	{
			std::string s = model.toString (itKmer->value());
			const char* sq = s.c_str();
			Node node = graph.buildNode(sq);
			double threshold=0;
			//Checking whether the node exists.
			if(graph.contains(node))
			{
				auto index = graph.nodeMPHFIndex(node);
				auto abund = graph.queryAbundance(node);
				threshold = ceil((log(abund)/log(base)));
				if(threshold>abund)
				{
					threshold=abund;
				}
				if(threshold<1)
				{
					threshold=1;
				}
				if(counter[index] < threshold)
				{
					counter[index]=counter[index]+1;
				}
			}
		}
		for (itKmer1.first(); !itKmer1.isDone(); itKmer1.next())
	    	{
			std::string s = model.toString (itKmer1->value());
			const char* sq = s.c_str();
			Node node = graph.buildNode(sq);
			double threshold=0;
			//Checking whether the node exists.
			if(graph.contains(node))
			{
				auto index = graph.nodeMPHFIndex(node);
				auto abund = graph.queryAbundance(node);
				threshold = ceil((log(abund)/log(base)));
				if(threshold>abund)
				{
					threshold=abund;
				}
				if(threshold<1)
				{
					threshold=1;
				}
				if(counter[index] < threshold)
				{
					counter[index]=counter[index]+1;
				}
			}
	    	}
	    	OutDataset->insert(s1);
		OutDataset->insert(s2);
		count++;
	    }
	    else if(acceptance1>0 || acceptance2>0){
	      	tempBank.push_back(tmp);
	    }
	    else{
	    }
	    tmp++;
        }

	int coun=0;
	int tmp_index=0;
	std::cout << "Second Iteration" <<  std::endl;

	for (itPair.first(); !itPair.isDone() && tmp_index<tempBank.size(); itPair.next())
	{
        	if(coun==tempBank[tmp_index])
        	{
		    Sequence& s1 = itPair.item().first;
		    Sequence& s2 = itPair.item().second;

		    int acceptance1=0;
		    int acceptance2=0;
		    int acceptance=0;

		    itKmer.setData (s1.getData());
		    itKmer1.setData (s2.getData());

		    //checking the threshold
		    acceptance1 = readacceptance(graph, itKmer, model, counter, base);
		    acceptance2 = readacceptance(graph, itKmer1, model, counter, base);

		    if(acceptance1 > 0 || acceptance2 > 0)
		    {
			for (itKmer1.first(); !itKmer1.isDone(); itKmer1.next())
		    	{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				double threshold=0;
				//Checking whether the node exists.
				if(graph.contains(node)){
					auto index = graph.nodeMPHFIndex(node);
					auto abund = graph.queryAbundance(node);
					threshold = ceil((log(abund)/log(base)));
					if(threshold>abund){
						threshold=abund;
					}
					if(threshold<1){
						threshold=1;
					}
					if(counter[index] < threshold){
						counter[index]=counter[index]+1;
					}
				}
			}
			for (itKmer.first(); !itKmer.isDone(); itKmer.next())
		    	{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				double threshold=0;
				//Checking whether the node exists.
				if(graph.contains(node))
				{
					auto index = graph.nodeMPHFIndex(node);
					auto abund = graph.queryAbundance(node);
					threshold = ceil((log(abund)/log(base)));
					if(threshold>abund)
					{
						threshold=abund;
					}
					if(threshold<1)
					{
						threshold=1;
					}
					if(counter[index] < threshold)
					{
						counter[index]=counter[index]+1;
					}
				}
		    	}
			OutDataset->insert(s1);
			OutDataset->insert(s2);
			count++;
		   }
		   tmp_index++;
		}
		coun++;
        }
	std::cout << "kept " << count << " reads" <<  std::endl;
	bank1->flush();
	bank2->flush();
	delete [] counter;
	outBank->flush();
}

class ORNA : public Tool
{
public:
	ORNA(): Tool("ORNA")
	{
		getParser()->push_front (new OptionOneParam (STR_KMER, "kmer required",  false, "21"));
	        getParser()->push_front (new OptionOneParam (STR_INPUT, "Input File",  false, "ORNAERROR"));
	        getParser()->push_front (new OptionOneParam (STR_OUTPUT, "Output File",  false, "Normalized.fa"));
		getParser()->push_front (new OptionOneParam (STR_BASE, "Base for the logarithmic function",  false, "1.7"));
		getParser()->push_front (new OptionOneParam (STR_PAIR1, "First read of the pair", false, "ORNAERROR" ));
		getParser()->push_front (new OptionOneParam (STR_PAIR2, "Second read of the pair", false, "ORNAERROR" ));
	}
	void execute()
	{
		const char* filename = (getInput()->get(STR_INPUT))->getString();
		const char* read1= (getInput()->get(STR_PAIR1))->getString();
		const char* read2= (getInput()->get(STR_PAIR2))->getString();
		double base=getInput()->getDouble(STR_BASE);
		int user_kmer = getInput()->getInt(STR_KMER);
		const char* out_file= (getInput()->get(STR_OUTPUT))->getString();
		int nbCores = getInput()->getInt(STR_NB_CORES);
		unsigned short pairflag = 0;
		unsigned short kmer = user_kmer + 1;
		unsigned short cores = sysconf(_SC_NPROCESSORS_ONLN);
		if(nbCores==cores){
			nbCores=1;
		}
		if(std::strcmp(filename, "ORNAERROR") == 0)
		{
			if((std::strcmp(read1, "ORNAERROR") == 0) && (std::strcmp(read2, "ORNAERROR") == 0))
			{
				std::cout << "Input File(s) missing. Please refer to the help" << std::endl;
			}
			if (((std::strcmp(read1, "ORNAERROR") != 0) && (std::strcmp(read2, "ORNAERROR") == 0)) || ((std::strcmp(read1, "ORNAERROR") == 0) && (std::strcmp(read2, "ORNAERROR") != 0)))
			{
				std::cout << "One of the pair files is missing. Please refer to the help" << std::endl;
			}
			if((std::strcmp(read1, "ORNAERROR") != 0) && (std::strcmp(read2, "ORNAERROR") != 0))
			{
				pairflag = 1;
			}
		}
		if(pairflag==0)
		{
			std::cout << "Running ORNA in single end mode" << std::endl;
			singleend(filename, out_file, base, kmer, nbCores);
		}
		else
		{
			std::cout << "Running ORNA in paired end mode" << std::endl;
			pairedend(read1, read2, out_file, base, kmer);
		}
	}
};

int main (int argc, char* argv[])
{
	try{
		ORNA().run(argc,argv);
		return EXIT_SUCCESS;
	}
	catch(Exception& e){
		std::cout << "EXCEPTION: " << e.getMessage() << std::endl;
        	return EXIT_FAILURE;
	}

}

<commit_msg>Update main.cpp<commit_after>/*
	Optimal Read Normalization Algorithm:
	Developed by : Dilip A Durai and Marcel H Schulz
	ORNA uses GATB library for graph building and k-mer counting. We are thankful for their support
*/

#include <gatb/gatb_core.hpp>
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>

typedef Kmer<>::Type bloom;
static const char* STR_BASE = "-base";
static const char* STR_INPUT = "-input";
static const char* STR_OUTPUT = "-output";
static const char* STR_KMER = "-kmer";
static const char* STR_PAIR1 = "-pair1";
static const char* STR_PAIR2 = "-pair2";

int readacceptance(Graph graph, Kmer<>::ModelCanonical::Iterator itKmer, Kmer<>::ModelCanonical model, unsigned short *counter, double base){
	int acceptance=0;
	for (itKmer.first(); !itKmer.isDone(); itKmer.next())
	{
		std::string s = model.toString (itKmer->value());
		const char* sq = s.c_str();
		Node node = graph.buildNode(sq);
		double threshold=0;
		//Checking whether the node exists.
		auto index = graph.nodeMPHFIndex(node);
		auto abund = graph.queryAbundance(node);
		threshold = ceil((log(abund)/log(base)));
		if(threshold>abund)
		{
			threshold=abund;
		}
		if(threshold<1)
		{
			threshold=1;
		}
		if(counter[index] < threshold)
		{
			acceptance=acceptance+1;
			break;
			//__sync_fetch_and_add (&counter[index], 1);
	       	}
	}
	return acceptance;
}

void singleend(const char* filename, const char* out_file, double base, unsigned short kmer, int nbCores)
{
	int count=0;

	//Multithreading functionality provided by GATB library
	Dispatcher dispatcher(nbCores) ;
	ISynchronizer* sync = System::thread().newSynchronizer();	//Locking a section

	//Variables required for GATB
	IBank* InputDataset = Bank::open (filename);
	ProgressIterator<Sequence> itSeq (*InputDataset);
	IBank* OutDataset = new BankFasta (out_file);

	//Creating a graph and an iterator. from the parameters. The threshold value is kept as the minimum abundance parameter of the graph. kmer size is the actual kmer+1
	Graph graph = Graph::create (Bank::open(filename), "-kmer-size %d -abundance-min 1", kmer);
	GraphIterator<Node> it = graph.iterator();

	long node_size= it.size();
	unsigned short *counter = new unsigned short[node_size];

	//Initializing the counter for each node in the de Bruijn graph
	for(int i=0;i<node_size;i++)
	{
	    counter[i]=0;
	}

	//Iterating over sequences the GATB way
	dispatcher.iterate (itSeq, [&] (Sequence& seq)
	{
		int length = seq.getDataSize();
		int flag=1;
		int gb = 1;
		int acceptance=0;

		Kmer<>::ModelCanonical model (kmer);
		Kmer<>::ModelCanonical::Iterator itKmer (model);
		itKmer.setData (seq.getData());
		char* data = seq.getDataBuffer();

		//checking the thresholding
		if(flag==1){
			acceptance=readacceptance(graph, itKmer, model, counter, base);
		}
		if(acceptance > 0)
		{
			for (itKmer.first(); !itKmer.isDone(); itKmer.next())
			{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				//Checking whether the node exists.
				if(graph.contains(node))
	       			{
					auto index = graph.nodeMPHFIndex(node);
					__sync_fetch_and_add (&counter[index], 1);
				}
			}
			sync->lock();
			OutDataset->insert(seq);
			count++;
			sync->unlock();
		}

	});
	std::cout << "Kept " << count << " reads" <<  std::endl;

	//Free the memory
	std::string filename1 = string(filename).substr(string(filename).find_last_of("/\\") + 1);
	size_t lindex = filename1.find_last_of(".");
	filename1 = (filename1.substr(0,lindex)) + string(".h5");
	remove(filename1.c_str());

	delete [] counter;
	InputDataset->flush();
	OutDataset->flush();
}

void pairedend(const char* read1, const char* read2, const char* out_file, double base, unsigned short kmer )
{
	IBank* InputDataset1 = Bank::open (read1);
	LOCAL (InputDataset1);
        IBank* InputDataset2 = Bank::open (read2);
	LOCAL (InputDataset2);

	IBank* OutDataset = new BankFasta (out_file);

	Graph graph = Graph::create ("-in %s,%s -kmer-size %d -abundance-min 1", read1, read2, kmer);
	GraphIterator<Node> NodeIterator = graph.iterator();
	long node_size= NodeIterator.size();
	unsigned short *counter = new unsigned short[node_size];

	for(int i=0;i<node_size;i++)
        {
            counter[i]=0;
        }

	int cnt=0;
	int count=0;
	int num_sequence=0;
	int *pos;
	int size;
	int index;
	unsigned short length;
	int tmp=0;

	//Iterating paired end sequences using GATB's paired end iterator
        PairedIterator<Sequence> itPair (InputDataset1->iterator(), InputDataset2->iterator());
        for(itPair.first(); !itPair.isDone(); itPair.next())
        {
        	num_sequence++;
        }
        std::vector<int> tempBank;

	Kmer<>::ModelCanonical model (kmer);
	Kmer<>::ModelCanonical::Iterator itKmer (model);
	Kmer<>::ModelCanonical::Iterator itKmer1 (model);

	//Iteration 1

	for (itPair.first(); !itPair.isDone(); itPair.next())
        {
            Sequence& s1 = itPair.item().first;
            Sequence& s2 = itPair.item().second;

	    int acceptance1=0;
	    int acceptance2=0;

	    itKmer.setData (s1.getData());
	    itKmer1.setData (s2.getData());

	    //checking the threshold
	    acceptance1 = readacceptance(graph, itKmer, model, counter, base);
	    acceptance2 = readacceptance(graph, itKmer1, model, counter, base);
	    if(acceptance1 > 0 && acceptance2>0)
	    {
		for (itKmer.first(); !itKmer.isDone(); itKmer.next())
	    	{
			std::string s = model.toString (itKmer->value());
			const char* sq = s.c_str();
			Node node = graph.buildNode(sq);
			double threshold=0;
			//Checking whether the node exists.
			if(graph.contains(node))
			{
				auto index = graph.nodeMPHFIndex(node);
				auto abund = graph.queryAbundance(node);
				threshold = ceil((log(abund)/log(base)));
				if(threshold>abund)
				{
					threshold=abund;
				}
				if(threshold<1)
				{
					threshold=1;
				}
				if(counter[index] < threshold)
				{
					counter[index]=counter[index]+1;
				}
			}
		}
		for (itKmer1.first(); !itKmer1.isDone(); itKmer1.next())
	    	{
			std::string s = model.toString (itKmer1->value());
			const char* sq = s.c_str();
			Node node = graph.buildNode(sq);
			double threshold=0;
			//Checking whether the node exists.
			if(graph.contains(node))
			{
				auto index = graph.nodeMPHFIndex(node);
				auto abund = graph.queryAbundance(node);
				threshold = ceil((log(abund)/log(base)));
				if(threshold>abund)
				{
					threshold=abund;
				}
				if(threshold<1)
				{
					threshold=1;
				}
				if(counter[index] < threshold)
				{
					counter[index]=counter[index]+1;
				}
			}
	    	}
	    	OutDataset->insert(s1);
		OutDataset->insert(s2);
		count++;
	    }
	    else if(acceptance1>0 || acceptance2>0){
	      	tempBank.push_back(tmp);
	    }
	    else{
	    }
	    tmp++;
        }

	int coun=0;
	int tmp_index=0;
	std::cout << "Second Iteration" <<  std::endl;

	for (itPair.first(); !itPair.isDone() && tmp_index<tempBank.size(); itPair.next())
	{
        	if(coun==tempBank[tmp_index])
        	{
		    Sequence& s1 = itPair.item().first;
		    Sequence& s2 = itPair.item().second;

		    int acceptance1=0;
		    int acceptance2=0;
		    int acceptance=0;

		    itKmer.setData (s1.getData());
		    itKmer1.setData (s2.getData());

		    //checking the threshold
		    acceptance1 = readacceptance(graph, itKmer, model, counter, base);
		    acceptance2 = readacceptance(graph, itKmer1, model, counter, base);

		    if(acceptance1 > 0 || acceptance2 > 0)
		    {
			for (itKmer1.first(); !itKmer1.isDone(); itKmer1.next())
		    	{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				double threshold=0;
				//Checking whether the node exists.
				if(graph.contains(node)){
					auto index = graph.nodeMPHFIndex(node);
					auto abund = graph.queryAbundance(node);
					threshold = ceil((log(abund)/log(base)));
					if(threshold>abund){
						threshold=abund;
					}
					if(threshold<1){
						threshold=1;
					}
					if(counter[index] < threshold){
						counter[index]=counter[index]+1;
					}
				}
			}
			for (itKmer.first(); !itKmer.isDone(); itKmer.next())
		    	{
				std::string s = model.toString (itKmer->value());
				const char* sq = s.c_str();
				Node node = graph.buildNode(sq);
				double threshold=0;
				//Checking whether the node exists.
				if(graph.contains(node))
				{
					auto index = graph.nodeMPHFIndex(node);
					auto abund = graph.queryAbundance(node);
					threshold = ceil((log(abund)/log(base)));
					if(threshold>abund)
					{
						threshold=abund;
					}
					if(threshold<1)
					{
						threshold=1;
					}
					if(counter[index] < threshold)
					{
						counter[index]=counter[index]+1;
					}
				}
		    	}
			OutDataset->insert(s1);
			OutDataset->insert(s2);
			count++;
		   }
		   tmp_index++;
		}
		coun++;
        }
	std::cout << "kept " << count << " reads" <<  std::endl;
	InputDataset1->flush();
	InputDataset2->flush();
	delete [] counter;
	OutDataset->flush();
}

class ORNA : public Tool
{
public:
	ORNA(): Tool("ORNA")
	{
		getParser()->push_front (new OptionOneParam (STR_KMER, "kmer required",  false, "21"));
	        getParser()->push_front (new OptionOneParam (STR_INPUT, "Input File",  false, "ORNAERROR"));
	        getParser()->push_front (new OptionOneParam (STR_OUTPUT, "Output File",  false, "Normalized.fa"));
		getParser()->push_front (new OptionOneParam (STR_BASE, "Base for the logarithmic function",  false, "1.7"));
		getParser()->push_front (new OptionOneParam (STR_PAIR1, "First read of the pair", false, "ORNAERROR" ));
		getParser()->push_front (new OptionOneParam (STR_PAIR2, "Second read of the pair", false, "ORNAERROR" ));
	}
	void execute()
	{
		const char* filename = (getInput()->get(STR_INPUT))->getString();
		const char* read1= (getInput()->get(STR_PAIR1))->getString();
		const char* read2= (getInput()->get(STR_PAIR2))->getString();
		double base=getInput()->getDouble(STR_BASE);
		int user_kmer = getInput()->getInt(STR_KMER);
		const char* out_file= (getInput()->get(STR_OUTPUT))->getString();
		int nbCores = getInput()->getInt(STR_NB_CORES);
		unsigned short pairflag = 0;
		unsigned short kmer = user_kmer + 1;
		unsigned short cores = sysconf(_SC_NPROCESSORS_ONLN);
		if(nbCores==cores){
			nbCores=1;
		}
		if(std::strcmp(filename, "ORNAERROR") == 0)
		{
			if((std::strcmp(read1, "ORNAERROR") == 0) && (std::strcmp(read2, "ORNAERROR") == 0))
			{
				std::cout << "Input File(s) missing. Please refer to the help" << std::endl;
			}
			if (((std::strcmp(read1, "ORNAERROR") != 0) && (std::strcmp(read2, "ORNAERROR") == 0)) || ((std::strcmp(read1, "ORNAERROR") == 0) && (std::strcmp(read2, "ORNAERROR") != 0)))
			{
				std::cout << "One of the pair files is missing. Please refer to the help" << std::endl;
			}
			if((std::strcmp(read1, "ORNAERROR") != 0) && (std::strcmp(read2, "ORNAERROR") != 0))
			{
				pairflag = 1;
			}
		}
		if(pairflag==0)
		{
			std::cout << "Running ORNA in single end mode" << std::endl;
			singleend(filename, out_file, base, kmer, nbCores);
		}
		else
		{
			std::cout << "Running ORNA in paired end mode" << std::endl;
			pairedend(read1, read2, out_file, base, kmer);
		}
	}
};

int main (int argc, char* argv[])
{
	try{
		ORNA().run(argc,argv);
		return EXIT_SUCCESS;
	}
	catch(Exception& e){
		std::cout << "EXCEPTION: " << e.getMessage() << std::endl;
        	return EXIT_FAILURE;
	}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <cstdint>
#include <exception>

#include "components/command_line.hpp"
#include "spdlog/spdlog.h"
#include "config.hpp"

using add_arg = command_line::option;

int main(int argc, char *argv[])
{
    const command_line::options opts{
        add_arg("-h", "--help",      "Display this text and exit "),
        add_arg("-v", "--version",   "Print version information"),
        add_arg("-l", "--log",       "Set logging level to info"),

        /* Exclusive arguments; cannot be combined with any other arguments. */
        add_arg("-d", "--ident",     "Specify an item identification (such as DOI, URL, etc.)", "IDENT"),

        /* Main arguments; at least one of these are required. */
        /* auto main = command_line::add_group( */
        /*     "main", "necessarily inclusive arguments; at least one required" */
        /* ); */
        add_arg("-a", "--author",    "Specify authors", "AUTHOR"),
        add_arg("-t", "--title",     "Specify title", "TITLE"),
        add_arg("-s", "--serie",     "Specify serie", "SERIE"),
        add_arg("-p", "--publisher", "Specify publisher", "PUBLISHER"),

        /* Exact data arguments; all are optional. */
        add_arg("-y", "--year",      "Specify year of release", "YEAR"),
        add_arg("-L", "--language",  "Specify text language", "LANG"),
        add_arg("-e", "--edition",   "Specify item edition", "EDITION"),
        add_arg("-E", "--extension", "Specify item extension", "EXT",
                {"epub", "pdf", "djvu"}),
        add_arg("-i", "--isbn",      "Specify item ISBN", "ISBN"),
    };

    uint8_t exit_code = EXIT_SUCCESS;

    auto logger = spdlog::stdout_color_mt("logger");
    spdlog::set_pattern("%l: %v");
    spdlog::set_level(spdlog::level::err);

    try {
        /* Parse command line arguments. */
        std::string progname = argv[0];
        std::vector<std::string> args(argv + 1, argv + argc);

        cliparser::make_type cli = cliparser::make(std::move(progname), std::move(opts));
        cli->process_arguments(args);

        if (cli->has("log"))
            spdlog::set_level(spdlog::level::info);

        logger->info("the mighty eldwyrm has been summoned!");

        if (cli->has("help")) {
            cli->usage();
            return EXIT_SUCCESS;
        } else if (cli->has("version")) {
            print_build_info();
            return EXIT_SUCCESS;
        } else if (args.empty()) {
            cli->usage();
            return EXIT_FAILURE;
        }

    } catch (const std::exception &err) {
        logger->error(err.what());
        exit_code = EXIT_FAILURE;
    }

    return exit_code;
}
<commit_msg>don't forget to drop all loggers<commit_after>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <cstdint>
#include <exception>

#include "components/command_line.hpp"
#include "spdlog/spdlog.h"
#include "config.hpp"

using add_arg = command_line::option;

int main(int argc, char *argv[])
{
    const command_line::options opts{
        add_arg("-h", "--help",      "Display this text and exit "),
        add_arg("-v", "--version",   "Print version information"),
        add_arg("-l", "--log",       "Set logging level to info"),

        /* Exclusive arguments; cannot be combined with any other arguments. */
        add_arg("-d", "--ident",     "Specify an item identification (such as DOI, URL, etc.)", "IDENT"),

        /* Main arguments; at least one of these are required. */
        /* auto main = command_line::add_group( */
        /*     "main", "necessarily inclusive arguments; at least one required" */
        /* ); */
        add_arg("-a", "--author",    "Specify authors", "AUTHOR"),
        add_arg("-t", "--title",     "Specify title", "TITLE"),
        add_arg("-s", "--serie",     "Specify serie", "SERIE"),
        add_arg("-p", "--publisher", "Specify publisher", "PUBLISHER"),

        /* Exact data arguments; all are optional. */
        add_arg("-y", "--year",      "Specify year of release", "YEAR"),
        add_arg("-L", "--language",  "Specify text language", "LANG"),
        add_arg("-e", "--edition",   "Specify item edition", "EDITION"),
        add_arg("-E", "--extension", "Specify item extension", "EXT",
                {"epub", "pdf", "djvu"}),
        add_arg("-i", "--isbn",      "Specify item ISBN", "ISBN"),
    };

    uint8_t exit_code = EXIT_SUCCESS;

    auto logger = spdlog::stdout_color_mt("logger");
    spdlog::set_pattern("%l: %v");
    spdlog::set_level(spdlog::level::err);

    try {
        /* Parse command line arguments. */
        std::string progname = argv[0];
        std::vector<std::string> args(argv + 1, argv + argc);

        cliparser::make_type cli = cliparser::make(std::move(progname), std::move(opts));
        cli->process_arguments(args);

        if (cli->has("log"))
            spdlog::set_level(spdlog::level::info);

        logger->info("the mighty eldwyrm has been summoned!");

        if (cli->has("help")) {
            cli->usage();
            return EXIT_SUCCESS;
        } else if (cli->has("version")) {
            print_build_info();
            return EXIT_SUCCESS;
        } else if (args.empty()) {
            cli->usage();
            return EXIT_FAILURE;
        }

    } catch (const std::exception &err) {
        logger->error(err.what());
        exit_code = EXIT_FAILURE;
    }

    spdlog::drop_all();
    return exit_code;
}
<|endoftext|>


<commit_before>#include "../config.h"
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <runningaverage.h>

#ifdef SENSOR_DS18S20
#include <OneWire.h>
#define ONE_WIRE_BUS 2  // DS18S20 pin
OneWire ds(ONE_WIRE_BUS);
#endif

#ifdef SENSOR_DHT22
#include <DHT.h>
#include "../config.h"
#define DHTPIN  2
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
#endif

MDNSResponder mdns;
ESP8266WebServer server(80);
RunningAverage temp_aggregator(6);
RunningAverage hum_aggregator(6);
bool sensor_ok = false;
enum SensorState {
	MEASURED_OK,
	MEASURED_FAILED,
	TOO_EARLY
};

String webString="";     // String to display
// Generally, you should use "unsigned long" for variables that hold time
unsigned long previousMillis = 0;        // will store last temp was read
const long interval = 10000;             // interval at which to read sensor

int ICACHE_FLASH_ATTR gettemperature(float& temp, float& humidity) {
  // Wait at least 2 seconds seconds between measurements.
  // if the difference between the current time and last time you read
  // the sensor is bigger than the interval you set, read the sensor
  // Works better than delay for things happening elsewhere also
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis >= interval) {
    // save the last time you read the sensor
    previousMillis = currentMillis;

#ifdef SENSOR_DS18S20
		// This is the code for receiving temperature readings from a DS18S20.
		// see https://github.com/esp8266/Arduino/blob/esp8266/libraries/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde
		byte i;
		byte present = 0;
		byte type_s;
		byte data[12];
		byte addr[8];

		ds.reset();
		ds.reset_search();
		if ( !ds.search(addr)) {
			Serial.println("No more addresses.");
			Serial.println();
			ds.reset_search();
			delay(250);
			return MEASURED_FAILED;
		}

		//Serial.print("ROM =");
		//for( i = 0; i < 8; i++) {
		//	Serial.write(' ');
		//	Serial.print(addr[i], HEX);
		//}

		if (OneWire::crc8(addr, 7) != addr[7]) {
			Serial.println("CRC is not valid!");
			return MEASURED_FAILED;
		}
		//Serial.println();

		// the first ROM byte indicates which chip
		switch (addr[0]) {
			case 0x10:
				//Serial.println("  Chip = DS18S20");  // or old DS1820
				type_s = 1;
				break;
			case 0x28:
				//Serial.println("  Chip = DS18B20");
				type_s = 0;
				break;
			case 0x22:
				//Serial.println("  Chip = DS1822");
				type_s = 0;
				break;
			default:
				Serial.println("Device is not a DS18x20 family device.");
				return MEASURED_FAILED;
		}

		ds.reset();
		ds.select(addr);
		ds.write(0x44, 0);        // start conversion, no parasitic power

		delay(750);     // maybe 750ms is enough, maybe not
		// we might do a ds.depower() here, but the reset will take care of it.

		present = ds.reset();
		ds.select(addr);
		ds.write(0xBE);         // Read Scratchpad

		//Serial.print("  Data = ");
		//Serial.print(present, HEX);
		//Serial.print(" ");
		for ( i = 0; i < 9; i++) {           // we need 9 bytes
			data[i] = ds.read();
			//Serial.print(data[i], HEX);
			//Serial.print(" ");
		}
		//Serial.print(" CRC=");
		//Serial.print(OneWire::crc8(data, 8), HEX);
		//Serial.println();

		// Convert the data to actual temperature
		// because the result is a 16 bit signed integer, it should
		// be stored to an "int16_t" type, which is always 16 bits
		// even when compiled on a 32 bit processor.
		int16_t raw = (data[1] << 8) | data[0];
		if (type_s) {
			raw = raw << 3; // 9 bit resolution default
			if (data[7] == 0x10) {
				// "count remain" gives full 12 bit resolution
				raw = (raw & 0xFFF0) + 12 - data[6];
			}
		} else {
			byte cfg = (data[4] & 0x60);
			// at lower res, the low bits are undefined, so let's zero them
			if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
			else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
			else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
			//// default is 12 bit resolution, 750 ms conversion time
		}
		temp = (float)raw / 16.0;
		//Serial.print("Temperature: ");
		//Serial.println(temp);
#endif // of DS18S20-related code

#ifdef SENSOR_DHT22 // Read temp&hum from DHT22
		// Reading temperature for humidity takes about 250 milliseconds!
		// Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
		humidity = dht.readHumidity();          // Read humidity (percent)
		temp = dht.readTemperature(false);     // Read temperature as Celsius
#endif

		//Serial.print("Free heap:");
		//Serial.println(ESP.getFreeHeap(),DEC);

		if (isnan(temp) || temp==85.0 || temp==(-127.0)) {
			Serial.println("Failed to read from sensor");
			// resetting the previous measurement time so that a failed attempt
			// will be repeated with the next query.
			previousMillis=currentMillis-2000;
			if (previousMillis < 0) previousMillis = 0;
			return MEASURED_FAILED;
		} else {
			return MEASURED_OK;
		}
	} else {
		return TOO_EARLY; // no measurement taken - time not elapsed
	}
}

void ICACHE_FLASH_ATTR handleNotFound(){
	String message = "File Not Found\n\n";
	message += "URI: ";
	message += server.uri();
	message += "\nMethod: ";
	message += (server.method() == HTTP_GET)?"GET":"POST";
	message += "\nArguments: ";
	message += server.args();
	message += "\n";
	for (uint8_t i=0; i<server.args(); i++){
		message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
	}
	server.send(404, "text/plain", message);
}

void ICACHE_FLASH_ATTR setup(void){
	Serial.begin(9600);
	WiFi.begin(ssid, password);
	Serial.println("");
	Serial.println("Wifi temperature sensor v0.1");

	// Wait for connection
	while (WiFi.status() != WL_CONNECTED) {
		delay(500);
		Serial.print(".");
	}

	Serial.println("");
	Serial.print("Connected to ");
	Serial.println(ssid);
	Serial.print("IP address: ");
	Serial.println(WiFi.localIP());

	if (mdns.begin(hostname, WiFi.localIP())) {
		Serial.println("MDNS responder started");
	}

	server.on("/", [](){
			if (sensor_ok) {       // read sensor
				webString = "Sensor " + String(hostname) + " reports:\n";
				webString+="Temperature: "+String(temp_aggregator.getAverage())+" degree Celsius\n";
#ifdef SENSOR_DHT22 // Read temp&hum from DHT22
				webString+="Humidity: "+String(hum_aggregator.getAverage())+" % r.H.\n";
#endif
				server.send(200, "text/plain", webString);            // send to someones browser when asked
			} else {
				webString="{\"error\": \"Cannot read data from sensor.\"";
				server.send(503, "text/plain", webString);            // send to someones browser when asked
			}
			});
	server.on("/temperature", [](){
			if (sensor_ok) {       // read sensor
				webString="{\"temperature\": "+String(temp_aggregator.getAverage())+",\"unit\": \"Celsius\"}";
				server.send(200, "text/plain", webString);            // send to someones browser when asked
			} else {
				webString="{\"error\": \"Cannot read data from sensor.\"";
				server.send(503, "text/plain", webString);            // send to someones browser when asked
			}
			});
#ifdef SENSOR_DHT22 // Read humidity from DHT22
	server.on("/humidity", [](){
			if (sensor_ok) {       // read sensor
				webString="{\"humidity\": "+String(hum_aggregator.getAverage())+",\"unit\": \"% r.H.\"}";
				server.send(200, "text/plain", webString);            // send to someones browser when asked
			} else {
				webString="{\"error\": \"Cannot read data from sensor.\"";
				server.send(503, "text/plain", webString);            // send to someones browser when asked
			}
			});

#endif

	server.onNotFound(handleNotFound);

	server.begin();
	ESP.wdtEnable(5000);
}

void ICACHE_FLASH_ATTR loop(void){
	server.handleClient();
	ESP.wdtFeed();
	float temp = 0.0;
	float humidity = 0.0;
	switch (gettemperature(temp, humidity)) {
		case MEASURED_OK:
			sensor_ok = true;
			Serial.println("Updating accumulator w/ new measurements");
			temp_aggregator.addValue(temp);
			hum_aggregator.addValue(humidity);
			break;
		case MEASURED_FAILED:
			Serial.println("Measurement failed");
			sensor_ok = false;
			break;
		case TOO_EARLY:
			;;
			break;
	}
}

<commit_msg>scanning onewire bus for more than one sensor - still need a multiplexer for the runningaverage class<commit_after>#include "../config.h"
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <runningaverage.h>

#ifdef SENSOR_DS18S20
#include <OneWire.h>
#define ONE_WIRE_BUS 2  // DS18S20 pin
OneWire ds(ONE_WIRE_BUS);
#endif

#ifdef SENSOR_DHT22
#include <DHT.h>
#include "../config.h"
#define DHTPIN  2
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
#endif

MDNSResponder mdns;
ESP8266WebServer server(80);
RunningAverage temp_aggregator(6);
RunningAverage hum_aggregator(6);
bool sensor_ok = false;
enum SensorState {
	MEASURED_OK,
	MEASURED_FAILED,
	TOO_EARLY
};

String webString="";     // String to display
// Generally, you should use "unsigned long" for variables that hold time
unsigned long previousMillis = 0;        // will store last temp was read
const long interval = 10000;             // interval at which to read sensor

// read the sensor with the given bus index. Sets temperature in temp,
// humidity in humidity. Returns the SensorState.
int ICACHE_FLASH_ATTR read_sensors(byte bus_idx, float& temp, float& humidity) {
  // Wait at least 2 seconds seconds between measurements.
  // if the difference between the current time and last time you read
  // the sensor is bigger than the interval you set, read the sensor
  // Works better than delay for things happening elsewhere also
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis >= interval) {
    // save the last time you read the sensor
    previousMillis = currentMillis;

#ifdef SENSOR_DS18S20
		// This is the code for receiving temperature readings from a DS18S20.
		// see https://github.com/esp8266/Arduino/blob/esp8266/libraries/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde
		byte i;
		byte present = 0;
		byte type_s;
		byte data[12];
		byte max_addr = 4;
		byte addr[max_addr][8]; // can hold four addresses of 8 byte each
		byte addr_count = 0;

		ds.reset();
		ds.reset_search();

		for (addr_count = 0; addr_count < max_addr; ++addr_count) {
			if ( !ds.search(addr[addr_count])) {
				//Serial.println("No more addresses.");
				ds.reset_search();
				delay(250);
				break;
			} //else {
				//Serial.print("found address ");
				//for( i = 0; i < 8; i++) {
				//	Serial.write(' ');
				//	Serial.print(addr[addr_count][i], HEX);
				//}
				//Serial.println();
			//}
		}

		//Serial.print("found ");
		//Serial.print(addr_count);
		//Serial.println(" addresses.");

		if (addr_count == 0) {
			Serial.println("No sensors found.");
			return MEASURED_FAILED;
		}

		if (bus_idx >= addr_count) {
			Serial.print("Requested sensor ");
			Serial.print(bus_idx);
			Serial.println(" but not that many sensors on bus.");
			return MEASURED_FAILED;
		}

		if (OneWire::crc8(addr[bus_idx], 7) != addr[bus_idx][7]) {
			Serial.println("CRC is not valid!");
			return MEASURED_FAILED;
		}
		//Serial.println();

		// the first ROM byte indicates which chip
		switch (addr[bus_idx][0]) {
			case 0x10:
				//Serial.println("  Chip = DS18S20");  // or old DS1820
				type_s = 1;
				break;
			case 0x28:
				//Serial.println("  Chip = DS18B20");
				type_s = 0;
				break;
			case 0x22:
				//Serial.println("  Chip = DS1822");
				type_s = 0;
				break;
			default:
				Serial.println("Device is not a DS18x20 family device.");
				return MEASURED_FAILED;
		}

		ds.reset();
		ds.select(addr[bus_idx]);

		ds.write(0x44, 0);        // start conversion, no parasitic power

		delay(750);     // maybe 750ms is enough, maybe not
		// we might do a ds.depower() here, but the reset will take care of it.

		present = ds.reset();
		ds.select(addr[bus_idx]);
		ds.write(0xBE);         // Read Scratchpad

		//Serial.print("  Data = ");
		//Serial.print(present, HEX);
		//Serial.print(" ");
		for ( i = 0; i < 9; i++) {           // we need 9 bytes
			data[i] = ds.read();
			//Serial.print(data[i], HEX);
			//Serial.print(" ");
		}
		//Serial.print(" CRC=");
		//Serial.print(OneWire::crc8(data, 8), HEX);
		//Serial.println();

		// Convert the data to actual temperature
		// because the result is a 16 bit signed integer, it should
		// be stored to an "int16_t" type, which is always 16 bits
		// even when compiled on a 32 bit processor.
		int16_t raw = (data[1] << 8) | data[0];
		if (type_s) {
			raw = raw << 3; // 9 bit resolution default
			if (data[7] == 0x10) {
				// "count remain" gives full 12 bit resolution
				raw = (raw & 0xFFF0) + 12 - data[6];
			}
		} else {
			byte cfg = (data[4] & 0x60);
			// at lower res, the low bits are undefined, so let's zero them
			if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
			else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
			else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
			//// default is 12 bit resolution, 750 ms conversion time
		}
		temp = (float)raw / 16.0;
		//Serial.print("Temperature: ");
		//Serial.println(temp);
#endif // of DS18S20-related code

#ifdef SENSOR_DHT22 // Read temp&hum from DHT22
		// Reading temperature for humidity takes about 250 milliseconds!
		// Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
		humidity = dht.readHumidity();          // Read humidity (percent)
		temp = dht.readTemperature(false);     // Read temperature as Celsius
#endif

		//Serial.print("Free heap:");
		//Serial.println(ESP.getFreeHeap(),DEC);

		if (isnan(temp) || temp==85.0 || temp==(-127.0)) {
			Serial.println("Failed to read from sensor");
			// resetting the previous measurement time so that a failed attempt
			// will be repeated with the next query.
			previousMillis=currentMillis-2000;
			if (previousMillis < 0) previousMillis = 0;
			return MEASURED_FAILED;
		} else {
			return MEASURED_OK;
		}
	} else {
		return TOO_EARLY; // no measurement taken - time not elapsed
	}
}

void ICACHE_FLASH_ATTR handleNotFound(){
	String message = "File Not Found\n\n";
	message += "URI: ";
	message += server.uri();
	message += "\nMethod: ";
	message += (server.method() == HTTP_GET)?"GET":"POST";
	message += "\nArguments: ";
	message += server.args();
	message += "\n";
	for (uint8_t i=0; i<server.args(); i++){
		message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
	}
	server.send(404, "text/plain", message);
}

void ICACHE_FLASH_ATTR setup(void){
	Serial.begin(9600);
	WiFi.begin(ssid, password);
	Serial.println("");
	Serial.println("Wifi temperature sensor v0.1");

	// Wait for connection
	while (WiFi.status() != WL_CONNECTED) {
		delay(500);
		Serial.print(".");
	}

	Serial.println("");
	Serial.print("Connected to ");
	Serial.println(ssid);
	Serial.print("IP address: ");
	Serial.println(WiFi.localIP());

	if (mdns.begin(mdnsname, WiFi.localIP())) {
		Serial.println("MDNS responder started");
	}

	server.on("/", [](){
			if (sensor_ok) {       // read sensor
				webString = "Sensor " + String(mdnsname) + " reports:\n";
				webString+="Temperature: "+String(temp_aggregator.getAverage())+" degree Celsius\n";
#ifdef SENSOR_DHT22 // Read temp&hum from DHT22
				webString+="Humidity: "+String(hum_aggregator.getAverage())+" % r.H.\n";
#endif
				server.send(200, "text/plain", webString);            // send to someones browser when asked
			} else {
				webString="{\"error\": \"Cannot read data from sensor.\"";
				server.send(503, "text/plain", webString);            // send to someones browser when asked
			}
			});
	server.on("/temperature", [](){
			if (sensor_ok) {       // read sensor
				webString="{\"temperature\": "+String(temp_aggregator.getAverage())+",\"unit\": \"Celsius\"}";
				server.send(200, "text/plain", webString);            // send to someones browser when asked
			} else {
				webString="{\"error\": \"Cannot read data from sensor.\"";
				server.send(503, "text/plain", webString);            // send to someones browser when asked
			}
			});
#ifdef SENSOR_DHT22 // Read humidity from DHT22
	server.on("/humidity", [](){
			if (sensor_ok) {       // read sensor
				webString="{\"humidity\": "+String(hum_aggregator.getAverage())+",\"unit\": \"% r.H.\"}";
				server.send(200, "text/plain", webString);            // send to someones browser when asked
			} else {
				webString="{\"error\": \"Cannot read data from sensor.\"";
				server.send(503, "text/plain", webString);            // send to someones browser when asked
			}
			});

#endif

	server.onNotFound(handleNotFound);

	server.begin();
	ESP.wdtEnable(5000);
}

void ICACHE_FLASH_ATTR loop(void){
	server.handleClient();
	ESP.wdtFeed();
	float temp = 0.0;
	float humidity = 0.0;
	switch (read_sensors(0, temp, humidity)) {
		case MEASURED_OK:
			sensor_ok = true;
			//Serial.println("Updating accumulator w/ new measurements");
			temp_aggregator.addValue(temp);
			hum_aggregator.addValue(humidity);
			break;
		case MEASURED_FAILED:
			Serial.println("Measurement failed");
			sensor_ok = false;
			break;
		case TOO_EARLY:
			;;
			break;
	}
}

<|endoftext|>


<commit_before>#ifndef _PNMC_MC_STATISTICS_HH_
#define _PNMC_MC_STATISTICS_HH_

#include <chrono>
#include <iosfwd>

#include "conf/configuration.hh"

namespace pnmc { namespace mc {

/*------------------------------------------------------------------------------------------------*/

struct statistics
{
  const conf::pnmc_configuration& conf;

  std::chrono::duration<double> relation_duration;
  std::chrono::duration<double> rewrite_duration;
  std::chrono::duration<double> state_space_duration;
  std::chrono::duration<double> dead_states_relation_duration;
  std::chrono::duration<double> dead_states_rewrite_duration;
  std::chrono::duration<double> dead_states_duration;

  long double nb_states;

  bool interrupted ;

  statistics(const conf::pnmc_configuration& c)
    : conf(c), relation_duration(), rewrite_duration(), state_space_duration()
    , dead_states_relation_duration(), dead_states_rewrite_duration(), dead_states_duration()
    , nb_states(0), interrupted(false)
  {}

  template<class Archive>
  void
  save(Archive& archive)
  const
  {
    archive( cereal::make_nvp("interrupted", interrupted)
           , cereal::make_nvp("relation time", relation_duration.count())
           , cereal::make_nvp("rewrite time", rewrite_duration.count())
           , cereal::make_nvp("state space time", state_space_duration.count())
           );

    if (conf.compute_dead_states)
    {
      archive( cereal::make_nvp("dead states relation time", dead_states_relation_duration.count())
             , cereal::make_nvp("dead states rewrite time", dead_states_rewrite_duration.count())
             , cereal::make_nvp("dead states time", dead_states_duration.count())
             );
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::mc

#endif // _PNMC_MC_STATISTICS_HH_
<commit_msg>Put the number of states in the JSON statistics file.<commit_after>#ifndef _PNMC_MC_STATISTICS_HH_
#define _PNMC_MC_STATISTICS_HH_

#include <chrono>
#include <iosfwd>

#include "conf/configuration.hh"

namespace pnmc { namespace mc {

/*------------------------------------------------------------------------------------------------*/

struct statistics
{
  const conf::pnmc_configuration& conf;

  std::chrono::duration<double> relation_duration;
  std::chrono::duration<double> rewrite_duration;
  std::chrono::duration<double> state_space_duration;
  std::chrono::duration<double> dead_states_relation_duration;
  std::chrono::duration<double> dead_states_rewrite_duration;
  std::chrono::duration<double> dead_states_duration;

  long double nb_states;

  bool interrupted;

  statistics(const conf::pnmc_configuration& c)
    : conf(c), relation_duration(), rewrite_duration(), state_space_duration()
    , dead_states_relation_duration(), dead_states_rewrite_duration(), dead_states_duration()
    , nb_states(0), interrupted(false)
  {}

  template<class Archive>
  void
  save(Archive& archive)
  const
  {
    archive( cereal::make_nvp("interrupted", interrupted)
           , cereal::make_nvp("states", nb_states)
           , cereal::make_nvp("states as string", std::to_string(nb_states))
           , cereal::make_nvp("relation time", relation_duration.count())
           , cereal::make_nvp("rewrite time", rewrite_duration.count())
           , cereal::make_nvp("state space time", state_space_duration.count())
           );

    if (conf.compute_dead_states)
    {
      archive( cereal::make_nvp("dead states relation time", dead_states_relation_duration.count())
             , cereal::make_nvp("dead states rewrite time", dead_states_rewrite_duration.count())
             , cereal::make_nvp("dead states time", dead_states_duration.count())
             );
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::mc

#endif // _PNMC_MC_STATISTICS_HH_
<|endoftext|>


<commit_before>#include "overlap.h"

namespace MHAP {

  uint32_t Overlap::read1_id() const {
    return a_id;
  }

  uint32_t Overlap::read2_id() const {
    return b_id;
  }

  bool Overlap::use_prefix(uint32_t read_id) const {
    if (read_id == a_id) {
      return a_lo == 0;
    } else if (read_id == b_id) {
      return b_lo == 0;
    }

    return false;
  }

  bool Overlap::use_suffix(uint32_t read_id) const {
    if (read_id == a_id) {
      return a_hi == a_len;
    } else if (read_id == b_id) {
      return b_hi == b_len;
    }

    return false;
  }
}
<commit_msg>mhap: fix use_suffix and use_prefix functions for rc reads<commit_after>#include "overlap.h"

namespace MHAP {

  uint32_t Overlap::read1_id() const {
    return a_id;
  }

  uint32_t Overlap::read2_id() const {
    return b_id;
  }

  bool Overlap::use_prefix(uint32_t read_id) const {
    if (read_id == a_id) {
      if (a_fwd) {
        return a_lo == 0;
      } else {
        return a_hi == a_len;
      }
    } else if (read_id == b_id) {
      if (b_fwd) {
        return b_lo == 0;
      } else {
        return b_hi == b_len;
      }
    }

    return false;
  }

  bool Overlap::use_suffix(uint32_t read_id) const {
    if (read_id == a_id) {
      if (a_fwd) {
        return a_hi == a_len;
      } else {
        return a_lo == 0;
      }
    } else if (read_id == b_id) {
      if (a_fwd) {
        return b_hi == b_len;
      } else {
        return b_lo == 0;
      }
    }

    return false;
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <memory>
#include <vector>

/*  Neste problema, pede-se para armazenar, gerenciar e buscar por
    indivíduos definidos por
        um identificador único (inteiro)
        Primeiro nome
        último nome,
        data de nascimento
        telefone.
*/
struct Person
{
    Person( int _id = 0,
            const std::string &_first_name = "",
            const std::string &_last_name = "",
            const std::string &_birthday = "",
            const std::string &_phone = ""):
        id(_id),
        first_name(_first_name),
        last_name(_last_name),
        birthday(_birthday),
        phone(_phone)
        {
        }
    int id;
    std::string first_name;
    std::string last_name;
    std::string birthday;
    std::string phone;
    std::shared_ptr<Person> collision;
};

typedef std::shared_ptr<Person> Person_ptr;
typedef std::vector<Person_ptr> HashTable;

class PersonManager
{
    public:
        PersonManager(void):
            max_elements(503),
            id_table(max_elements),
            fn_table(max_elements),
            ln_table(max_elements),
            birth_table(max_elements),
            phone_table(max_elements)
        {
        }

        /*  somente imprime na saída quando ocorre erro na inserção de um individuo,
            ocorrida na inserção de individuo com identificador duplicado.
        */
        void add(int id,
            const std::string &first_name,
            const std::string &last_name,
            const std::string &birthday,
            const std::string &phone)
        {
            if((id < 0) || (id > max_elements))
            {
                std::cout << "invalid id" << std::endl;
                return;
            }

            if(id_table[id] != NULL)
            {
                std::cout << "ID " << id << " ja cadastrado." << std::endl;
            }

            std::shared_ptr<Person> person(new Person(id,first_name,last_name,birthday,phone));

            id_table[id] = person;

            unsigned int hash_number = hash(first_name);

            insert_on_table(fn_table,person,hash_number);

            hash_number = hash(last_name);
            insert_on_table(ln_table,person,hash_number);

            hash_number = hash(birthday);
            insert_on_table(birth_table,person,hash_number);

            hash_number = hash(phone);
            insert_on_table(phone_table,person,hash_number);
        }

        /*  O comando ''del'' remove todos dados relacionados a um determinado identificador,
            e retorna erro se não existir individuo com o identificador fornecido.
        */
        void del(int id)
        {
            if((id < 0) || (id > max_elements) || (id_table[id] == NULL))
            {
                std::cout << "ID " << id << " nao existente" << std::endl;
                return;
            }

            remove_from_table(fn_table,id_table[id],hash(id_table[id]->first_name));
            remove_from_table(ln_table,id_table[id],hash(id_table[id]->last_name));
            remove_from_table(birth_table,id_table[id],hash(id_table[id]->birthday));
            remove_from_table(phone_table,id_table[id],hash(id_table[id]->phone));
            id_table[id].reset();
        }
    private:
        const unsigned int max_elements; // Large prime number chosen
        HashTable id_table;
        HashTable fn_table;
        HashTable ln_table;
        HashTable birth_table;
        HashTable phone_table;

        unsigned int hash(const std::string &str)
        {
            unsigned int hash_number = 0;
            unsigned int mult = 1;

            for(char c : str)
            {
                hash_number += c * mult;
                ++mult;
            }

            return hash_number % max_elements;
        }

        void insert_on_table(HashTable &table,Person_ptr person,unsigned int hash_number)
        {
            if(table[hash_number] != NULL)
            {
                person->collision = table[hash_number];
            }

            table[hash_number] = person;
        }

        void remove_from_table(HashTable &table,Person_ptr person,unsigned int hash_number)
        {
            if(table[hash_number] != NULL)
            {
                Person_ptr last_person;
                Person_ptr people_itr = table[hash_number];
                do
                {
                    if(people_itr->id == person->id)
                    {
                        break;
                    }
                    last_person = people_itr;
                    people_itr = people_itr->collision;
                }while(people_itr != NULL);

                if(last_person != NULL)
                {
                    last_person->collision = people_itr->collision;
                    people_itr.reset();
                }
                else
                {
                    table[hash_number] = table[hash_number]->collision;
                }
            }
        }
};

int main(void)
{
    return 0;
}
<commit_msg>info coded<commit_after>#include <iostream>
#include <string>
#include <memory>
#include <vector>

/*  Neste problema, pede-se para armazenar, gerenciar e buscar por
    indivíduos definidos por
        um identificador único (inteiro)
        Primeiro nome
        último nome,
        data de nascimento
        telefone.
*/
struct Person
{
    Person( int _id = 0,
            const std::string &_first_name = "",
            const std::string &_last_name = "",
            const std::string &_birthday = "",
            const std::string &_phone = ""):
        id(_id),
        first_name(_first_name),
        last_name(_last_name),
        birthday(_birthday),
        phone(_phone)
        {
        }
    int id;
    std::string first_name;
    std::string last_name;
    std::string birthday;
    std::string phone;
    std::shared_ptr<Person> collision;
};

typedef std::shared_ptr<Person> Person_ptr;
typedef std::vector<Person_ptr> HashTable;

class PersonManager
{
    public:
        PersonManager(void):
            max_elements(503),
            id_table(max_elements),
            fn_table(max_elements),
            ln_table(max_elements),
            birth_table(max_elements),
            phone_table(max_elements)
        {
        }

        /*  somente imprime na saída quando ocorre erro na inserção de um individuo,
            ocorrida na inserção de individuo com identificador duplicado.
        */
        void add(int id,
            const std::string &first_name,
            const std::string &last_name,
            const std::string &birthday,
            const std::string &phone)
        {
            if((id < 0) || (id > max_elements))
            {
                std::cout << "invalid id" << std::endl;
                return;
            }

            if(id_table[id] != NULL)
            {
                std::cout << "ID " << id << " ja cadastrado." << std::endl;
            }

            std::shared_ptr<Person> person(new Person(id,first_name,last_name,birthday,phone));

            id_table[id] = person;

            unsigned int hash_number = hash(first_name);

            insert_on_table(fn_table,person,hash_number);

            hash_number = hash(last_name);
            insert_on_table(ln_table,person,hash_number);

            hash_number = hash(birthday);
            insert_on_table(birth_table,person,hash_number);

            hash_number = hash(phone);
            insert_on_table(phone_table,person,hash_number);
        }

        /*  O comando ''del'' remove todos dados relacionados a um determinado identificador,
            e retorna erro se não existir individuo com o identificador fornecido.
        */
        void del(int id)
        {
            if((id < 0) || (id > max_elements) || (id_table[id] == NULL))
            {
                std::cout << "ID " << id << " nao existente" << std::endl;
                return;
            }

            remove_from_table(fn_table,id_table[id],hash(id_table[id]->first_name));
            remove_from_table(ln_table,id_table[id],hash(id_table[id]->last_name));
            remove_from_table(birth_table,id_table[id],hash(id_table[id]->birthday));
            remove_from_table(phone_table,id_table[id],hash(id_table[id]->phone));
            id_table[id].reset();
        }

        void info(int id)
        {
            if((id < 0) || (id > max_elements) || (id_table[id] == NULL))
            {
                std::cout << "ID " << id << " nao existente." << std::endl;
                return;
            }

            std::cout << id_table[id]->first_name << " "
                      << id_table[id]->last_name << " "
                      << id_table[id]->birthday << " "
                      << id_table[id]->phone << std::endl;
        }
    private:
        const unsigned int max_elements; // Large prime number chosen
        HashTable id_table;
        HashTable fn_table;
        HashTable ln_table;
        HashTable birth_table;
        HashTable phone_table;

        unsigned int hash(const std::string &str)
        {
            unsigned int hash_number = 0;
            unsigned int mult = 1;

            for(char c : str)
            {
                hash_number += c * mult;
                ++mult;
            }

            return hash_number % max_elements;
        }

        void insert_on_table(HashTable &table,Person_ptr person,unsigned int hash_number)
        {
            if(table[hash_number] != NULL)
            {
                person->collision = table[hash_number];
            }

            table[hash_number] = person;
        }

        void remove_from_table(HashTable &table,Person_ptr person,unsigned int hash_number)
        {
            if(table[hash_number] != NULL)
            {
                Person_ptr last_person;
                Person_ptr people_itr = table[hash_number];
                do
                {
                    if(people_itr->id == person->id)
                    {
                        break;
                    }
                    last_person = people_itr;
                    people_itr = people_itr->collision;
                }while(people_itr != NULL);

                if(last_person != NULL)
                {
                    last_person->collision = people_itr->collision;
                    people_itr.reset();
                }
                else
                {
                    table[hash_number] = table[hash_number]->collision;
                }
            }
        }
};

int main(void)
{
    return 0;
}
<|endoftext|>


<commit_before>#include <tclap/CmdLine.h>
#include <llvm/IR/Module.h>
#include <fstream>
#include <sstream>
#include <chrono>

#include "utils/util.hpp"
#include "utils/error.hpp"
#include "lexer.hpp"
#include "parser/tokenParser.hpp"
#include "parser/xmlParser.hpp"
#include "llvm/compiler.hpp"
#include "llvm/runner.hpp"

enum ExitCodes: int {
  NORMAL_EXIT = 0, ///< Everything is OK
  TCLAP_ERROR = 11, ///< TCLAP did something bad, should not happen
  CLI_ERROR = 1, ///< The user used a wrong combination of options
  USER_PROGRAM_ERROR = 2, ///< The thing we had to lex/parse/run has an issue
  INTERNAL_ERROR = 3 ///< Unrecoverable error in this program, almost always a bug
};

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-declarations"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#endif

std::unique_ptr<AST> parseXML(fs::path filePath, std::string cliEval) {
  if (!filePath.empty()) {
    // Read from file
    auto file = rapidxml::file<>(filePath.c_str());
    return std::make_unique<AST>(XMLParser().parse(file).getTree());
  } else {
    // Read from CLI
    char* mutableCode = new char[cliEval.size() + 1];
    std::move(ALL(cliEval), mutableCode);
    mutableCode[cliEval.size()] = '\0';
    return std::make_unique<AST>(XMLParser().parse(mutableCode).getTree());
  }
}

std::vector<Token> tokenize(fs::path filePath, std::string cliEval) {
  std::string input;
  if (!filePath.empty()) {
    std::ifstream file(filePath);
    std::stringstream buffer;
    buffer << file.rdbuf();
    input = buffer.str();
  } else {
    input = cliEval;
  }
  auto lx = Lexer();
  return lx.tokenize(input, filePath.empty() ? "<cli-eval>" : filePath).getTokens();
}

/// Throw if the assertion is false
void assertCliIntegrity(TCLAP::CmdLine& cmd, bool assertion, std::string message) {
  if (!assertion) return;
  TCLAP::ArgException arg(message);
  cmd.getOutput()->failure(cmd, arg);
}

/// Pseudo-main used to allow early returns while measuring execution time
int notReallyMain(int argc, const char* argv[]) {
  try {
    TCLAP::CmdLine cmd("Xylene", ' ', "pre-release");

    TCLAP::SwitchArg asXML("", "xml", "Read file using the XML parser", cmd);

    TCLAP::SwitchArg printTokens("", "tokens", "Print token list (if applicable)", cmd);
    TCLAP::SwitchArg printAST("", "ast", "Print AST (if applicable)", cmd);
    TCLAP::SwitchArg printIR("", "ir", "Print LLVM IR (if applicable)", cmd);

    TCLAP::SwitchArg doNotParse("", "no-parse", "Don't parse the token list", cmd);
    TCLAP::SwitchArg doNotRun("", "no-run", "Don't execute the AST", cmd);

    std::vector<std::string> runnerValues {"interpret", "compile"};
    TCLAP::ValuesConstraint<std::string> runnerConstraint(runnerValues);
    TCLAP::ValueArg<std::string> runner("r", "runner", "How to run this code", false,
      "interpret", &runnerConstraint, cmd, nullptr);

    TCLAP::ValueArg<std::string> code("e", "eval", "Code to evaluate", false,
      std::string(), "string", cmd, nullptr);
    TCLAP::ValueArg<std::string> filePath("f", "file", "Load code from this file",
      false, std::string(), "path", cmd, nullptr);
    TCLAP::ValueArg<std::string> outPath("o", "output", "Write exe to this file",
      false, std::string(), "path", cmd, nullptr);
    cmd.parse(argc, argv);

    // There must be at least one input
    assertCliIntegrity(cmd, code.getValue().empty() && filePath.getValue().empty(),
      "Must specify either option -e or -f");

    // There is not much you can do to the XML without parsing it
    assertCliIntegrity(cmd, asXML.getValue() && doNotParse.getValue(),
      "--no-parse and --xml are incompatible");

    // The XML parser does not use tokens
    assertCliIntegrity(cmd, asXML.getValue() && printTokens.getValue(),
      "--tokens and --xml are incompatible");

    // Can't print AST without creating it first
    assertCliIntegrity(cmd, printAST.getValue() && doNotParse.getValue(),
      "--no-parse and --ast are incompatible");

    // Can't print IR without parsing the AST
    assertCliIntegrity(cmd, printIR.getValue() && doNotParse.getValue(),
      "--no-parse and --ir are incompatible");

    std::unique_ptr<AST> ast;

    if (asXML.getValue()) {
      ast = parseXML(filePath.getValue(), code.getValue());
    } else {
      auto tokens = tokenize(filePath.getValue(), code.getValue());
      if (printTokens.getValue()) for (auto tok : tokens) println(tok);

      if (doNotParse.getValue()) return NORMAL_EXIT;
      ast = std::make_unique<AST>(TokenParser().parse(tokens).getTree());
    }

    if (printAST.getValue()) ast->print();
    if (doNotRun.getValue()) return NORMAL_EXIT;

    ModuleCompiler::Link mc = ModuleCompiler::create("Command Line Module", *ast);
    mc->visit();
    if (printIR.getValue()) mc->getModule()->dump();

    if (runner.getValue() == "interpret") {
      return Runner(mc).run();
    } else if (runner.getValue() == "compile") {
      Compiler(std::unique_ptr<llvm::Module>(mc->getModule()),
        filePath.getValue(), outPath.getValue()).compile();
      return NORMAL_EXIT;
    }
  } catch (const TCLAP::ExitException& arg) {
    return CLI_ERROR;
  } catch (const TCLAP::ArgException& arg) {
    println("TCLAP error", arg.error(), "for", arg.argId());
    return TCLAP_ERROR;
  } catch (const Error& err) {
    println(err.what());
    return USER_PROGRAM_ERROR;
  }
  // If we're debugging, crash the program on InternalError
  #ifndef CRASH_ON_INTERNAL_ERROR
  catch (const InternalError& err) {
    println(err.what());
    return INTERNAL_ERROR;
  }
  #endif
  return 0;
}

#pragma GCC diagnostic pop

/// Measures execution time if XYLENE_MEASURE_TIME is defined \see notReallyMain
int main(int argc, const char* argv[]) {
  #ifdef XYLENE_MEASURE_TIME
  auto begin = std::chrono::steady_clock::now();
  #endif

  int exitCode = notReallyMain(argc, argv);

  #ifdef XYLENE_MEASURE_TIME
  auto end = std::chrono::steady_clock::now();
  println(
    "Time diff:",
    std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count(),
    "μs"
  );
  #endif

  return exitCode;
}
<commit_msg>Fix -Wunused-exception-parameter warning<commit_after>#include <tclap/CmdLine.h>
#include <llvm/IR/Module.h>
#include <fstream>
#include <sstream>
#include <chrono>

#include "utils/util.hpp"
#include "utils/error.hpp"
#include "lexer.hpp"
#include "parser/tokenParser.hpp"
#include "parser/xmlParser.hpp"
#include "llvm/compiler.hpp"
#include "llvm/runner.hpp"

enum ExitCodes: int {
  NORMAL_EXIT = 0, ///< Everything is OK
  TCLAP_ERROR = 11, ///< TCLAP did something bad, should not happen
  CLI_ERROR = 1, ///< The user used a wrong combination of options
  USER_PROGRAM_ERROR = 2, ///< The thing we had to lex/parse/run has an issue
  INTERNAL_ERROR = 3 ///< Unrecoverable error in this program, almost always a bug
};

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-declarations"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#endif

std::unique_ptr<AST> parseXML(fs::path filePath, std::string cliEval) {
  if (!filePath.empty()) {
    // Read from file
    auto file = rapidxml::file<>(filePath.c_str());
    return std::make_unique<AST>(XMLParser().parse(file).getTree());
  } else {
    // Read from CLI
    char* mutableCode = new char[cliEval.size() + 1];
    std::move(ALL(cliEval), mutableCode);
    mutableCode[cliEval.size()] = '\0';
    return std::make_unique<AST>(XMLParser().parse(mutableCode).getTree());
  }
}

std::vector<Token> tokenize(fs::path filePath, std::string cliEval) {
  std::string input;
  if (!filePath.empty()) {
    std::ifstream file(filePath);
    std::stringstream buffer;
    buffer << file.rdbuf();
    input = buffer.str();
  } else {
    input = cliEval;
  }
  auto lx = Lexer();
  return lx.tokenize(input, filePath.empty() ? "<cli-eval>" : filePath).getTokens();
}

/// Throw if the assertion is false
void assertCliIntegrity(TCLAP::CmdLine& cmd, bool assertion, std::string message) {
  if (!assertion) return;
  TCLAP::ArgException arg(message);
  cmd.getOutput()->failure(cmd, arg);
}

/// Pseudo-main used to allow early returns while measuring execution time
int notReallyMain(int argc, const char* argv[]) {
  try {
    TCLAP::CmdLine cmd("Xylene", ' ', "pre-release");

    TCLAP::SwitchArg asXML("", "xml", "Read file using the XML parser", cmd);

    TCLAP::SwitchArg printTokens("", "tokens", "Print token list (if applicable)", cmd);
    TCLAP::SwitchArg printAST("", "ast", "Print AST (if applicable)", cmd);
    TCLAP::SwitchArg printIR("", "ir", "Print LLVM IR (if applicable)", cmd);

    TCLAP::SwitchArg doNotParse("", "no-parse", "Don't parse the token list", cmd);
    TCLAP::SwitchArg doNotRun("", "no-run", "Don't execute the AST", cmd);

    std::vector<std::string> runnerValues {"interpret", "compile"};
    TCLAP::ValuesConstraint<std::string> runnerConstraint(runnerValues);
    TCLAP::ValueArg<std::string> runner("r", "runner", "How to run this code", false,
      "interpret", &runnerConstraint, cmd, nullptr);

    TCLAP::ValueArg<std::string> code("e", "eval", "Code to evaluate", false,
      std::string(), "string", cmd, nullptr);
    TCLAP::ValueArg<std::string> filePath("f", "file", "Load code from this file",
      false, std::string(), "path", cmd, nullptr);
    TCLAP::ValueArg<std::string> outPath("o", "output", "Write exe to this file",
      false, std::string(), "path", cmd, nullptr);
    cmd.parse(argc, argv);

    // There must be at least one input
    assertCliIntegrity(cmd, code.getValue().empty() && filePath.getValue().empty(),
      "Must specify either option -e or -f");

    // There is not much you can do to the XML without parsing it
    assertCliIntegrity(cmd, asXML.getValue() && doNotParse.getValue(),
      "--no-parse and --xml are incompatible");

    // The XML parser does not use tokens
    assertCliIntegrity(cmd, asXML.getValue() && printTokens.getValue(),
      "--tokens and --xml are incompatible");

    // Can't print AST without creating it first
    assertCliIntegrity(cmd, printAST.getValue() && doNotParse.getValue(),
      "--no-parse and --ast are incompatible");

    // Can't print IR without parsing the AST
    assertCliIntegrity(cmd, printIR.getValue() && doNotParse.getValue(),
      "--no-parse and --ir are incompatible");

    std::unique_ptr<AST> ast;

    if (asXML.getValue()) {
      ast = parseXML(filePath.getValue(), code.getValue());
    } else {
      auto tokens = tokenize(filePath.getValue(), code.getValue());
      if (printTokens.getValue()) for (auto tok : tokens) println(tok);

      if (doNotParse.getValue()) return NORMAL_EXIT;
      ast = std::make_unique<AST>(TokenParser().parse(tokens).getTree());
    }

    if (printAST.getValue()) ast->print();
    if (doNotRun.getValue()) return NORMAL_EXIT;

    ModuleCompiler::Link mc = ModuleCompiler::create("Command Line Module", *ast);
    mc->visit();
    if (printIR.getValue()) mc->getModule()->dump();

    if (runner.getValue() == "interpret") {
      return Runner(mc).run();
    } else if (runner.getValue() == "compile") {
      Compiler(std::unique_ptr<llvm::Module>(mc->getModule()),
        filePath.getValue(), outPath.getValue()).compile();
      return NORMAL_EXIT;
    }
  } catch (const TCLAP::ExitException&) {
    return CLI_ERROR;
  } catch (const TCLAP::ArgException& arg) {
    println("TCLAP error", arg.error(), "for", arg.argId());
    return TCLAP_ERROR;
  } catch (const Error& err) {
    println(err.what());
    return USER_PROGRAM_ERROR;
  }
  // If we're debugging, crash the program on InternalError
  #ifndef CRASH_ON_INTERNAL_ERROR
  catch (const InternalError& err) {
    println(err.what());
    return INTERNAL_ERROR;
  }
  #endif
  return 0;
}

#pragma GCC diagnostic pop

/// Measures execution time if XYLENE_MEASURE_TIME is defined \see notReallyMain
int main(int argc, const char* argv[]) {
  #ifdef XYLENE_MEASURE_TIME
  auto begin = std::chrono::steady_clock::now();
  #endif

  int exitCode = notReallyMain(argc, argv);

  #ifdef XYLENE_MEASURE_TIME
  auto end = std::chrono::steady_clock::now();
  println(
    "Time diff:",
    std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count(),
    "μs"
  );
  #endif

  return exitCode;
}
<|endoftext|>


<commit_before>#include "blackmagicsdk_video_source.h"

namespace gg
{

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK()
    : IVideoSource()
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    // This constructor should never be called,
    // therefore setting I420 arbitrarily for the
    // buffer video frame here.
    , _buffer_video_frame(VideoFrame(I420))
    , _running(false)
{
    // nop
}

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK(size_t deck_link_index,
                                                   ColourSpace colour)
    : IVideoSource(colour)
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _buffer_video_frame(VideoFrame(colour, false)) // TODO manage data?
    , _deck_link(nullptr)
    , _deck_link_input(nullptr)
    , _running(false)
{
    switch(_colour)
    {
    case BGRA:
        break;
    case I420:
    default:
        release_deck_link();
        throw VideoSourceError(
            "BlackmagicSDK video source supports only BGRA"
        );
    }

    // Get an iterator through the available DeckLink ports
    IDeckLinkIterator * deck_link_iterator = CreateDeckLinkIteratorInstance();
    if (deck_link_iterator == nullptr)
    {
        release_deck_link();
        throw VideoSourceError("DeckLink drivers do not appear to be installed");
    }

    HRESULT res;

    // Get the desired DeckLink index (port)
    int idx = deck_link_index;
    while ((res = deck_link_iterator->Next(&_deck_link)) == S_OK)
    {
        if (idx == 0)
            break;
        --idx;

        _deck_link->Release();
    }
    if (deck_link_iterator != nullptr)
        deck_link_iterator->Release();
    // No glory: release everything and throw exception
    if (res != S_OK or _deck_link == nullptr)
    {
        release_deck_link();
        throw VideoSourceError(
            std::string("Could not get DeckLink device ").append(std::to_string(deck_link_index))
        );
    }

    // Get the input interface of connected DeckLink port
    res = _deck_link->QueryInterface(IID_IDeckLinkInput, reinterpret_cast<void **>(&_deck_link_input));
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not connect to any Blackmagic DeckLink device");
    }

    // Set this object (IDeckLinkInputCallback instance) as callback
    res = _deck_link_input->SetCallback(this);
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not set the callback of Blackmagic DeckLink device");
    }

    // Try to set the first available of the following modes (in descending frame-rate order)
    std::vector<BMDDisplayMode> display_modes =
        { bmdModeHD1080p6000, bmdModeHD1080p5994, bmdModeHD1080p50,
          bmdModeHD1080p30, bmdModeHD1080p2997, bmdModeHD1080p25,
          bmdModeHD1080p24, bmdModeHD1080p2398 };
    // and BGRA as pixel format
    BMDPixelFormat pixel_format = bmdFormat8BitBGRA;
    // and these video flags
    BMDVideoInputFlags video_input_flags = bmdVideoInputFlagDefault | bmdVideoInputEnableFormatDetection;
    // These two are output variables
    BMDDisplayModeSupport display_mode_support;
    IDeckLinkDisplayMode * deck_link_display_mode = nullptr;
    // Flag for indicating the result of the video input enable attempt
    bool enabled_video_input = false;
    // And an error string to be set according to any failing intermediate step
    std::string error_msg = "";

    // Now loop through the set of modes
    for (BMDDisplayMode display_mode : display_modes)
    {
        // Check whether the mode is supported
        res = _deck_link_input->DoesSupportVideoMode(
            display_mode, pixel_format, video_input_flags,
            &display_mode_support, &deck_link_display_mode
        );
        // No glory (could not even check mode support)
        if (res != S_OK or deck_link_display_mode == nullptr)
        {
            error_msg = "Could not check video mode support of Blackmagic DeckLink device";
            break;
        }

        // If mode supported, set it and exit loop
        if (display_mode_support == bmdDisplayModeSupported)
        {
            // Get frame rate of DeckLink device
            BMDTimeValue frame_rate_duration, frame_rate_scale;
            res = deck_link_display_mode->GetFrameRate(&frame_rate_duration, &frame_rate_scale);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not infer frame rate of Blackmagic DeckLink device";
                break;
            }
            _frame_rate = (double) frame_rate_scale / (double) frame_rate_duration;

            // Enable video input
            res = _deck_link_input->EnableVideoInput(display_mode,
                                                     pixel_format,
                                                     video_input_flags);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not enable video input of Blackmagic DeckLink device";
                break;
            }
        }

        // Release the DeckLink display mode object at each iteration
        if (deck_link_display_mode != nullptr)
        {
            deck_link_display_mode->Release();
            deck_link_display_mode = nullptr;
        }

        if (enabled_video_input)
            break;
    }

    // Release the DeckLink display mode object in case loop pre-maturely broken
    if (deck_link_display_mode != nullptr)
        deck_link_display_mode->Release();

    // No glory (loop exited without success): release everything and throw exception
    if (not enabled_video_input)
    {
        release_deck_link();
        // If all modes checked, and none is supported!
        if (error_msg.empty())
            error_msg = "Could not enable video input of Blackmagic DeckLink device";
        // Else: an intermediate step went wrong, so put that into the exception
        throw VideoSourceError(error_msg);
    }

    // Disable audio input
    res = _deck_link_input->DisableAudioInput();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not disable audio input of Blackmagic DeckLink device");
    }

    // Start streaming
    _running = true;
    res = _deck_link_input->StartStreams();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        _running = false;
        release_deck_link();
        throw VideoSourceError("Could not start streaming from the Blackmagic DeckLink device");
    }
}

VideoSourceBlackmagicSDK::~VideoSourceBlackmagicSDK()
{
    // Make sure streamer thread not trying to access buffer
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);
    _running = false;

    // Stop streaming and disable enabled inputs
    _deck_link_input->StopStreams();
    _deck_link_input->DisableVideoInput();

    // Release DeckLink members
    release_deck_link();

    // Release allocated memory
    free(_video_buffer);
}

bool VideoSourceBlackmagicSDK::get_frame_dimensions(int & width, int & height)
{
    // TODO
}

bool VideoSourceBlackmagicSDK::get_frame(VideoFrame & frame)
{
    // TODO
    return false;
}

double VideoSourceBlackmagicSDK::get_frame_rate()
{
    return _frame_rate;
}

void VideoSourceBlackmagicSDK::set_sub_frame(int x, int y, int width, int height)
{
    // TODO
}

void VideoSourceBlackmagicSDK::get_full_frame()
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::QueryInterface(REFIID iid, LPVOID * ppv)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::AddRef(void)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::Release(void)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents events,
    IDeckLinkDisplayMode * display_mode,
    BMDDetectedVideoInputFormatFlags format_flags
)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame * video_frame,
    IDeckLinkAudioInputPacket * audio_packet
)
{
    // TODO
}

void VideoSourceBlackmagicSDK::release_deck_link() noexcept
{
    this->Release();

    if (_deck_link_input != nullptr)
    {
        _deck_link_input->Release();
        _deck_link_input = nullptr;
    }

    if (_deck_link != nullptr)
        _deck_link->Release();
}

}
<commit_msg>Issue #5: added missing line signaling video input enabled to mode selection loop<commit_after>#include "blackmagicsdk_video_source.h"

namespace gg
{

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK()
    : IVideoSource()
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    // This constructor should never be called,
    // therefore setting I420 arbitrarily for the
    // buffer video frame here.
    , _buffer_video_frame(VideoFrame(I420))
    , _running(false)
{
    // nop
}

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK(size_t deck_link_index,
                                                   ColourSpace colour)
    : IVideoSource(colour)
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _buffer_video_frame(VideoFrame(colour, false)) // TODO manage data?
    , _deck_link(nullptr)
    , _deck_link_input(nullptr)
    , _running(false)
{
    switch(_colour)
    {
    case BGRA:
        break;
    case I420:
    default:
        release_deck_link();
        throw VideoSourceError(
            "BlackmagicSDK video source supports only BGRA"
        );
    }

    // Get an iterator through the available DeckLink ports
    IDeckLinkIterator * deck_link_iterator = CreateDeckLinkIteratorInstance();
    if (deck_link_iterator == nullptr)
    {
        release_deck_link();
        throw VideoSourceError("DeckLink drivers do not appear to be installed");
    }

    HRESULT res;

    // Get the desired DeckLink index (port)
    int idx = deck_link_index;
    while ((res = deck_link_iterator->Next(&_deck_link)) == S_OK)
    {
        if (idx == 0)
            break;
        --idx;

        _deck_link->Release();
    }
    if (deck_link_iterator != nullptr)
        deck_link_iterator->Release();
    // No glory: release everything and throw exception
    if (res != S_OK or _deck_link == nullptr)
    {
        release_deck_link();
        throw VideoSourceError(
            std::string("Could not get DeckLink device ").append(std::to_string(deck_link_index))
        );
    }

    // Get the input interface of connected DeckLink port
    res = _deck_link->QueryInterface(IID_IDeckLinkInput, reinterpret_cast<void **>(&_deck_link_input));
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not connect to any Blackmagic DeckLink device");
    }

    // Set this object (IDeckLinkInputCallback instance) as callback
    res = _deck_link_input->SetCallback(this);
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not set the callback of Blackmagic DeckLink device");
    }

    // Try to set the first available of the following modes (in descending frame-rate order)
    std::vector<BMDDisplayMode> display_modes =
        { bmdModeHD1080p6000, bmdModeHD1080p5994, bmdModeHD1080p50,
          bmdModeHD1080p30, bmdModeHD1080p2997, bmdModeHD1080p25,
          bmdModeHD1080p24, bmdModeHD1080p2398 };
    // and BGRA as pixel format
    BMDPixelFormat pixel_format = bmdFormat8BitBGRA;
    // and these video flags
    BMDVideoInputFlags video_input_flags = bmdVideoInputFlagDefault | bmdVideoInputEnableFormatDetection;
    // These two are output variables
    BMDDisplayModeSupport display_mode_support;
    IDeckLinkDisplayMode * deck_link_display_mode = nullptr;
    // Flag for indicating the result of the video input enable attempt
    bool enabled_video_input = false;
    // And an error string to be set according to any failing intermediate step
    std::string error_msg = "";

    // Now loop through the set of modes
    for (BMDDisplayMode display_mode : display_modes)
    {
        // Check whether the mode is supported
        res = _deck_link_input->DoesSupportVideoMode(
            display_mode, pixel_format, video_input_flags,
            &display_mode_support, &deck_link_display_mode
        );
        // No glory (could not even check mode support)
        if (res != S_OK or deck_link_display_mode == nullptr)
        {
            error_msg = "Could not check video mode support of Blackmagic DeckLink device";
            break;
        }

        // If mode supported, set it and exit loop
        if (display_mode_support == bmdDisplayModeSupported)
        {
            // Get frame rate of DeckLink device
            BMDTimeValue frame_rate_duration, frame_rate_scale;
            res = deck_link_display_mode->GetFrameRate(&frame_rate_duration, &frame_rate_scale);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not infer frame rate of Blackmagic DeckLink device";
                break;
            }
            _frame_rate = (double) frame_rate_scale / (double) frame_rate_duration;

            // Enable video input
            res = _deck_link_input->EnableVideoInput(display_mode,
                                                     pixel_format,
                                                     video_input_flags);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not enable video input of Blackmagic DeckLink device";
                break;
            }

            enabled_video_input = true;
        }

        // Release the DeckLink display mode object at each iteration
        if (deck_link_display_mode != nullptr)
        {
            deck_link_display_mode->Release();
            deck_link_display_mode = nullptr;
        }

        if (enabled_video_input)
            break;
    }

    // Release the DeckLink display mode object in case loop pre-maturely broken
    if (deck_link_display_mode != nullptr)
        deck_link_display_mode->Release();

    // No glory (loop exited without success): release everything and throw exception
    if (not enabled_video_input)
    {
        release_deck_link();
        // If all modes checked, and none is supported!
        if (error_msg.empty())
            error_msg = "Could not enable video input of Blackmagic DeckLink device";
        // Else: an intermediate step went wrong, so put that into the exception
        throw VideoSourceError(error_msg);
    }

    // Disable audio input
    res = _deck_link_input->DisableAudioInput();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not disable audio input of Blackmagic DeckLink device");
    }

    // Start streaming
    _running = true;
    res = _deck_link_input->StartStreams();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        _running = false;
        release_deck_link();
        throw VideoSourceError("Could not start streaming from the Blackmagic DeckLink device");
    }
}

VideoSourceBlackmagicSDK::~VideoSourceBlackmagicSDK()
{
    // Make sure streamer thread not trying to access buffer
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);
    _running = false;

    // Stop streaming and disable enabled inputs
    _deck_link_input->StopStreams();
    _deck_link_input->DisableVideoInput();

    // Release DeckLink members
    release_deck_link();

    // Release allocated memory
    free(_video_buffer);
}

bool VideoSourceBlackmagicSDK::get_frame_dimensions(int & width, int & height)
{
    // TODO
}

bool VideoSourceBlackmagicSDK::get_frame(VideoFrame & frame)
{
    // TODO
    return false;
}

double VideoSourceBlackmagicSDK::get_frame_rate()
{
    return _frame_rate;
}

void VideoSourceBlackmagicSDK::set_sub_frame(int x, int y, int width, int height)
{
    // TODO
}

void VideoSourceBlackmagicSDK::get_full_frame()
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::QueryInterface(REFIID iid, LPVOID * ppv)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::AddRef(void)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::Release(void)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents events,
    IDeckLinkDisplayMode * display_mode,
    BMDDetectedVideoInputFormatFlags format_flags
)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame * video_frame,
    IDeckLinkAudioInputPacket * audio_packet
)
{
    // TODO
}

void VideoSourceBlackmagicSDK::release_deck_link() noexcept
{
    this->Release();

    if (_deck_link_input != nullptr)
    {
        _deck_link_input->Release();
        _deck_link_input = nullptr;
    }

    if (_deck_link != nullptr)
        _deck_link->Release();
}

}
<|endoftext|>