<commit_before>//
// Created by Dennis Goldfarb on 11/14/16.
//
#include <iostream>
#include <fstream>
#include <string>

#include <OpenMS/FORMAT/MzMLFile.h>
#include <OpenMS/MATH/MISC/MathFunctions.h>

#include "Ion.h"
#include "SpectrumUtilities.h"
#include "Stats.h"

void normalizeDist(std::vector<std::pair<double, double> > &dist)
{
    double maxProb = 0;
    for (auto itr = dist.begin(); itr != dist.end(); ++itr)
    {
        maxProb = std::max(maxProb, itr->second);
    }
    for (int i = 0; i < dist.size(); ++i)
    {
        dist[i].second /= maxProb;
    }
}

void outputDist(std::ofstream &out, std::vector<std::pair<double, double> > &dist, std::string ion_name, int ionIndex,
                std::string isotope_range, std::string name)
{

    for (int i = 0; i < dist.size(); ++i)
    {
        out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << dist[i].first << "\t"
                 << dist[i].second << "\t" << name << "\t" << std::endl;
    }
}

void outputScores(std::ofstream &out, std::string ion_name, int ionIndex, std::string isotope_range, std::string name, double score, double x, double y)
{
    out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << name << "\t" << score << "\t" << x << "\t" << y << std::endl;
}

void usage()
{
    std::cout << "Usage: " << std::endl;
}

int main(int argc, char * argv[])
{

    OpenMS::MzMLFile mzMLDataFileProfile, mzMLDataFileCentroid;
    OpenMS::MSExperiment<OpenMS::Peak1D> msExperimentProfile, msExperimentCentroid;
    try {
        mzMLDataFileProfile.load(argv[1], msExperimentProfile);
        mzMLDataFileCentroid.load(argv[2], msExperimentCentroid);
    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
        usage();
        return 1;
    }

    std::ofstream out(argv[3]);
    std::ofstream calc_out(argv[4]);
    std::ofstream scores_out(argv[5]);

    out << "isotope.range" << "\t" << "ion.index" << "\t" << "ion.name" << "\t" << "mz" << "\t" << "int" << std::endl;
    calc_out << "isotope.range" << "\t" << "ion.index" << "\t" << "ion.name" << "\t" << "mz" << "\t" << "int" << "\t" << "method" << std::endl;
    scores_out << "isotope.range" << "\t" << "ion.index" << "\t" << "ion.name" << "\t" << "method" << "\t" << "label" << "\t" << "x" << "\t" << "y" << std::endl;

    const Ion precursorIon = Ion(OpenMS::AASequence::fromString("[-18.010565]ELYENKPRRPYIL"), OpenMS::Residue::Full, 3);

    //create list of b and y ions
    std::vector<Ion> ionList;
    Ion::generateFragmentIons(ionList, precursorIon.sequence, precursorIon.charge);

    double isotopeStep = OpenMS::Constants::NEUTRON_MASS_U / precursorIon.charge;

    //Loop through all spectra
    //for (int specIndex = 0; specIndex < msExperimentCentroid.getNrSpectra(); ++specIndex) {
    for (int specIndex = 0; specIndex < 10; ++specIndex) {

        OpenMS::MSSpectrum<OpenMS::Peak1D> currentSpectrumCentroid = msExperimentCentroid.getSpectrum(specIndex);
        OpenMS::MSSpectrum<OpenMS::Peak1D> currentSpectrumProfile = msExperimentProfile.getSpectrum(specIndex);

        if (currentSpectrumCentroid.getMSLevel() == 1) continue;

        currentSpectrumCentroid.sortByPosition();

        const OpenMS::Precursor precursorInfo = currentSpectrumCentroid.getPrecursors()[0];
        std::set<OpenMS::UInt> precursorIsotopes;

        //fill precursor isotopes vector
        SpectrumUtilities::whichPrecursorIsotopes(precursorIsotopes,
                               precursorInfo,
                               precursorIon,
                               0);

        OpenMS::UInt minIsotope = *std::min_element(precursorIsotopes.begin(), precursorIsotopes.end());
        OpenMS::UInt maxIsotope = *std::max_element(precursorIsotopes.begin(), precursorIsotopes.end());
        //loop through each fragment ion
        for (int ionIndex = 0; ionIndex < ionList.size(); ++ionIndex) {
            //compute search peak matching tolerance
            double tol = OpenMS::Math::ppmToMass(20.0, ionList[ionIndex].monoMz);

            OpenMS::Int peakIndex = -1;
            for (int i = 0; i <= maxIsotope && peakIndex == -1; ++i)
            {
                //find nearest peak to ion mz within tolerance
                peakIndex = currentSpectrumCentroid.findNearest(ionList[ionIndex].monoMz + (isotopeStep * i), tol);
            }

            // peak not found
            if (peakIndex == -1) continue;

            std::vector<std::pair<double, double> > exactPrecursorDist;
            std::vector<std::pair<double, double> > approxPrecursorFromWeightDist;
            std::vector<std::pair<double, double> > approxFragmentFromWeightDist;
            std::vector<std::pair<double, double> > approxFragmentFromWeightAndSulfurDist;
            std::vector<std::pair<double, double> > exactConditionalFragmentDist;
            std::vector<std::pair<double, double> > observedDist;

            SpectrumUtilities::exactConditionalFragmentIsotopeDist(exactConditionalFragmentDist,
                                                                   precursorIsotopes,
                                                                   ionList[ionIndex],
                                                                   precursorIon.sequence,
                                                                   precursorIon.charge);

            SpectrumUtilities::approxFragmentFromWeightIsotopeDist(approxFragmentFromWeightDist,
                                                precursorIsotopes,
                                                ionList[ionIndex],
                                                precursorIon.sequence,
                                                precursorIon.charge);

            SpectrumUtilities::approxFragmentFromWeightAndSIsotopeDist(approxFragmentFromWeightAndSulfurDist,
                                                    precursorIsotopes,
                                                    ionList[ionIndex],
                                                    precursorIon.sequence,
                                                    precursorIon.charge);

            //match theoretical distribution with observed peaks
            SpectrumUtilities::observedDistribution(observedDist, exactConditionalFragmentDist, currentSpectrumCentroid);
            //scale observed intensities across distribution
            SpectrumUtilities::scaleDistribution(observedDist);

            std::string isotope_range = std::to_string(minIsotope);
            if (precursorIsotopes.size() > 1) isotope_range += "-" + std::to_string(maxIsotope);

            std::string ion_type = (ionList[ionIndex].type == OpenMS::Residue::ResidueType::BIon) ? "B" : "Y";
            ion_type += std::to_string(ionList[ionIndex].sequence.size());
            for (int i = 0; i < ionList[ionIndex].charge; ++i) ion_type += "+";
            std::string ion_name = ion_type + " " + ionList[ionIndex].sequence.toUnmodifiedString();

            float maxIntensity = 0;
            for (auto itr = currentSpectrumProfile.begin(); itr != currentSpectrumProfile.end(); ++itr)
            {
                if (itr->getMZ() >= observedDist.front().first - 0.5 &&
                    itr->getMZ() <= observedDist.back().first + 1)
                {
                    maxIntensity = std::max(maxIntensity, itr->getIntensity());
                }
            }

            out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << ionList[ionIndex].monoMz - 0.5 << "\t" << 0 << std::endl;
            for (auto itr = currentSpectrumProfile.begin(); itr != currentSpectrumProfile.end(); ++itr)
            {
                if (itr->getMZ() >= observedDist.front().first - 0.5 &&
                        itr->getMZ() <= observedDist.back().first + 1)
                {
                    out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << itr->getMZ() << "\t" << itr->getIntensity()/maxIntensity << std::endl;
                }
            }
            out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << ionList[ionIndex].monoMz + 3.3 << "\t" << 0 << std::endl;

            normalizeDist(observedDist);
            normalizeDist(exactConditionalFragmentDist);
            normalizeDist(approxFragmentFromWeightDist);
            normalizeDist(approxFragmentFromWeightAndSulfurDist);

            //compute chi-squared with observed to Conditional
            double exactCondFragmentX2 = Stats::computeX2(observedDist, exactConditionalFragmentDist);
            double approxFragmentFromWeightX2 = Stats::computeX2(observedDist, approxFragmentFromWeightDist);
            double approxFragmentFromWeightAndSulfurX2 = Stats::computeX2(observedDist,
                                                                          approxFragmentFromWeightAndSulfurDist);

            outputDist(calc_out, exactConditionalFragmentDist, ion_name, ionIndex, isotope_range, "Exact Fragment");
            outputDist(calc_out, approxFragmentFromWeightDist, ion_name, ionIndex, isotope_range, "Approx Fragment");
            outputDist(calc_out, approxFragmentFromWeightAndSulfurDist, ion_name, ionIndex, isotope_range, "Approx Fragment S");

            outputScores(scores_out, ion_name, ionIndex, isotope_range, "Exact Fragment", exactCondFragmentX2, observedDist.front().first, 1.0);
            outputScores(scores_out, ion_name, ionIndex, isotope_range, "Approx Fragment", approxFragmentFromWeightX2, observedDist.front().first, 0.8);
            outputScores(scores_out, ion_name, ionIndex, isotope_range, "Approx Fragment S", approxFragmentFromWeightAndSulfurX2, observedDist.front().first, 0.6);
        }

    }

    return 0;
}<commit_msg>fixing scripts<commit_after>//
// Created by Dennis Goldfarb on 11/14/16.
//
#include <iostream>
#include <fstream>
#include <string>

#include <OpenMS/FORMAT/MzMLFile.h>
#include <OpenMS/MATH/MISC/MathFunctions.h>

#include "Ion.h"
#include "SpectrumUtilities.h"
#include "Stats.h"

void normalizeDist(std::vector<std::pair<double, double> > &dist)
{
    double maxProb = 0;
    for (auto itr = dist.begin(); itr != dist.end(); ++itr)
    {
        maxProb = std::max(maxProb, itr->second);
    }
    for (int i = 0; i < dist.size(); ++i)
    {
        dist[i].second /= maxProb;
    }
}

void outputDist(std::ofstream &out, std::vector<std::pair<double, double> > &dist, std::string ion_name, int ionIndex,
                std::string isotope_range, std::string name)
{

    for (int i = 0; i < dist.size(); ++i)
    {
        out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << dist[i].first << "\t"
                 << dist[i].second << "\t" << name << std::endl;
    }
}

void outputScores(std::ofstream &out, std::string ion_name, int ionIndex, std::string isotope_range, std::string name, double score, double x, double y)
{
    out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << name << "\t" << score << "\t" << x << "\t" << y << std::endl;
}

void usage()
{
    std::cout << "Usage: " << std::endl;
}

