<commit_before>#include <iostream>
#include "process_curve.h"
#include "init_curves.h"
#include "spline.h"

#define BORDER 100

using namespace std;

// Resolution: the number of discrete line segments in each curve.
//  numPoints: the number of points to plot; number of splines is
//             thus numPoints - 2.
//    numSets: the number of spline curve sets to calculate.
int resolution, numPoints, numSets;
// Keep track of largest/smallest x/y vals
float hix = -10000.0, lox = 10000.0, hiy = -10000.0, loy = 10000.0;
float normx = 1, normy = 1;

Point** finVals;
Point** sets;

void Splines::init() {
   cin >> resolution >> numPoints >> numSets;

   sets = new Point*[numSets];

   for (int set = 0; set < numSets; set++) {
      sets[set] = new Point[numPoints];

      for (int point = 0; point < numPoints; point++) {
         float x, y;

         cin >> x >> y;

         if (x > hix) {
            hix = x;
         }
         if (x < lox) {
            lox = x;
         }

         if (y > hiy) {
            hiy = y;
         }
         if (y < loy) {
            loy = y;
         }

         sets[set][point].x = x;
         sets[set][point].y = y;
      }
   }
}

void Splines::transform(int n, int e, int s, int w) {
   normx = (1 - e) / (lox - hix);
   normy = (1 - s) / (loy - hiy);
   float offx = ((1 - e) * -lox) / (lox - hix);
   float offy = ((1 - s) * -loy) / (loy - hiy);

   for (int set = 0; set < numSets; set++) {
      for (int point = 0; point < numPoints; point++) {
         sets[set][point].x = sets[set][point].x * normx + offx;
         sets[set][point].y = sets[set][point].y * normy + offy;
      }
   }
}

void Splines::generate() {
   finVals = generatePoints(sets, numSets, numPoints, resolution);
}

void Splines::iterate(
 void (*process)(int setNum, int numPoints, int resolution, Point* vals)) {
   for (int set = 0; set < numSets; set++) {
      process(set, numPoints, resolution, finVals[set]);
   }
}

void Splines::cleanup() {
   for (int set = 0; set < numSets; set++) {
      delete [] sets[set];
   }

   delete []sets;
}
<commit_msg>Add printout to indicate what values should be passed in<commit_after>#include <iostream>
#include "process_curve.h"
#include "init_curves.h"
#include "spline.h"

#define BORDER 100

using namespace std;

// Resolution: the number of discrete line segments in each curve.
//  numPoints: the number of points to plot; number of splines is
//             thus numPoints - 2.
//    numSets: the number of spline curve sets to calculate.
int resolution, numPoints, numSets;
// Keep track of largest/smallest x/y vals
float hix = -10000.0, lox = 10000.0, hiy = -10000.0, loy = 10000.0;
float normx = 1, normy = 1;

Point** finVals;
Point** sets;

void Splines::init() {
   cout << "Enter [resolution numPoints numSets] followed by " << endl;
   cout << "data points, one per line: ";
   cin >> resolution >> numPoints >> numSets;

   sets = new Point*[numSets];

   for (int set = 0; set < numSets; set++) {
      sets[set] = new Point[numPoints];

      for (int point = 0; point < numPoints; point++) {
         float x, y;

         cin >> x >> y;

         if (x > hix) {
            hix = x;
         }
         if (x < lox) {
            lox = x;
         }

         if (y > hiy) {
            hiy = y;
         }
         if (y < loy) {
            loy = y;
         }

         sets[set][point].x = x;
         sets[set][point].y = y;
      }
   }
}

void Splines::transform(int n, int e, int s, int w) {
   normx = (1 - e) / (lox - hix);
   normy = (1 - s) / (loy - hiy);
   float offx = ((1 - e) * -lox) / (lox - hix);
   float offy = ((1 - s) * -loy) / (loy - hiy);

   for (int set = 0; set < numSets; set++) {
      for (int point = 0; point < numPoints; point++) {
         sets[set][point].x = sets[set][point].x * normx + offx;
         sets[set][point].y = sets[set][point].y * normy + offy;
      }
   }
}

void Splines::generate() {
   finVals = generatePoints(sets, numSets, numPoints, resolution);
}

void Splines::iterate(
 void (*process)(int setNum, int numPoints, int resolution, Point* vals)) {
   for (int set = 0; set < numSets; set++) {
      process(set, numPoints, resolution, finVals[set]);
   }
}

void Splines::cleanup() {
   for (int set = 0; set < numSets; set++) {
      delete [] sets[set];
   }

   delete []sets;
}
<|endoftext|>


<commit_before>//
//  inpal_prime.cpp
//  InversePalindrome
//
//  Created by Bryan Triana on 7/13/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#include "inpal_prime.hpp"
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>

std::vector<std::size_t> inpal::prime::prime_list(std::size_t range)
{
    auto primes = prime_sieve(range);
    std::vector<std::size_t> p_list;

    for(std::size_t i=2; i<=range; i++) if(primes[i]) p_list.push_back(i);

    return p_list;
}

std::vector<std::size_t> inpal::prime::factor_list(std::size_t num)
{
    std::vector<std::size_t> p_fac;
    std::size_t prime_factor = 2;

    //trial division
    while(prime_factor<=num)
    {
        while(num%prime_factor==0)
        {
            p_fac.push_back(prime_factor);
            num=num/prime_factor;
        }
        prime_factor += prime_factor==2 ? 1 : 2;
    }

    return p_fac;
}

std::size_t inpal::prime::prime_count(std::size_t range)
{
    auto primes = prime_sieve(range);

    return std::count(primes.begin(), primes.end(), true);
}

std::size_t inpal::prime::max_prime(std::size_t num)
{
    auto primes = prime_sieve(num);
    auto it = std::find(primes.rbegin(), primes.rend(), true);

    return primes.size()-std::distance(primes.rbegin(), it)-1;
}

double inpal::prime::prime_density(double range)
{
    return prime_count(range)/range;
}

bool inpal::prime::prime_test(std::size_t num)
{
    return num == max_prime(num);
}

bool inpal::prime::twin_test(std::size_t num)
{
    auto primes = prime_sieve(num+2);

    return num!=2 && primes[primes.size()-3] && (primes[primes.size()-1] || primes[primes.size()-5]);
}

bool inpal::prime::cousin_test(std::size_t num)
{
    auto primes = prime_sieve(num+4);

    return  num!=2 && primes[primes.size()-5] && (primes[primes.size()-1] || primes[primes.size()-9]);
}

bool inpal::prime::sexy_test(std::size_t num)
{
    auto primes = prime_sieve(num+6);

    return (num!=2 && num!=3) && primes[primes.size()-7] && (primes[primes.size()-1] || primes[primes.size()-13]);
}