int main(int argc, char * argv[])
{

    OpenMS::MzMLFile mzMLDataFileProfile, mzMLDataFileCentroid;
    OpenMS::MSExperiment<OpenMS::Peak1D> msExperimentProfile, msExperimentCentroid;
    try {
        mzMLDataFileProfile.load(argv[1], msExperimentProfile);
        mzMLDataFileCentroid.load(argv[2], msExperimentCentroid);
    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
        usage();
        return 1;
    }

    std::ofstream out(argv[3]);
    std::ofstream calc_out(argv[4]);
    std::ofstream scores_out(argv[5]);

    out << "isotope.range" << "\t" << "ion.index" << "\t" << "ion.name" << "\t" << "mz" << "\t" << "int" << std::endl;
    calc_out << "isotope.range" << "\t" << "ion.index" << "\t" << "ion.name" << "\t" << "mz" << "\t" << "int" << "\t" << "method" << std::endl;
    scores_out << "isotope.range" << "\t" << "ion.index" << "\t" << "ion.name" << "\t" << "method" << "\t" << "label" << "\t" << "x" << "\t" << "y" << std::endl;

    const Ion precursorIon = Ion(OpenMS::AASequence::fromString("[-18.010565]ELYENKPRRPYIL"), OpenMS::Residue::Full, 3);

    //create list of b and y ions
    std::vector<Ion> ionList;
    Ion::generateFragmentIons(ionList, precursorIon.sequence, precursorIon.charge);

    double isotopeStep = OpenMS::Constants::NEUTRON_MASS_U / precursorIon.charge;

    //Loop through all spectra
    //for (int specIndex = 0; specIndex < msExperimentCentroid.getNrSpectra(); ++specIndex) {
    for (int specIndex = 0; specIndex < 10; ++specIndex) {

        OpenMS::MSSpectrum<OpenMS::Peak1D> currentSpectrumCentroid = msExperimentCentroid.getSpectrum(specIndex);
        OpenMS::MSSpectrum<OpenMS::Peak1D> currentSpectrumProfile = msExperimentProfile.getSpectrum(specIndex);

        if (currentSpectrumCentroid.getMSLevel() == 1) continue;

        currentSpectrumCentroid.sortByPosition();

        const OpenMS::Precursor precursorInfo = currentSpectrumCentroid.getPrecursors()[0];
        std::set<OpenMS::UInt> precursorIsotopes;

        //fill precursor isotopes vector
        SpectrumUtilities::whichPrecursorIsotopes(precursorIsotopes,
                               precursorInfo,
                               precursorIon,
                               0);

        OpenMS::UInt minIsotope = *std::min_element(precursorIsotopes.begin(), precursorIsotopes.end());
        OpenMS::UInt maxIsotope = *std::max_element(precursorIsotopes.begin(), precursorIsotopes.end());
        //loop through each fragment ion
        for (int ionIndex = 0; ionIndex < ionList.size(); ++ionIndex) {
            //compute search peak matching tolerance
            double tol = OpenMS::Math::ppmToMass(20.0, ionList[ionIndex].monoMz);

            OpenMS::Int peakIndex = -1;
            for (int i = 0; i <= maxIsotope && peakIndex == -1; ++i)
            {
                //find nearest peak to ion mz within tolerance
                peakIndex = currentSpectrumCentroid.findNearest(ionList[ionIndex].monoMz + (isotopeStep * i), tol);
            }

            // peak not found
            if (peakIndex == -1) continue;

            std::vector<std::pair<double, double> > exactPrecursorDist;
            std::vector<std::pair<double, double> > approxPrecursorFromWeightDist;
            std::vector<std::pair<double, double> > approxFragmentFromWeightDist;
            std::vector<std::pair<double, double> > approxFragmentFromWeightAndSulfurDist;
            std::vector<std::pair<double, double> > exactConditionalFragmentDist;
            std::vector<std::pair<double, double> > observedDist;

            SpectrumUtilities::exactConditionalFragmentIsotopeDist(exactConditionalFragmentDist,
                                                                   precursorIsotopes,
                                                                   ionList[ionIndex],
                                                                   precursorIon.sequence,
                                                                   precursorIon.charge);

            SpectrumUtilities::approxFragmentFromWeightIsotopeDist(approxFragmentFromWeightDist,
                                                precursorIsotopes,
                                                ionList[ionIndex],
                                                precursorIon.sequence,
                                                precursorIon.charge);

            SpectrumUtilities::approxFragmentFromWeightAndSIsotopeDist(approxFragmentFromWeightAndSulfurDist,
                                                    precursorIsotopes,
                                                    ionList[ionIndex],
                                                    precursorIon.sequence,
                                                    precursorIon.charge);

            //match theoretical distribution with observed peaks
            SpectrumUtilities::observedDistribution(observedDist, exactConditionalFragmentDist, currentSpectrumCentroid);
            //scale observed intensities across distribution
            SpectrumUtilities::scaleDistribution(observedDist);

            std::string isotope_range = std::to_string(minIsotope);
            if (precursorIsotopes.size() > 1) isotope_range += "-" + std::to_string(maxIsotope);

            std::string ion_type = (ionList[ionIndex].type == OpenMS::Residue::ResidueType::BIon) ? "B" : "Y";
            ion_type += std::to_string(ionList[ionIndex].sequence.size());
            for (int i = 0; i < ionList[ionIndex].charge; ++i) ion_type += "+";
            std::string ion_name = ion_type + " " + ionList[ionIndex].sequence.toUnmodifiedString();

            float maxIntensity = 0;
            for (auto itr = currentSpectrumProfile.begin(); itr != currentSpectrumProfile.end(); ++itr)
            {
                if (itr->getMZ() >= observedDist.front().first - 0.5 &&
                    itr->getMZ() <= observedDist.back().first + 1)
                {
                    maxIntensity = std::max(maxIntensity, itr->getIntensity());
                }
            }

            out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << ionList[ionIndex].monoMz - 0.5 << "\t" << 0 << std::endl;
            for (auto itr = currentSpectrumProfile.begin(); itr != currentSpectrumProfile.end(); ++itr)
            {
                if (itr->getMZ() >= observedDist.front().first - 0.5 &&
                        itr->getMZ() <= observedDist.back().first + 1)
                {
                    out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << itr->getMZ() << "\t" << itr->getIntensity()/maxIntensity << std::endl;
                }
            }
            out << isotope_range << "\t" << ionIndex << "\t" << ion_name << "\t" << ionList[ionIndex].monoMz + 3.3 << "\t" << 0 << std::endl;

            normalizeDist(observedDist);
            normalizeDist(exactConditionalFragmentDist);
            normalizeDist(approxFragmentFromWeightDist);
            normalizeDist(approxFragmentFromWeightAndSulfurDist);

            //compute chi-squared with observed to Conditional
            double exactCondFragmentX2 = Stats::computeX2(observedDist, exactConditionalFragmentDist);
            double approxFragmentFromWeightX2 = Stats::computeX2(observedDist, approxFragmentFromWeightDist);
            double approxFragmentFromWeightAndSulfurX2 = Stats::computeX2(observedDist,
                                                                          approxFragmentFromWeightAndSulfurDist);

            outputDist(calc_out, exactConditionalFragmentDist, ion_name, ionIndex, isotope_range, "Exact Fragment");
            outputDist(calc_out, approxFragmentFromWeightDist, ion_name, ionIndex, isotope_range, "Approx Fragment");
            outputDist(calc_out, approxFragmentFromWeightAndSulfurDist, ion_name, ionIndex, isotope_range, "Approx Fragment S");

            outputScores(scores_out, ion_name, ionIndex, isotope_range, "Exact Fragment", exactCondFragmentX2, observedDist.front().first, 1.0);
            outputScores(scores_out, ion_name, ionIndex, isotope_range, "Approx Fragment", approxFragmentFromWeightX2, observedDist.front().first, 0.8);
            outputScores(scores_out, ion_name, ionIndex, isotope_range, "Approx Fragment S", approxFragmentFromWeightAndSulfurX2, observedDist.front().first, 0.6);
        }

    }

    return 0;
}<|endoftext|>


<commit_before>// Copyright © 2012, Université catholique de Louvain
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// *  Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// *  Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <mozart.hh>
#include <boostenv.hh>

#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

using namespace mozart;
namespace fs = boost::filesystem;

atom_t pathToAtom(VM vm, const fs::path& path) {
  auto nativeStr = path.native();
  auto mozartStr = toUTF<nchar>(
    makeLString(nativeStr.c_str(), nativeStr.size()));
  return vm->getAtom(mozartStr.length, mozartStr.string);
}

int main(int argc, char** argv) {
  boostenv::BoostBasedVM boostBasedVM;
  VM vm = boostBasedVM.vm;

  fs::path appPath = fs::path(argv[0]).parent_path();

  // Hacky way to guess if we are in an installed setting
  bool isInstalled = appPath.empty() || (appPath.filename() == "bin");

  fs::path ozHome;
  {
    char* ozHomeVar = std::getenv("OZHOME");
    if (ozHomeVar == nullptr)
      ozHomeVar = std::getenv("OZ_HOME");

    if (ozHomeVar != nullptr)
      ozHome = fs::path(ozHomeVar);
    else if (isInstalled)
      ozHome = appPath.parent_path();
    else
      ozHome = appPath;

    auto propValue = build(vm, pathToAtom(vm, ozHome));

    auto propName = build(vm, MOZART_STR("oz.emulator.home"));
    vm->getPropertyRegistry().put(vm, propName, propValue);

    propName = build(vm, MOZART_STR("oz.configure.home"));
    vm->getPropertyRegistry().put(vm, propName, propValue);
  }

  fs::path bootSearchPath;
  {
    char* bootSearchPathVar = std::getenv("OZ_BOOT_PATH");
    if (bootSearchPathVar != nullptr)
      bootSearchPath = fs::path(bootSearchPathVar);
    else if (isInstalled)
      bootSearchPath = ozHome / "share" / "mozart" / "boot";
    else
      bootSearchPath = ozHome / "boot";

    vm->getPropertyRegistry().registerConstantProp(
      vm, MOZART_STR("oz.search.boot"), pathToAtom(vm, bootSearchPath));
  }

  {
    if (argc < 2) {
      std::cerr << "usage: ozengine AppURL" << std::endl;
      return 1;
    }

    boostBasedVM.setApplicationURL(argv[1]);
    boostBasedVM.setApplicationArgs(argc-2, argv+2);
  }

  {
    // Load the Base environment and the Init functor

    UnstableNode baseEnv = OptVar::build(vm);
    UnstableNode initFunctor = OptVar::build(vm);

    vm->getPropertyRegistry().registerConstantProp(
      vm, MOZART_STR("internal.boot.base"), baseEnv);
    vm->getPropertyRegistry().registerConstantProp(
      vm, MOZART_STR("internal.boot.init"), initFunctor);

    UnstableNode baseValue, initValue;
    auto& bootLoader = boostBasedVM.getBootLoader();
    fs::path systemSearchPath = bootSearchPath / "x-oz" / "system";

    if (!bootLoader(vm, (systemSearchPath / "Base.ozf").native(), baseValue)) {
      std::cerr << "panic: could not load Base functor" << std::endl;
      return 1;
    }

    if (!bootLoader(vm, (systemSearchPath / "Init.ozf").native(), initValue)) {
      std::cerr << "panic: could not load Init functor" << std::endl;
      return 1;
    }

    // Create the thread that loads the Base environment
    if (Callable(baseValue).isProcedure(vm)) {
      ozcalls::asyncOzCall(vm, baseValue, baseEnv);
    } else {
      // Assume it is a functor that does not import anything
      UnstableNode applyAtom = build(vm, MOZART_STR("apply"));
      UnstableNode applyProc = Dottable(baseValue).dot(vm, applyAtom);
      UnstableNode importParam = build(vm, MOZART_STR("import"));
      ozcalls::asyncOzCall(vm, applyProc, importParam, baseEnv);
    }

    // Create the thread that loads the Init functor
    if (Callable(initValue).isProcedure(vm)) {
      ozcalls::asyncOzCall(vm, initValue, initFunctor);
    } else {
      // Assume it is already the Init functor
      DataflowVariable(initFunctor).bind(vm, initValue);
    }

    boostBasedVM.run();
  }

  {
    // Base.'Base' = Base
    UnstableNode Base;
    auto BaseProperty = build(vm, MOZART_STR("internal.boot.base"));
    vm->getPropertyRegistry().get(vm, BaseProperty, Base);

    auto BaseAtom = build(vm, MOZART_STR("Base"));
    auto BaseField = Dottable(Base).dot(vm, BaseAtom);

    if (RichNode(BaseField).isTransient())
      DataflowVariable(BaseField).bind(vm, Base);
  }

  {
    // Apply the Init functor

    UnstableNode InitFunctor;
    auto InitFunctorProperty = build(vm, MOZART_STR("internal.boot.init"));
    vm->getPropertyRegistry().get(vm, InitFunctorProperty, InitFunctor);

    auto ApplyAtom = build(vm, MOZART_STR("apply"));
    auto ApplyProc = Dottable(InitFunctor).dot(vm, ApplyAtom);

    auto BootModule = vm->findBuiltinModule(MOZART_STR("Boot"));
    auto ImportRecord = buildRecord(
      vm, buildArity(vm, MOZART_STR("import"), MOZART_STR("Boot")),
      BootModule);

    ozcalls::asyncOzCall(vm, ApplyProc, ImportRecord, OptVar::build(vm));

    boostBasedVM.run();
  }
}
<commit_msg>Updated for a Base that does not export 'Base'.<commit_after>// Copyright © 2012, Université catholique de Louvain
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// *  Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// *  Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include <mozart.hh>
#include <boostenv.hh>

#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

using namespace mozart;
namespace fs = boost::filesystem;

atom_t pathToAtom(VM vm, const fs::path& path) {
  auto nativeStr = path.native();
  auto mozartStr = toUTF<nchar>(
    makeLString(nativeStr.c_str(), nativeStr.size()));
  return vm->getAtom(mozartStr.length, mozartStr.string);
}

int main(int argc, char** argv) {
  boostenv::BoostBasedVM boostBasedVM;
  VM vm = boostBasedVM.vm;

  fs::path appPath = fs::path(argv[0]).parent_path();

  // Hacky way to guess if we are in an installed setting
  bool isInstalled = appPath.empty() || (appPath.filename() == "bin");

  fs::path ozHome;
  {
    char* ozHomeVar = std::getenv("OZHOME");
    if (ozHomeVar == nullptr)
      ozHomeVar = std::getenv("OZ_HOME");

    if (ozHomeVar != nullptr)
      ozHome = fs::path(ozHomeVar);
    else if (isInstalled)
      ozHome = appPath.parent_path();
    else
      ozHome = appPath;

    auto propValue = build(vm, pathToAtom(vm, ozHome));

    auto propName = build(vm, MOZART_STR("oz.emulator.home"));
    vm->getPropertyRegistry().put(vm, propName, propValue);

    propName = build(vm, MOZART_STR("oz.configure.home"));
    vm->getPropertyRegistry().put(vm, propName, propValue);
  }

  fs::path bootSearchPath;
  {
    char* bootSearchPathVar = std::getenv("OZ_BOOT_PATH");
    if (bootSearchPathVar != nullptr)
      bootSearchPath = fs::path(bootSearchPathVar);
    else if (isInstalled)
      bootSearchPath = ozHome / "share" / "mozart" / "boot";
    else
      bootSearchPath = ozHome / "boot";

    vm->getPropertyRegistry().registerConstantProp(
      vm, MOZART_STR("oz.search.boot"), pathToAtom(vm, bootSearchPath));
  }

  {
    if (argc < 2) {
      std::cerr << "usage: ozengine AppURL" << std::endl;
      return 1;
    }

    boostBasedVM.setApplicationURL(argv[1]);
    boostBasedVM.setApplicationArgs(argc-2, argv+2);
  }

  {
    // Load the Base environment and the Init functor

    UnstableNode baseEnv = OptVar::build(vm);
    UnstableNode initFunctor = OptVar::build(vm);

    vm->getPropertyRegistry().registerConstantProp(
      vm, MOZART_STR("internal.boot.base"), baseEnv);
    vm->getPropertyRegistry().registerConstantProp(
      vm, MOZART_STR("internal.boot.init"), initFunctor);

    UnstableNode baseValue, initValue;
    auto& bootLoader = boostBasedVM.getBootLoader();
    fs::path systemSearchPath = bootSearchPath / "x-oz" / "system";

    if (!bootLoader(vm, (systemSearchPath / "Base.ozf").native(), baseValue)) {
      std::cerr << "panic: could not load Base functor" << std::endl;
      return 1;
    }

    if (!bootLoader(vm, (systemSearchPath / "Init.ozf").native(), initValue)) {
      std::cerr << "panic: could not load Init functor" << std::endl;
      return 1;
    }

    // Create the thread that loads the Base environment
    if (Callable(baseValue).isProcedure(vm)) {
      ozcalls::asyncOzCall(vm, baseValue, baseEnv);
    } else {
      // Assume it is a functor that does not import anything
      UnstableNode applyAtom = build(vm, MOZART_STR("apply"));
      UnstableNode applyProc = Dottable(baseValue).dot(vm, applyAtom);
      UnstableNode importParam = build(vm, MOZART_STR("import"));
      ozcalls::asyncOzCall(vm, applyProc, importParam, baseEnv);
    }

    // Create the thread that loads the Init functor
    if (Callable(initValue).isProcedure(vm)) {
      ozcalls::asyncOzCall(vm, initValue, initFunctor);
    } else {
      // Assume it is already the Init functor
      DataflowVariable(initFunctor).bind(vm, initValue);
    }

    boostBasedVM.run();
  }

  {
    // Apply the Init functor

    UnstableNode InitFunctor;
    auto InitFunctorProperty = build(vm, MOZART_STR("internal.boot.init"));
    vm->getPropertyRegistry().get(vm, InitFunctorProperty, InitFunctor);

    auto ApplyAtom = build(vm, MOZART_STR("apply"));
    auto ApplyProc = Dottable(InitFunctor).dot(vm, ApplyAtom);

    auto BootModule = vm->findBuiltinModule(MOZART_STR("Boot"));
    auto ImportRecord = buildRecord(
      vm, buildArity(vm, MOZART_STR("import"), MOZART_STR("Boot")),
      BootModule);

    ozcalls::asyncOzCall(vm, ApplyProc, ImportRecord, OptVar::build(vm));

    boostBasedVM.run();
  }
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2006 Tim Beaulen <tbscope@gmail.com>
    Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "effect.h"
#include <QVariant>
#include "xineengine.h"
#include <QMutexLocker>
#include "events.h"
#include "keepreference.h"

namespace Phonon
{
namespace Xine
{

xine_audio_port_t *EffectXT::audioPort() const
{
    const_cast<EffectXT *>(this)->ensureInstance();
    Q_ASSERT(m_plugin);
    Q_ASSERT(m_plugin->audio_input);
    Q_ASSERT(m_plugin->audio_input[0]);
    return m_plugin->audio_input[0];
}

xine_post_out_t *EffectXT::audioOutputPort() const
{
    const_cast<EffectXT *>(this)->ensureInstance();
    Q_ASSERT(m_plugin);
    xine_post_out_t *x = xine_post_output(m_plugin, "audio out");
    Q_ASSERT(x);
    return x;
}

void EffectXT::rewireTo(SourceNodeXT *source)
{
    if (!source->audioOutputPort()) {
        return;
    }
    ensureInstance();
    xine_post_in_t *x = xine_post_input(m_plugin, "audio in");
    Q_ASSERT(x);
    xine_post_wire(source->audioOutputPort(), x);
}

// lazy initialization
void EffectXT::ensureInstance()
{
    QMutexLocker lock(&m_mutex);
    if (m_plugin) {
        return;
    }
    createInstance();
    Q_ASSERT(m_plugin);
}

xine_audio_port_t *EffectXT::fakeAudioPort()
{
    if (!m_fakeAudioPort) {
        m_fakeAudioPort = xine_open_audio_driver(m_xine, "none", 0);
    }
    return m_fakeAudioPort;
}

void EffectXT::createInstance()
{
    debug() << Q_FUNC_INFO << "m_pluginName =" << m_pluginName;
    Q_ASSERT(m_plugin == 0 && m_pluginApi == 0);
    if (!m_pluginName) {
        qWarning( "tried to create invalid Effect");
        return;
    }

    fakeAudioPort();
    m_plugin = xine_post_init(m_xine, m_pluginName, 1, &m_fakeAudioPort, 0);
    xine_post_in_t *paraInput = xine_post_input(m_plugin, "parameters");
    if (!paraInput) {
        return;
    }
    Q_ASSERT(paraInput->type == XINE_POST_DATA_PARAMETERS);
    Q_ASSERT(paraInput->data);
    m_pluginApi = reinterpret_cast<xine_post_api_t *>(paraInput->data);
    if (!m_parameterList.isEmpty()) {
        return;
    }
    xine_post_api_descr_t *desc = m_pluginApi->get_param_descr();
    if (m_pluginParams) {
        m_pluginApi->set_parameters(m_plugin, m_pluginParams);
    } else {
        m_pluginParams = static_cast<char *>(malloc(desc->struct_size));
        m_pluginApi->get_parameters(m_plugin, m_pluginParams);
        for (int i = 0; desc->parameter[i].type != POST_PARAM_TYPE_LAST; ++i) {
            xine_post_api_parameter_t &p = desc->parameter[i];
            switch (p.type) {
            case POST_PARAM_TYPE_INT:          /* integer (or vector of integers)    */
                if (p.enum_values) {
                    // it's an enum
                    QVariantList values;
                    for (int j = 0; p.enum_values[j]; ++j) {
                        values << QString::fromUtf8(p.enum_values[j]);
                    }
                    m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), 0,
                            *reinterpret_cast<int *>(m_pluginParams + p.offset),
                            0, values.count() - 1, values);
                } else {
                    m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), EffectParameter::IntegerHint,
                            *reinterpret_cast<int *>(m_pluginParams + p.offset),
                            static_cast<int>(p.range_min), static_cast<int>(p.range_max), QVariantList());
                }
                break;
            case POST_PARAM_TYPE_DOUBLE:       /* double (or vector of doubles)      */
                m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), 0,
                        *reinterpret_cast<double *>(m_pluginParams + p.offset),
                        p.range_min, p.range_max, QVariantList());
                break;
            case POST_PARAM_TYPE_CHAR:         /* char (or vector of chars = string) */
            case POST_PARAM_TYPE_STRING:       /* (char *), ASCIIZ                   */
            case POST_PARAM_TYPE_STRINGLIST:   /* (char **) list, NULL terminated    */
                qWarning() << "char/string/stringlist parameter '" << (p.description ? p.description : p.name) << "' not supported.";
                break;
            case POST_PARAM_TYPE_BOOL:         /* integer (0 or 1)                   */
                m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), EffectParameter::ToggledHint,
                        static_cast<bool>(*reinterpret_cast<int *>(m_pluginParams + p.offset)),
                        QVariant(), QVariant(), QVariantList());
                break;
            case POST_PARAM_TYPE_LAST:         /* terminator of parameter list       */
            default:
                abort();
            }
        }
    }
}