std::size_t inpal::prime::max_palprime(std::size_t num)
{
    auto primes = prime_sieve(num);

    for(std::size_t i=num; i>=2; --i) if(primes[i] && pal_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::max_factor(std::size_t num)
{
    return factor_list(num).back();
}

std::size_t inpal::prime::factor_count(std::size_t num)
{
    return factor_list(num).size();
}

std::vector<bool> inpal::prime::prime_sieve(std::size_t range)
{
    std::vector<bool> p_test(range+1, false);

    //defines square root of range for future usage
    std::size_t root = ceil(sqrt(range));

    //sieve axioms
    for(std::size_t x=1; x<=root; x++)
        for(std::size_t y=1; y<=root; y++)
        {
            std::size_t i = (4*x*x)+(y*y);
            if (i<=range && (i%12==1 || i%12==5))
            {
                p_test[i].flip();
            }

            i = (3*x*x)+(y*y);
            if(i<=range && i%12==7)
            {
                p_test[i].flip();
            }

            i = (3*x*x)-(y*y);
            if(x>y && i<=range && i%12==11)
            {
                p_test[i].flip();
            }
        }

    //marks 2,3,5 and 7 as prime numbers to deal with input smaller than 7
    p_test[2]=p_test[3]=p_test[5]=p_test[7]=true;

    //marks all multiples of primes as non primes
    for(std::size_t r=5; r<=root; r++)
    {
        if((p_test[r]))
        {
            for(std::size_t j=r*r; j<=range; j+=r*r)
            {
                p_test[j]=false;
            }
        }
    }

    return p_test;
}

bool inpal::prime::pal_test(std::size_t num)
{
    std::string rev = std::to_string(num);

    //checks if half the reverse of rev is equal to the other half of rev
    if(std::equal(rev.begin(), rev.begin()+rev.size()/2, rev.rbegin()))
    {
        return true;
    }

    return false;
}
<commit_msg>Update inpal_prime.cpp<commit_after>//
//  inpal_prime.cpp
//  InversePalindrome
//
//  Created by Bryan Triana on 7/13/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#include "inpal_prime.hpp"
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>

std::vector<std::size_t> inpal::prime::prime_list(std::size_t range)
{
    auto primes = prime_sieve(range);
    std::vector<std::size_t> p_list;

    for(std::size_t i=2; i<=range; i++) if(primes[i]) p_list.push_back(i);

    return p_list;
}

std::vector<std::size_t> inpal::prime::factor_list(std::size_t num)
{
    std::vector<std::size_t> p_fac;
    std::size_t prime_factor = 2;

    //trial division
    while(prime_factor<=num)
    {
        while(num%prime_factor==0)
        {
            p_fac.push_back(prime_factor);
            num=num/prime_factor;
        }
        prime_factor += prime_factor==2 ? 1 : 2;
    }

    return p_fac;
}

std::size_t inpal::prime::max_prime(std::size_t num)
{
    auto primes = prime_sieve(num);
    auto it = std::find(primes.rbegin(), primes.rend(), true);

    return primes.size()-std::distance(primes.rbegin(), it)-1;
}

std::size_t inpal::prime::prime_count(std::size_t range)
{
    auto primes = prime_sieve(range);

    return std::count(primes.begin(), primes.end(), true);
}

double inpal::prime::prime_density(double range)
{
    return prime_count(range)/range;
}

bool inpal::prime::prime_test(std::size_t num)
{
    return num == max_prime(num);
}

bool inpal::prime::twin_test(std::size_t num)
{
    auto primes = prime_sieve(num+2);

    return num!=2 && primes[primes.size()-3] && (primes[primes.size()-1] || primes[primes.size()-5]);
}

bool inpal::prime::cousin_test(std::size_t num)
{
    auto primes = prime_sieve(num+4);

    return  num!=2 && primes[primes.size()-5] && (primes[primes.size()-1] || primes[primes.size()-9]);
}

bool inpal::prime::sexy_test(std::size_t num)
{
    auto primes = prime_sieve(num+6);

    return (num!=2 && num!=3) && primes[primes.size()-7] && (primes[primes.size()-1] || primes[primes.size()-13]);
}

std::size_t inpal::prime::max_palprime(std::size_t num)
{
    auto primes = prime_sieve(num);

    for(std::size_t i=num; i>=2; --i) if(primes[i] && pal_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::max_factor(std::size_t num)
{
    return factor_list(num).back();
}

std::size_t inpal::prime::factor_count(std::size_t num)
{
    return factor_list(num).size();
}

std::vector<bool> inpal::prime::prime_sieve(std::size_t range)
{
    std::vector<bool> p_test(range+1, false);

    //defines square root of range for future usage
    std::size_t root = ceil(sqrt(range));

    //sieve axioms
    for(std::size_t x=1; x<=root; x++)
        for(std::size_t y=1; y<=root; y++)
        {
            std::size_t i = (4*x*x)+(y*y);
            if (i<=range && (i%12==1 || i%12==5))
            {
                p_test[i].flip();
            }

            i = (3*x*x)+(y*y);
            if(i<=range && i%12==7)
            {
                p_test[i].flip();
            }

            i = (3*x*x)-(y*y);
            if(x>y && i<=range && i%12==11)
            {
                p_test[i].flip();
            }
        }

    //marks 2,3,5 and 7 as prime numbers to deal with input smaller than 7
    p_test[2]=p_test[3]=p_test[5]=p_test[7]=true;

    //marks all multiples of primes as non primes
    for(std::size_t r=5; r<=root; r++)
    {
        if((p_test[r]))
        {
            for(std::size_t j=r*r; j<=range; j+=r*r)
            {
                p_test[j]=false;
            }
        }
    }

    return p_test;
}

bool inpal::prime::pal_test(std::size_t num)
{
    std::string rev = std::to_string(num);

    //checks if half the reverse of rev is equal to the other half of rev
    if(std::equal(rev.begin(), rev.begin()+rev.size()/2, rev.rbegin()))
    {
        return true;
    }

    return false;
}
<|endoftext|>


<commit_before>//
//  inpal_prime.cpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/21/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#include "inpal_prime.hpp"
#include "inpal_algorithm.hpp"

std::vector<std::size_t> inpal::prime::prime_list(std::size_t range)
{
    const auto primes = prime_sieve(range);
    std::vector<std::size_t> p_list;

    for(std::size_t i=2; i<=range; i++) if(primes[i]) p_list.push_back(i);

    return p_list;
}

std::vector<bool> inpal::prime::prime_sieve(std::size_t range)
{
    std::vector<bool> p_test(range+1, false);

    //defines square root of range for future usage
    const std::size_t root = ceil(sqrt(range));

    //sieve axioms
    for(std::size_t x=1; x<=root; x++)
        for(std::size_t y=1; y<=root; y++)
        {
            std::size_t i = (4*x*x)+(y*y);
            if (i<=range && (i%12==1 || i%12==5))
            {
                p_test[i].flip();
            }

            i = (3*x*x)+(y*y);
            if(i<=range && i%12==7)
            {
                p_test[i].flip();
            }

            i = (3*x*x)-(y*y);
            if(x>y && i<=range && i%12==11)
            {
                p_test[i].flip();
            }
        }

    //marks 2,3,5 and 7 as prime numbers to deal with input smaller than 7
    p_test[2]=p_test[3]=p_test[5]=p_test[7]=true;

    //marks all multiples of primes as non primes
    for(std::size_t r=5; r<=root; r++)
    {
        if((p_test[r]))
        {
            for(std::size_t j=r*r; j<=range; j+=r*r)
            {
                p_test[j]=false;
            }
        }
    }

    return p_test;
}

std::vector<std::size_t> inpal::prime::factor_list(std::size_t num)
{
    if(num<100000)
    {
        return algorithm::trial_division(num);
    }

    std::vector<std::size_t> factors;
    std::vector<std::size_t> primes;

    std::size_t factor = algorithm::pollard_rho(num);
    factors.push_back(num/factor);
    factors.push_back(factor);

    do
    {
        std::size_t m = factors.back();
        factors.pop_back();

        if(m==1) continue;
        if(prime_test(m))
        {
            primes.push_back(m);

            //decomposes the factors into primes
            for(std::size_t i=0; i<factors.size(); i++)
            {
                std::size_t k = factors[i];
                if(k%m==0)
                {
                    do k/=m;
                    while(k%m==0);

                    factors[i]=k;
                }
            }
        }
        else
        {
            factor=algorithm::pollard_rho(m);
            factors.push_back(m/factor);
            factors.push_back(factor);
        }
    }
    while(!factors.empty());

    return primes;
}

std::size_t inpal::prime::prime_locate(std::size_t pos)
{
    //index starts at 1 instead of 0, eg 1st prime is 2
    pos = pos-1;

    //return values for input less or equal to 10
    const auto small_primes = prime_list(29);
    if(pos<10) return small_primes[pos];

    //denotes the limit of the sieve
    std::size_t limit = pos*log(pos)+pos*log(log(pos));
    const auto primes = prime_list(limit);

    return primes[pos];
}

std::size_t inpal::prime::max_prime(std::size_t num)
{
    const auto primes = prime_sieve(num);
    auto it = std::find(primes.rbegin(), primes.rend(), true);

    return primes.size()-std::distance(primes.rbegin(), it)-1;
}

std::size_t inpal::prime::prime_count(std::size_t range)
{
    const auto primes = prime_sieve(range);

    return std::count(primes.begin(), primes.end(), true);
}

double inpal::prime::prime_density(double range)
{
    return prime_count(range)/range;
}

bool inpal::prime::prime_test(std::size_t num)
{
    if(num!=2 && num%2==0) return false;

    const std::size_t iteration = 20;
    std::size_t s = num-1;
    while(s%2==0) s/=2;

    for(std::size_t i=0; i<iteration; i++)
    {
        std::size_t a = rand()%(num-1)+1;
        std::size_t b = s;
        std::size_t mod = algorithm::modulo(a,b,num);

        while(b!=num-1 && mod!=1 && mod!=num-1)
        {
            mod=algorithm::mulmod(mod,mod,num);
            b*=2;
        }
        if(mod!=num-1 && b%2==0) return false;
    }

    return true;
}

bool inpal::prime::twin_test(std::size_t num)
{
    return prime_test(num) && (prime_test(num-2) || prime_test(num+2));
}

bool inpal::prime::cousin_test(std::size_t num)
{
    return  prime_test(num) && (prime_test(num-4) || prime_test(num+4));
}

bool inpal::prime::sexy_test(std::size_t num)
{
    return num!=3 && prime_test(num) && (prime_test(num-6) || prime_test(num+6));
}

std::size_t inpal::prime::max_palprime(std::size_t num)
{
    const auto primes = prime_sieve(num);

    for(std::size_t i=num; i>=2; --i) if(primes[i] && algorithm::pal_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::max_factor(std::size_t num)
{
    return factor_list(num).back();
}

std::size_t inpal::prime::factor_count(std::size_t num)
{
    return factor_list(num).size();
}

<commit_msg>Update inpal_prime.cpp<commit_after>//
//  inpal_prime.cpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/21/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#include "inpal_prime.hpp"
#include "inpal_algorithm.hpp"

std::vector<std::size_t> inpal::prime::prime_list(std::size_t range)
{
    const auto primes = prime_sieve(range);
    std::vector<std::size_t> p_list;

    for(std::size_t i=2; i<=range; i++) if(primes[i]) p_list.push_back(i);

    return p_list;
}

std::vector<bool> inpal::prime::prime_sieve(std::size_t range)
{
    std::vector<bool> p_test(range+1, false);

    //defines square root of range for future usage
    const std::size_t root = ceil(sqrt(range));

    //sieve axioms
    for(std::size_t x=1; x<=root; x++)
        for(std::size_t y=1; y<=root; y++)
        {
            std::size_t i = (4*x*x)+(y*y);
            if (i<=range && (i%12==1 || i%12==5))
            {
                p_test[i].flip();
            }

            i = (3*x*x)+(y*y);
            if(i<=range && i%12==7)
            {
                p_test[i].flip();
            }

            i = (3*x*x)-(y*y);
            if(x>y && i<=range && i%12==11)
            {
                p_test[i].flip();
            }
        }

    //marks 2,3,5 and 7 as prime numbers to deal with input smaller than 7
    p_test[2]=p_test[3]=p_test[5]=p_test[7]=true;

    //marks all multiples of primes as non primes
    for(std::size_t r=5; r<=root; r++)
    {
        if((p_test[r]))
        {
            for(std::size_t j=r*r; j<=range; j+=r*r)
            {
                p_test[j]=false;
            }
        }
    }

    return p_test;
}

std::vector<std::size_t> inpal::prime::factor_list(std::size_t num)
{
    std::vector<std::size_t> factors;
    std::vector<std::size_t> primes;

    std::size_t factor = algorithm::pollard_rho(num);
    factors.push_back(num/factor);
    factors.push_back(factor);

    do
    {
        std::size_t m = factors.back();
        factors.pop_back();

        if(m==1) continue;
        if(prime_test(m))
        {
            primes.push_back(m);

            //decomposes the factors into primes
            for(std::size_t i=0; i<factors.size(); i++)
            {
                std::size_t k = factors[i];
                if(k%m==0)
                {
                    do k/=m;
                    while(k%m==0);

                    factors[i]=k;
                }
            }
        }
        else
        {
            factor=algorithm::pollard_rho(m);
            factors.push_back(m/factor);
            factors.push_back(factor);
        }
    }
    while(!factors.empty());

    std::sort(primes.begin(), primes.end());

    return primes;
}

std::size_t inpal::prime::prime_locate(std::size_t pos)
{
    //index starts at 1 instead of 0, eg 1st prime is 2
    pos = pos-1;

    //return values for input less or equal to 10
    const auto small_primes = prime_list(29);
    if(pos<10) return small_primes[pos];

    //denotes the limit of the sieve
    std::size_t limit = pos*log(pos)+pos*log(log(pos));
    const auto primes = prime_list(limit);

    return primes[pos];
}

std::size_t inpal::prime::max_prime(std::size_t num)
{
    const auto primes = prime_sieve(num);
    auto it = std::find(primes.rbegin(), primes.rend(), true);

    return primes.size()-std::distance(primes.rbegin(), it)-1;
}

std::size_t inpal::prime::prime_count(std::size_t range)
{
    const auto primes = prime_sieve(range);

    return std::count(primes.begin(), primes.end(), true);
}

double inpal::prime::prime_density(double range)
{
    return prime_count(range)/range;
}

bool inpal::prime::prime_test(std::size_t num)
{
    if(num!=2 && num%2==0) return false;

    const std::size_t iteration = 20;
    std::size_t s = num-1;
    while(s%2==0) s/=2;

    for(std::size_t i=0; i<iteration; i++)
    {
        std::size_t a = rand()%(num-1)+1;
        std::size_t b = s;
        std::size_t mod = algorithm::modulo(a,b,num);

        while(b!=num-1 && mod!=1 && mod!=num-1)
        {
            mod=algorithm::mulmod(mod,mod,num);
            b*=2;
        }
        if(mod!=num-1 && b%2==0) return false;
    }

    return true;
}

bool inpal::prime::twin_test(std::size_t num)
{
    return prime_test(num) && (prime_test(num-2) || prime_test(num+2));
}

bool inpal::prime::cousin_test(std::size_t num)
{
    return  prime_test(num) && (prime_test(num-4) || prime_test(num+4));
}

bool inpal::prime::sexy_test(std::size_t num)
{
    return num!=3 && prime_test(num) && (prime_test(num-6) || prime_test(num+6));
}

std::size_t inpal::prime::max_palprime(std::size_t num)
{
    const auto primes = prime_sieve(num);

    for(std::size_t i=num; i>=2; --i) if(primes[i] && algorithm::pal_test(i)) return i;

    return 2;
}

std::size_t inpal::prime::max_factor(std::size_t num)
{
    return factor_list(num).back();
}

std::size_t inpal::prime::factor_count(std::size_t num)
{
    return factor_list(num).size();
}

<|endoftext|>


<commit_before>#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>

#include <mist/defines.h>
#include "input.h"
#include <sstream>
#include <fstream>
#include <iterator>

namespace Mist {
  Input * Input::singleton = NULL;

  void Input::userCallback(char * data, size_t len, unsigned int id){
    for (int i = 0; i < 5; i++){
      long tid = ((long)(data[0]) << 24) | ((long)(data[1]) << 16) | ((long)(data[2]) << 8) | ((long)(data[3]));
      if (tid){
        long keyNum = ((long)(data[4]) << 8) | ((long)(data[5]));
        bufferFrame(tid, keyNum + 1);//Try buffer next frame
      }
    }
  }

  void Input::doNothing(char * data, size_t len, unsigned int id){
    DEBUG_MSG(DLVL_DONTEVEN, "Doing 'nothing'");
    singleton->userCallback(data, 30, id);//call the userCallback for this input
  }

  Input::Input(Util::Config * cfg) {
    config = cfg;
    JSON::Value option;
    option["long"] = "json";
    option["short"] = "j";
    option["help"] = "Output MistIn info in JSON format, then exit.";
    option["value"].append(0ll);
    config->addOption("json", option);
    option.null();
    option["arg_num"] = 1ll;
    option["arg"] = "string";
    option["help"] = "Name of the input file or - for stdin";
    option["value"].append("-");
    config->addOption("input", option);
    option.null();
    option["arg_num"] = 2ll;
    option["arg"] = "string";
    option["help"] = "Name of the output file or - for stdout";
    option["value"].append("-");
    config->addOption("output", option);
    option.null();
    option["arg"] = "string";
    option["short"] = "s";
    option["long"] = "stream";
    option["help"] = "The name of the stream that this connector will transmit.";
    config->addOption("streamname", option);
    option.null();
    option["short"] = "p";
    option["long"] = "player";
    option["help"] = "Makes this connector into a player";
    config->addOption("player", option);

    packTime = 0;
    lastActive = Util::epoch();
    playing = 0;
    playUntil = 0;

    singleton = this;
    isBuffer = false;
  }

  void Input::checkHeaderTimes(std::string streamFile){
    std::string headerFile = streamFile + ".dtsh";
    FILE * tmp = fopen(headerFile.c_str(),"r");
	  if (tmp == NULL) {
      INFO_MSG("can't open file: %s (no header times compared, nothing removed)", headerFile.c_str() );
	    return;
	  }
	  struct stat bufStream;
    struct stat bufHeader;
    //fstat(fileno(streamFile), &bufStream);
    //fstat(fileno(tmp), &bufHeader);

    if (stat(streamFile.c_str(), &bufStream) !=0 || stat(headerFile.c_str(), &bufHeader) !=0){
		  ERROR_MSG("could not get file info (no header times compared, nothing removed)");
      fclose(tmp);
		  return;
    }

	  int timeStream = bufStream.st_mtime;
    int timeHeader = bufHeader.st_mtime;
    fclose(tmp);
    INFO_MSG("time header: %i time stream: %i ", timeHeader, timeStream);
    if (timeHeader < timeStream) {
	    INFO_MSG("removing old header file: %s ",headerFile.c_str());
		  //delete filename
		  remove(headerFile.c_str());
    }
  }

  int Input::run() {
    if (config->getBool("json")) {
      std::cerr << capa.toString() << std::endl;
      return 0;
    }
    if (!setup()) {
      std::cerr << config->getString("cmd") << " setup failed." << std::endl;
      return 0;
    }
    checkHeaderTimes(config->getString("input"));
    if (!readHeader()) {
      std::cerr << "Reading header for " << config->getString("input") << " failed." << std::endl;
      return 0;
    }
    parseHeader();

    if (!config->getBool("player")){
      //check filename for no -
      if (config->getString("output") != "-"){
        std::string filename = config->getString("output");
        if (filename.size() < 5 || filename.substr(filename.size() - 5) != ".dtsc"){
          filename += ".dtsc";
        }
        //output to dtsc
        DTSC::Meta newMeta = myMeta;
        newMeta.reset();
        JSON::Value tempVal;
        std::ofstream file(filename.c_str());
        long long int bpos = 0;
        seek(0);
        getNext();
        while (lastPack){
          tempVal = lastPack.toJSON();
          tempVal["bpos"] = bpos;
          newMeta.update(tempVal);
          file << std::string(lastPack.getData(), lastPack.getDataLen());
          bpos += lastPack.getDataLen();
          getNext();
        }
        //close file
        file.close();
        //create header
        file.open((filename+".dtsh").c_str());
        file << newMeta.toJSON().toNetPacked();
        file.close();
      }else{
        DEBUG_MSG(DLVL_FAIL,"No filename specified, exiting");
      }
    }else{
      //after this player functionality

#ifdef __CYGWIN__
  metaPage.init(config->getString("streamname"), 8 * 1024 * 1024, true);
#else
  metaPage.init(config->getString("streamname"), (isBuffer ? 8 * 1024 * 1024 : myMeta.getSendLen()), true);
#endif
      myMeta.writeTo(metaPage.mapped);
      userPage.init(config->getString("streamname") + "_users", 30, true);

      if (!isBuffer){
        for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
          bufferFrame(it->first, 1);
        }
      }

      IPC::semaphore waiting(std::string("/wait_" + config->getString("streamname")).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 0);
      if (!waiting){
        DEBUG_MSG(DLVL_FAIL, "Failed to open semaphore - cancelling");
        return -1;
      }
      waiting.post();
      waiting.close();

      DEBUG_MSG(DLVL_HIGH,"Pre-While");

      long long int activityCounter = Util::getMS();
      while ((Util::getMS() - activityCounter) < 10000){//10 second timeout
        DEBUG_MSG(DLVL_HIGH, "Timer running");
        Util::sleep(1000);
        removeUnused();
        userPage.parseEach(doNothing);
        if (userPage.amount){
          activityCounter = Util::getMS();
          DEBUG_MSG(DLVL_HIGH, "Connected users: %d", userPage.amount);
        }
      }
      DEBUG_MSG(DLVL_DEVEL,"Closing clean");
      //end player functionality
    }
    return 0;
  }

  void Input::removeUnused(){
    for (std::map<unsigned int, std::map<unsigned int, unsigned int> >::iterator it = pageCounter.begin(); it != pageCounter.end(); it++){
      for (std::map<unsigned int, unsigned int>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++){
        it2->second--;
      }
      bool change = true;
      while (change){
        change = false;
        for (std::map<unsigned int, unsigned int>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++){
          if (!it2->second){
            dataPages[it->first].erase(it2->first);
            pageCounter[it->first].erase(it2->first);
            change = true;
            break;
          }
        }
      }
    }
  }

  void Input::parseHeader(){
    DEBUG_MSG(DLVL_DEVEL,"Parsing the header");
    //Select all tracks for parsing header
    selectedTracks.clear();
    std::stringstream trackSpec;
    for (std::map<int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) {
      DEBUG_MSG(DLVL_VERYHIGH, "Track %d encountered", it->first);
      if (trackSpec.str() != ""){
        trackSpec << " ";
      }
      trackSpec << it->first;
      DEBUG_MSG(DLVL_VERYHIGH, "Trackspec now %s", trackSpec.str().c_str());
      for (std::deque<DTSC::Key>::iterator it2 = it->second.keys.begin(); it2 != it->second.keys.end(); it2++){
        keyTimes[it->first].insert(it2->getTime());
      }
    }
    trackSelect(trackSpec.str());

    std::map<int, DTSCPageData> curData;
    std::map<int, booking> bookKeeping;

    seek(0);
    getNext();

    while(lastPack){//loop through all
      int tid = lastPack.getTrackId();
      if (!tid){
        getNext(false);
        continue;
      }
      if (!bookKeeping.count(tid)){
        bookKeeping[tid].first = 1;
        bookKeeping[tid].curPart = 0;
        bookKeeping[tid].curKey = 0;

        curData[tid].lastKeyTime = 0xFFFFFFFF;
        curData[tid].keyNum = 1;
        curData[tid].partNum = 0;
        curData[tid].dataSize = 0;
        curData[tid].curOffset = 0;
        curData[tid].firstTime = myMeta.tracks[tid].keys[0].getTime();

        char tmpId[20];
        sprintf(tmpId, "%d", tid);
        indexPages[tid].init(config->getString("streamname") + tmpId, 8 * 1024, true);//Pages of 8kb in size, room for 512 parts.
      }
      if (myMeta.tracks[tid].keys[bookKeeping[tid].curKey].getParts() == curData[tid].partNum){
        if (curData[tid].dataSize > 8 * 1024 * 1024) {
          pagesByTrack[tid][bookKeeping[tid].first] = curData[tid];
          bookKeeping[tid].first += curData[tid].keyNum;
          curData[tid].keyNum = 0;
          curData[tid].dataSize = 0;
          curData[tid].firstTime = myMeta.tracks[tid].keys[bookKeeping[tid].curKey].getTime();
        }
        bookKeeping[tid].curKey++;
        curData[tid].keyNum++;
        curData[tid].partNum = 0;
      }
      curData[tid].dataSize += lastPack.getDataLen();
      curData[tid].partNum ++;
      bookKeeping[tid].curPart ++;
      getNext(false);
    }
    for (std::map<int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) {
      if (curData.count(it->first) && !pagesByTrack[it->first].count(bookKeeping[it->first].first)){
        pagesByTrack[it->first][bookKeeping[it->first].first] = curData[it->first];
      }
      if (!pagesByTrack.count(it->first)){
        DEBUG_MSG(DLVL_WARN, "No pages for track %d found", it->first);
      }else{
        DEBUG_MSG(DLVL_DEVEL, "Track %d (%s) split into %lu pages", it->first, myMeta.tracks[it->first].codec.c_str(), pagesByTrack[it->first].size());
        for (std::map<int, DTSCPageData>::iterator it2 = pagesByTrack[it->first].begin(); it2 != pagesByTrack[it->first].end(); it2++){
          DEBUG_MSG(DLVL_DEVEL, "Page %u-%u", it2->first, it2->first + it2->second.keyNum - 1);
        }
      }
    }
  }

  bool Input::bufferFrame(int track, int keyNum){
    if (keyNum < 1){keyNum = 1;}
    if (!pagesByTrack.count(track)){
      return false;
    }
    std::map<int, DTSCPageData>::iterator it = pagesByTrack[track].upper_bound(keyNum);
    if (it != pagesByTrack[track].begin()){
      it--;
    }
    int pageNum = it->first;
    pageCounter[track][pageNum] = 15;///Keep page 15seconds in memory after last use

    DEBUG_MSG(DLVL_DONTEVEN, "Attempting to buffer page %d key %d->%d", track, keyNum, pageNum);
    if (dataPages[track].count(pageNum)){
      return true;
    }
    char pageId[100];
    int pageIdLen = sprintf(pageId, "%s%d_%d", config->getString("streamname").c_str(), track, pageNum);
    std::string tmpString(pageId, pageIdLen);
#ifdef __CYGWIN__
    dataPages[track][pageNum].init(tmpString, 26 * 1024 * 1024, true);
#else
    dataPages[track][pageNum].init(tmpString, it->second.dataSize, true);
#endif
    DEBUG_MSG(DLVL_DEVEL, "Buffering track %d page %d through %d", track, pageNum, pageNum-1 + it->second.keyNum);

    std::stringstream trackSpec;
    trackSpec << track;
    trackSelect(trackSpec.str());
    seek(myMeta.tracks[track].keys[pageNum-1].getTime());
    long long unsigned int stopTime = myMeta.tracks[track].lastms + 1;
    if ((int)myMeta.tracks[track].keys.size() > pageNum-1 + it->second.keyNum){
      stopTime = myMeta.tracks[track].keys[pageNum-1 + it->second.keyNum].getTime();
    }
    DEBUG_MSG(DLVL_HIGH, "Playing from %ld to %llu", myMeta.tracks[track].keys[pageNum-1].getTime(), stopTime);
    it->second.curOffset = 0;
    getNext();
    //in case earlier seeking was inprecise, seek to the exact point
    while (lastPack && lastPack.getTime() < (unsigned long long)myMeta.tracks[track].keys[pageNum-1].getTime()){
      getNext();
    }
    while (lastPack && lastPack.getTime() < stopTime){
      if (it->second.curOffset + lastPack.getDataLen() > pagesByTrack[track][pageNum].dataSize){
        DEBUG_MSG(DLVL_WARN, "Trying to write %u bytes on pos %llu where size is %llu (time: %llu / %llu, track %u page %u)", lastPack.getDataLen(), it->second.curOffset, pagesByTrack[track][pageNum].dataSize, lastPack.getTime(), stopTime, track, pageNum);
        break;
      }else{
        memcpy(dataPages[track][pageNum].mapped + it->second.curOffset, lastPack.getData(), lastPack.getDataLen());
        it->second.curOffset += lastPack.getDataLen();
      }
      getNext();
    }
    for (int i = 0; i < indexPages[track].len / 8; i++){
      if (((long long int*)indexPages[track].mapped)[i] == 0){
        ((long long int*)indexPages[track].mapped)[i] = (((long long int)htonl(pageNum)) << 32) | htonl(it->second.keyNum);
        break;
      }
    }
    return true;
  }

  bool Input::atKeyFrame(){
    static std::map<int, unsigned long long> lastSeen;
    //not in keyTimes? We're not at a keyframe.
    unsigned int c = keyTimes[lastPack.getTrackId()].count(lastPack.getTime());
    if (!c){
      return false;
    }
    //skip double times
    if (lastSeen.count(lastPack.getTrackId()) && lastSeen[lastPack.getTrackId()] == lastPack.getTime()){
      return false;
    }
    //set last seen, and return true
    lastSeen[lastPack.getTrackId()] = lastPack.getTime();
    return true;
  }

  void Input::play(int until) {
    playing = -1;
    playUntil = until;
    initialTime = 0;
    benchMark = Util::getMS();
  }

  void Input::playOnce() {
    if (playing <= 0) {
      playing = 1;
    }
    ++playing;
    benchMark = Util::getMS();
  }

  void Input::quitPlay() {
    playing = 0;
  }
}

<commit_msg>Fixed Erik's silly mistake. Oh Erik. :')<commit_after>#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>

#include <mist/defines.h>
#include "input.h"
#include <sstream>
#include <fstream>
#include <iterator>

namespace Mist {
  Input * Input::singleton = NULL;

  void Input::userCallback(char * data, size_t len, unsigned int id){
    for (int i = 0; i < 5; i++){
      long tid = ((long)(data[i*6]) << 24) | ((long)(data[i*6+1]) << 16) | ((long)(data[i*6+2]) << 8) | ((long)(data[i*6+3]));
      if (tid){
        long keyNum = ((long)(data[i*6+4]) << 8) | ((long)(data[i*6+5]));
        bufferFrame(tid, keyNum + 1);//Try buffer next frame
      }
    }
  }

  void Input::doNothing(char * data, size_t len, unsigned int id){
    DEBUG_MSG(DLVL_DONTEVEN, "Doing 'nothing'");
    singleton->userCallback(data, 30, id);//call the userCallback for this input
  }

  Input::Input(Util::Config * cfg) {
    config = cfg;
    JSON::Value option;
    option["long"] = "json";
    option["short"] = "j";
    option["help"] = "Output MistIn info in JSON format, then exit.";
    option["value"].append(0ll);
    config->addOption("json", option);
    option.null();
    option["arg_num"] = 1ll;
    option["arg"] = "string";
    option["help"] = "Name of the input file or - for stdin";
    option["value"].append("-");
    config->addOption("input", option);
    option.null();
    option["arg_num"] = 2ll;
    option["arg"] = "string";
    option["help"] = "Name of the output file or - for stdout";
    option["value"].append("-");
    config->addOption("output", option);
    option.null();
    option["arg"] = "string";
    option["short"] = "s";
    option["long"] = "stream";
    option["help"] = "The name of the stream that this connector will transmit.";
    config->addOption("streamname", option);
    option.null();
    option["short"] = "p";
    option["long"] = "player";
    option["help"] = "Makes this connector into a player";
    config->addOption("player", option);

    packTime = 0;
    lastActive = Util::epoch();
    playing = 0;
    playUntil = 0;

    singleton = this;
    isBuffer = false;
  }

  void Input::checkHeaderTimes(std::string streamFile){
    std::string headerFile = streamFile + ".dtsh";
    FILE * tmp = fopen(headerFile.c_str(),"r");
	  if (tmp == NULL) {
      INFO_MSG("can't open file: %s (no header times compared, nothing removed)", headerFile.c_str() );
	    return;
	  }
	  struct stat bufStream;
    struct stat bufHeader;
    //fstat(fileno(streamFile), &bufStream);
    //fstat(fileno(tmp), &bufHeader);

    if (stat(streamFile.c_str(), &bufStream) !=0 || stat(headerFile.c_str(), &bufHeader) !=0){
		  ERROR_MSG("could not get file info (no header times compared, nothing removed)");
      fclose(tmp);
		  return;
    }

	  int timeStream = bufStream.st_mtime;
    int timeHeader = bufHeader.st_mtime;
    fclose(tmp);
    INFO_MSG("time header: %i time stream: %i ", timeHeader, timeStream);
    if (timeHeader < timeStream) {
	    INFO_MSG("removing old header file: %s ",headerFile.c_str());
		  //delete filename
		  remove(headerFile.c_str());
    }
  }

  int Input::run() {
    if (config->getBool("json")) {
      std::cerr << capa.toString() << std::endl;
      return 0;
    }
    if (!setup()) {
      std::cerr << config->getString("cmd") << " setup failed." << std::endl;
      return 0;
    }
    checkHeaderTimes(config->getString("input"));
    if (!readHeader()) {
      std::cerr << "Reading header for " << config->getString("input") << " failed." << std::endl;
      return 0;
    }
    parseHeader();

    if (!config->getBool("player")){
      //check filename for no -
      if (config->getString("output") != "-"){
        std::string filename = config->getString("output");
        if (filename.size() < 5 || filename.substr(filename.size() - 5) != ".dtsc"){
          filename += ".dtsc";
        }
        //output to dtsc
        DTSC::Meta newMeta = myMeta;
        newMeta.reset();
        JSON::Value tempVal;
        std::ofstream file(filename.c_str());
        long long int bpos = 0;
        seek(0);
        getNext();
        while (lastPack){
          tempVal = lastPack.toJSON();
          tempVal["bpos"] = bpos;
          newMeta.update(tempVal);
          file << std::string(lastPack.getData(), lastPack.getDataLen());
          bpos += lastPack.getDataLen();
          getNext();
        }
        //close file
        file.close();
        //create header
        file.open((filename+".dtsh").c_str());
        file << newMeta.toJSON().toNetPacked();
        file.close();
      }else{
        DEBUG_MSG(DLVL_FAIL,"No filename specified, exiting");
      }
    }else{
      //after this player functionality

#ifdef __CYGWIN__
  metaPage.init(config->getString("streamname"), 8 * 1024 * 1024, true);
#else
  metaPage.init(config->getString("streamname"), (isBuffer ? 8 * 1024 * 1024 : myMeta.getSendLen()), true);
#endif
      myMeta.writeTo(metaPage.mapped);
      userPage.init(config->getString("streamname") + "_users", 30, true);

      if (!isBuffer){
        for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
          bufferFrame(it->first, 1);
        }
      }

      IPC::semaphore waiting(std::string("/wait_" + config->getString("streamname")).c_str(), O_CREAT | O_RDWR, ACCESSPERMS, 0);
      if (!waiting){
        DEBUG_MSG(DLVL_FAIL, "Failed to open semaphore - cancelling");
        return -1;
      }
      waiting.post();
      waiting.close();

      DEBUG_MSG(DLVL_HIGH,"Pre-While");

      long long int activityCounter = Util::getMS();
      while ((Util::getMS() - activityCounter) < 10000){//10 second timeout
        DEBUG_MSG(DLVL_HIGH, "Timer running");
        Util::sleep(1000);
        removeUnused();
        userPage.parseEach(doNothing);
        if (userPage.amount){
          activityCounter = Util::getMS();
          DEBUG_MSG(DLVL_HIGH, "Connected users: %d", userPage.amount);
        }
      }
      DEBUG_MSG(DLVL_DEVEL,"Closing clean");
      //end player functionality
    }
    return 0;
  }

  void Input::removeUnused(){
    for (std::map<unsigned int, std::map<unsigned int, unsigned int> >::iterator it = pageCounter.begin(); it != pageCounter.end(); it++){
      for (std::map<unsigned int, unsigned int>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++){
        it2->second--;
      }
      bool change = true;
      while (change){
        change = false;
        for (std::map<unsigned int, unsigned int>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++){
          if (!it2->second){
            dataPages[it->first].erase(it2->first);
            pageCounter[it->first].erase(it2->first);
            change = true;
            break;
          }
        }
      }
    }
  }

  void Input::parseHeader(){
    DEBUG_MSG(DLVL_DEVEL,"Parsing the header");
    //Select all tracks for parsing header
    selectedTracks.clear();
    std::stringstream trackSpec;
    for (std::map<int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) {
      DEBUG_MSG(DLVL_VERYHIGH, "Track %d encountered", it->first);
      if (trackSpec.str() != ""){
        trackSpec << " ";
      }
      trackSpec << it->first;
      DEBUG_MSG(DLVL_VERYHIGH, "Trackspec now %s", trackSpec.str().c_str());
      for (std::deque<DTSC::Key>::iterator it2 = it->second.keys.begin(); it2 != it->second.keys.end(); it2++){
        keyTimes[it->first].insert(it2->getTime());
      }
    }
    trackSelect(trackSpec.str());

    std::map<int, DTSCPageData> curData;
    std::map<int, booking> bookKeeping;

    seek(0);
    getNext();

    while(lastPack){//loop through all
      int tid = lastPack.getTrackId();
      if (!tid){
        getNext(false);
        continue;
      }
      if (!bookKeeping.count(tid)){
        bookKeeping[tid].first = 1;
        bookKeeping[tid].curPart = 0;
        bookKeeping[tid].curKey = 0;

        curData[tid].lastKeyTime = 0xFFFFFFFF;
        curData[tid].keyNum = 1;
        curData[tid].partNum = 0;
        curData[tid].dataSize = 0;
        curData[tid].curOffset = 0;
        curData[tid].firstTime = myMeta.tracks[tid].keys[0].getTime();

        char tmpId[20];
        sprintf(tmpId, "%d", tid);
        indexPages[tid].init(config->getString("streamname") + tmpId, 8 * 1024, true);//Pages of 8kb in size, room for 512 parts.
      }
      if (myMeta.tracks[tid].keys[bookKeeping[tid].curKey].getParts() == curData[tid].partNum){
        if (curData[tid].dataSize > 8 * 1024 * 1024) {
          pagesByTrack[tid][bookKeeping[tid].first] = curData[tid];
          bookKeeping[tid].first += curData[tid].keyNum;
          curData[tid].keyNum = 0;
          curData[tid].dataSize = 0;
          curData[tid].firstTime = myMeta.tracks[tid].keys[bookKeeping[tid].curKey].getTime();
        }
        bookKeeping[tid].curKey++;
        curData[tid].keyNum++;
        curData[tid].partNum = 0;
      }
      curData[tid].dataSize += lastPack.getDataLen();
      curData[tid].partNum ++;
      bookKeeping[tid].curPart ++;
      getNext(false);
    }
    for (std::map<int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) {
      if (curData.count(it->first) && !pagesByTrack[it->first].count(bookKeeping[it->first].first)){
        pagesByTrack[it->first][bookKeeping[it->first].first] = curData[it->first];
      }
      if (!pagesByTrack.count(it->first)){
        DEBUG_MSG(DLVL_WARN, "No pages for track %d found", it->first);
      }else{
        DEBUG_MSG(DLVL_DEVEL, "Track %d (%s) split into %lu pages", it->first, myMeta.tracks[it->first].codec.c_str(), pagesByTrack[it->first].size());
        for (std::map<int, DTSCPageData>::iterator it2 = pagesByTrack[it->first].begin(); it2 != pagesByTrack[it->first].end(); it2++){
          DEBUG_MSG(DLVL_DEVEL, "Page %u-%u", it2->first, it2->first + it2->second.keyNum - 1);
        }
      }
    }
  }

  bool Input::bufferFrame(int track, int keyNum){
    if (keyNum < 1){keyNum = 1;}
    if (!pagesByTrack.count(track)){
      return false;
    }
    std::map<int, DTSCPageData>::iterator it = pagesByTrack[track].upper_bound(keyNum);
    if (it != pagesByTrack[track].begin()){
      it--;
    }
    int pageNum = it->first;
    pageCounter[track][pageNum] = 15;///Keep page 15seconds in memory after last use

    DEBUG_MSG(DLVL_DONTEVEN, "Attempting to buffer page %d key %d->%d", track, keyNum, pageNum);
    if (dataPages[track].count(pageNum)){
      return true;
    }
    char pageId[100];
    int pageIdLen = sprintf(pageId, "%s%d_%d", config->getString("streamname").c_str(), track, pageNum);
    std::string tmpString(pageId, pageIdLen);
#ifdef __CYGWIN__
    dataPages[track][pageNum].init(tmpString, 26 * 1024 * 1024, true);
#else
    dataPages[track][pageNum].init(tmpString, it->second.dataSize, true);
#endif
    DEBUG_MSG(DLVL_DEVEL, "Buffering track %d page %d through %d", track, pageNum, pageNum-1 + it->second.keyNum);

    std::stringstream trackSpec;
    trackSpec << track;
    trackSelect(trackSpec.str());
    seek(myMeta.tracks[track].keys[pageNum-1].getTime());
    long long unsigned int stopTime = myMeta.tracks[track].lastms + 1;
    if ((int)myMeta.tracks[track].keys.size() > pageNum-1 + it->second.keyNum){
      stopTime = myMeta.tracks[track].keys[pageNum-1 + it->second.keyNum].getTime();
    }
    DEBUG_MSG(DLVL_HIGH, "Playing from %ld to %llu", myMeta.tracks[track].keys[pageNum-1].getTime(), stopTime);
    it->second.curOffset = 0;
    getNext();
    //in case earlier seeking was inprecise, seek to the exact point
    while (lastPack && lastPack.getTime() < (unsigned long long)myMeta.tracks[track].keys[pageNum-1].getTime()){
      getNext();
    }
    while (lastPack && lastPack.getTime() < stopTime){
      if (it->second.curOffset + lastPack.getDataLen() > pagesByTrack[track][pageNum].dataSize){
        DEBUG_MSG(DLVL_WARN, "Trying to write %u bytes on pos %llu where size is %llu (time: %llu / %llu, track %u page %u)", lastPack.getDataLen(), it->second.curOffset, pagesByTrack[track][pageNum].dataSize, lastPack.getTime(), stopTime, track, pageNum);
        break;
      }else{
        memcpy(dataPages[track][pageNum].mapped + it->second.curOffset, lastPack.getData(), lastPack.getDataLen());
        it->second.curOffset += lastPack.getDataLen();
      }
      getNext();
    }
    for (int i = 0; i < indexPages[track].len / 8; i++){
      if (((long long int*)indexPages[track].mapped)[i] == 0){
        ((long long int*)indexPages[track].mapped)[i] = (((long long int)htonl(pageNum)) << 32) | htonl(it->second.keyNum);
        break;
      }
    }
    return true;
  }

  bool Input::atKeyFrame(){
    static std::map<int, unsigned long long> lastSeen;
    //not in keyTimes? We're not at a keyframe.
    unsigned int c = keyTimes[lastPack.getTrackId()].count(lastPack.getTime());
    if (!c){
      return false;
    }
    //skip double times
    if (lastSeen.count(lastPack.getTrackId()) && lastSeen[lastPack.getTrackId()] == lastPack.getTime()){
      return false;
    }
    //set last seen, and return true
    lastSeen[lastPack.getTrackId()] = lastPack.getTime();
    return true;
  }

  void Input::play(int until) {
    playing = -1;
    playUntil = until;
    initialTime = 0;
    benchMark = Util::getMS();
  }

  void Input::playOnce() {
    if (playing <= 0) {
      playing = 1;
    }
    ++playing;
    benchMark = Util::getMS();
  }

  void Input::quitPlay() {
    playing = 0;
  }
}

<|endoftext|>


<commit_before>#include <cstdlib>
#include <cstdarg>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include "perf.hpp"
#include "iproto.hpp"
#include "iproto_conn.hpp"

#define LOG_DEBUG 0

namespace IProto {

int stderr_printf(char const* format, ...) {
	va_list args;
	va_start(args, format);
	int result = vfprintf(stderr, format, args);
	va_end(args);
	fprintf(stderr, "\n");
	return result;
}

Conn::Conn(boost::asio::io_service &_io, const boost::asio::ip::tcp::endpoint &_ep, uint32_t _connect_timeout, uint32_t _read_timeout)
	: io(_io), ep(_ep), sock(_io), timer(_io), ping_timer(_io) {
		if( _read_timeout==0 ) _read_timeout=_connect_timeout;
		connect_timeout=_connect_timeout;
		read_timeout=_read_timeout;
		write_queue_len=0;
		write_is_active=ping_enabled=true;
		log_func = stderr_printf;
}

Conn::~Conn() {
	if( LOG_DEBUG )
		log_func("[iproto_conn] destructor");

	close();
	dismissCallbacks(CB_ERR);
}

void Conn::close() {
	boost::system::error_code ec = boost::asio::error::interrupted;
	for(int i=0; i<3 && sock.is_open() && ec == boost::asio::error::interrupted; ++i)
		sock.close(ec);
}

void Conn::disablePing() {
	ping_enabled=false;
	ping_timer.cancel();
}

void Conn::setupPing(const boost::system::error_code& error) {
	if( error || !ping_enabled )
		return;
	if( !sock.is_open() )
		beginConnect();
	//Write a ping packet into socket
	static const IProto::Header hdr{0xff00, 0};
	static const IProto::PacketPtr pkt{hdr};
	Write(IProto::Packet(&pkt), boost::bind(&Conn::pingCb, shared_from_this(), _1)  );
}

void Conn::pingCb(RequestResult res) {
	if( unlikely(res.code != CB_OK) ) {
		//Reconnect
		log_func("[iproto_conn] ping failed, code %u", res.code);
		if( res.code == CB_TIMEOUT ) {
			reconnect();
			return;
		}
	}
	ping_timer.expires_from_now( boost::posix_time::milliseconds(300) );
	ping_timer.async_wait( boost::bind(&Conn::setupPing, shared_from_this(), boost::asio::placeholders::error) );
}

bool Conn::checkConnect() {
	if( unlikely(!sock.is_open()) ) {
		beginConnect();
		return true;
	}
	return false;
}
void Conn::beginConnect() {
	write_is_active=false;
	ping_timer.cancel();
	//Limit connection time
	timer.expires_from_now( boost::posix_time::milliseconds(connect_timeout) );
	timer.async_wait( boost::bind(&Conn::reconnectByTimer, shared_from_this(), boost::asio::placeholders::error) );

	sock.async_connect( ep, boost::bind(&Conn::onConnect, shared_from_this(), boost::asio::placeholders::error) );
	if( LOG_DEBUG )
		log_func("[iproto_conn] Connecting to %s:%d", ep.address().to_string().c_str(), ep.port() );
}
void Conn::reconnect() {
	close();
	if( LOG_DEBUG )
		log_func("[iproto_conn] reconnect");
	beginConnect();
}
void Conn::dismissCallbacks(CB_Result res) {
	if( LOG_DEBUG )
		log_func("[iproto_conn] dismissCallbacks");
	ping_timer.cancel();
	for(auto it=callbacks_map.begin(); it!=callbacks_map.end(); ) {
		it = invokeCallback(it, RequestResult(res));
	}
	callbacks_map.clear();
}
void Conn::reconnectByTimer(const boost::system::error_code& error) {
	if( !error )
		reconnect();
}
void Conn::onConnect(const boost::system::error_code& error) {
	if( likely(!error) ) {
		if( LOG_DEBUG )
			log_func("[iproto_conn] Connected");
		timer.cancel();
		setupReadHandler();
		sock.set_option( boost::asio::ip::tcp::no_delay(true) );
		if( ping_enabled )
			setupPing( boost::system::error_code() );
		else
			ensureWriteBuffer( boost::system::error_code() );
	}
}

void Conn::setupReadHandler() {
	if( likely(!rd_buf || rd_buf->size()==0) )
		rd_buf.reset(new boost::asio::streambuf);
	onRead( boost::system::error_code() );
}
void Conn::onRead(const boost::system::error_code& error) {
	if( unlikely(error) ) {
		log_func("[iproto_conn] %s:%u: read error: %s", ep.address().to_string().c_str(), ep.port(), error.message().c_str() );
		dismissCallbacks(CB_ERR);
		if( error != boost::asio::error::operation_aborted ) {
			beginConnect();
		}
		return;
	}
	if( LOG_DEBUG )
		log_func("[iproto_conn] onRead rd_buf->size=%zu", rd_buf->size());
	while( rd_buf->size() >= sizeof(Header) ) {
		const PacketPtr *buf = boost::asio::buffer_cast< const PacketPtr * >( rd_buf->data() );
		size_t want_read = sizeof(Header)+buf->hdr.len;
		if( want_read <= rd_buf->size() ) {
			invokeCallback(buf->hdr.sync, RequestResult(CB_OK, Packet(buf)) );
			rd_buf->consume( sizeof(Header) + buf->hdr.len );
		}else{
			boost::asio::async_read(sock, *rd_buf, boost::asio::transfer_at_least(want_read - rd_buf->size()),
				boost::bind(&Conn::onRead, shared_from_this(), boost::asio::placeholders::error) );
			return;
		}
	}
	if( likely(sock.is_open()) )
		boost::asio::async_read(sock, *rd_buf, boost::asio::transfer_at_least(sizeof(Header)-rd_buf->size()),
			boost::bind(&Conn::onRead, shared_from_this(), boost::asio::placeholders::error) );
}
void Conn::ensureWriteBuffer(const boost::system::error_code& error, const char *wr_buf) {
	if( unlikely(error) ) {
		log_func("[iproto_conn] %s:%u: write error: %s", ep.address().to_string().c_str(), ep.port(), error.message().c_str() );
		if( error != boost::asio::error::operation_aborted ) {
			if( error == boost::asio::error::broken_pipe ) {
				//Packet was not completely transfered, we can do a retry
				write_queue.push_back( wr_buf );
				write_queue_len++;
				wr_buf=nullptr;//Prevent free
			}
			beginConnect();
		}else{
			dismissCallbacks(CB_ERR);
		}
		if( likely(wr_buf != nullptr) )
			::free((void*)wr_buf);
		return;
	}
	if( likely(wr_buf != nullptr) )
		::free((void*)wr_buf);

	if( likely(write_queue_len>0 && (wr_buf || !write_is_active)) ) {
		const char *wr = write_queue.front();
		write_queue.pop_front();
		write_queue_len--;
		const Header *hdr = reinterpret_cast< const Header * >(wr);
		boost::asio::async_write(sock, boost::asio::buffer(wr, sizeof(*hdr)+hdr->len),
			boost::bind(&Conn::ensureWriteBuffer, shared_from_this(), boost::asio::placeholders::error, wr) );
		if( LOG_DEBUG )
			log_func("[iproto_conn] Write packet sync=%u len=%u", hdr->sync, hdr->len);
		write_is_active=true;
	} else
		write_is_active=false;
}
bool Conn::dropPacketWrite(Packet &&pkt) {
	write_queue.push_back( pkt.data );
	pkt.data=nullptr;
	write_queue_len++;

	if( unlikely(checkConnect()) ) {
		log_func("[iproto_conn] dropPacketWrite deferred (no connect)");
		return false;
	}

	ensureWriteBuffer( boost::system::error_code() );
	return true;
}
bool Conn::Write(Packet &&pkt, callbacks_func_type &&cb) {
	auto timer = new boost::asio::deadline_timer(io);
	timer->expires_from_now( boost::posix_time::milliseconds(read_timeout) );
	timer->async_wait( boost::bind(&Conn::onTimeout, shared_from_this(), boost::asio::placeholders::error, pkt.hdr.sync) );

	callbacks_map[pkt.hdr.sync] = std::make_pair(timer, std::forward<callbacks_func_type>(cb));
	return dropPacketWrite( std::forward<Packet>(pkt) );
}
void Conn::Shutdown() {
	if( LOG_DEBUG )
		log_func("[iproto_conn] Shutdown");
	close();
	dismissCallbacks(CB_ERR);
}
bool Conn::GentleShutdown() {
	if( LOG_DEBUG )
		log_func("[iproto_conn] GentleShutdown");

	if( callbacks_map.empty() && !write_is_active ) {
		Shutdown();
		return true;
	}
	return false;
}
void Conn::onTimeout(const boost::system::error_code& error, uint32_t sync) {
	if( unlikely(!error) ) {
		if( LOG_DEBUG )
			log_func("[iproto_conn] Packet with sync=%u timed out", sync);
		invokeCallback(sync, RequestResult(CB_TIMEOUT));
	}
}
void Conn::invokeCallback(uint32_t sync, RequestResult &&req_res) {
	auto it = callbacks_map.find(sync);
	if( it != callbacks_map.end() )
		invokeCallback(it, std::forward<RequestResult>(req_res));
}
Conn::callbacks_map_type::iterator Conn::invokeCallback(Conn::callbacks_map_type::iterator it, RequestResult &&req_res) {
	if( LOG_DEBUG )
		log_func("[iproto_conn] invokeCallback sync=%u res.code=%u", it->first, req_res.code);

	callbacks_map_type::iterator ret_it;
	auto timer_and_cb = it->second;
	ret_it = callbacks_map.erase(it);
	if( likely(timer_and_cb.first) ) {
		timer_and_cb.first->cancel();
		delete timer_and_cb.first;
	}
	if( likely(timer_and_cb.second) ) try {
		io.post( boost::bind(timer_and_cb.second, std::forward<RequestResult>(req_res)) ); //Scared of resume coroutines which already current
	} catch(std::exception &e) {
		log_func("[iproto_conn] invokeCallback uncatched exception: %s", e.what() );
		abort(); //It's your guilt
	}
	return ret_it;
}

};
<commit_msg>iproto_conn: fix reconnect bug, fix logging<commit_after>#include <cstdlib>
#include <cstdarg>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include "perf.hpp"
#include "iproto.hpp"
#include "iproto_conn.hpp"

#define LOG_DEBUG 0

namespace IProto {

int stderr_printf(char const* format, ...) {
	va_list args;
	va_start(args, format);
	int result = vfprintf(stderr, format, args);
	va_end(args);
	fprintf(stderr, "\n");
	return result;
}

Conn::Conn(boost::asio::io_service &_io, const boost::asio::ip::tcp::endpoint &_ep, uint32_t _connect_timeout, uint32_t _read_timeout)
	: io(_io), ep(_ep), sock(_io), timer(_io), ping_timer(_io) {
		if( _read_timeout==0 ) _read_timeout=_connect_timeout;
		connect_timeout=_connect_timeout;
		read_timeout=_read_timeout;
		write_queue_len=0;
		write_is_active=ping_enabled=true;
		log_func = stderr_printf;
}

Conn::~Conn() {
	if( LOG_DEBUG )
		log_func("[iproto_conn] %s:%u destructor", ep.address().to_string().c_str(), ep.port());

	close();
	dismissCallbacks(CB_ERR);
}

void Conn::close() {
	boost::system::error_code ec = boost::asio::error::interrupted;
	for(int i=0; i<3 && sock.is_open() && ec == boost::asio::error::interrupted; ++i)
		sock.close(ec);
}

void Conn::disablePing() {
	ping_enabled=false;
	ping_timer.cancel();
}

void Conn::setupPing(const boost::system::error_code& error) {
	if( error || !ping_enabled )
		return;
	if( !sock.is_open() )
		beginConnect();
	//Write a ping packet into socket
	static const IProto::Header hdr{0xff00, 0};
	static const IProto::PacketPtr pkt{hdr};
	Write(IProto::Packet(&pkt), boost::bind(&Conn::pingCb, shared_from_this(), _1)  );
}

void Conn::pingCb(RequestResult res) {
	if( unlikely(res.code != CB_OK) ) {
		//Reconnect
		log_func("[iproto_conn] %s:%u ping failed, code %u", ep.address().to_string().c_str(), ep.port(), res.code);
		if( res.code == CB_TIMEOUT ) {
			reconnect();
			return;
		}
	}
	ping_timer.expires_from_now( boost::posix_time::milliseconds(300) );
	ping_timer.async_wait( boost::bind(&Conn::setupPing, shared_from_this(), boost::asio::placeholders::error) );
}

bool Conn::checkConnect() {
	if( unlikely(!sock.is_open()) ) {
		beginConnect();
		return true;
	}
	return false;
}
void Conn::beginConnect() {
	write_is_active=false;
	ping_timer.cancel();
	//Limit connection time
	timer.expires_from_now( boost::posix_time::milliseconds(connect_timeout) );
	timer.async_wait( boost::bind(&Conn::reconnectByTimer, shared_from_this(), boost::asio::placeholders::error) );

	sock.async_connect( ep, boost::bind(&Conn::onConnect, shared_from_this(), boost::asio::placeholders::error) );
	if( LOG_DEBUG )
		log_func("[iproto_conn] Connecting to %s:%d", ep.address().to_string().c_str(), ep.port() );
}
void Conn::reconnect() {
	close();
	if( LOG_DEBUG )
		log_func("[iproto_conn] %s:%u reconnect", ep.address().to_string().c_str(), ep.port());
	beginConnect();
}
void Conn::dismissCallbacks(CB_Result res) {
	if( LOG_DEBUG )
		log_func("[iproto_conn] %s:%u dismissCallbacks", ep.address().to_string().c_str(), ep.port());
	ping_timer.cancel();
	for(auto it=callbacks_map.begin(); it!=callbacks_map.end(); ) {
		it = invokeCallback(it, RequestResult(res));
	}
	callbacks_map.clear();
}
void Conn::reconnectByTimer(const boost::system::error_code& error) {
	if( !error )
		reconnect();
}
void Conn::onConnect(const boost::system::error_code& error) {
	if( likely(!error) ) {
		if( LOG_DEBUG )
			log_func("[iproto_conn] %s:%u connected", ep.address().to_string().c_str(), ep.port());
		timer.cancel();
		setupReadHandler();
		sock.set_option( boost::asio::ip::tcp::no_delay(true) );
		if( ping_enabled )
			setupPing( boost::system::error_code() );
		else
			ensureWriteBuffer( boost::system::error_code() );
	}else
		log_func("[iproto_conn] %s:%u connect failed: %s", ep.address().to_string().c_str(), ep.port(), error.message().c_str() );
}

void Conn::setupReadHandler() {
	if( likely(!rd_buf || rd_buf->size()==0) )
		rd_buf.reset(new boost::asio::streambuf);
	onRead( boost::system::error_code() );
}
void Conn::onRead(const boost::system::error_code& error) {
	if( unlikely(error) ) {
		log_func("[iproto_conn] %s:%u read error: %s", ep.address().to_string().c_str(), ep.port(), error.message().c_str() );
		dismissCallbacks(CB_ERR);
		if( error != boost::asio::error::operation_aborted ) {
			reconnect();
		}
		return;
	}
	if( LOG_DEBUG )
		log_func("[iproto_conn] %s:%u onRead rd_buf->size=%zu", ep.address().to_string().c_str(), ep.port(), rd_buf->size());
	while( rd_buf->size() >= sizeof(Header) ) {
		const PacketPtr *buf = boost::asio::buffer_cast< const PacketPtr * >( rd_buf->data() );
		size_t want_read = sizeof(Header)+buf->hdr.len;
		if( want_read <= rd_buf->size() ) {
			invokeCallback(buf->hdr.sync, RequestResult(CB_OK, Packet(buf)) );
			rd_buf->consume( sizeof(Header) + buf->hdr.len );
		}else{
			boost::asio::async_read(sock, *rd_buf, boost::asio::transfer_at_least(want_read - rd_buf->size()),
				boost::bind(&Conn::onRead, shared_from_this(), boost::asio::placeholders::error) );
			return;
		}
	}
	if( likely(sock.is_open()) )
		boost::asio::async_read(sock, *rd_buf, boost::asio::transfer_at_least(sizeof(Header)-rd_buf->size()),
			boost::bind(&Conn::onRead, shared_from_this(), boost::asio::placeholders::error) );
}
void Conn::ensureWriteBuffer(const boost::system::error_code& error, const char *wr_buf) {
	if( unlikely(error) ) {
		log_func("[iproto_conn] %s:%u write error: %s", ep.address().to_string().c_str(), ep.port(), error.message().c_str() );
		if( error != boost::asio::error::operation_aborted ) {
			if( error == boost::asio::error::broken_pipe ) {
				//Packet was not completely transfered, we can do a retry
				write_queue.push_back( wr_buf );
				write_queue_len++;
				wr_buf=nullptr;//Prevent free
			}
			reconnect();
		}else{
			dismissCallbacks(CB_ERR);
		}
		if( likely(wr_buf != nullptr) )
			::free((void*)wr_buf);
		return;
	}
	if( likely(wr_buf != nullptr) )
		::free((void*)wr_buf);

	if( likely(write_queue_len>0 && (wr_buf || !write_is_active)) ) {
		const char *wr = write_queue.front();
		write_queue.pop_front();
		write_queue_len--;
		const Header *hdr = reinterpret_cast< const Header * >(wr);
		boost::asio::async_write(sock, boost::asio::buffer(wr, sizeof(*hdr)+hdr->len),
			boost::bind(&Conn::ensureWriteBuffer, shared_from_this(), boost::asio::placeholders::error, wr) );
		if( LOG_DEBUG )
			log_func("[iproto_conn] %s:%u write packet sync=%u len=%u", ep.address().to_string().c_str(), ep.port(), hdr->sync, hdr->len);
		write_is_active=true;
	} else
		write_is_active=false;
}
bool Conn::dropPacketWrite(Packet &&pkt) {
	write_queue.push_back( pkt.data );
	pkt.data=nullptr;
	write_queue_len++;

	if( unlikely(checkConnect()) ) {
		log_func("[iproto_conn] %s:%u dropPacketWrite deferred (no connect)", ep.address().to_string().c_str(), ep.port());
		return false;
	}

	ensureWriteBuffer( boost::system::error_code() );
	return true;
}
bool Conn::Write(Packet &&pkt, callbacks_func_type &&cb) {
	auto timer = new boost::asio::deadline_timer(io);
	timer->expires_from_now( boost::posix_time::milliseconds(read_timeout) );
	timer->async_wait( boost::bind(&Conn::onTimeout, shared_from_this(), boost::asio::placeholders::error, pkt.hdr.sync) );

	callbacks_map[pkt.hdr.sync] = std::make_pair(timer, std::forward<callbacks_func_type>(cb));
	return dropPacketWrite( std::forward<Packet>(pkt) );
}
void Conn::Shutdown() {
	if( LOG_DEBUG )
		log_func("[iproto_conn] %s:%u shutdown", ep.address().to_string().c_str(), ep.port());
	close();
	dismissCallbacks(CB_ERR);
}
bool Conn::GentleShutdown() {
	if( LOG_DEBUG )
		log_func("[iproto_conn] %s:%u GentleShutdown", ep.address().to_string().c_str(), ep.port());

	if( callbacks_map.empty() && !write_is_active ) {
		Shutdown();
		return true;
	}
	return false;
}
void Conn::onTimeout(const boost::system::error_code& error, uint32_t sync) {
	if( unlikely(!error) ) {
		if( LOG_DEBUG )
			log_func("[iproto_conn] %s:%u Packet with sync=%u timed out", ep.address().to_string().c_str(), ep.port(), sync);
		invokeCallback(sync, RequestResult(CB_TIMEOUT));
	}
}
void Conn::invokeCallback(uint32_t sync, RequestResult &&req_res) {
	auto it = callbacks_map.find(sync);
	if( it != callbacks_map.end() )
		invokeCallback(it, std::forward<RequestResult>(req_res));
}
Conn::callbacks_map_type::iterator Conn::invokeCallback(Conn::callbacks_map_type::iterator it, RequestResult &&req_res) {
	if( LOG_DEBUG )
		log_func("[iproto_conn] %s:%u invokeCallback sync=%u res.code=%u", ep.address().to_string().c_str(), ep.port(), it->first, req_res.code);

	callbacks_map_type::iterator ret_it;
	auto timer_and_cb = it->second;
	ret_it = callbacks_map.erase(it);
	if( likely(timer_and_cb.first) ) {
		timer_and_cb.first->cancel();
		delete timer_and_cb.first;
	}
	if( likely(timer_and_cb.second) ) try {
		io.post( boost::bind(timer_and_cb.second, std::forward<RequestResult>(req_res)) ); //Scared of resume coroutines which already current
	} catch(std::exception &e) {
		log_func("[iproto_conn] %s:%u invokeCallback uncatched exception: %s", ep.address().to_string().c_str(), ep.port(), e.what() );
		abort(); //It's your guilt
	}
	return ret_it;
}

};
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#include "job.h"

#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>

#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <boost/filesystem.hpp>
#include <boost/uuid/uuid.hpp>

#include "db/driver.h"
#include "db/eq-inserter.h"
#include "db/query.h"
#include "db/statement-driver.h"

namespace flint {
namespace job {

namespace {

class NextJob : db::StatementDriver {
public:
	explicit NextJob(sqlite3 *db)
		: db::StatementDriver(db, "SELECT rowid, ps_id FROM jobs WHERE status = 'pending' LIMIT 1")
	{
	}

	/*
	 * Return 1 if a pending job is found, 0 if no more pending one, or -1 otherwise.
	 */
	int Get(int *rowid, int *ps_id)
	{
		int e;
		e = sqlite3_step(stmt());
		if (e == SQLITE_DONE) {
			// no more pending row
			return 0;
		}
		if (e != SQLITE_ROW) {
			std::cerr << "failed to get a next job: " << e << std::endl;
			return -1;
		}
		*rowid = sqlite3_column_int(stmt(), 0);
		*ps_id = sqlite3_column_int(stmt(), 1);
		return 1;
	}
};

class Inserter {
public:
	Inserter(sqlite3 *db, FILE *fp)
		: inserter_("parameter_eqs", db)
		, fp_(fp)
	{}

	bool Insert(const char *name, const char *rhs)
	{
		std::fprintf(fp_, "%s=%s\n", name, rhs);

		std::ostringstream oss;
		oss << "(eq %" << name << ' ' << rhs << ')';
		std::string math = oss.str();
		return inserter_.Insert(math.c_str());
	}

	bool Insert(const boost::uuids::uuid &uuid, const char *math)
	{
		return inserter_.Insert(uuid, math);
	}

private:
	db::EqInserter inserter_;
	FILE *fp_;
};

int SaveParameter(void *data, int argc, char **argv, char **names)
{
	Inserter *inserter = static_cast<Inserter *>(data);
	for (int i=0;i<argc;i++) {
		if (!inserter->Insert(names[i], argv[i]))
			return 1;
	}
	return 0;
}

int SaveEquation(void *data, int argc, char **argv, char **names)
{
	Inserter *inserter = static_cast<Inserter *>(data);
	(void)names;
	assert(argc == 2);
	boost::uuids::uuid uuid;
	assert(argv[0]);
	std::memcpy(&uuid, argv[0], uuid.size());
	return (inserter->Insert(uuid, argv[1])) ? 0 : 1;
}

class Generator {
public:
	Generator(sqlite3 *input, sqlite3 *output, FILE *fp)
		: input_(input)
		, inserter_(output, fp)
	{}

	bool Generate(int rowid, int ps_id) {
		char query[1024];
		char *em;
		int e;

		/* print equations */
		std::sprintf(query, "SELECT * FROM parameter_samples WHERE rowid = '%d'", ps_id);
		e = sqlite3_exec(input_, query, SaveParameter, &inserter_, &em);
		if (e != SQLITE_OK) {
			if (e != SQLITE_ABORT)
				std::cerr << "failed to select parameter_samples: " << e
						  << ": " << em << std::endl;
			sqlite3_free(em);
			return false;
		}
		e = sqlite3_exec(input_, "SELECT uuid, body FROM equations", SaveEquation, &inserter_, &em);
		if (e != SQLITE_OK) {
			if (e != SQLITE_ABORT)
				std::cerr << "failed to select equations: " << e << ": " << em << std::endl;
			sqlite3_free(em);
			return false;
		}

		/* mark it generated */
		std::sprintf(query, "UPDATE jobs SET status = 'generated' WHERE rowid = '%d'", rowid);
		e = sqlite3_exec(input_, query, nullptr, nullptr, &em);
		if (e != SQLITE_OK) {
			std::fprintf(stderr, "failed to update jobs: %d: %s\n", e, em);
			sqlite3_free(em);
			return false;
		}

		return true;
	}

private:
	sqlite3 *input_;
	Inserter inserter_;
};

}

bool Generate(sqlite3 *input, const char *dir, int *job_id)
{
	int rowid;
	int ps_id;
	{
		NextJob nj(input);
		int r = nj.Get(&rowid, &ps_id);
		if (r == 0) {
			*job_id = 0;
			return true;
		}
		if (r < 0) return false;
	}
	std::unique_ptr<char[]> path(BuildPath(dir, rowid));
	boost::system::error_code ec;
	boost::filesystem::create_directories(path.get(), ec);
	if (ec) {
		std::cerr << "failed to create directories: " << path.get()
			 << ": " << ec << std::endl;
		return false;
	}
	char filename[96];
	std::sprintf(filename, "%s/generated.db", path.get());
	db::Driver driver(filename);
	sqlite3 *output = driver.db();
	if (!output)
		return false;
	if (!BeginTransaction(output))
		return false;
	if (!CreateTable(output, "parameter_eqs", "(uuid BLOB, math TEXT)"))
		return false;
	std::sprintf(filename, "%s/values.txt.tmp", path.get());
	FILE *fp = std::fopen(filename, "w");
	if (!fp) {
		std::perror(filename);
		return false;
	}
	if (!BeginTransaction(input)) {
		std::fclose(fp);
		return false;
	}
	Generator g(input, output, fp);
	if (!g.Generate(rowid, ps_id)) {
		std::fclose(fp);
		return false;
	}
	if (!CommitTransaction(input)) {
		std::fclose(fp);
		return false;
	}
	std::fclose(fp);
	char values_file[96]; // large enough
	std::sprintf(values_file, "%s/values.txt", path.get());
	if (std::rename(filename, values_file) != 0) {
		std::cerr << "failed to rename " << filename
			 << " to " << values_file
			 << std::endl;
		std::remove(filename);
		return false;
	}

	if (!CommitTransaction(output))
		return false;
	*job_id = rowid;
	return true;
}

}
}
<commit_msg>Destruct objects earlier<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#include "job.h"

#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>

#define BOOST_FILESYSTEM_NO_DEPRECATED
#include <boost/filesystem.hpp>
#include <boost/uuid/uuid.hpp>

#include "db/driver.h"
#include "db/eq-inserter.h"
#include "db/query.h"
#include "db/statement-driver.h"

namespace flint {
namespace job {

namespace {

class NextJob : db::StatementDriver {
public:
	explicit NextJob(sqlite3 *db)
		: db::StatementDriver(db, "SELECT rowid, ps_id FROM jobs WHERE status = 'pending' LIMIT 1")
	{
	}

	/*
	 * Return 1 if a pending job is found, 0 if no more pending one, or -1 otherwise.
	 */
	int Get(int *rowid, int *ps_id)
	{
		int e;
		e = sqlite3_step(stmt());
		if (e == SQLITE_DONE) {
			// no more pending row
			return 0;
		}
		if (e != SQLITE_ROW) {
			std::cerr << "failed to get a next job: " << e << std::endl;
			return -1;
		}
		*rowid = sqlite3_column_int(stmt(), 0);
		*ps_id = sqlite3_column_int(stmt(), 1);
		return 1;
	}
};

class Inserter {
public:
	Inserter(sqlite3 *db, FILE *fp)
		: inserter_("parameter_eqs", db)
		, fp_(fp)
	{}

	bool Insert(const char *name, const char *rhs)
	{
		std::fprintf(fp_, "%s=%s\n", name, rhs);

		std::ostringstream oss;
		oss << "(eq %" << name << ' ' << rhs << ')';
		std::string math = oss.str();
		return inserter_.Insert(math.c_str());
	}

	bool Insert(const boost::uuids::uuid &uuid, const char *math)
	{
		return inserter_.Insert(uuid, math);
	}

private:
	db::EqInserter inserter_;
	FILE *fp_;
};

int SaveParameter(void *data, int argc, char **argv, char **names)
{
	Inserter *inserter = static_cast<Inserter *>(data);
	for (int i=0;i<argc;i++) {
		if (!inserter->Insert(names[i], argv[i]))
			return 1;
	}
	return 0;
}

int SaveEquation(void *data, int argc, char **argv, char **names)
{
	Inserter *inserter = static_cast<Inserter *>(data);
	(void)names;
	assert(argc == 2);
	boost::uuids::uuid uuid;
	assert(argv[0]);
	std::memcpy(&uuid, argv[0], uuid.size());
	return (inserter->Insert(uuid, argv[1])) ? 0 : 1;
}

class Generator {
public:
	Generator(sqlite3 *input, sqlite3 *output, FILE *fp)
		: input_(input)
		, inserter_(output, fp)
	{}

	bool Generate(int rowid, int ps_id) {
		char query[1024];
		char *em;
		int e;

		/* print equations */
		std::sprintf(query, "SELECT * FROM parameter_samples WHERE rowid = '%d'", ps_id);
		e = sqlite3_exec(input_, query, SaveParameter, &inserter_, &em);
		if (e != SQLITE_OK) {
			if (e != SQLITE_ABORT)
				std::cerr << "failed to select parameter_samples: " << e
						  << ": " << em << std::endl;
			sqlite3_free(em);
			return false;
		}
		e = sqlite3_exec(input_, "SELECT uuid, body FROM equations", SaveEquation, &inserter_, &em);
		if (e != SQLITE_OK) {
			if (e != SQLITE_ABORT)
				std::cerr << "failed to select equations: " << e << ": " << em << std::endl;
			sqlite3_free(em);
			return false;
		}

		/* mark it generated */
		std::sprintf(query, "UPDATE jobs SET status = 'generated' WHERE rowid = '%d'", rowid);
		e = sqlite3_exec(input_, query, nullptr, nullptr, &em);
		if (e != SQLITE_OK) {
			std::fprintf(stderr, "failed to update jobs: %d: %s\n", e, em);
			sqlite3_free(em);
			return false;
		}

		return true;
	}

private:
	sqlite3 *input_;
	Inserter inserter_;
};

}

bool Generate(sqlite3 *input, const char *dir, int *job_id)
{
	int rowid;
	int ps_id;
	{
		NextJob nj(input);
		int r = nj.Get(&rowid, &ps_id);
		if (r == 0) {
			*job_id = 0;
			return true;
		}
		if (r < 0) return false;
	}
	std::unique_ptr<char[]> path(BuildPath(dir, rowid));
	boost::system::error_code ec;
	boost::filesystem::create_directories(path.get(), ec);
	if (ec) {
		std::cerr << "failed to create directories: " << path.get()
			 << ": " << ec << std::endl;
		return false;
	}
	char filename[96];
	std::sprintf(filename, "%s/generated.db", path.get());
	{
		db::Driver driver(filename);
		sqlite3 *output = driver.db();
		if (!output)
			return false;
		if (!BeginTransaction(output))
			return false;
		if (!CreateTable(output, "parameter_eqs", "(uuid BLOB, math TEXT)"))
			return false;
		std::sprintf(filename, "%s/values.txt.tmp", path.get());
		FILE *fp = std::fopen(filename, "w");
		if (!fp) {
			std::perror(filename);
			return false;
		}
		if (!BeginTransaction(input)) {
			std::fclose(fp);
			return false;
		}
		{
			Generator g(input, output, fp);
			if (!g.Generate(rowid, ps_id)) {
				std::fclose(fp);
				return false;
			}
		}
		if (!CommitTransaction(input)) {
			std::fclose(fp);
			return false;
		}
		std::fclose(fp);
		if (!CommitTransaction(output))
			return false;
	}

	char values_file[96]; // large enough
	std::sprintf(values_file, "%s/values.txt", path.get());
	if (std::rename(filename, values_file) != 0) {
		std::cerr << "failed to rename " << filename
			 << " to " << values_file
			 << std::endl;
		std::remove(filename);
		return false;
	}

	*job_id = rowid;
	return true;
}

}
}
<|endoftext|>


<commit_before>/**
 * Copyright 2017 Shusheng Shao <iblackangel@163.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <mpl/mthread.h>

#ifdef M_OS_WIN

#ifdef __cplusplus
extern "C" {
#endif

	static unsigned int __stdcall thread_routine(void *arg)
	{
		mpl::MThread *self = (mpl::MThread *) arg;
		if (NULL != self) {
			self->exec();
		}
		return 0;
	}

#ifdef __cplusplus
}
#endif

#else  /* LINUX */

#ifdef __cplusplus
extern "C" {
#endif

	static void *thread_routine(void *arg)
	{
		mpl::MThread *self = (mpl::MThread *) arg;
		if (NULL != self) {
			self->exec();
		}
		return NULL;
	}

#ifdef __cplusplus
}
#endif

#endif /* M_OS_WIN */

MPL_BEGIN_NAMESPACE

MThread::MThread()
{
	_self = 0;
}

MThread::~MThread()
{
}

bool MThread::start()
{
	int res = 0;
	res = pthread_create(&_self, NULL, thread_routine, this);
	if (0 != res)
		perror("create thread");
	return res == 0;
}

void MThread::stop()
{
	interrupt();
	join();
}

int MThread::join()
{
	return pthread_join(_self, NULL);
}

int MThread::detach()
{
	return pthread_detach(_self);
}

int MThread::cancel()
{
	return pthread_cancel(_self);
}

int64_t MThread::id()
{
	return _self;
}

// void MThread::setPriority(Priority priority)
// {
// 	MScopedLock locker(_mutex);
// 	_priority = priority;
// }

// MThread::Priority MThread::priority() const
// {
// 	return _priority;
// }

void MThread::interrupt()
{
	MScopedLock locker(_mutex);
	_interrupt = true;
}

bool MThread::isInterrupted() const
{
	return _interrupt;
}

void MThread::exec()
{
	_interrupt = false;

	run();
}

// Begin functions
// get_thread_id
int64_t threadId()
{
	return pthread_self();
}

MPL_END_NAMESPACE
<commit_msg>update mthread, add Windows implement<commit_after>/**
 * Copyright 2017 Shusheng Shao <iblackangel@163.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <mpl/mthread.h>

#ifdef M_OS_WIN

#ifdef __cplusplus
extern "C" {
#endif

	static unsigned int __stdcall thread_routine(void *arg)
	{
		mpl::MThread *self = (mpl::MThread *) arg;
		if (NULL != self) {
			self->exec();
		}
		return 0;
	}

#ifdef __cplusplus
}
#endif

#else  /* LINUX */

#ifdef __cplusplus
extern "C" {
#endif

	static void *thread_routine(void *arg)
	{
		mpl::MThread *self = (mpl::MThread *) arg;
		if (NULL != self) {
			self->exec();
		}
		return NULL;
	}

#ifdef __cplusplus
}
#endif

#endif /* M_OS_WIN */

MPL_BEGIN_NAMESPACE

#if defined(M_OS_WIN) || defined(_MSC_VER)

MThread::MThread()
	: _self(0)
{
}

MThread::~MThread()
{
}

bool MThread::start()
{
	LPSECURITY_ATTRIBUTES thread_attr = NULL;
	_self = (HANDLE) _beginthreadex(NULL, 0, thread_routine, this, 0, NULL);
	if (NULL == _self) {
		perror("can't create thread");
		return false;
	}
	return true;
}

void MThread::stop()
{
	interrupt();
	join();
}

int MThread::join()
{
	DWORD rc = WaitForSingleObject(_self, INFINITE);
	if (WAIT_FAILED == rc) return -1;
	BOOL rc2 = CloseHandle(_self);
	if (!rc2) return -1;
	return 0;
}

int MThread::detach()
{
	// TODO:: must be rewrite later
	return 0;
}

int MThread::cancel()
{
	// TODO:: must be rewrite later
	BOOL res = TerminateThread(_self, 0);
	if (res) return 0;
	return -1;
}

int64_t MThread::id()
{
	return _self;
}

void MThread::interrupt()
{
	MScopedLock locker(_mutex);
	_interrupt = true;
}

bool MThread::isInterrupted() const
{
	return _interrupt;
}

void MThread::exec()
{
	_interrupt = false;

	run();
}

#else

MThread::MThread()
{
	_self = 0;
}

MThread::~MThread()
{
}

bool MThread::start()
{
	int res = 0;
	res = pthread_create(&_self, NULL, thread_routine, this);
	if (0 != res)
		perror("create thread");
	return res == 0;
}

void MThread::stop()
{
	interrupt();
	join();
}

int MThread::join()
{
	return pthread_join(_self, NULL);
}

int MThread::detach()
{
	return pthread_detach(_self);
}

int MThread::cancel()
{
	return pthread_cancel(_self);
}

int64_t MThread::id()
{
	return _self;
}

void MThread::interrupt()
{
	MScopedLock locker(_mutex);
	_interrupt = true;
}

bool MThread::isInterrupted() const
{
	return _interrupt;
}

void MThread::exec()
{
	_interrupt = false;

	run();
}

#endif

// Begin functions
#if defined(M_OS_WIN) || defined(_MSC_VER)

int64_t threadId()
{
	return GetCurrentThreadId();
}

#else

// get_thread_id
int64_t threadId()
{
	return pthread_self();
}

#endif

MPL_END_NAMESPACE
<|endoftext|>


<commit_before>#include "UpdateDialogGtkFactory.h"

#include "FileUtils.h"
#include "Log.h"
#include "UpdateDialog.h"
#include "StringUtils.h"

#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

class UpdateDialogGtk;

// GTK updater UI library embedded into
// the updater binary
extern unsigned char libupdatergtk_so[];
extern unsigned int libupdatergtk_so_len;

// pointers to helper functions in the GTK updater UI library
UpdateDialogGtk* (*update_dialog_gtk_new)() = 0;

#if __cplusplus >= 201103L
#define TYPEOF(x) decltype(x)
#else
#define TYPEOF(x) typeof(x)
#endif

#define BIND_FUNCTION(library,function) \
	function = reinterpret_cast<TYPEOF(function)>(dlsym(library,#function));

bool extractFileFromBinary(int fd, const void* buffer, size_t length)
{
	size_t count = write(fd,buffer,length);
	close(fd);
	return count >= length;
}

UpdateDialog* UpdateDialogGtkFactory::createDialog()
{
	char* libPath = strdup("/tmp/mendeley-libUpdaterGtk.so.XXXXXX");

	int libFd = mkostemp(libPath, O_CREAT | O_WRONLY | O_TRUNC);
	if (libFd == -1)
	{
		LOG(Warn,"Failed to create temporary file - " + std::string(strerror(errno)));
		return 0;
	}

	if (!extractFileFromBinary(libFd,libupdatergtk_so,libupdatergtk_so_len))
	{
		LOG(Warn,"Failed to load the GTK UI library - " + std::string(strerror(errno)));
		return 0;
	}

	void* gtkLib = dlopen(libPath,RTLD_LAZY);
	if (!gtkLib)
	{
		LOG(Warn,"Failed to load the GTK UI - " + std::string(dlerror()));
		return 0;
	}

	BIND_FUNCTION(gtkLib,update_dialog_gtk_new);

	FileUtils::removeFile(libPath);
	return reinterpret_cast<UpdateDialog*>(update_dialog_gtk_new());
}
<commit_msg>Uses stack-allocated array.<commit_after>#include "UpdateDialogGtkFactory.h"

#include "FileUtils.h"
#include "Log.h"
#include "UpdateDialog.h"
#include "StringUtils.h"

#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>

class UpdateDialogGtk;

// GTK updater UI library embedded into
// the updater binary
extern unsigned char libupdatergtk_so[];
extern unsigned int libupdatergtk_so_len;

// pointers to helper functions in the GTK updater UI library
UpdateDialogGtk* (*update_dialog_gtk_new)() = 0;

#if __cplusplus >= 201103L
#define TYPEOF(x) decltype(x)
#else
#define TYPEOF(x) typeof(x)
#endif

#define BIND_FUNCTION(library,function) \
	function = reinterpret_cast<TYPEOF(function)>(dlsym(library,#function));

#define MAX_FILE_PATH 4096

bool extractFileFromBinary(int fd, const void* buffer, size_t length)
{
	size_t count = write(fd,buffer,length);
	close(fd);
	return count >= length;
}

UpdateDialog* UpdateDialogGtkFactory::createDialog()
{
    	char libPath[MAX_FILE_PATH];
	strncpy(libPath, "/tmp/mendeley-libUpdaterGtk.so.XXXXXX", MAX_FILE_PATH);

	int libFd = mkostemp(libPath, O_CREAT | O_WRONLY | O_TRUNC);
	if (libFd == -1)
	{
		LOG(Warn,"Failed to create temporary file - " + std::string(strerror(errno)));
		return 0;
	}

	if (!extractFileFromBinary(libFd,libupdatergtk_so,libupdatergtk_so_len))
	{
		LOG(Warn,"Failed to load the GTK UI library - " + std::string(strerror(errno)));
		return 0;
	}

	void* gtkLib = dlopen(libPath,RTLD_LAZY);
	if (!gtkLib)
	{
		LOG(Warn,"Failed to load the GTK UI - " + std::string(dlerror()));
		return 0;
	}

	BIND_FUNCTION(gtkLib,update_dialog_gtk_new);

	FileUtils::removeFile(libPath);
	return reinterpret_cast<UpdateDialog*>(update_dialog_gtk_new());
}
<|endoftext|>


<commit_before>/*
  Dorm LED Project: led_desk_anim_cmds.cpp
  This file contains the desk LED animation commands.

  These are meant to be executed using the multithreaded system.
  Note: First element in the var stack is to store number of complete executions (resetable).

  Created by: Michael Fischler
  10/22/2016 @ WPI
*/

#include <Adafruit_NeoPixel.h>

/*
  Template for a Command
  LocakStack* cmd(LocalStack* var_stack)

  LocakStack* cmd(LocalStack* var_stack){
    // set variables
    int i = var_stack->getInt(0);
    char t = var_stack->getChar(1);

    // run command code
    ...

    // update variables
    var_stack->update(0, &i);
    var_stack->update(1, &t);

    return var_stack;
  }
*/

/* ~~~~~~ Off Commands ~~~~~~ */

// &&& Functions for Off Commands &&&

void _desk1_off(){
  for(int i = 0; i < DESK1_LENGTH; i++){
    desk1.setPixelColor(i, desk1.Color(0,0,0));
  }

  desk1.show();
}

void _desk2_off(){
  for(int i = 0; i < DESK2_LENGTH; i++){
    desk2.setPixelColor(i, desk2.Color(0,0,0));
  }

  desk2.show();
}

// &&& Command Ready Functions for Off Commands &&&

// Every LED for Desk 1 set to {0,0,0}
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desk1_off(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk1_off();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

// Every LED for Desk 2 set to {0,0,0}
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desk2_off(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk2_off();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

// Every LED set to {0,0,0}
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desks_off(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk1_off();
  _desk2_off();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

/* ~~~~~~ Static Commands ~~~~~~ */

// &&& Functions for Static Commands &&&

void _desk_both_dim_ambient(){
  for(int i = 0; i < DESK1_LENGTH; i++){
    if(i%3 == 0){
      desk1.setPixelColor(i, desk1.Color(75,45,25));
    }else{
      desk1.setPixelColor(i, desk1.Color(0,0,0));
    }
  }

  for(int i = 0; i < DESK2_LENGTH; i++){
    if(i%3 == 0){
      desk2.setPixelColor(i, desk2.Color(75,45,25));
    }else{
      desk2.setPixelColor(i, desk2.Color(0,0,0));
    }
  }

  desk1.show();
  desk2.show();
}

// &&& Command Ready Functions for Static Commands &&&

// Every third LED gets a red tinted white
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desk_both_dim_ambient(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk_both_dim_ambient();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

/* ~~~~~~ Animated Commands ~~~~~~ */

// &&& Functions for Animated Commands &&&

void _desk_both_wpp_fade(int i){
  for(int y = 0; y < DESK1_LENGTH; y++){
    if(y%3 != 0){
      desk1.setPixelColor(y, desk1.Color((int)(((float)i / 150.0) * 100), 0, i));
    }else{
      desk1.setPixelColor(y, desk1.Color(75,45,25));
    }
  }

  for(int z = 0; z < DESK2_LENGTH; z++){
    if(z%3 != 0){
      desk2.setPixelColor(z, desk2.Color((int)(((float)i / 150.0) * 100), 0, i));
    }else{
      desk2.setPixelColor(z, desk2.Color(75,45,25));
    }
  }

  desk1.show();
  desk2.show();
}

// &&& Command Ready Functions for Animated Commands &&&

// Every third LED stays nice reddish white while the others fade in and out a calm purple
// Initial input var_stack : LocalStack* stack {0,0,true}
LocalStack* desk_both_wpp_fade(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);
  unsigned int i = var_stack->getUnsignInt(1);
  bool increasing = var_stack->getBool(2);

  // run command code
  _desk_both_wpp_fade(i);

  if(increasing){
    if(i == 150){
      i--;
      increasing = false;
    }else{
      i++;
    }
  }else{
    if(i == 0){
      i++;
      increasing = true;
      fec++;
    }else{
      i--;
    }
  }

  // update variables
  var_stack->update(0, &fec);
  var_stack->update(1, &i);
  var_stack->update(2, &increasing);

  return var_stack;
}
<commit_msg>formatting<commit_after>/*
  Dorm LED Project: led_desk_anim_cmds.cpp
  This file contains the desk LED animation commands.

  These are meant to be executed using the multithreaded system.
  Note: First element in the var stack is to store number of complete executions (resetable).

  Created by: Michael Fischler
  10/22/2016 @ WPI
*/

#include <Adafruit_NeoPixel.h>

/*
  Template for a Command
  LocakStack* cmd(LocalStack* var_stack)

  LocakStack* cmd(LocalStack* var_stack){
    // set variables
    int i = var_stack->getInt(0);
    char t = var_stack->getChar(1);

    // run command code
    ...

    // update variables
    var_stack->update(0, &i);
    var_stack->update(1, &t);

    return var_stack;
  }
*/

/* ~~~~~~ Off Commands ~~~~~~ */

// &&& Functions for Off Commands &&&

void _desk1_off(){
  for(int i = 0; i < DESK1_LENGTH; i++){
    desk1.setPixelColor(i, desk1.Color(0,0,0));
  }

  desk1.show();
}

void _desk2_off(){
  for(int i = 0; i < DESK2_LENGTH; i++){
    desk2.setPixelColor(i, desk2.Color(0,0,0));
  }

  desk2.show();
}

// &&& Command Ready Functions for Off Commands &&&

// Every LED for Desk 1 set to {0,0,0}
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desk1_off(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk1_off();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

// Every LED for Desk 2 set to {0,0,0}
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desk2_off(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk2_off();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

// Every LED set to {0,0,0}
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desks_off(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk1_off();
  _desk2_off();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

/* ~~~~~~ Static Commands ~~~~~~ */

// &&& Functions for Static Commands &&&

void _desk_both_dim_ambient(){
  for(int i = 0; i < DESK1_LENGTH; i++){
    if(i%3 == 0){
      desk1.setPixelColor(i, desk1.Color(75,45,25));
    }else{
      desk1.setPixelColor(i, desk1.Color(0,0,0));
    }
  }

  for(int i = 0; i < DESK2_LENGTH; i++){
    if(i%3 == 0){
      desk2.setPixelColor(i, desk2.Color(75,45,25));
    }else{
      desk2.setPixelColor(i, desk2.Color(0,0,0));
    }
  }

  desk1.show();
  desk2.show();
}

// &&& Command Ready Functions for Static Commands &&&

// Every third LED gets a red tinted white
// Initial input var_stack : LocalStack* stack [empty]
LocalStack* desk_both_dim_ambient(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);

  // run command code
  _desk_both_dim_ambient();

  // update variables
  fec++;
  var_stack->update(0, &fec);

  return var_stack;
}

/* ~~~~~~ Animated Commands ~~~~~~ */

// &&& Functions for Animated Commands &&&

void _desk_both_wpp_fade(int i){
  for(int y = 0; y < DESK1_LENGTH; y++){
    if(y%3 != 0){
      desk1.setPixelColor(y, desk1.Color((int)(((float)i / 150.0) * 100), 0, i));
    }else{
      desk1.setPixelColor(y, desk1.Color(75,45,25));
    }
  }

  for(int z = 0; z < DESK2_LENGTH; z++){
    if(z%3 != 0){
      desk2.setPixelColor(z, desk2.Color((int)(((float)i / 150.0) * 100), 0, i));
    }else{
      desk2.setPixelColor(z, desk2.Color(75,45,25));
    }
  }

  desk1.show();
  desk2.show();
}

// &&& Command Ready Functions for Animated Commands &&&

// Every third LED stays nice reddish white while the others fade in and out a calm purple
// Initial input var_stack : LocalStack* stack {0,0,true}
LocalStack* desk_both_wpp_fade(LocalStack* var_stack){
  // set variables
  int fec = var_stack->getInt(0);
  unsigned int i = var_stack->getUnsignInt(1);
  bool increasing = var_stack->getBool(2);

  // run command code
  _desk_both_wpp_fade(i);

  if(increasing){
    if(i == 150){
      i--;
      increasing = false;
    }else{
      i++;
    }
  }else{
    if(i == 0){
      i++;
      increasing = true;
      fec++;
    }else{
      i--;
    }
  }

  // update variables
  var_stack->update(0, &fec);
  var_stack->update(1, &i);
  var_stack->update(2, &increasing);

  return var_stack;
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "qt/pivx/balancebubble.h"
#include "qt/pivx/forms/ui_balancebubble.h"

#include "qt/pivx/qtutils.h"

#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
#include <QTimer>
#include <qt/bitcoinunits.h>

BalanceBubble::BalanceBubble(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::BalanceBubble)
{
    ui->setupUi(this);

    ui->frame->setProperty("cssClass", "container-popup");
    setCssProperty({ui->textTransparent, ui->textShielded}, "amount-small-popup");

    std::initializer_list<QWidget*> lblTitles = {ui->lblFirst, ui->lblSecond};
    setCssProperty(lblTitles, "text-title-topbar");
    QFont font;
    font.setWeight(QFont::Light);
    for (QWidget* w : lblTitles) { w->setFont(font); }
}

void BalanceBubble::updateValues(int64_t nTransparentBalance, int64_t nShieldedBalance, int unit)
{
    QString valueTrans = BitcoinUnits::formatWithUnit(unit, nTransparentBalance, false, BitcoinUnits::separatorAlways);
    valueTrans = valueTrans.replace(QChar(THIN_SP_CP), QString(","));
    QString valueShield = BitcoinUnits::formatWithUnit(unit, nShieldedBalance, false, BitcoinUnits::separatorAlways);
    valueShield = valueShield.replace(QChar(THIN_SP_CP), QString(","));

    ui->textTransparent->setText(valueTrans);
    ui->textShielded->setText(valueShield);
    adjustSize();
}

void BalanceBubble::showEvent(QShowEvent *event)
{
    QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
    this->setGraphicsEffect(eff);
    QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
    a->setDuration(400);
    a->setStartValue(0.1);
    a->setEndValue(1);
    a->setEasingCurve(QEasingCurve::InBack);
    a->start(QPropertyAnimation::DeleteWhenStopped);

    if (!hideTimer) hideTimer = new QTimer(this);
    connect(hideTimer, &QTimer::timeout, this, &BalanceBubble::hideTimeout);
    hideTimer->start(7000);
}

void BalanceBubble::hideEvent(QHideEvent *event)
{
    if (hideTimer) hideTimer->stop();
    QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
    this->setGraphicsEffect(eff);
    QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
    a->setDuration(800);
    a->setStartValue(1);
    a->setEndValue(0);
    a->setEasingCurve(QEasingCurve::OutBack);
    a->start(QPropertyAnimation::DeleteWhenStopped);
}

void BalanceBubble::hideTimeout()
{
    hide();
}

BalanceBubble::~BalanceBubble()
{
    delete ui;
}<commit_msg>Fixes double fade-in animation when clicking the question mark next to the 'Available' label in the top bar<commit_after>// Copyright (c) 2020 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "qt/pivx/balancebubble.h"
#include "qt/pivx/forms/ui_balancebubble.h"

#include "qt/pivx/qtutils.h"

#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
#include <QTimer>
#include <qt/bitcoinunits.h>

BalanceBubble::BalanceBubble(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::BalanceBubble)
{
    ui->setupUi(this);

    ui->frame->setProperty("cssClass", "container-popup");
    setCssProperty({ui->textTransparent, ui->textShielded}, "amount-small-popup");

    std::initializer_list<QWidget*> lblTitles = {ui->lblFirst, ui->lblSecond};
    setCssProperty(lblTitles, "text-title-topbar");
    QFont font;
    font.setWeight(QFont::Light);
    for (QWidget* w : lblTitles) { w->setFont(font); }
}

void BalanceBubble::updateValues(int64_t nTransparentBalance, int64_t nShieldedBalance, int unit)
{
    QString valueTrans = BitcoinUnits::formatWithUnit(unit, nTransparentBalance, false, BitcoinUnits::separatorAlways);
    valueTrans = valueTrans.replace(QChar(THIN_SP_CP), QString(","));
    QString valueShield = BitcoinUnits::formatWithUnit(unit, nShieldedBalance, false, BitcoinUnits::separatorAlways);
    valueShield = valueShield.replace(QChar(THIN_SP_CP), QString(","));

    ui->textTransparent->setText(valueTrans);
    ui->textShielded->setText(valueShield);
    adjustSize();
}

void BalanceBubble::showEvent(QShowEvent *event)
{
    QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
    this->setGraphicsEffect(eff);
    QPropertyAnimation *anim = new QPropertyAnimation(eff,"opacity");
    anim->setDuration(400);
    anim->setStartValue(0);
    anim->setEndValue(1);
    anim->setEasingCurve(QEasingCurve::Linear);
    anim->start(QPropertyAnimation::DeleteWhenStopped);

    if (!hideTimer) hideTimer = new QTimer(this);
    connect(hideTimer, &QTimer::timeout, this, &BalanceBubble::hideTimeout);
    hideTimer->start(7000);
}

void BalanceBubble::hideEvent(QHideEvent *event)
{
    if (hideTimer) hideTimer->stop();
    QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
    this->setGraphicsEffect(eff);
    QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
    a->setDuration(800);
    a->setStartValue(1);
    a->setEndValue(0);
    a->setEasingCurve(QEasingCurve::OutBack);
    a->start(QPropertyAnimation::DeleteWhenStopped);
}

void BalanceBubble::hideTimeout()
{
    hide();
}

BalanceBubble::~BalanceBubble()
{
    delete ui;
}
<|endoftext|>