Effect::Effect(int effectId, QObject *parent)
    : QObject(parent),
    SinkNode(new EffectXT(0)),
    SourceNode(static_cast<EffectXT *>(SinkNode::threadSafeObject().data()))
{
    K_XT(Effect);
    const char *const *postPlugins = xine_list_post_plugins_typed(xt->m_xine, XINE_POST_TYPE_AUDIO_FILTER);
    if (effectId >= 0x7F000000) {
        effectId -= 0x7F000000;
        for(int i = 0; postPlugins[i]; ++i) {
            if (i == effectId) {
                // found it
                xt->m_pluginName = postPlugins[i];
                break;
            }
        }
    }
}

Effect::Effect(EffectXT *xt, QObject *parent)
    : QObject(parent), SinkNode(xt), SourceNode(xt)
{
}

EffectXT::EffectXT(const char *name)
    : SourceNodeXT("Effect"), SinkNodeXT("Effect"), m_plugin(0), m_pluginApi(0), m_fakeAudioPort(0),
    m_pluginName(name), m_pluginParams(0)
{
    m_xine = Backend::xine();
}

EffectXT::~EffectXT()
{
    if (m_plugin) {
        xine_post_dispose(m_xine, m_plugin);
        m_plugin = 0;
        m_pluginApi = 0;
        if (m_fakeAudioPort) {
            xine_close_audio_driver(m_xine, m_fakeAudioPort);
            m_fakeAudioPort = 0;
        }
    }
    free(m_pluginParams);
    m_pluginParams = 0;
}

bool Effect::isValid() const
{
    K_XT(const Effect);
    return xt->m_pluginName != 0;
}

MediaStreamTypes Effect::inputMediaStreamTypes() const
{
    return Phonon::Xine::Audio;
}

MediaStreamTypes Effect::outputMediaStreamTypes() const
{
    return Phonon::Xine::Audio;
}

QList<EffectParameter> Effect::parameters() const
{
    const_cast<Effect *>(this)->ensureParametersReady();
    K_XT(const Effect);
    return xt->m_parameterList;
}

void Effect::ensureParametersReady()
{
    K_XT(Effect);
    xt->ensureInstance();
}

QVariant Effect::parameterValue(const EffectParameter &p) const
{
    const int parameterIndex = p.id();
    K_XT(const Effect);
    QMutexLocker lock(&xt->m_mutex);
    if (!xt->m_plugin || !xt->m_pluginApi) {
        return QVariant(); // invalid
    }

    xine_post_api_descr_t *desc = xt->m_pluginApi->get_param_descr();
    Q_ASSERT(xt->m_pluginParams);
    xt->m_pluginApi->get_parameters(xt->m_plugin, xt->m_pluginParams);
    int i = 0;
    for (; i < parameterIndex && desc->parameter[i].type != POST_PARAM_TYPE_LAST; ++i);
    if (i == parameterIndex) {
        xine_post_api_parameter_t &p = desc->parameter[i];
        switch (p.type) {
        case POST_PARAM_TYPE_INT:          /* integer (or vector of integers)    */
            return *reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
        case POST_PARAM_TYPE_DOUBLE:       /* double (or vector of doubles)      */
            return *reinterpret_cast<double *>(xt->m_pluginParams + p.offset);
        case POST_PARAM_TYPE_CHAR:         /* char (or vector of chars = string) */
        case POST_PARAM_TYPE_STRING:       /* (char *), ASCIIZ                   */
        case POST_PARAM_TYPE_STRINGLIST:   /* (char **) list, NULL terminated    */
            qWarning() <<  "char/string/stringlist parameter '" << (p.description ? p.description : p.name) << "' not supported.";
            return QVariant();
        case POST_PARAM_TYPE_BOOL:         /* integer (0 or 1)                   */
            return static_cast<bool>(*reinterpret_cast<int *>(xt->m_pluginParams + p.offset));
        case POST_PARAM_TYPE_LAST:         /* terminator of parameter list       */
            break;
        default:
            abort();
        }
    }
    qWarning() << "invalid parameterIndex passed to Effect::value";
    return QVariant();
}

void Effect::setParameterValue(const EffectParameter &p, const QVariant &newValue)
{
    K_XT(Effect);
    const int parameterIndex = p.id();
    QMutexLocker lock(&xt->m_mutex);
    if (!xt->m_plugin || !xt->m_pluginApi) {
        return;
    }

    xine_post_api_descr_t *desc = xt->m_pluginApi->get_param_descr();
    Q_ASSERT(xt->m_pluginParams);
    int i = 0;
    for (; i < parameterIndex && desc->parameter[i].type != POST_PARAM_TYPE_LAST; ++i);
    if (i == parameterIndex) {
        xine_post_api_parameter_t &p = desc->parameter[i];
        switch (p.type) {
        case POST_PARAM_TYPE_INT:          /* integer (or vector of integers)    */
            if (p.enum_values && newValue.type() == QVariant::String) {
                // need to convert to index
                int *value = reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
                const QString string = newValue.toString();
                for (int j = 0; p.enum_values[j]; ++j) {
                    if (string == QString::fromUtf8(p.enum_values[j])) {
                        *value = j;
                        break;
                    }
                }
            } else {
                int *value = reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
                *value = newValue.toInt();
            }
            break;
        case POST_PARAM_TYPE_DOUBLE:       /* double (or vector of doubles)      */
            {
                double *value = reinterpret_cast<double *>(xt->m_pluginParams + p.offset);
                *value = newValue.toDouble();
            }
            break;
        case POST_PARAM_TYPE_CHAR:         /* char (or vector of chars = string) */
        case POST_PARAM_TYPE_STRING:       /* (char *), ASCIIZ                   */
        case POST_PARAM_TYPE_STRINGLIST:   /* (char **) list, NULL terminated    */
            qWarning() << "char/string/stringlist parameter '" << (p.description ? p.description : p.name) << "' not supported." ;
            return;
        case POST_PARAM_TYPE_BOOL:         /* integer (0 or 1)                   */
            {
               int *value = reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
               *value = newValue.toBool() ? 1 : 0;
            }
            break;
        case POST_PARAM_TYPE_LAST:         /* terminator of parameter list       */
            qWarning() << "invalid parameterIndex passed to Effect::setValue";
            break;
        default:
            abort();
        }
        xt->m_pluginApi->set_parameters(xt->m_plugin, xt->m_pluginParams);
    } else {
        qWarning() << "invalid parameterIndex passed to Effect::setValue";
    }
}

void Effect::addParameter(const EffectParameter &p)
{
    K_XT(Effect);
    xt->m_parameterList << p;
}

void Effect::aboutToChangeXineEngine()
{
    K_XT(Effect);
    if (xt->m_plugin) {
        EffectXT *xt2 = new EffectXT(xt->m_pluginName);
        xt2->m_xine = xt->m_xine;
        xt2->m_plugin = xt->m_plugin;
        xt2->m_pluginApi = xt->m_pluginApi;
        xt2->m_fakeAudioPort = xt->m_fakeAudioPort;
        xt->m_plugin = 0;
        xt->m_pluginApi = 0;
        xt->m_fakeAudioPort = 0;
        KeepReference<> *keep = new KeepReference<>;
        keep->addObject(static_cast<SinkNodeXT *>(xt2));
        keep->ready();
    }
}

void Effect::xineEngineChanged()
{
    K_XT(Effect);
    if (!xt->m_xine) {
        xt->m_xine = Backend::xine();
    }
    //xt->createInstance();
}

}} //namespace Phonon::Xine

#include "moc_effect.cpp"
<commit_msg>newer gcc warns about this and suggests to insert a space<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2006 Tim Beaulen <tbscope@gmail.com>
    Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "effect.h"
#include <QVariant>
#include "xineengine.h"
#include <QMutexLocker>
#include "events.h"
#include "keepreference.h"

namespace Phonon
{
namespace Xine
{

xine_audio_port_t *EffectXT::audioPort() const
{
    const_cast<EffectXT *>(this)->ensureInstance();
    Q_ASSERT(m_plugin);
    Q_ASSERT(m_plugin->audio_input);
    Q_ASSERT(m_plugin->audio_input[0]);
    return m_plugin->audio_input[0];
}

xine_post_out_t *EffectXT::audioOutputPort() const
{
    const_cast<EffectXT *>(this)->ensureInstance();
    Q_ASSERT(m_plugin);
    xine_post_out_t *x = xine_post_output(m_plugin, "audio out");
    Q_ASSERT(x);
    return x;
}

void EffectXT::rewireTo(SourceNodeXT *source)
{
    if (!source->audioOutputPort()) {
        return;
    }
    ensureInstance();
    xine_post_in_t *x = xine_post_input(m_plugin, "audio in");
    Q_ASSERT(x);
    xine_post_wire(source->audioOutputPort(), x);
}

// lazy initialization
void EffectXT::ensureInstance()
{
    QMutexLocker lock(&m_mutex);
    if (m_plugin) {
        return;
    }
    createInstance();
    Q_ASSERT(m_plugin);
}

xine_audio_port_t *EffectXT::fakeAudioPort()
{
    if (!m_fakeAudioPort) {
        m_fakeAudioPort = xine_open_audio_driver(m_xine, "none", 0);
    }
    return m_fakeAudioPort;
}

void EffectXT::createInstance()
{
    debug() << Q_FUNC_INFO << "m_pluginName =" << m_pluginName;
    Q_ASSERT(m_plugin == 0 && m_pluginApi == 0);
    if (!m_pluginName) {
        qWarning( "tried to create invalid Effect");
        return;
    }

    fakeAudioPort();
    m_plugin = xine_post_init(m_xine, m_pluginName, 1, &m_fakeAudioPort, 0);
    xine_post_in_t *paraInput = xine_post_input(m_plugin, "parameters");
    if (!paraInput) {
        return;
    }
    Q_ASSERT(paraInput->type == XINE_POST_DATA_PARAMETERS);
    Q_ASSERT(paraInput->data);
    m_pluginApi = reinterpret_cast<xine_post_api_t *>(paraInput->data);
    if (!m_parameterList.isEmpty()) {
        return;
    }
    xine_post_api_descr_t *desc = m_pluginApi->get_param_descr();
    if (m_pluginParams) {
        m_pluginApi->set_parameters(m_plugin, m_pluginParams);
    } else {
        m_pluginParams = static_cast<char *>(malloc(desc->struct_size));
        m_pluginApi->get_parameters(m_plugin, m_pluginParams);
        for (int i = 0; desc->parameter[i].type != POST_PARAM_TYPE_LAST; ++i) {
            xine_post_api_parameter_t &p = desc->parameter[i];
            switch (p.type) {
            case POST_PARAM_TYPE_INT:          /* integer (or vector of integers)    */
                if (p.enum_values) {
                    // it's an enum
                    QVariantList values;
                    for (int j = 0; p.enum_values[j]; ++j) {
                        values << QString::fromUtf8(p.enum_values[j]);
                    }
                    m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), 0,
                            *reinterpret_cast<int *>(m_pluginParams + p.offset),
                            0, values.count() - 1, values);
                } else {
                    m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), EffectParameter::IntegerHint,
                            *reinterpret_cast<int *>(m_pluginParams + p.offset),
                            static_cast<int>(p.range_min), static_cast<int>(p.range_max), QVariantList());
                }
                break;
            case POST_PARAM_TYPE_DOUBLE:       /* double (or vector of doubles)      */
                m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), 0,
                        *reinterpret_cast<double *>(m_pluginParams + p.offset),
                        p.range_min, p.range_max, QVariantList());
                break;
            case POST_PARAM_TYPE_CHAR:         /* char (or vector of chars = string) */
            case POST_PARAM_TYPE_STRING:       /* (char *), ASCIIZ                   */
            case POST_PARAM_TYPE_STRINGLIST:   /* (char **) list, NULL terminated    */
                qWarning() << "char/string/stringlist parameter '" << (p.description ? p.description : p.name) << "' not supported.";
                break;
            case POST_PARAM_TYPE_BOOL:         /* integer (0 or 1)                   */
                m_parameterList << EffectParameter(i, QString::fromUtf8(p.description ? p.description : p.name), EffectParameter::ToggledHint,
                        static_cast<bool>(*reinterpret_cast<int *>(m_pluginParams + p.offset)),
                        QVariant(), QVariant(), QVariantList());
                break;
            case POST_PARAM_TYPE_LAST:         /* terminator of parameter list       */
            default:
                abort();
            }
        }
    }
}

Effect::Effect(int effectId, QObject *parent)
    : QObject(parent),
    SinkNode(new EffectXT(0)),
    SourceNode(static_cast<EffectXT *>(SinkNode::threadSafeObject().data()))
{
    K_XT(Effect);
    const char *const *postPlugins = xine_list_post_plugins_typed(xt->m_xine, XINE_POST_TYPE_AUDIO_FILTER);
    if (effectId >= 0x7F000000) {
        effectId -= 0x7F000000;
        for(int i = 0; postPlugins[i]; ++i) {
            if (i == effectId) {
                // found it
                xt->m_pluginName = postPlugins[i];
                break;
            }
        }
    }
}

Effect::Effect(EffectXT *xt, QObject *parent)
    : QObject(parent), SinkNode(xt), SourceNode(xt)
{
}

EffectXT::EffectXT(const char *name)
    : SourceNodeXT("Effect"), SinkNodeXT("Effect"), m_plugin(0), m_pluginApi(0), m_fakeAudioPort(0),
    m_pluginName(name), m_pluginParams(0)
{
    m_xine = Backend::xine();
}

EffectXT::~EffectXT()
{
    if (m_plugin) {
        xine_post_dispose(m_xine, m_plugin);
        m_plugin = 0;
        m_pluginApi = 0;
        if (m_fakeAudioPort) {
            xine_close_audio_driver(m_xine, m_fakeAudioPort);
            m_fakeAudioPort = 0;
        }
    }
    free(m_pluginParams);
    m_pluginParams = 0;
}

bool Effect::isValid() const
{
    K_XT(const Effect);
    return xt->m_pluginName != 0;
}

MediaStreamTypes Effect::inputMediaStreamTypes() const
{
    return Phonon::Xine::Audio;
}

MediaStreamTypes Effect::outputMediaStreamTypes() const
{
    return Phonon::Xine::Audio;
}

QList<EffectParameter> Effect::parameters() const
{
    const_cast<Effect *>(this)->ensureParametersReady();
    K_XT(const Effect);
    return xt->m_parameterList;
}

void Effect::ensureParametersReady()
{
    K_XT(Effect);
    xt->ensureInstance();
}

QVariant Effect::parameterValue(const EffectParameter &p) const
{
    const int parameterIndex = p.id();
    K_XT(const Effect);
    QMutexLocker lock(&xt->m_mutex);
    if (!xt->m_plugin || !xt->m_pluginApi) {
        return QVariant(); // invalid
    }

    xine_post_api_descr_t *desc = xt->m_pluginApi->get_param_descr();
    Q_ASSERT(xt->m_pluginParams);
    xt->m_pluginApi->get_parameters(xt->m_plugin, xt->m_pluginParams);
    int i = 0;
    for (; i < parameterIndex && desc->parameter[i].type != POST_PARAM_TYPE_LAST; ++i) ;
    if (i == parameterIndex) {
        xine_post_api_parameter_t &p = desc->parameter[i];
        switch (p.type) {
        case POST_PARAM_TYPE_INT:          /* integer (or vector of integers)    */
            return *reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
        case POST_PARAM_TYPE_DOUBLE:       /* double (or vector of doubles)      */
            return *reinterpret_cast<double *>(xt->m_pluginParams + p.offset);
        case POST_PARAM_TYPE_CHAR:         /* char (or vector of chars = string) */
        case POST_PARAM_TYPE_STRING:       /* (char *), ASCIIZ                   */
        case POST_PARAM_TYPE_STRINGLIST:   /* (char **) list, NULL terminated    */
            qWarning() <<  "char/string/stringlist parameter '" << (p.description ? p.description : p.name) << "' not supported.";
            return QVariant();
        case POST_PARAM_TYPE_BOOL:         /* integer (0 or 1)                   */
            return static_cast<bool>(*reinterpret_cast<int *>(xt->m_pluginParams + p.offset));
        case POST_PARAM_TYPE_LAST:         /* terminator of parameter list       */
            break;
        default:
            abort();
        }
    }
    qWarning() << "invalid parameterIndex passed to Effect::value";
    return QVariant();
}

void Effect::setParameterValue(const EffectParameter &p, const QVariant &newValue)
{
    K_XT(Effect);
    const int parameterIndex = p.id();
    QMutexLocker lock(&xt->m_mutex);
    if (!xt->m_plugin || !xt->m_pluginApi) {
        return;
    }

    xine_post_api_descr_t *desc = xt->m_pluginApi->get_param_descr();
    Q_ASSERT(xt->m_pluginParams);
    int i = 0;
    for (; i < parameterIndex && desc->parameter[i].type != POST_PARAM_TYPE_LAST; ++i) ;
    if (i == parameterIndex) {
        xine_post_api_parameter_t &p = desc->parameter[i];
        switch (p.type) {
        case POST_PARAM_TYPE_INT:          /* integer (or vector of integers)    */
            if (p.enum_values && newValue.type() == QVariant::String) {
                // need to convert to index
                int *value = reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
                const QString string = newValue.toString();
                for (int j = 0; p.enum_values[j]; ++j) {
                    if (string == QString::fromUtf8(p.enum_values[j])) {
                        *value = j;
                        break;
                    }
                }
            } else {
                int *value = reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
                *value = newValue.toInt();
            }
            break;
        case POST_PARAM_TYPE_DOUBLE:       /* double (or vector of doubles)      */
            {
                double *value = reinterpret_cast<double *>(xt->m_pluginParams + p.offset);
                *value = newValue.toDouble();
            }
            break;
        case POST_PARAM_TYPE_CHAR:         /* char (or vector of chars = string) */
        case POST_PARAM_TYPE_STRING:       /* (char *), ASCIIZ                   */
        case POST_PARAM_TYPE_STRINGLIST:   /* (char **) list, NULL terminated    */
            qWarning() << "char/string/stringlist parameter '" << (p.description ? p.description : p.name) << "' not supported." ;
            return;
        case POST_PARAM_TYPE_BOOL:         /* integer (0 or 1)                   */
            {
               int *value = reinterpret_cast<int *>(xt->m_pluginParams + p.offset);
               *value = newValue.toBool() ? 1 : 0;
            }
            break;
        case POST_PARAM_TYPE_LAST:         /* terminator of parameter list       */
            qWarning() << "invalid parameterIndex passed to Effect::setValue";
            break;
        default:
            abort();
        }
        xt->m_pluginApi->set_parameters(xt->m_plugin, xt->m_pluginParams);
    } else {
        qWarning() << "invalid parameterIndex passed to Effect::setValue";
    }
}

void Effect::addParameter(const EffectParameter &p)
{
    K_XT(Effect);
    xt->m_parameterList << p;
}

void Effect::aboutToChangeXineEngine()
{
    K_XT(Effect);
    if (xt->m_plugin) {
        EffectXT *xt2 = new EffectXT(xt->m_pluginName);
        xt2->m_xine = xt->m_xine;
        xt2->m_plugin = xt->m_plugin;
        xt2->m_pluginApi = xt->m_pluginApi;
        xt2->m_fakeAudioPort = xt->m_fakeAudioPort;
        xt->m_plugin = 0;
        xt->m_pluginApi = 0;
        xt->m_fakeAudioPort = 0;
        KeepReference<> *keep = new KeepReference<>;
        keep->addObject(static_cast<SinkNodeXT *>(xt2));
        keep->ready();
    }
}

void Effect::xineEngineChanged()
{
    K_XT(Effect);
    if (!xt->m_xine) {
        xt->m_xine = Backend::xine();
    }
    //xt->createInstance();
}

}} //namespace Phonon::Xine

#include "moc_effect.cpp"
<|endoftext|>


<commit_before>class crb_tc_intensity {
        title = "    Civilian Terrorist Cells Recruitment per Hour (relies on Ambient Civs)";
        values[]= {0,1,2,3,4,5};
        texts[]= {"None","8 Recruits","4 Recruits","2 Recruits","1 Recruit","0.5 Recruit"};
        default = 1;
};
class crb_tc_markers {
        title = "        Civilian Terrorist Insurgency Style Markers";
        values[]= {0,1};
        texts[]= {"Off","On"};
        default = 0;
};

<commit_msg>[ENEMY] Turned off terrorists until moved to clientside or fixed (breaks initalizing enemypop-modules)<commit_after>class crb_tc_intensity {
        title = "    Civilian Terrorist Cells Recruitment per Hour (relies on Ambient Civs)";
        values[]= {0,1,2,3,4,5};
        texts[]= {"None","8 Recruits","4 Recruits","2 Recruits","1 Recruit","0.5 Recruit"};
        default = 0;
};
class crb_tc_markers {
        title = "        Civilian Terrorist Insurgency Style Markers";
        values[]= {0,1};
        texts[]= {"Off","On"};
        default = 0;
};

<|endoftext|>


<commit_before><commit_msg>better timescale looks<commit_after><|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// This source file is part of Hect.
//
// Copyright (c) 2014 Colin Hill
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
///////////////////////////////////////////////////////////////////////////////
#include "TransformSystem.h"

#include "Hect/Logic/Systems/BoundingBoxSystem.h"
#include "Hect/Runtime/Engine.h"

using namespace hect;

TransformSystem::TransformSystem(Engine& engine, Scene& scene) :
    System(scene, SystemTickStage_Subsequent)
{
    (void)engine;
}

void TransformSystem::forceUpdate(Entity& entity)
{
    auto transform = entity.component<Transform>();
    if (transform)
    {
        forceUpdate(*transform);
    }
}

void TransformSystem::forceUpdate(Transform& transform)
{
    Entity& entity = transform.entity();
    auto parent = entity.parent();
    if (parent)
    {
        // Update the transform hierarchy starting at this entity's parent
        updateHeierarchy(*parent, entity);
    }
    else
    {
        // Local and global are the same if there is no parent
        transform.globalPosition = transform.localPosition;
        transform.globalScale = transform.localScale;
        transform.globalRotation = transform.localRotation;

        // Update the transform hierachy for all children
        for (Entity& child : entity.children())
        {
            updateHeierarchy(entity, child);
        }
    }

    // Force the bounding box to update
    BoundingBoxSystem& boundingBoxSystem = scene().system<BoundingBoxSystem>();
    boundingBoxSystem.forceUpdate(entity);
}

void TransformSystem::markForUpdate(Entity& entity)
{
    auto transform = entity.component<Transform>();
    if (transform)
    {
        markForUpdate(*transform);
    }
}

void TransformSystem::markForUpdate(Transform& transform)
{
    ComponentId id = transform.id();
    _markedForUpdate.push_back(id);
}

void TransformSystem::tick(Real timeStep)
{
    // Update all transforms marked for update
    for (ComponentId id : _markedForUpdate)
    {
        Transform& transform = scene().components<Transform>().withId(id);
        forceUpdate(transform);
    }
    _markedForUpdate.clear();
}

void TransformSystem::updateHeierarchy(Entity& parent, Entity& child)
{
    // Get the parent transform
    auto parentTransform = parent.component<Transform>();
    if (parentTransform)
    {
        // Get the child transform
        auto childTransform = child.component<Transform>();
        if (childTransform)
        {
            // Compute global transform
            childTransform->globalPosition = parentTransform->globalRotation * childTransform->localPosition;
            childTransform->globalPosition += parentTransform->globalPosition;
            childTransform->globalScale = parentTransform->globalScale * childTransform->localScale;
            childTransform->globalRotation = parentTransform->globalRotation * childTransform->localRotation;

            // Recursively update for all children
            for (Entity& nextChild : child.children())
            {
                updateHeierarchy(child, nextChild);
            }
        }
    }
}
<commit_msg>Fixed Clang warning<commit_after>///////////////////////////////////////////////////////////////////////////////
// This source file is part of Hect.
//
// Copyright (c) 2014 Colin Hill
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
///////////////////////////////////////////////////////////////////////////////
#include "TransformSystem.h"

#include "Hect/Logic/Systems/BoundingBoxSystem.h"
#include "Hect/Runtime/Engine.h"

using namespace hect;

TransformSystem::TransformSystem(Engine& engine, Scene& scene) :
    System(scene, SystemTickStage_Subsequent)
{
    (void)engine;
}

void TransformSystem::forceUpdate(Entity& entity)
{
    auto transform = entity.component<Transform>();
    if (transform)
    {
        forceUpdate(*transform);
    }
}

void TransformSystem::forceUpdate(Transform& transform)
{
    Entity& entity = transform.entity();
    auto parent = entity.parent();
    if (parent)
    {
        // Update the transform hierarchy starting at this entity's parent
        updateHeierarchy(*parent, entity);
    }
    else
    {
        // Local and global are the same if there is no parent
        transform.globalPosition = transform.localPosition;
        transform.globalScale = transform.localScale;
        transform.globalRotation = transform.localRotation;

        // Update the transform hierachy for all children
        for (Entity& child : entity.children())
        {
            updateHeierarchy(entity, child);
        }
    }

    // Force the bounding box to update
    BoundingBoxSystem& boundingBoxSystem = scene().system<BoundingBoxSystem>();
    boundingBoxSystem.forceUpdate(entity);
}

void TransformSystem::markForUpdate(Entity& entity)
{
    auto transform = entity.component<Transform>();
    if (transform)
    {
        markForUpdate(*transform);
    }
}

void TransformSystem::markForUpdate(Transform& transform)
{
    ComponentId id = transform.id();
    _markedForUpdate.push_back(id);
}

void TransformSystem::tick(Real timeStep)
{
    (void)timeStep;

    // Update all transforms marked for update
    for (ComponentId id : _markedForUpdate)
    {
        Transform& transform = scene().components<Transform>().withId(id);
        forceUpdate(transform);
    }
    _markedForUpdate.clear();
}

void TransformSystem::updateHeierarchy(Entity& parent, Entity& child)
{
    // Get the parent transform
    auto parentTransform = parent.component<Transform>();
    if (parentTransform)
    {
        // Get the child transform
        auto childTransform = child.component<Transform>();
        if (childTransform)
        {
            // Compute global transform
            childTransform->globalPosition = parentTransform->globalRotation * childTransform->localPosition;
            childTransform->globalPosition += parentTransform->globalPosition;
            childTransform->globalScale = parentTransform->globalScale * childTransform->localScale;
            childTransform->globalRotation = parentTransform->globalRotation * childTransform->localRotation;

            // Recursively update for all children
            for (Entity& nextChild : child.children())
            {
                updateHeierarchy(child, nextChild);
            }
        }
    }
}
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_HoveringText.cpp
 *  @brief  EC_HoveringText shows a hovering text attached to an entity.
 *  @note   The entity must EC_OgrePlaceable available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_HoveringText.h"
#include "IModule.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "Entity.h"
#include "OgreMaterialUtils.h"
#include "LoggingFunctions.h"
#include "SceneManager.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Touchable");

#include <Ogre.h>
#include <OgreBillboardSet.h>
#include <OgreTextureManager.h>
#include <OgreResource.h>

#include <QFile>
#include <QPainter>
#include <QTimer>
#include <QTimeLine>

#include "MemoryLeakCheck.h"

EC_HoveringText::EC_HoveringText(IModule *module) :
    IComponent(module->GetFramework()),
    font_(QFont("Arial", 100)),
    backgroundColor_(Qt::transparent),
    textColor_(Qt::black),
    billboardSet_(0),
    billboard_(0),
    visibility_animation_timeline_(new QTimeLine(1000, this)),
    visibility_timer_(new QTimer(this)),
    usingGradAttr(this, "Use Gradiant", false),
    textAttr(this, "Text"),
    fontAttr(this, "Font", "Arial"),
    fontColorAttr(this, "Font Color"),
    fontSizeAttr(this, "Font Size", 100),
    backgroundColorAttr(this, "Background Color", Color(1.0f,1.0f,1.0f,0.0f)),
    positionAttr(this, "Position", Vector3df(0.0f, 0.0f, 1.0f)),
    gradStartAttr(this, "Gradient Start", Color(0.0f,0.0f,0.0f,1.0f)),
    gradEndAttr(this, "Gradient End", Color(1.0f,1.0f,1.0f,1.0f))

{
    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);

    visibility_animation_timeline_->setFrameRange(0,100);
    visibility_animation_timeline_->setEasingCurve(QEasingCurve::InOutSine);
    visibility_timer_->setSingleShot(true);

    connect(visibility_animation_timeline_, SIGNAL(frameChanged(int)), SLOT(UpdateAnimationStep(int)));
    connect(visibility_animation_timeline_, SIGNAL(finished()), SLOT(AnimationFinished()));

    QObject::connect(this, SIGNAL(ParentEntitySet()), this, SLOT(UpdateSignals()));
}

EC_HoveringText::~EC_HoveringText()
{
    Destroy();
}

void EC_HoveringText::Destroy()
{
	boost::shared_ptr<OgreRenderer::Renderer> renderer = renderer_.lock();
    if (renderer)
    {
        try{
        Ogre::TextureManager::getSingleton().remove(textureName_);
        } catch(...)
        {
        }
        try{
        Ogre::MaterialManager::getSingleton().remove(materialName_);
        } catch(...)
        {
        }
		try{
		if (billboardSet_ && billboard_)
			billboardSet_->removeBillboard(billboard_);
        } catch(...)
        {
        }
		try{

		if (billboardSet_)
		{
			Ogre::SceneManager *scene = renderer->GetSceneManager();
			if (scene)
				scene->destroyBillboardSet(billboardSet_);
		}

        } catch(...)
        {
        }
    }

	billboard_ = 0;
	billboardSet_ = 0;
	textureName_ = "";
    materialName_ = "";
}

void EC_HoveringText::SetPosition(const Vector3df& position)
{
    if (billboard_)
        billboard_->setPosition(Ogre::Vector3(position.x, position.y, position.z));
}

void EC_HoveringText::SetFont(const QFont &font)
{
    font_ = font;
    Redraw();
}

void EC_HoveringText::SetTextColor(const QColor &color)
{
    textColor_ = color;
    Redraw();
}

void EC_HoveringText::SetBackgroundColor(const QColor &color)
{
    backgroundColor_ = color;
	//using_gradient_ = false;
    Redraw();
}

void EC_HoveringText::SetBackgroundGradient(const QColor &start_color, const QColor &end_color)
{
    bg_grad_.setColorAt(0.0, start_color);
    bg_grad_.setColorAt(1.0, end_color);
	//using_gradient_ = true;
}

void EC_HoveringText::Show()
{
    if (billboardSet_)
        billboardSet_->setVisible(true);
}

void EC_HoveringText::AnimatedShow()
{
    if (visibility_animation_timeline_->state() == QTimeLine::Running ||
        visibility_timer_->isActive() || IsVisible())
        return;

    UpdateAnimationStep(0);
    Show();

    visibility_animation_timeline_->setDirection(QTimeLine::Forward);
    visibility_animation_timeline_->start();
}

void EC_HoveringText::Clicked(int msec_to_show)
{
    if (visibility_timer_->isActive())
        visibility_timer_->stop();
    else
    {
        AnimatedShow();
        visibility_timer_->start(msec_to_show);
    }
}

void EC_HoveringText::Hide()
{
    if (billboardSet_)
        billboardSet_->setVisible(false);
}

void EC_HoveringText::AnimatedHide()
{
    if (visibility_animation_timeline_->state() == QTimeLine::Running ||
        visibility_timer_->isActive() || !IsVisible())
        return;

    UpdateAnimationStep(100);
    visibility_animation_timeline_->setDirection(QTimeLine::Backward);
    visibility_animation_timeline_->start();
}

void EC_HoveringText::UpdateAnimationStep(int step)
{
    if (materialName_.empty())
        return;

    float alpha = step;
    alpha /= 100;

    Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
    Ogre::MaterialPtr material = mgr.getByName(materialName_);
    assert(material.get());

    material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setAlphaOperation(
        Ogre::LBX_BLEND_MANUAL, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, 1.0, 0.0, alpha);
}

void EC_HoveringText::AnimationFinished()
{
    if (visibility_animation_timeline_->direction() == QTimeLine::Backward && IsVisible())
        Hide();
}

bool EC_HoveringText::IsVisible() const
{
    if (billboardSet_)
        return billboardSet_->isVisible();
    else
        return false;
}

void EC_HoveringText::ShowMessage(const QString &text)
{
    if (renderer_.expired())
        return;

    Ogre::SceneManager *scene = renderer_.lock()->GetSceneManager();
    assert(scene);
    if (!scene)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *node = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    if (!node)
        return;

    Ogre::SceneNode *sceneNode = node->GetSceneNode();
    assert(sceneNode);
    if (!sceneNode)
        return;

    // Create billboard if it doesn't exist.
    if (!billboardSet_ && !billboard_)
    {
        billboardSet_ = scene->createBillboardSet(renderer_.lock()->GetUniqueObjectName(), 1);
        assert(billboardSet_);

        materialName_ = std::string("HoveringTextMaterial") + renderer_.lock()->GetUniqueObjectName();
        OgreRenderer::CloneMaterial("HoveringText", materialName_);
        billboardSet_->setMaterialName(materialName_);
        billboardSet_->setCastShadows(false);

        billboard_ = billboardSet_->createBillboard(Ogre::Vector3(0, 0, 0.7f));
        assert(billboard_);
        billboardSet_->setDefaultDimensions(2, 1);

        sceneNode->attachObject(billboardSet_);
    }

    if (text.isNull() || text.isEmpty())
        return;

	//textAttr.Set(text);
    Redraw();
}

void EC_HoveringText::Redraw()
{
    if (renderer_.expired() || !billboardSet_ || !billboard_)
        return;

    // Get pixmap with text rendered to it.
    QPixmap pixmap = GetTextPixmap();
    if (pixmap.isNull())
        return;
    QImage img = pixmap.toImage();

    // Create Ogre texture
    Ogre::TexturePtr texPtr;
    try
    {
        if (textureName_.empty())
        {
            textureName_ = "HoveringTextTexture" + renderer_.lock()->GetUniqueObjectName();

            texPtr = Ogre::TextureManager::getSingleton().createManual(
                textureName_, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
                img.width(), img.height(), Ogre::MIP_DEFAULT, Ogre::PF_A8R8G8B8, Ogre::TU_DEFAULT);

            assert(!texPtr.isNull());
            if (texPtr.isNull())
            {
                LogError("Failed to create texture " + textureName_);
                return;
            }
        }
        else
        {
            texPtr = Ogre::TextureManager::getSingleton().getByName(textureName_);
            assert(!texPtr.isNull());
            // See if size/format changed, have to delete/recreate internal resources
            if (img.width() != texPtr->getWidth() || img.height() != texPtr->getHeight())
            {
                texPtr->freeInternalResources();
                texPtr->setWidth(img.width());
                texPtr->setHeight(img.height());
                texPtr->setFormat(Ogre::PF_A8R8G8B8);
                texPtr->createInternalResources();
            }
        }

        Ogre::Box dimensions(0,0, img.width(), img.height());
        Ogre::PixelBox pixel_box(dimensions, Ogre::PF_A8R8G8B8, (void*)img.bits());
        if (!texPtr->getBuffer().isNull())
            texPtr->getBuffer()->blitFromMemory(pixel_box);
    }
    catch (Ogre::Exception &e)
    {
        LogError("Failed to create texture " + textureName_  + ": " + std::string(e.what()));
        return;
    }

    // Set new texture for the material
    assert(!materialName_.empty());
    if (!materialName_.empty())
    {
        Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mgr.getByName(materialName_);
        assert(material.get());
        OgreRenderer::SetTextureUnitOnMaterial(material, textureName_);
    }
}

QPixmap EC_HoveringText::GetTextPixmap()
{
///\todo Resize the font size according to the render window size and distance
/// avatar's distance from the camera
//    const int minWidth =
//    const int minHeight =
//    Ogre::Viewport* viewport = renderer_.lock()->GetViewport();
//    const int max_width = viewport->getActualWidth()/4;
//    int max_height = viewport->getActualHeight()/10;

	//if (renderer_.expired() || text_.isEmpty() || text_ == " ")
    if (renderer_.expired())
        return 0;

    QRect max_rect(0, 0, 1024, 512);

    // Create transparent pixmap
    QPixmap pixmap(max_rect.size());
    pixmap.fill(Qt::transparent);

    // Init painter with pixmap as the paint device
    QPainter painter(&pixmap);

    // Ask painter the rect for the text
    painter.setFont(font_);
    QRect rect = painter.boundingRect(max_rect, Qt::AlignCenter | Qt::TextWordWrap, textAttr.Get());

    // Add some padding to it
    QFontMetrics metric(font_);
    int width = metric.width(textAttr.Get()) + metric.averageCharWidth();
    int height = metric.height() + 20;
    rect.setWidth(width);
    rect.setHeight(height);

    // Set background brush
    if (usingGradAttr.Get())
    {   bg_grad_.setStart(QPointF(0,rect.top()));
        bg_grad_.setFinalStop(QPointF(0,rect.bottom()));
        painter.setBrush(QBrush(bg_grad_));
    }
    else
        painter.setBrush(backgroundColor_);

    // Draw background rect
    painter.setPen(QColor(255,255,255,150));
    painter.drawRoundedRect(rect, 20.0, 20.0);

    // Draw text
    painter.setPen(textColor_);
    painter.drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, textAttr.Get());

    return pixmap;
}

void EC_HoveringText::UpdateSignals()
{
    disconnect(this, SLOT(AttributeUpdated(IComponent *, IAttribute *)));
    if(GetParentEntity())
    {
        Scene::SceneManager *scene = GetParentEntity()->GetScene();
        if(scene)
        connect(scene, SIGNAL(AttributeChanged(IComponent*, IAttribute*, AttributeChange::Type)),
                this, SLOT(AttributeUpdated(IComponent*, IAttribute*)));
    }
}

void EC_HoveringText::AttributeUpdated(IComponent *component, IAttribute *attribute)
{
    if(component != this)
        return;

    QString attrName = QString::fromStdString(attribute->GetNameString());

	if(QString::fromStdString(fontAttr.GetNameString()) == attrName ||QString::fromStdString(fontSizeAttr.GetNameString()) == attrName)
    {
		SetFont(QFont(fontAttr.Get(), fontSizeAttr.Get()));
    }

	else if(QString::fromStdString(backgroundColorAttr.GetNameString()) == attrName)
	{
		Color col = backgroundColorAttr.Get();
		backgroundColor_.setRgbF(col.r, col.g, col.b, col.a);
	}

	else if(QString::fromStdString(fontColorAttr.GetNameString()) == attrName)
	{
		Color col = fontColorAttr.Get();
		textColor_.setRgbF(col.r, col.g, col.b, col.a);
	}

	else if(QString::fromStdString(positionAttr.GetNameString()) == attrName)
	{
		SetPosition(positionAttr.Get());
	}

	else if(QString::fromStdString(gradEndAttr.GetNameString()) == attrName || QString::fromStdString(gradStartAttr.GetNameString()) == attrName || QString::fromStdString(gradEndAttr.GetNameString()) == attrName)
	{
		QColor colStart;
		QColor colEnd;
		Color col = gradStartAttr.Get();
		colStart.setRgbF(col.r, col.g, col.b);
		col = gradEndAttr.Get();
		colEnd.setRgbF(col.r, col.g, col.b);
		SetBackgroundGradient(colStart, colEnd);
	}

	// Repaint the new text with new appearance.
	ShowMessage(textAttr.Get());

}

<commit_msg>Disable EC_HoveringText texture mipmap levels due to Ogre automatic mip level regeneration timing issue.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_HoveringText.cpp
 *  @brief  EC_HoveringText shows a hovering text attached to an entity.
 *  @note   The entity must EC_OgrePlaceable available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_HoveringText.h"
#include "IModule.h"
#include "Renderer.h"
#include "EC_OgrePlaceable.h"
#include "Entity.h"
#include "OgreMaterialUtils.h"
#include "LoggingFunctions.h"
#include "SceneManager.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Touchable");

#include <Ogre.h>
#include <OgreBillboardSet.h>
#include <OgreTextureManager.h>
#include <OgreResource.h>

#include <QFile>
#include <QPainter>
#include <QTimer>
#include <QTimeLine>

#include "MemoryLeakCheck.h"

EC_HoveringText::EC_HoveringText(IModule *module) :
    IComponent(module->GetFramework()),
    font_(QFont("Arial", 100)),
    backgroundColor_(Qt::transparent),
    textColor_(Qt::black),
    billboardSet_(0),
    billboard_(0),
    visibility_animation_timeline_(new QTimeLine(1000, this)),
    visibility_timer_(new QTimer(this)),
    usingGradAttr(this, "Use Gradiant", false),
    textAttr(this, "Text"),
    fontAttr(this, "Font", "Arial"),
    fontColorAttr(this, "Font Color"),
    fontSizeAttr(this, "Font Size", 100),
    backgroundColorAttr(this, "Background Color", Color(1.0f,1.0f,1.0f,0.0f)),
    positionAttr(this, "Position", Vector3df(0.0f, 0.0f, 1.0f)),
    gradStartAttr(this, "Gradient Start", Color(0.0f,0.0f,0.0f,1.0f)),
    gradEndAttr(this, "Gradient End", Color(1.0f,1.0f,1.0f,1.0f))

{
    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);

    visibility_animation_timeline_->setFrameRange(0,100);
    visibility_animation_timeline_->setEasingCurve(QEasingCurve::InOutSine);
    visibility_timer_->setSingleShot(true);

    connect(visibility_animation_timeline_, SIGNAL(frameChanged(int)), SLOT(UpdateAnimationStep(int)));
    connect(visibility_animation_timeline_, SIGNAL(finished()), SLOT(AnimationFinished()));

    QObject::connect(this, SIGNAL(ParentEntitySet()), this, SLOT(UpdateSignals()));
}

EC_HoveringText::~EC_HoveringText()
{
    Destroy();
}

void EC_HoveringText::Destroy()
{
	boost::shared_ptr<OgreRenderer::Renderer> renderer = renderer_.lock();
    if (renderer)
    {
        try{
        Ogre::TextureManager::getSingleton().remove(textureName_);
        } catch(...)
        {
        }
        try{
        Ogre::MaterialManager::getSingleton().remove(materialName_);
        } catch(...)
        {
        }
		try{
		if (billboardSet_ && billboard_)
			billboardSet_->removeBillboard(billboard_);
        } catch(...)
        {
        }
		try{

		if (billboardSet_)
		{
			Ogre::SceneManager *scene = renderer->GetSceneManager();
			if (scene)
				scene->destroyBillboardSet(billboardSet_);
		}

        } catch(...)
        {
        }
    }

	billboard_ = 0;
	billboardSet_ = 0;
	textureName_ = "";
    materialName_ = "";
}

void EC_HoveringText::SetPosition(const Vector3df& position)
{
    if (billboard_)
        billboard_->setPosition(Ogre::Vector3(position.x, position.y, position.z));
}

void EC_HoveringText::SetFont(const QFont &font)
{
    font_ = font;
    Redraw();
}

void EC_HoveringText::SetTextColor(const QColor &color)
{
    textColor_ = color;
    Redraw();
}

void EC_HoveringText::SetBackgroundColor(const QColor &color)
{
    backgroundColor_ = color;
	//using_gradient_ = false;
    Redraw();
}

void EC_HoveringText::SetBackgroundGradient(const QColor &start_color, const QColor &end_color)
{
    bg_grad_.setColorAt(0.0, start_color);
    bg_grad_.setColorAt(1.0, end_color);
	//using_gradient_ = true;
}

void EC_HoveringText::Show()
{
    if (billboardSet_)
        billboardSet_->setVisible(true);
}

void EC_HoveringText::AnimatedShow()
{
    if (visibility_animation_timeline_->state() == QTimeLine::Running ||
        visibility_timer_->isActive() || IsVisible())
        return;

    UpdateAnimationStep(0);
    Show();

    visibility_animation_timeline_->setDirection(QTimeLine::Forward);
    visibility_animation_timeline_->start();
}

void EC_HoveringText::Clicked(int msec_to_show)
{
    if (visibility_timer_->isActive())
        visibility_timer_->stop();
    else
    {
        AnimatedShow();
        visibility_timer_->start(msec_to_show);
    }
}

void EC_HoveringText::Hide()
{
    if (billboardSet_)
        billboardSet_->setVisible(false);
}

void EC_HoveringText::AnimatedHide()
{
    if (visibility_animation_timeline_->state() == QTimeLine::Running ||
        visibility_timer_->isActive() || !IsVisible())
        return;

    UpdateAnimationStep(100);
    visibility_animation_timeline_->setDirection(QTimeLine::Backward);
    visibility_animation_timeline_->start();
}

void EC_HoveringText::UpdateAnimationStep(int step)
{
    if (materialName_.empty())
        return;

    float alpha = step;
    alpha /= 100;

    Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
    Ogre::MaterialPtr material = mgr.getByName(materialName_);
    assert(material.get());

    material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setAlphaOperation(
        Ogre::LBX_BLEND_MANUAL, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, 1.0, 0.0, alpha);
}

void EC_HoveringText::AnimationFinished()
{
    if (visibility_animation_timeline_->direction() == QTimeLine::Backward && IsVisible())
        Hide();
}

bool EC_HoveringText::IsVisible() const
{
    if (billboardSet_)
        return billboardSet_->isVisible();
    else
        return false;
}

void EC_HoveringText::ShowMessage(const QString &text)
{
    if (renderer_.expired())
        return;

    Ogre::SceneManager *scene = renderer_.lock()->GetSceneManager();
    assert(scene);
    if (!scene)
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *node = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    if (!node)
        return;

    Ogre::SceneNode *sceneNode = node->GetSceneNode();
    assert(sceneNode);
    if (!sceneNode)
        return;

    // Create billboard if it doesn't exist.
    if (!billboardSet_ && !billboard_)
    {
        billboardSet_ = scene->createBillboardSet(renderer_.lock()->GetUniqueObjectName(), 1);
        assert(billboardSet_);

        materialName_ = std::string("HoveringTextMaterial") + renderer_.lock()->GetUniqueObjectName();
        OgreRenderer::CloneMaterial("HoveringText", materialName_);
        billboardSet_->setMaterialName(materialName_);
        billboardSet_->setCastShadows(false);

        billboard_ = billboardSet_->createBillboard(Ogre::Vector3(0, 0, 0.7f));
        assert(billboard_);
        billboardSet_->setDefaultDimensions(2, 1);

        sceneNode->attachObject(billboardSet_);
    }

    if (text.isNull() || text.isEmpty())
        return;

	//textAttr.Set(text);
    Redraw();
}

void EC_HoveringText::Redraw()
{
    if (renderer_.expired() || !billboardSet_ || !billboard_)
        return;

    // Get pixmap with text rendered to it.
    QPixmap pixmap = GetTextPixmap();
    if (pixmap.isNull())
        return;
    QImage img = pixmap.toImage();

    // Create Ogre texture
    Ogre::TexturePtr texPtr;
    try
    {
        if (textureName_.empty())
        {
            textureName_ = "HoveringTextTexture" + renderer_.lock()->GetUniqueObjectName();

            texPtr = Ogre::TextureManager::getSingleton().createManual(
                textureName_, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
                img.width(), img.height(), 0, Ogre::PF_A8R8G8B8, Ogre::TU_DEFAULT);
    ///\todo Disabled mip map generation for now, since the line 'texPtr->getBuffer()->blitFromMemory(pixel_box);' below
    /// will not regenerate them.
//                img.width(), img.height(), Ogre::MIP_DEFAULT, Ogre::PF_A8R8G8B8, Ogre::TU_DEFAULT);

            assert(!texPtr.isNull());
            if (texPtr.isNull())
            {
                LogError("Failed to create texture " + textureName_);
                return;
            }
        }
        else
        {
            texPtr = Ogre::TextureManager::getSingleton().getByName(textureName_);
            assert(!texPtr.isNull());
            // See if size/format changed, have to delete/recreate internal resources
            if (img.width() != texPtr->getWidth() || img.height() != texPtr->getHeight())
            {
                texPtr->freeInternalResources();
                texPtr->setWidth(img.width());
                texPtr->setHeight(img.height());
                texPtr->setFormat(Ogre::PF_A8R8G8B8);
                texPtr->createInternalResources();
            }
        }

        Ogre::Box dimensions(0,0, img.width(), img.height());
        Ogre::PixelBox pixel_box(dimensions, Ogre::PF_A8R8G8B8, (void*)img.bits());
        if (!texPtr->getBuffer().isNull())
        {
            texPtr->getBuffer()->blitFromMemory(pixel_box);
        }
    }
    catch (Ogre::Exception &e)
    {
        LogError("Failed to create texture " + textureName_  + ": " + std::string(e.what()));
        return;
    }

    // Set new texture for the material
    assert(!materialName_.empty());
    if (!materialName_.empty())
    {
        Ogre::MaterialManager &mgr = Ogre::MaterialManager::getSingleton();
        Ogre::MaterialPtr material = mgr.getByName(materialName_);
        assert(material.get());
        OgreRenderer::SetTextureUnitOnMaterial(material, textureName_);
    }
}

QPixmap EC_HoveringText::GetTextPixmap()
{
///\todo Resize the font size according to the render window size and distance
/// avatar's distance from the camera
//    const int minWidth =
//    const int minHeight =
//    Ogre::Viewport* viewport = renderer_.lock()->GetViewport();
//    const int max_width = viewport->getActualWidth()/4;
//    int max_height = viewport->getActualHeight()/10;

	//if (renderer_.expired() || text_.isEmpty() || text_ == " ")
    if (renderer_.expired())
        return 0;

    QRect max_rect(0, 0, 1024, 512);

    // Create transparent pixmap
    QPixmap pixmap(max_rect.size());
    pixmap.fill(Qt::transparent);

    // Init painter with pixmap as the paint device
    QPainter painter(&pixmap);

    // Ask painter the rect for the text
    painter.setFont(font_);
    QRect rect = painter.boundingRect(max_rect, Qt::AlignCenter | Qt::TextWordWrap, textAttr.Get());

    // Add some padding to it
    QFontMetrics metric(font_);
    int width = metric.width(textAttr.Get()) + metric.averageCharWidth();
    int height = metric.height() + 20;
    rect.setWidth(width);
    rect.setHeight(height);

    // Set background brush
    if (usingGradAttr.Get())
    {   bg_grad_.setStart(QPointF(0,rect.top()));
        bg_grad_.setFinalStop(QPointF(0,rect.bottom()));
        painter.setBrush(QBrush(bg_grad_));
    }
    else
        painter.setBrush(backgroundColor_);

    // Draw background rect
    painter.setPen(QColor(255,255,255,150));
    painter.drawRoundedRect(rect, 20.0, 20.0);

    // Draw text
    painter.setPen(textColor_);
    painter.drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, textAttr.Get());

    return pixmap;
}

void EC_HoveringText::UpdateSignals()
{
    disconnect(this, SLOT(AttributeUpdated(IComponent *, IAttribute *)));
    if(GetParentEntity())
    {
        Scene::SceneManager *scene = GetParentEntity()->GetScene();
        if(scene)
        connect(scene, SIGNAL(AttributeChanged(IComponent*, IAttribute*, AttributeChange::Type)),
                this, SLOT(AttributeUpdated(IComponent*, IAttribute*)));
    }
}

void EC_HoveringText::AttributeUpdated(IComponent *component, IAttribute *attribute)
{
    if(component != this)
        return;

    QString attrName = QString::fromStdString(attribute->GetNameString());

	if(QString::fromStdString(fontAttr.GetNameString()) == attrName ||QString::fromStdString(fontSizeAttr.GetNameString()) == attrName)
    {
		SetFont(QFont(fontAttr.Get(), fontSizeAttr.Get()));
    }

	else if(QString::fromStdString(backgroundColorAttr.GetNameString()) == attrName)
	{
		Color col = backgroundColorAttr.Get();
		backgroundColor_.setRgbF(col.r, col.g, col.b, col.a);
	}

	else if(QString::fromStdString(fontColorAttr.GetNameString()) == attrName)
	{
		Color col = fontColorAttr.Get();
		textColor_.setRgbF(col.r, col.g, col.b, col.a);
	}

	else if(QString::fromStdString(positionAttr.GetNameString()) == attrName)
	{
		SetPosition(positionAttr.Get());
	}

	else if(QString::fromStdString(gradEndAttr.GetNameString()) == attrName || QString::fromStdString(gradStartAttr.GetNameString()) == attrName || QString::fromStdString(gradEndAttr.GetNameString()) == attrName)
	{
		QColor colStart;
		QColor colEnd;
		Color col = gradStartAttr.Get();
		colStart.setRgbF(col.r, col.g, col.b);
		col = gradEndAttr.Get();
		colEnd.setRgbF(col.r, col.g, col.b);
		SetBackgroundGradient(colStart, colEnd);
	}

	// Repaint the new text with new appearance.
	ShowMessage(textAttr.Get());

}

<|endoftext|>