<commit_before>// $Id$
//
//  Copyright (c) 2007, Novartis Institutes for BioMedical Research Inc.
//  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.
//     * Neither the name of Novartis Institutues for BioMedical Research Inc.
//       nor the names of its contributors may be used to endorse or promote
//       products derived from this software without specific prior written permission.
//
// 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
// OWNER 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 <boost/python.hpp>
#include <GraphMol/ChemReactions/Reaction.h>
#include <GraphMol/ChemReactions/ReactionPickler.h>
#include <GraphMol/ChemReactions/ReactionParser.h>

#include <RDBoost/Wrap.h>
#include <RDBoost/Exceptions.h>
#include <GraphMol/SanitException.h>
#include <RDGeneral/FileParseException.h>

namespace python = boost::python;

void rdChemicalReactionParserExceptionTranslator(RDKit::ChemicalReactionParserException const& x){
  std::ostringstream ss;
  ss << "ChemicalReactionParserException: " << x.message();
  PyErr_SetString(PyExc_ValueError,ss.str().c_str());
}
void rdChemicalReactionExceptionTranslator(RDKit::ChemicalReactionException const& x){
  std::ostringstream ss;
  ss << "ChemicalParserException: " << x.message();
  PyErr_SetString(PyExc_ValueError,ss.str().c_str());
}

namespace RDKit {
  std::string ReactionToBinary(const ChemicalReaction &self){
    std::string res;
    ReactionPickler::pickleReaction(self,res);
    return res;
  }
  //
  // allows reactions to be pickled.
  //
  struct reaction_pickle_suite : python::pickle_suite
  {
    static python::tuple
    getinitargs(const ChemicalReaction & self)
    {
      return python::make_tuple(ReactionToBinary(self));
    };
  };

  template <typename T>
  PyObject* RunReactants(ChemicalReaction *self,T reactants){
    if(!self->isInitialized()){
      self->initReactantMatchers();
    }
    MOL_SPTR_VECT reacts;
    unsigned int len1 = python::extract<unsigned int>(reactants.attr("__len__")());
    reacts.resize(len1);
    for(unsigned int i=0;i<len1;++i){
      reacts[i] = python::extract<ROMOL_SPTR>(reactants[i]);
    }
    std::vector<MOL_SPTR_VECT> mols;
    mols = self->runReactants(reacts);
    PyObject *res=PyTuple_New(mols.size());

    for(unsigned int i=0;i<mols.size();++i){
      PyObject *lTpl =PyTuple_New(mols[i].size());
      for(unsigned int j=0;j<mols[i].size();++j){
        PyTuple_SetItem(lTpl,j,
          python::converter::shared_ptr_to_python(mols[i][j]));
      }
      PyTuple_SetItem(res,i,lTpl);
    }
    return res;
  }

  python::tuple ValidateReaction(const ChemicalReaction *self,bool silent=false){
    unsigned int numWarn,numError;
    self->validate(numWarn,numError,silent);
    return python::make_tuple(numWarn,numError);
  }

  ROMol * GetProductTemplate(const ChemicalReaction *self,unsigned int which){
    if(which>=self->getNumProductTemplates()){
      throw_value_error("requested template index too high");
    }
    MOL_SPTR_VECT::const_iterator iter=self->beginProductTemplates();
    iter += which;
    ROMol *res = const_cast<ROMol *>(iter->get());
    return res;
  }
  ROMol * GetReactantTemplate(const ChemicalReaction *self,unsigned int which){
    if(which>=self->getNumReactantTemplates()){
      throw_value_error("requested template index too high");
    }
    MOL_SPTR_VECT::const_iterator iter=self->beginReactantTemplates();
    iter += which;
    ROMol *res = const_cast<ROMol *>(iter->get());
    return res;
  }

}

BOOST_PYTHON_MODULE(rdChemReactions) {
  python::scope().attr("__doc__") =
    "Module containing classes and functions for working with chemical reactions."
    ;

  python::register_exception_translator<RDKit::ChemicalReactionParserException>(&rdChemicalReactionParserExceptionTranslator);
  python::register_exception_translator<RDKit::ChemicalReactionException>(&rdChemicalReactionExceptionTranslator);

  std::string docString = "A class for storing and applying chemical reactions.\n\
\n\
Sample Usage:\n\
>>> rxn = rdChemReactions.ReactionFromSmarts('[C:1](=[O:2])O.[N:3]>>[C:1](=[O:2])[N:3]')\n\
>>> reacts = (Chem.MolFromSmiles('C(=O)O'),Chem.MolFromSmiles('CNC'))\n\
>>> products = rxn.RunReactants(reacts)\n\
>>> len(products)\n\
1\n\
>>> len(products[0])\n\
1\n\
>>> Chem.MolToSmiles(products[0])\n\
'CN(C)C=O'\n\
\n\
";
  python::class_<RDKit::ChemicalReaction>("ChemicalReaction",docString.c_str(),
                                          python::init<>("Constructor, takes no arguments"))
    .def(python::init<const std::string &>())
    .def("GetNumReactantTemplates",&RDKit::ChemicalReaction::getNumReactantTemplates,
         "returns the number of reactants this reaction expects")
    .def("GetNumProductTemplates",&RDKit::ChemicalReaction::getNumProductTemplates,
         "returns the number of products this reaction generates")
    .def("AddReactantTemplate",&RDKit::ChemicalReaction::addReactantTemplate,
         "adds a reactant (a Molecule) to the reaction")
    .def("AddProductTemplate",&RDKit::ChemicalReaction::addProductTemplate,
         "adds a product (a Molecule)")
    .def("RunReactants",(PyObject *(*)(RDKit::ChemicalReaction *,python::tuple))RDKit::RunReactants,
         "apply the reaction to a sequence of reactant molecules and return the products as a tuple of tuples")
    .def("RunReactants",(PyObject *(*)(RDKit::ChemicalReaction *,python::list))RDKit::RunReactants,
         "apply the reaction to a sequence of reactant molecules and return the products as a tuple of tuples")
    .def("Initialize",&RDKit::ChemicalReaction::initReactantMatchers,
         "initializes the reaction so that it can be used")
    .def("IsInitialized",&RDKit::ChemicalReaction::isInitialized,
         "checks if the reaction is ready for use")
    .def("Validate",&RDKit::ValidateReaction,
         (python::arg("self"),python::arg("silent")=false),
         "checks the reaction for potential problems, returns (numWarnings,numErrors)")
    .def("GetProductTemplate",&RDKit::GetProductTemplate,
         (python::arg("self"),python::arg("which")),
         python::return_value_policy<python::reference_existing_object>(),
         "returns one of our product templates")
    .def("GetReactantTemplate",&RDKit::GetReactantTemplate,
         (python::arg("self"),python::arg("which")),
         python::return_value_policy<python::reference_existing_object>(),
         "returns one of our reactant templates")
    .def("_setImplicitPropertiesFlag",&RDKit::ChemicalReaction::setImplicitPropertiesFlag,
         (python::arg("self"),python::arg("val")),
         "EXPERT USER: indicates that the reaction can have implicit properties")
    .def("_getImplicitPropertiesFlag",&RDKit::ChemicalReaction::getImplicitPropertiesFlag,
         (python::arg("self")),
         "EXPERT USER: returns whether or not the reaction can have implicit properties")
    .def("ToBinary",RDKit::ReactionToBinary,
         "Returns a binary string representation of the reaction.\n")
    // enable pickle support
    .def_pickle(RDKit::reaction_pickle_suite())

  ;

  def("ReactionFromSmarts",RDKit::RxnSmartsToChemicalReaction,
      "construct a ChemicalReaction from a reaction SMARTS string",
      python::return_value_policy<python::manage_new_object>());
  def("ReactionFromRxnFile",RDKit::RxnFileToChemicalReaction,
      "construct a ChemicalReaction from an MDL rxn file",
      python::return_value_policy<python::manage_new_object>());
  def("ReactionFromRxnBlock",RDKit::RxnBlockToChemicalReaction,
      "construct a ChemicalReaction from an string in MDL rxn format",
      python::return_value_policy<python::manage_new_object>());
  def("ReactionToSmarts",RDKit::ChemicalReactionToRxnSmarts,
      (python::arg("reaction")),
      "construct a reaction SMARTS string for a ChemicalReaction");
}

<commit_msg>checked that in too early<commit_after>// $Id$
//
//  Copyright (c) 2007, Novartis Institutes for BioMedical Research Inc.
//  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.
//     * Neither the name of Novartis Institutues for BioMedical Research Inc.
//       nor the names of its contributors may be used to endorse or promote
//       products derived from this software without specific prior written permission.
//
// 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
// OWNER 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 <boost/python.hpp>
#include <GraphMol/ChemReactions/Reaction.h>
#include <GraphMol/ChemReactions/ReactionPickler.h>
#include <GraphMol/ChemReactions/ReactionParser.h>

#include <RDBoost/Wrap.h>
#include <RDBoost/Exceptions.h>
#include <GraphMol/SanitException.h>
#include <RDGeneral/FileParseException.h>

namespace python = boost::python;

void rdChemicalReactionParserExceptionTranslator(RDKit::ChemicalReactionParserException const& x){
  std::ostringstream ss;
  ss << "ChemicalReactionParserException: " << x.message();
  PyErr_SetString(PyExc_ValueError,ss.str().c_str());
}
void rdChemicalReactionExceptionTranslator(RDKit::ChemicalReactionException const& x){
  std::ostringstream ss;
  ss << "ChemicalParserException: " << x.message();
  PyErr_SetString(PyExc_ValueError,ss.str().c_str());
}

namespace RDKit {
  std::string ReactionToBinary(const ChemicalReaction &self){
    std::string res;
    ReactionPickler::pickleReaction(self,res);
    return res;
  }
  //
  // allows reactions to be pickled.
  //
  struct reaction_pickle_suite : python::pickle_suite
  {
    static python::tuple
    getinitargs(const ChemicalReaction & self)
    {
      return python::make_tuple(ReactionToBinary(self));
    };
  };

  template <typename T>
  PyObject* RunReactants(ChemicalReaction *self,T reactants){
    if(!self->isInitialized()){
      self->initReactantMatchers();
    }
    MOL_SPTR_VECT reacts;
    unsigned int len1 = python::extract<unsigned int>(reactants.attr("__len__")());
    reacts.resize(len1);
    for(unsigned int i=0;i<len1;++i){
      reacts[i] = python::extract<ROMOL_SPTR>(reactants[i]);
    }
    std::vector<MOL_SPTR_VECT> mols;
    mols = self->runReactants(reacts);
    PyObject *res=PyTuple_New(mols.size());

    for(unsigned int i=0;i<mols.size();++i){
      PyObject *lTpl =PyTuple_New(mols[i].size());
      for(unsigned int j=0;j<mols[i].size();++j){
        PyTuple_SetItem(lTpl,j,
          python::converter::shared_ptr_to_python(mols[i][j]));
      }
      PyTuple_SetItem(res,i,lTpl);
    }
    return res;
  }

  python::tuple ValidateReaction(const ChemicalReaction *self,bool silent=false){
    unsigned int numWarn,numError;
    self->validate(numWarn,numError,silent);
    return python::make_tuple(numWarn,numError);
  }

  ROMol * GetProductTemplate(const ChemicalReaction *self,unsigned int which){
    if(which>=self->getNumProductTemplates()){
      throw_value_error("requested template index too high");
    }
    MOL_SPTR_VECT::const_iterator iter=self->beginProductTemplates();
    iter += which;
    ROMol *res = const_cast<ROMol *>(iter->get());
    return res;
  }
  ROMol * GetReactantTemplate(const ChemicalReaction *self,unsigned int which){
    if(which>=self->getNumReactantTemplates()){
      throw_value_error("requested template index too high");
    }
    MOL_SPTR_VECT::const_iterator iter=self->beginReactantTemplates();
    iter += which;
    ROMol *res = const_cast<ROMol *>(iter->get());
    return res;
  }

}

BOOST_PYTHON_MODULE(rdChemReactions) {
  python::scope().attr("__doc__") =
    "Module containing classes and functions for working with chemical reactions."
    ;

  python::register_exception_translator<RDKit::ChemicalReactionParserException>(&rdChemicalReactionParserExceptionTranslator);
  python::register_exception_translator<RDKit::ChemicalReactionException>(&rdChemicalReactionExceptionTranslator);

  std::string docString = "A class for storing and applying chemical reactions.\n\
\n\
Sample Usage:\n\
>>> rxn = rdChemReactions.ReactionFromSmarts('[C:1](=[O:2])O.[N:3]>>[C:1](=[O:2])[N:3]')\n\
>>> reacts = (Chem.MolFromSmiles('C(=O)O'),Chem.MolFromSmiles('CNC'))\n\
>>> products = rxn.RunReactants(reacts)\n\
>>> len(products)\n\
1\n\
>>> len(products[0])\n\
1\n\
>>> Chem.MolToSmiles(products[0])\n\
'CN(C)C=O'\n\
\n\
";
  python::class_<RDKit::ChemicalReaction>("ChemicalReaction",docString.c_str(),
                                          python::init<>("Constructor, takes no arguments"))
    .def(python::init<const std::string &>())
    .def("GetNumReactantTemplates",&RDKit::ChemicalReaction::getNumReactantTemplates,
         "returns the number of reactants this reaction expects")
    .def("GetNumProductTemplates",&RDKit::ChemicalReaction::getNumProductTemplates,
         "returns the number of products this reaction generates")
    .def("AddReactantTemplate",&RDKit::ChemicalReaction::addReactantTemplate,
         "adds a reactant (a Molecule) to the reaction")
    .def("AddProductTemplate",&RDKit::ChemicalReaction::addProductTemplate,
         "adds a product (a Molecule)")
    .def("RunReactants",(PyObject *(*)(RDKit::ChemicalReaction *,python::tuple))RDKit::RunReactants,
         "apply the reaction to a sequence of reactant molecules and return the products as a tuple of tuples")
    .def("RunReactants",(PyObject *(*)(RDKit::ChemicalReaction *,python::list))RDKit::RunReactants,
         "apply the reaction to a sequence of reactant molecules and return the products as a tuple of tuples")
    .def("Initialize",&RDKit::ChemicalReaction::initReactantMatchers,
         "initializes the reaction so that it can be used")
    .def("IsInitialized",&RDKit::ChemicalReaction::isInitialized,
         "checks if the reaction is ready for use")
    .def("Validate",&RDKit::ValidateReaction,
         (python::arg("self"),python::arg("silent")=false),
         "checks the reaction for potential problems, returns (numWarnings,numErrors)")
    .def("GetProductTemplate",&RDKit::GetProductTemplate,
         (python::arg("self"),python::arg("which")),
         python::return_value_policy<python::reference_existing_object>(),
         "returns one of our product templates")
    .def("GetReactantTemplate",&RDKit::GetReactantTemplate,
         (python::arg("self"),python::arg("which")),
         python::return_value_policy<python::reference_existing_object>(),
         "returns one of our reactant templates")
    .def("_setImplicitPropertiesFlag",&RDKit::ChemicalReaction::setImplicitPropertiesFlag,
         (python::arg("self"),python::arg("val")),
         "EXPERT USER: indicates that the reaction can have implicit properties")
    .def("_getImplicitPropertiesFlag",&RDKit::ChemicalReaction::getImplicitPropertiesFlag,
         (python::arg("self")),
         "EXPERT USER: returns whether or not the reaction can have implicit properties")
    .def("ToBinary",RDKit::ReactionToBinary,
         "Returns a binary string representation of the reaction.\n")
    // enable pickle support
    .def_pickle(RDKit::reaction_pickle_suite())

  ;

  def("ReactionFromSmarts",RDKit::RxnSmartsToChemicalReaction,
      "construct a ChemicalReaction from a reaction SMARTS string",
      python::return_value_policy<python::manage_new_object>());
  def("ReactionFromRxnFile",RDKit::RxnFileToChemicalReaction,
      "construct a ChemicalReaction from an MDL rxn file",
      python::return_value_policy<python::manage_new_object>());
  def("ReactionFromRxnBlock",RDKit::RxnBlockToChemicalReaction,
      "construct a ChemicalReaction from an string in MDL rxn format",
      python::return_value_policy<python::manage_new_object>());
  //def("ReactionToSmarts",RDKit::ChemicalReactionToRxnSmarts,
  //    (python::arg("reaction")),
  //    "construct a reaction SMARTS string for a ChemicalReaction");
}

<|endoftext|>


<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "server_update.h"
#include "../urlplugin/IUrlFactory.h"
#include "../Interface/Server.h"
#include "../Interface/File.h"
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include "DataplanDb.h"
#include <stdlib.h>
#include <memory>

extern IUrlFactory *url_fak;

namespace
{
	std::string urbackup_update_url = "http://update5.urbackup.org/";
	std::string urbackup_update_url_alt;

	struct SUpdatePlatform
	{
		SUpdatePlatform(std::string extension,
			std::string basename, std::string versionname)
			: extension(extension), basename(basename),
			versionname(versionname)
		{}
		std::string extension;
		std::string basename;
		std::string versionname;
	};
}

ServerUpdate::ServerUpdate(void)
{
}

void ServerUpdate::update_client()
{
	if(url_fak==NULL)
	{
		Server->Log("Urlplugin not found. Cannot download client for autoupdate.", LL_ERROR);
		return;
	}

	read_update_location();

	std::string http_proxy = Server->getServerParameter("http_proxy");

	std::vector<SUpdatePlatform> update_files;

	update_files.push_back(SUpdatePlatform("exe", "UrBackupUpdate", "version.txt"));
	update_files.push_back(SUpdatePlatform("sh", "UrBackupUpdateMac", "version_osx.txt"));
	update_files.push_back(SUpdatePlatform("sh", "UrBackupUpdateLinux", "version_linux.txt"));

	std::string curr_update_url = urbackup_update_url;

	for (size_t i = 0; i < update_files.size(); ++i)
	{
		SUpdatePlatform& curr = update_files[i];

		std::string errmsg;
		Server->Log("Downloading version file...", LL_INFO);
		std::string version = url_fak->downloadString(curr_update_url + curr.versionname, http_proxy, &errmsg);
		if (version.empty())
		{
			if (curr_update_url == urbackup_update_url
				&& !urbackup_update_url_alt.empty())
			{
				curr_update_url = urbackup_update_url_alt;
				version = url_fak->downloadString(curr_update_url + curr.versionname, http_proxy, &errmsg);
			}

			if (version.empty())
			{
				Server->Log("Error while downloading version info from " + curr_update_url + curr.versionname + ": " + errmsg, LL_ERROR);
				continue;
			}
		}

		std::string curr_version = getFile("urbackup/"+curr.versionname);
		if (curr_version.empty()) curr_version = "0";

		if (version!=curr_version)
		{
			Server->Log("Downloading signature...", LL_INFO);

			bool dl_ok = true;

			std::auto_ptr<IFile> sig_file(Server->openFile("urbackup/" + curr.basename + ".sig2.new", MODE_WRITE));
			if (sig_file.get() == NULL)
			{
				Server->Log("Error opening signature output file urbackup/" + curr.basename + ".sig2.new", LL_ERROR);
				return;
			}

			bool b = url_fak->downloadFile(curr_update_url + curr.basename + ".sig2", sig_file.get(), http_proxy, &errmsg);

			if (!b)
			{
				Server->Log("Error while downloading update signature from " + curr_update_url + curr.basename + ".sig2: " + errmsg, LL_ERROR);
				dl_ok = false;
			}

			if (curr.extension == "exe")
			{
				Server->Log("Downloading old signature...", LL_INFO);

				std::auto_ptr<IFile> old_sig_file(Server->openFile("urbackup/" + curr.basename + ".sig.new", MODE_WRITE));
				if (old_sig_file.get() == NULL)
				{
					Server->Log("Error opening signature output file urbackup/" + curr.basename + ".sig.new", LL_ERROR);
					return;
				}

				bool b = url_fak->downloadFile(curr_update_url + curr.basename + ".sig", old_sig_file.get(), http_proxy, &errmsg);

				if (!b)
				{
					Server->Log("Error while downloading old update signature from " + curr_update_url + curr.basename + ".sig: " + errmsg, LL_ERROR);
					dl_ok = false;
				}
				else
				{
					old_sig_file->Sync();
				}
			}

			Server->Log("Getting update file URL...", LL_INFO);
			std::string update_url = url_fak->downloadString(curr_update_url + curr.basename + ".url", http_proxy, &errmsg);
			std::auto_ptr<IFile> update_file;

			if (update_url.empty())
			{
				Server->Log("Error while downloading update url from " + curr_update_url + curr.basename + ".url: " + errmsg, LL_ERROR);
				dl_ok = false;
			}
			else
			{
				update_file.reset(Server->openFile("urbackup/" + curr.basename + "." + curr.extension + ".new", MODE_WRITE));
				if (update_file.get() == NULL)
				{
					Server->Log("Error opening update output file urbackup/" + curr.basename + "." + curr.extension, LL_ERROR);
					return;
				}

				Server->Log("Downloading update file...", LL_INFO);
				b = url_fak->downloadFile(update_url, update_file.get(), http_proxy, &errmsg);

				if (!b)
				{
					Server->Log("Error while downloading update file from " + update_url + ": " + errmsg, LL_ERROR);
					dl_ok = false;
				}
			}

			if (dl_ok)
			{
				sig_file->Sync();
				update_file->Sync();

				sig_file.reset();
				update_file.reset();

				void* trans = os_start_transaction();

				if (os_rename_file("urbackup/" + curr.basename + ".sig2.new", "urbackup/" + curr.basename + ".sig2", trans)
					&& os_rename_file("urbackup/" + curr.basename + "." + curr.extension + ".new", "urbackup/" + curr.basename + "." + curr.extension, trans)
					&& (curr.extension != "exe" || os_rename_file("urbackup/" + curr.basename + ".sig.new", "urbackup/" + curr.basename + ".sig", trans))
					&& (trans==NULL || os_finish_transaction(trans)) )
				{
					Server->Log("Successfully downloaded update file.", LL_INFO);
					writestring(version, "urbackup/" + curr.versionname);
				}
				else
				{
					Server->Log("Renaming update files to final location failed. " + os_last_error_str(), LL_ERROR);
				}
			}
			else
			{
				std::string del_fn = sig_file->getFilename();
				sig_file.reset();
				Server->deleteFile(del_fn);

				del_fn = update_file->getFilename();
				update_file.reset();
				Server->deleteFile(del_fn);
			}
		}
	}
}

void ServerUpdate::update_server_version_info()
{
	if(url_fak==NULL)
	{
		Server->Log("Urlplugin not found. Cannot download server version info.", LL_ERROR);
		return;
	}

	read_update_location();

	std::string http_proxy = Server->getServerParameter("http_proxy");

	std::string errmsg;
	Server->Log("Downloading server version info...", LL_INFO);

	std::auto_ptr<IFile> server_version_info(Server->openFile("urbackup/server_version_info.properties.new", MODE_WRITE));

	if(!server_version_info.get())
	{
		Server->Log("Error opening urbackup/server_version_info.properties.new for writing", LL_ERROR);
	}
	else
	{
		if(!url_fak->downloadFile(urbackup_update_url+"server_version_info.properties",
			server_version_info.get(), http_proxy, &errmsg) )
		{
			Server->Log("Error downloading server version information: " + errmsg, LL_ERROR);
		}
		else
		{
			server_version_info.reset();
			if (!os_rename_file("urbackup/server_version_info.properties.new",
								"urbackup/server_version_info.properties"))
			{
				Server->Log("Error renaming server_version_info.properties . " + os_last_error_str(), LL_ERROR);
			}
		}
	}
}

void ServerUpdate::update_dataplan_db()
{
	if (url_fak == NULL)
	{
		Server->Log("Urlplugin not found. Cannot download dataplan database.", LL_ERROR);
		return;
	}

	read_update_location();

	std::string http_proxy = Server->getServerParameter("http_proxy");

	std::string errmsg;
	Server->Log("Downloading dataplan database...", LL_INFO);

	std::auto_ptr<IFile> dataplan_db(Server->openFile("urbackup/dataplan_db.txt.new", MODE_WRITE));
	if (!dataplan_db.get())
	{
		Server->Log("Error opening urbackup/dataplan_db.txt.new for writing", LL_ERROR);
	}
	else
	{
		if (!url_fak->downloadFile(urbackup_update_url + "dataplan_db.txt",
			dataplan_db.get(), http_proxy, &errmsg))
		{
			Server->Log("Error downloading dataplan database: " + errmsg, LL_ERROR);
		}
		else
		{
			dataplan_db.reset();
			if (!os_rename_file("urbackup/dataplan_db.txt.new",
				"urbackup/dataplan_db.txt"))
			{
				Server->Log("Error renaming urbackup/dataplan_db.txt. " + os_last_error_str(), LL_ERROR);
			}

			DataplanDb::getInstance()->read("urbackup/dataplan_db.txt");
		}

	}
}

void ServerUpdate::read_update_location()
{
	std::string read_update_location = trim(getFile("urbackup/server_update_location.url"));

	if (!read_update_location.empty())
	{
		urbackup_update_url_alt = read_update_location;
		urbackup_update_url = urbackup_update_url_alt;

		if (!urbackup_update_url.empty()
			&& urbackup_update_url[urbackup_update_url.size() - 1] != '/')
			urbackup_update_url += "/";

		urbackup_update_url += "2.2.x/";
	}
}
<commit_msg>Change update location<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "server_update.h"
#include "../urlplugin/IUrlFactory.h"
#include "../Interface/Server.h"
#include "../Interface/File.h"
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include "DataplanDb.h"
#include <stdlib.h>
#include <memory>

extern IUrlFactory *url_fak;

namespace
{
	std::string urbackup_update_url = "http://update6.urbackup.org/";
	std::string urbackup_update_url_alt;

	struct SUpdatePlatform
	{
		SUpdatePlatform(std::string extension,
			std::string basename, std::string versionname)
			: extension(extension), basename(basename),
			versionname(versionname)
		{}
		std::string extension;
		std::string basename;
		std::string versionname;
	};
}

ServerUpdate::ServerUpdate(void)
{
}

void ServerUpdate::update_client()
{
	if(url_fak==NULL)
	{
		Server->Log("Urlplugin not found. Cannot download client for autoupdate.", LL_ERROR);
		return;
	}

	read_update_location();

	std::string http_proxy = Server->getServerParameter("http_proxy");

	std::vector<SUpdatePlatform> update_files;

	update_files.push_back(SUpdatePlatform("exe", "UrBackupUpdate", "version.txt"));
	update_files.push_back(SUpdatePlatform("sh", "UrBackupUpdateMac", "version_osx.txt"));
	update_files.push_back(SUpdatePlatform("sh", "UrBackupUpdateLinux", "version_linux.txt"));

	std::string curr_update_url = urbackup_update_url;

	for (size_t i = 0; i < update_files.size(); ++i)
	{
		SUpdatePlatform& curr = update_files[i];

		std::string errmsg;
		Server->Log("Downloading version file...", LL_INFO);
		std::string version = url_fak->downloadString(curr_update_url + curr.versionname, http_proxy, &errmsg);
		if (version.empty())
		{
			if (curr_update_url == urbackup_update_url
				&& !urbackup_update_url_alt.empty())
			{
				curr_update_url = urbackup_update_url_alt;
				version = url_fak->downloadString(curr_update_url + curr.versionname, http_proxy, &errmsg);
			}

			if (version.empty())
			{
				Server->Log("Error while downloading version info from " + curr_update_url + curr.versionname + ": " + errmsg, LL_ERROR);
				continue;
			}
		}

		std::string curr_version = getFile("urbackup/"+curr.versionname);
		if (curr_version.empty()) curr_version = "0";

		if (version!=curr_version)
		{
			Server->Log("Downloading signature...", LL_INFO);

			bool dl_ok = true;

			std::auto_ptr<IFile> sig_file(Server->openFile("urbackup/" + curr.basename + ".sig2.new", MODE_WRITE));
			if (sig_file.get() == NULL)
			{
				Server->Log("Error opening signature output file urbackup/" + curr.basename + ".sig2.new", LL_ERROR);
				return;
			}

			bool b = url_fak->downloadFile(curr_update_url + curr.basename + ".sig2", sig_file.get(), http_proxy, &errmsg);

			if (!b)
			{
				Server->Log("Error while downloading update signature from " + curr_update_url + curr.basename + ".sig2: " + errmsg, LL_ERROR);
				dl_ok = false;
			}

			if (curr.extension == "exe")
			{
				Server->Log("Downloading old signature...", LL_INFO);

				std::auto_ptr<IFile> old_sig_file(Server->openFile("urbackup/" + curr.basename + ".sig.new", MODE_WRITE));
				if (old_sig_file.get() == NULL)
				{
					Server->Log("Error opening signature output file urbackup/" + curr.basename + ".sig.new", LL_ERROR);
					return;
				}

				bool b = url_fak->downloadFile(curr_update_url + curr.basename + ".sig", old_sig_file.get(), http_proxy, &errmsg);

				if (!b)
				{
					Server->Log("Error while downloading old update signature from " + curr_update_url + curr.basename + ".sig: " + errmsg, LL_ERROR);
					dl_ok = false;
				}
				else
				{
					old_sig_file->Sync();
				}
			}

			Server->Log("Getting update file URL...", LL_INFO);
			std::string update_url = url_fak->downloadString(curr_update_url + curr.basename + ".url", http_proxy, &errmsg);
			std::auto_ptr<IFile> update_file;

			if (update_url.empty())
			{
				Server->Log("Error while downloading update url from " + curr_update_url + curr.basename + ".url: " + errmsg, LL_ERROR);
				dl_ok = false;
			}
			else
			{
				update_file.reset(Server->openFile("urbackup/" + curr.basename + "." + curr.extension + ".new", MODE_WRITE));
				if (update_file.get() == NULL)
				{
					Server->Log("Error opening update output file urbackup/" + curr.basename + "." + curr.extension, LL_ERROR);
					return;
				}

				Server->Log("Downloading update file...", LL_INFO);
				b = url_fak->downloadFile(update_url, update_file.get(), http_proxy, &errmsg);

				if (!b)
				{
					Server->Log("Error while downloading update file from " + update_url + ": " + errmsg, LL_ERROR);
					dl_ok = false;
				}
			}

			if (dl_ok)
			{
				sig_file->Sync();
				update_file->Sync();

				sig_file.reset();
				update_file.reset();

				void* trans = os_start_transaction();

				if (os_rename_file("urbackup/" + curr.basename + ".sig2.new", "urbackup/" + curr.basename + ".sig2", trans)
					&& os_rename_file("urbackup/" + curr.basename + "." + curr.extension + ".new", "urbackup/" + curr.basename + "." + curr.extension, trans)
					&& (curr.extension != "exe" || os_rename_file("urbackup/" + curr.basename + ".sig.new", "urbackup/" + curr.basename + ".sig", trans))
					&& (trans==NULL || os_finish_transaction(trans)) )
				{
					Server->Log("Successfully downloaded update file.", LL_INFO);
					writestring(version, "urbackup/" + curr.versionname);
				}
				else
				{
					Server->Log("Renaming update files to final location failed. " + os_last_error_str(), LL_ERROR);
				}
			}
			else
			{
				std::string del_fn = sig_file->getFilename();
				sig_file.reset();
				Server->deleteFile(del_fn);

				del_fn = update_file->getFilename();
				update_file.reset();
				Server->deleteFile(del_fn);
			}
		}
	}
}

void ServerUpdate::update_server_version_info()
{
	if(url_fak==NULL)
	{
		Server->Log("Urlplugin not found. Cannot download server version info.", LL_ERROR);
		return;
	}

	read_update_location();

	std::string http_proxy = Server->getServerParameter("http_proxy");

	std::string errmsg;
	Server->Log("Downloading server version info...", LL_INFO);

	std::auto_ptr<IFile> server_version_info(Server->openFile("urbackup/server_version_info.properties.new", MODE_WRITE));

	if(!server_version_info.get())
	{
		Server->Log("Error opening urbackup/server_version_info.properties.new for writing", LL_ERROR);
	}
	else
	{
		if(!url_fak->downloadFile(urbackup_update_url+"server_version_info.properties",
			server_version_info.get(), http_proxy, &errmsg) )
		{
			Server->Log("Error downloading server version information: " + errmsg, LL_ERROR);
		}
		else
		{
			server_version_info.reset();
			if (!os_rename_file("urbackup/server_version_info.properties.new",
								"urbackup/server_version_info.properties"))
			{
				Server->Log("Error renaming server_version_info.properties . " + os_last_error_str(), LL_ERROR);
			}
		}
	}
}

void ServerUpdate::update_dataplan_db()
{
	if (url_fak == NULL)
	{
		Server->Log("Urlplugin not found. Cannot download dataplan database.", LL_ERROR);
		return;
	}

	read_update_location();

	std::string http_proxy = Server->getServerParameter("http_proxy");

	std::string errmsg;
	Server->Log("Downloading dataplan database...", LL_INFO);

	std::auto_ptr<IFile> dataplan_db(Server->openFile("urbackup/dataplan_db.txt.new", MODE_WRITE));
	if (!dataplan_db.get())
	{
		Server->Log("Error opening urbackup/dataplan_db.txt.new for writing", LL_ERROR);
	}
	else
	{
		if (!url_fak->downloadFile(urbackup_update_url + "dataplan_db.txt",
			dataplan_db.get(), http_proxy, &errmsg))
		{
			Server->Log("Error downloading dataplan database: " + errmsg, LL_ERROR);
		}
		else
		{
			dataplan_db.reset();
			if (!os_rename_file("urbackup/dataplan_db.txt.new",
				"urbackup/dataplan_db.txt"))
			{
				Server->Log("Error renaming urbackup/dataplan_db.txt. " + os_last_error_str(), LL_ERROR);
			}

			DataplanDb::getInstance()->read("urbackup/dataplan_db.txt");
		}

	}
}

void ServerUpdate::read_update_location()
{
	std::string read_update_location = trim(getFile("urbackup/server_update_location.url"));

	if (!read_update_location.empty())
	{
		urbackup_update_url_alt = read_update_location;
		urbackup_update_url = urbackup_update_url_alt;

		if (!urbackup_update_url.empty()
			&& urbackup_update_url[urbackup_update_url.size() - 1] != '/')
			urbackup_update_url += "/";

		urbackup_update_url += "2.2.x/";
	}
}
<|endoftext|>


<commit_before>//
//  EnvelopeGenerator.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 01/05/2020.
//  Copyright © 2020 Thomas Harte. All rights reserved.
//

#ifndef EnvelopeGenerator_h
#define EnvelopeGenerator_h

#include <optional>
#include <functional>
#include "LowFrequencyOscillator.hpp"

namespace Yamaha {
namespace OPL {

/*!
	Models an OPL-style envelope generator.

	Damping is optional; if damping is enabled then if there is a transition to key-on while
	attenuation is less than maximum then attenuation will be quickly transitioned to maximum
	before the attack phase can begin.

	in real hardware damping is used by the envelope generators associated with
	carriers, with phases being reset upon the transition from damping to attack.

	This code considers application of tremolo to be a function of the envelope generator;
	this is largely for logical conformity with the phase generator that necessarily has to
	apply vibrato.

	TODO: use envelope_precision.
*/
template <int envelope_precision, int period_precision> class EnvelopeGenerator {
	public:
		/*!
			Advances the envelope generator a single step, given the current state of the low-frequency oscillator, @c oscillator.
		*/
		void update(const LowFrequencyOscillator &oscillator) {
			// Apply tremolo, which is fairly easy.
			tremolo_ = tremolo_enable_ * oscillator.tremolo << 4;

			// Something something something...
			const int key_scaling_rate = key_scale_rate_ >> key_scale_rate_shift_;
			switch(phase_) {
				case Phase::Damp:
					update_decay(oscillator, 12 << 2);
					if(attenuation_ == 511) {
						(*will_attack_)();
						phase_ = Phase::Attack;
					}
				break;

				case Phase::Attack:
					update_attack(oscillator, attack_rate_ + key_scaling_rate);

					// Two possible terminating conditions: (i) the attack rate is 15; (ii) full volume has been reached.
					if((attack_rate_ + key_scaling_rate) > 60 || attenuation_ <= 0) {
						attenuation_ = 0;
						phase_ = Phase::Decay;
					}
				break;

				case Phase::Decay:
					update_decay(oscillator, decay_rate_ + key_scaling_rate);
					if(attenuation_ >= sustain_level_) {
						attenuation_ = sustain_level_;
						phase_ = use_sustain_level_ ? Phase::Sustain : Phase::Release;
					}
				break;

				case Phase::Sustain:
					// Nothing to do.
				break;

				case Phase::Release:
					update_decay(oscillator, release_rate_ + key_scaling_rate);
				break;
			}
		}

		/*!
			@returns The current attenuation from this envelope generator. This is independent of the envelope precision.
		*/
		int attenuation() const {
			return (attenuation_ + tremolo_) << 3;
		}

		/*!
			Enables or disables damping on this envelope generator. If damping is enabled then this envelope generator will
			use the damping phase when necessary (i.e. when transitioning to key on if attenuation is not already at maximum)
			and in any case will call @c will_attack before transitioning from any other state to attack.

			@param will_attack Supply a will_attack callback to enable damping mode; supply nullopt to disable damping mode.
		*/
		void set_should_damp(const std::optional<std::function<void(void)>> &will_attack) {
			will_attack_ = will_attack;
		}

		/*!
			Sets the current state of the key-on input.
		*/
		void set_key_on(bool key_on) {
			// Do nothing if this is not a leading or trailing edge.
			if(key_on == key_on_) return;
			key_on_ = key_on;

			// Always transition to release upon a key off.
			if(!key_on_) {
				phase_ = Phase::Release;
				return;
			}

			// On key on: if this is an envelope generator with damping, and damping is required,
			// schedule that. If damping is not required, announce a pending attack now and
			// transition to attack.
			if(will_attack_) {
				if(attenuation_ != 511) {
					phase_ = Phase::Damp;
					return;
				}

				(*will_attack_)();
			}
			phase_ = Phase::Attack;
		}

		/*!
			Sets the attack rate, which should be in the range 0–15.
		*/
		void set_attack_rate(int rate) {
			attack_rate_ = rate << 2;
		}

		/*!
			Sets the decay rate, which should be in the range 0–15.
		*/
		void set_decay_rate(int rate) {
			decay_rate_ = rate << 2;
		}

		/*!
			Sets the release rate, which should be in the range 0–15.
		*/
		void set_release_rate(int rate) {
			release_rate_ = rate << 2;
		}

		/*!
			Sets the sustain level, which should be in the range 0–15.
		*/
		void set_sustain_level(int level) {
			sustain_level_ = level << 3;
			// TODO: verify the shift level here. Especially re: precision.
		}

		/*!
			Enables or disables use of the sustain level. If this is disabled, the envelope proceeds
			directly from decay to release.
		*/
		void set_use_sustain_level(bool use) {
			use_sustain_level_ = use;
		}

		/*!
			Enables or disables key-rate scaling.
		*/
		void set_key_scaling_rate_enabled(bool enabled) {
			key_scale_rate_shift_ = int(enabled) * 2;
		}

		/*!
			Enables or disables application of the low-frequency oscillator's tremolo.
		*/
		void set_tremolo_enabled(bool enabled) {
			tremolo_enable_ = int(enabled);
		}

		/*!
			Sets the current period associated with the channel that owns this envelope generator;
			this is used to select a key scaling rate if key-rate scaling is enabled.
		*/
		void set_period(int period, int octave) {
			key_scale_rate_ = (octave << 1) | (period >> (period_precision - 1));
		}

	private:
		enum class Phase {
			Attack, Decay, Sustain, Release, Damp
		} phase_ = Phase::Release;
		int attenuation_ = 511, tremolo_ = 0;

		bool key_on_ = false;
		std::optional<std::function<void(void)>> will_attack_;

		int key_scale_rate_ = 0;
		int key_scale_rate_shift_ = 0;

		int tremolo_enable_ = 0;

		int attack_rate_ = 0;
		int decay_rate_ = 0;
		int release_rate_ = 0;
		int sustain_level_ = 0;
		bool use_sustain_level_ = false;

		static constexpr int dithering_patterns[4][8] = {
			{0, 1, 0, 1, 0, 1, 0, 1},
			{0, 1, 0, 1, 1, 1, 0, 1},
			{0, 1, 1, 1, 0, 1, 1, 1},
			{0, 1, 1, 1, 1, 1, 1, 1},
		};

		void update_attack(const LowFrequencyOscillator &oscillator, int rate) {
			// Rules:
			//
			// An attack rate of '13' has 32 samples in the attack phase; a rate of '12' has the same 32 steps, but spread out over 64 samples, etc.
			// An attack rate of '14' uses a divide by four instead of two.
			// 15 is instantaneous.

			if(rate >= 56) {
				attenuation_ -= (attenuation_ >> 2) - 1;
			} else {
				const int sample_length = 1 << (14 - (rate >> 2));	// TODO: don't throw away KSR bits.
				if(!(oscillator.counter & (sample_length - 1))) {
					attenuation_ -= (attenuation_ >> 3) - 1;
				}
			}
		}

		void update_decay(const LowFrequencyOscillator &oscillator, int rate) {
			// Special case: no decay.
			if(rate < 4) {
				return;
			}

			// Work out the number of cycles between each adjustment tick, and stop now
			// if not at the next adjustment boundary.
			const int shift_size = 13 - (std::min(rate, 52) >> 2);
			if(oscillator.counter & ((1 << shift_size) - 1)) {
				return;
			}

			// Apply dithered adjustment and clamp.
			const int rate_shift = 1 + (rate > 59) + (rate > 55);
			attenuation_ += dithering_patterns[rate & 3][(oscillator.counter >> shift_size) & 7] * (4 << rate_shift);
			attenuation_ = std::min(attenuation_, 511);
		}
};

}
}

#endif /* EnvelopeGenerator_h */
<commit_msg>Attempts to implement the proper attack phase.<commit_after>//
//  EnvelopeGenerator.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 01/05/2020.
//  Copyright © 2020 Thomas Harte. All rights reserved.
//

#ifndef EnvelopeGenerator_h
#define EnvelopeGenerator_h

#include <optional>
#include <functional>
#include "LowFrequencyOscillator.hpp"

namespace Yamaha {
namespace OPL {

/*!
	Models an OPL-style envelope generator.

	Damping is optional; if damping is enabled then if there is a transition to key-on while
	attenuation is less than maximum then attenuation will be quickly transitioned to maximum
	before the attack phase can begin.

	in real hardware damping is used by the envelope generators associated with
	carriers, with phases being reset upon the transition from damping to attack.

	This code considers application of tremolo to be a function of the envelope generator;
	this is largely for logical conformity with the phase generator that necessarily has to
	apply vibrato.

	TODO: use envelope_precision.
*/
template <int envelope_precision, int period_precision> class EnvelopeGenerator {
	public:
		/*!
			Advances the envelope generator a single step, given the current state of the low-frequency oscillator, @c oscillator.
		*/
		void update(const LowFrequencyOscillator &oscillator) {
			// Apply tremolo, which is fairly easy.
			tremolo_ = tremolo_enable_ * oscillator.tremolo << 4;

			// Something something something...
			const int key_scaling_rate = key_scale_rate_ >> key_scale_rate_shift_;
			switch(phase_) {
				case Phase::Damp:
					update_decay(oscillator, 12 << 2);
					if(attenuation_ == 511) {
						(*will_attack_)();
						phase_ = Phase::Attack;
					}
				break;

				case Phase::Attack:
					update_attack(oscillator, attack_rate_ + key_scaling_rate);

					// Two possible terminating conditions: (i) the attack rate is 15; (ii) full volume has been reached.
					if(attenuation_ <= 0) {
						attenuation_ = 0;
						phase_ = Phase::Decay;
					}
				break;

				case Phase::Decay:
					update_decay(oscillator, decay_rate_ + key_scaling_rate);
					if(attenuation_ >= sustain_level_) {
						attenuation_ = sustain_level_;
						phase_ = use_sustain_level_ ? Phase::Sustain : Phase::Release;
					}
				break;

				case Phase::Sustain:
					// Nothing to do.
				break;

				case Phase::Release:
					update_decay(oscillator, release_rate_ + key_scaling_rate);
				break;
			}
		}

		/*!
			@returns The current attenuation from this envelope generator. This is independent of the envelope precision.
		*/
		int attenuation() const {
			return (attenuation_ + tremolo_) << 3;
		}

		/*!
			Enables or disables damping on this envelope generator. If damping is enabled then this envelope generator will
			use the damping phase when necessary (i.e. when transitioning to key on if attenuation is not already at maximum)
			and in any case will call @c will_attack before transitioning from any other state to attack.

			@param will_attack Supply a will_attack callback to enable damping mode; supply nullopt to disable damping mode.
		*/
		void set_should_damp(const std::optional<std::function<void(void)>> &will_attack) {
			will_attack_ = will_attack;
		}

		/*!
			Sets the current state of the key-on input.
		*/
		void set_key_on(bool key_on) {
			// Do nothing if this is not a leading or trailing edge.
			if(key_on == key_on_) return;
			key_on_ = key_on;

			// Always transition to release upon a key off.
			if(!key_on_) {
				phase_ = Phase::Release;
				return;
			}

			// On key on: if this is an envelope generator with damping, and damping is required,
			// schedule that. If damping is not required, announce a pending attack now and
			// transition to attack.
			if(will_attack_) {
				if(attenuation_ != 511) {
					phase_ = Phase::Damp;
					return;
				}

				(*will_attack_)();
			}
			phase_ = Phase::Attack;
		}

		/*!
			Sets the attack rate, which should be in the range 0–15.
		*/
		void set_attack_rate(int rate) {
			attack_rate_ = rate << 2;
		}

		/*!
			Sets the decay rate, which should be in the range 0–15.
		*/
		void set_decay_rate(int rate) {
			decay_rate_ = rate << 2;
		}

		/*!
			Sets the release rate, which should be in the range 0–15.
		*/
		void set_release_rate(int rate) {
			release_rate_ = rate << 2;
		}

		/*!
			Sets the sustain level, which should be in the range 0–15.
		*/
		void set_sustain_level(int level) {
			sustain_level_ = level << 3;
			// TODO: verify the shift level here. Especially re: precision.
		}

		/*!
			Enables or disables use of the sustain level. If this is disabled, the envelope proceeds
			directly from decay to release.
		*/
		void set_use_sustain_level(bool use) {
			use_sustain_level_ = use;
		}

		/*!
			Enables or disables key-rate scaling.
		*/
		void set_key_scaling_rate_enabled(bool enabled) {
			key_scale_rate_shift_ = int(enabled) * 2;
		}

		/*!
			Enables or disables application of the low-frequency oscillator's tremolo.
		*/
		void set_tremolo_enabled(bool enabled) {
			tremolo_enable_ = int(enabled);
		}

		/*!
			Sets the current period associated with the channel that owns this envelope generator;
			this is used to select a key scaling rate if key-rate scaling is enabled.
		*/
		void set_period(int period, int octave) {
			key_scale_rate_ = (octave << 1) | (period >> (period_precision - 1));
		}

	private:
		enum class Phase {
			Attack, Decay, Sustain, Release, Damp
		} phase_ = Phase::Release;
		int attenuation_ = 511, tremolo_ = 0;

		bool key_on_ = false;
		std::optional<std::function<void(void)>> will_attack_;

		int key_scale_rate_ = 0;
		int key_scale_rate_shift_ = 0;

		int tremolo_enable_ = 0;

		int attack_rate_ = 0;
		int decay_rate_ = 0;
		int release_rate_ = 0;
		int sustain_level_ = 0;
		bool use_sustain_level_ = false;

		static constexpr int dithering_patterns[4][8] = {
			{0, 1, 0, 1, 0, 1, 0, 1},
			{0, 1, 0, 1, 1, 1, 0, 1},
			{0, 1, 1, 1, 0, 1, 1, 1},
			{0, 1, 1, 1, 1, 1, 1, 1},
		};

		void update_attack(const LowFrequencyOscillator &oscillator, int rate) {
			// Special case: no attack.
			if(rate < 4) {
				return;
			}

			// Special case: instant attack.
			if(rate >= 60) {
				attenuation_ = 0;
				return;
			}

			// Work out the number of cycles between each adjustment tick, and stop now
			// if not at the next adjustment boundary.
			const int shift_size = 13 - (std::min(rate, 52) >> 2);
			if(oscillator.counter & ((1 << shift_size) - 1)) {
				return;
			}

			// Apply dithered adjustment.
			const int rate_shift = (rate > 55);
			const int step = dithering_patterns[rate & 3][(oscillator.counter >> shift_size) & 7];
			attenuation_ -= ((attenuation_ >> (3 - rate_shift)) + 1) * step;
		}

		void update_decay(const LowFrequencyOscillator &oscillator, int rate) {
			// Special case: no decay.
			if(rate < 4) {
				return;
			}

			// Work out the number of cycles between each adjustment tick, and stop now
			// if not at the next adjustment boundary.
			const int shift_size = 13 - (std::min(rate, 52) >> 2);
			if(oscillator.counter & ((1 << shift_size) - 1)) {
				return;
			}

			// Apply dithered adjustment and clamp.
			const int rate_shift = 1 + (rate > 59) + (rate > 55);
			attenuation_ += dithering_patterns[rate & 3][(oscillator.counter >> shift_size) & 7] * (4 << rate_shift);
			attenuation_ = std::min(attenuation_, 511);
		}
};

}
}

#endif /* EnvelopeGenerator_h */
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <string>
#include <ctype.h>

#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/superres.hpp"
#include "opencv2/superres/optical_flow.hpp"
#include "opencv2/opencv_modules.hpp"

using namespace std;
using namespace cv;
using namespace cv::superres;

#define MEASURE_TIME(op) \
    { \
        TickMeter tm; \
        tm.start(); \
        op; \
        tm.stop(); \
        cout << tm.getTimeSec() << " sec" << endl; \
    }

static Ptr<cv::superres::DenseOpticalFlowExt> createOptFlow(const string& name, bool useGpu)
{
    if (name == "farneback")
    {
        if (useGpu)
            return cv::superres::createOptFlow_Farneback_CUDA();
        else
            return cv::superres::createOptFlow_Farneback();
    }
    /*else if (name == "simple")
        return createOptFlow_Simple();*/
    else if (name == "tvl1")
    {
        if (useGpu)
            return cv::superres::createOptFlow_DualTVL1_CUDA();
        else
            return cv::superres::createOptFlow_DualTVL1();
    }
    else if (name == "brox")
        return cv::superres::createOptFlow_Brox_CUDA();
    else if (name == "pyrlk")
        return cv::superres::createOptFlow_PyrLK_CUDA();
    else
        cerr << "Incorrect Optical Flow algorithm - " << name << endl;

    return Ptr<cv::superres::DenseOpticalFlowExt>();
}

int main(int argc, const char* argv[])
{
    CommandLineParser cmd(argc, argv,
        "{ v video      |           | Input video }"
        "{ o output     |           | Output video }"
        "{ s scale      | 4         | Scale factor }"
        "{ i iterations | 180       | Iteration count }"
        "{ t temporal   | 4         | Radius of the temporal search area }"
        "{ f flow       | farneback | Optical flow algorithm (farneback, simple, tvl1, brox, pyrlk) }"
        "{ g gpu        | false     | CPU as default device, cuda for CUDA }"
        "{ h help       | false     | Print help message }"
    );

    if (cmd.get<bool>("help"))
    {
        cout << "This sample demonstrates Super Resolution algorithms for video sequence" << endl;
        cmd.printMessage();
        return EXIT_SUCCESS;
    }

    const string inputVideoName = cmd.get<string>("video");
    const string outputVideoName = cmd.get<string>("output");
    const int scale = cmd.get<int>("scale");
    const int iterations = cmd.get<int>("iterations");
    const int temporalAreaRadius = cmd.get<int>("temporal");
    const string optFlow = cmd.get<string>("flow");
    string gpuOption = cmd.get<string>("gpu");

    std::transform(gpuOption.begin(), gpuOption.end(), gpuOption.begin(), ::tolower);

    bool useCuda = gpuOption.compare("cuda") == 0;
    Ptr<SuperResolution> superRes;

    if (useCuda)
        superRes = createSuperResolution_BTVL1_CUDA();
    else
        superRes = createSuperResolution_BTVL1();

    Ptr<cv::superres::DenseOpticalFlowExt> of = createOptFlow(optFlow, useCuda);

    if (of.empty())
        return EXIT_FAILURE;
    superRes->setOpticalFlow(of);

    superRes->setScale(scale);
    superRes->setIterations(iterations);
    superRes->setTemporalAreaRadius(temporalAreaRadius);

    Ptr<FrameSource> frameSource;
    if (useCuda)
    {
        // Try to use gpu Video Decoding
        try
        {
            frameSource = createFrameSource_Video_CUDA(inputVideoName);
            Mat frame;
            frameSource->nextFrame(frame);
        }
        catch (const cv::Exception&)
        {
            frameSource.release();
        }
    }
    if (!frameSource)
        frameSource = createFrameSource_Video(inputVideoName);

    // skip first frame, it is usually corrupted
    {
        Mat frame;
        frameSource->nextFrame(frame);
        cout << "Input           : " << inputVideoName << " " << frame.size() << endl;
        cout << "Scale factor    : " << scale << endl;
        cout << "Iterations      : " << iterations << endl;
        cout << "Temporal radius : " << temporalAreaRadius << endl;
        cout << "Optical Flow    : " << optFlow << endl;
        cout << "Mode            : " << (useCuda ? "CUDA" : "CPU") << endl;
    }

    superRes->setInput(frameSource);

    VideoWriter writer;

    for (int i = 0;; ++i)
    {
        cout << '[' << setw(3) << i << "] : ";
        Mat result;

        MEASURE_TIME(superRes->nextFrame(result));

        if (result.empty())
            break;

        imshow("Super Resolution", result);

        if (waitKey(1000) > 0)
            break;

        if (!outputVideoName.empty())
        {
            if (!writer.isOpened())
                writer.open(outputVideoName, VideoWriter::fourcc('X', 'V', 'I', 'D'), 25.0, result.size());
            writer << result;
        }
    }

    return 0;
}
<commit_msg>Minor update for example-gpu-super_resolution<commit_after>#include <iostream>
#include <iomanip>
#include <string>
#include <ctype.h>

#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/superres.hpp"
#include "opencv2/superres/optical_flow.hpp"
#include "opencv2/opencv_modules.hpp"

using namespace std;
using namespace cv;
using namespace cv::superres;

#define MEASURE_TIME(op) \
    { \
        TickMeter tm; \
        tm.start(); \
        op; \
        tm.stop(); \
        cout << tm.getTimeSec() << " sec" << endl; \
    }

static Ptr<cv::superres::DenseOpticalFlowExt> createOptFlow(const string& name, bool useGpu)
{
    if (name == "farneback")
    {
        if (useGpu)
            return cv::superres::createOptFlow_Farneback_CUDA();
        else
            return cv::superres::createOptFlow_Farneback();
    }
    /*else if (name == "simple")
        return createOptFlow_Simple();*/
    else if (name == "tvl1")
    {
        if (useGpu)
            return cv::superres::createOptFlow_DualTVL1_CUDA();
        else
            return cv::superres::createOptFlow_DualTVL1();
    }
    else if (name == "brox")
        return cv::superres::createOptFlow_Brox_CUDA();
    else if (name == "pyrlk")
        return cv::superres::createOptFlow_PyrLK_CUDA();
    else
        cerr << "Incorrect Optical Flow algorithm - " << name << endl;

    return Ptr<cv::superres::DenseOpticalFlowExt>();
}

int main(int argc, const char* argv[])
{
    CommandLineParser cmd(argc, argv,
        "{ v video      |           | Input video }"
        "{ o output     |           | Output video }"
        "{ s scale      | 4         | Scale factor }"
        "{ i iterations | 180       | Iteration count }"
        "{ t temporal   | 4         | Radius of the temporal search area }"
        "{ f flow       | farneback | Optical flow algorithm (farneback, tvl1, brox, pyrlk) }"
        "{ g gpu        | false     | CPU as default device, cuda for CUDA }"
        "{ h help       | false     | Print help message }"
    );

    if (cmd.get<bool>("help"))
    {
        cout << "This sample demonstrates Super Resolution algorithms for video sequence" << endl;
        cmd.printMessage();
        return EXIT_SUCCESS;
    }

    const string inputVideoName = cmd.get<string>("video");
    const string outputVideoName = cmd.get<string>("output");
    const int scale = cmd.get<int>("scale");
    const int iterations = cmd.get<int>("iterations");
    const int temporalAreaRadius = cmd.get<int>("temporal");
    const string optFlow = cmd.get<string>("flow");
    string gpuOption = cmd.get<string>("gpu");

    std::transform(gpuOption.begin(), gpuOption.end(), gpuOption.begin(), ::tolower);

    bool useCuda = gpuOption.compare("cuda") == 0;
    Ptr<SuperResolution> superRes;

    if (useCuda)
        superRes = createSuperResolution_BTVL1_CUDA();
    else
        superRes = createSuperResolution_BTVL1();

    Ptr<cv::superres::DenseOpticalFlowExt> of = createOptFlow(optFlow, useCuda);

    if (of.empty())
        return EXIT_FAILURE;
    superRes->setOpticalFlow(of);

    superRes->setScale(scale);
    superRes->setIterations(iterations);
    superRes->setTemporalAreaRadius(temporalAreaRadius);

    Ptr<FrameSource> frameSource;
    if (useCuda)
    {
        // Try to use gpu Video Decoding
        try
        {
            frameSource = createFrameSource_Video_CUDA(inputVideoName);
            Mat frame;
            frameSource->nextFrame(frame);
        }
        catch (const cv::Exception&)
        {
            frameSource.release();
        }
    }
    if (!frameSource)
        frameSource = createFrameSource_Video(inputVideoName);

    // skip first frame, it is usually corrupted
    {
        Mat frame;
        frameSource->nextFrame(frame);
        cout << "Input           : " << inputVideoName << " " << frame.size() << endl;
        cout << "Scale factor    : " << scale << endl;
        cout << "Iterations      : " << iterations << endl;
        cout << "Temporal radius : " << temporalAreaRadius << endl;
        cout << "Optical Flow    : " << optFlow << endl;
        cout << "Mode            : " << (useCuda ? "CUDA" : "CPU") << endl;
    }

    superRes->setInput(frameSource);

    VideoWriter writer;

    for (int i = 0;; ++i)
    {
        cout << '[' << setw(3) << i << "] : " << flush;
        Mat result;

        MEASURE_TIME(superRes->nextFrame(result));

        if (result.empty())
            break;

        imshow("Super Resolution", result);

        if (waitKey(1000) > 0)
            break;

        if (!outputVideoName.empty())
        {
            if (!writer.isOpened())
                writer.open(outputVideoName, VideoWriter::fourcc('X', 'V', 'I', 'D'), 25.0, result.size());
            writer << result;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/prdfErrlUtil.H $                            */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2002,2013              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifndef __prdfErrlUtil_H
#define __prdfErrlUtil_H

/**
 * @file  prdfErrlUtil.H
 * @brief PRD error logging code specific to hostboot.
 *
 * This file contains the Processor Runtime Diagnostics error logging
 * related declarations specific to hostboot.
 */

#include <prdfEnums.H>

/**
 * @brief create ErrlEntry in Hostboot
 */
/* This macro does not use the below FSP input parms:

   - i_etype    : errlEventType
   - i_type     : srciType
   - i_srcAttr  : srcAttr
   - i_refCode  : serviceCodes
*/
#define  PRDF_CREATE_ERRL(io_errl, i_sev, i_etype, i_type,            \
                          i_srcAttr, i_mid, i_refCode, i_reasonCode,  \
                          i_user1 ,  i_user2,  i_user3 ,  i_user4)    \
    io_errl = new ERRORLOG::ErrlEntry(ERRORLOG::i_sev,             \
                                      i_mid,                       \
                                      i_reasonCode,                \
                                      PRDF_GET_UINT64_FROM_UINT32( \
                                      i_user1,                     \
                                      i_user2),                    \
                                      PRDF_GET_UINT64_FROM_UINT32( \
                                      i_user3,                     \
                                      i_user4))

/**
 * @brief Add user data to the log
 */
#define PRDF_ADD_FFDC(io_errl, i_buf, i_size, i_ver, i_subsec) \
    io_errl->addFFDC(PRDF_COMP_ID, i_buf, i_size, i_ver, i_subsec)

/**
 * @brief Commit the log
 */
// FIXME:RTC: 65609 will address this issue.
// hberr does not use i_actions for commit
#define PRDF_COMMIT_ERRL(io_errl, i_actions) \
    if(i_actions) {} \
    errlCommit(io_errl, PRDF_COMP_ID)

/**
 * @brief Collect component trace
 */
#define PRDF_COLLECT_TRACE(io_errl, i_max) \
    io_errl->collectTrace(PRDF_COMP_NAME, i_max)

/**
 * @brief Add a procedure ( software ) callout
 */
#define PRDF_ADD_PROCEDURE_CALLOUT(io_errl, i_priority, i_procedure) \
    io_errl->addProcedureCallout((const HWAS::epubProcedureID)i_procedure, \
                                 (const HWAS::callOutPriority)i_priority)

/**
 * @brief Adds a software section to the log
 * mostly used as a stack call indicator
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl hasn't added this in yet so make it a no-op for now
#define PRDF_ADD_SW_ERR(io_errl, i_rc, i_fileId, i_codeloc)

/**
 * @brief Set the platform Log Id
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_SET_PLID(io_errl, i_plid)

/**
 * @brief Get the platform Log Id
 */
#define PRDF_GET_PLID(io_errl, o_plid) \
    o_plid = io_errl->plid()

/**
 * @brief Set 32 bit user defined return code
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_SET_RC(io_errl, i_rc)

/**
 * @brief Get 32 bit user defined return code
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_GET_RC(io_errl, o_rc)

/**
 * @brief Get reason code
 */
#define PRDF_GET_REASONCODE(io_errl, o_reasonCode) \
    o_reasonCode = io_errl->reasonCode()

/**
 * @brief get previously stored SRC
 *        A special index ( 0 ) is used to a
 *        ccess the primary src.
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_GET_SRC(io_errl, o_src, i_idx)

/**
 * @brief Determine if the src is terminating
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_GET_TERM_SRC(io_errl, o_termSRC)

/**
 * @brief write SRC termination flag
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_SRC_WRITE_TERM_STATE_ON(io_errl, i_flags)

// end Singleton macros

/*--------------------------------------------------------------------*/
/*  HW Deconfig Errl macros for Hostboot                              */
/*--------------------------------------------------------------------*/

// FIXME:RTC: 65609 will address this issue.
// defines for enums that are not available in hostboot
// these ERRL sevs are currently not supported in HB
#define ERRL_SEV_PREDICTIVE          ERRL_SEV_UNRECOVERABLE
#define ERRL_SEV_RECOVERED           ERRL_SEV_INFORMATIONAL

/**
 * @brief function to create an error log.
 */
#define  PRDF_HW_CREATE_ERRL(io_errl,      \
                             i_sev,        \
                             i_etype,      \
                             i_type,       \
                             i_srcAttr,    \
                             i_mid,        \
                             i_refCode,    \
                             i_reasonCode, \
                             i_userData1,  \
                             i_userData2,  \
                             i_userData3,  \
                             i_userData4,  \
                             i_termFlag,   \
                             i_pldCheck)   \
  PRDF_CREATE_ERRL(io_errl, i_sev, i_etype, i_type,            \
                   i_srcAttr, i_mid, i_refCode, i_reasonCode,  \
                   i_userData1, i_userData2, i_userData3, i_userData4)

/**
 * @brief Add a procedure callout to an existing error log
 */
#define PRDF_HW_ADD_PROC_CALLOUT(i_procedure,   \
                                 i_priority,    \
                                 io_errl,       \
                                 i_severity)    \
  PRDF_ADD_PROCEDURE_CALLOUT(io_errl, i_priority, i_procedure)

/**
 * @brief Error log interface to add a HW callout to an existing error log.
 * @note  convert immediate deconfig to delayed deconfig in HB.
 */
#define PRDF_HW_ADD_CALLOUT(i_target, i_priority,         \
                            i_deconfigState, i_gardState,             \
                            io_errl, i_writeVpd,                      \
                            i_gardErrType, i_severity, i_hcdb_update) \
  HWAS::DeconfigEnum deconfigState =                                 \
                        (i_deconfigState == HWAS::DECONFIG ?         \
                        HWAS::DELAYED_DECONFIG : i_deconfigState);   \
  io_errl->addHwCallout(i_target,                                    \
                        (const HWAS::callOutPriority)i_priority,     \
                        deconfigState,                               \
                        (const HWAS::GARD_ErrorType)i_gardErrType);  \
  (void)(i_hcdb_update)

/**
 * @brief Process's pending deconfig and GARD service actions
 *        and thencommits and deletes the error log.
 */
#define PRDF_HW_COMMIT_ERRL(io_sysTerm, io_errl, i_deferDeconfig, \
                            i_action, i_continue)                 \
  io_sysTerm = false;  \
  PRDF_COMMIT_ERRL(io_errl, i_action);

/**
 * @brief  indicate whether an abort is active or not
 */
// no-op in Hostboot
#define PRDF_ABORTING(o_abort) \
  o_abort = false;

/**
 * @brief Interface to request a Hardware Unit dump collection
 */
// FIXME:RTC: 65609 will address this issue.
// need to implement in Hostboot
#define PRDF_HWUDUMP( i_errl, i_content, i_huid ) \
  SUCCESS

#endif // __prdfErrlUtil_H
<commit_msg>PRD: fix local var declaration conflict in PRDF_HW_ADD_CALLOUT macro<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/prdfErrlUtil.H $                            */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2002,2013              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifndef __prdfErrlUtil_H
#define __prdfErrlUtil_H

/**
 * @file  prdfErrlUtil.H
 * @brief PRD error logging code specific to hostboot.
 *
 * This file contains the Processor Runtime Diagnostics error logging
 * related declarations specific to hostboot.
 */

#include <prdfEnums.H>

/**
 * @brief create ErrlEntry in Hostboot
 */
/* This macro does not use the below FSP input parms:

   - i_etype    : errlEventType
   - i_type     : srciType
   - i_srcAttr  : srcAttr
   - i_refCode  : serviceCodes
*/
#define  PRDF_CREATE_ERRL(io_errl, i_sev, i_etype, i_type,            \
                          i_srcAttr, i_mid, i_refCode, i_reasonCode,  \
                          i_user1 ,  i_user2,  i_user3 ,  i_user4)    \
    io_errl = new ERRORLOG::ErrlEntry(ERRORLOG::i_sev,             \
                                      i_mid,                       \
                                      i_reasonCode,                \
                                      PRDF_GET_UINT64_FROM_UINT32( \
                                      i_user1,                     \
                                      i_user2),                    \
                                      PRDF_GET_UINT64_FROM_UINT32( \
                                      i_user3,                     \
                                      i_user4))

/**
 * @brief Add user data to the log
 */
#define PRDF_ADD_FFDC(io_errl, i_buf, i_size, i_ver, i_subsec) \
    io_errl->addFFDC(PRDF_COMP_ID, i_buf, i_size, i_ver, i_subsec)

/**
 * @brief Commit the log
 */
// FIXME:RTC: 65609 will address this issue.
// hberr does not use i_actions for commit
#define PRDF_COMMIT_ERRL(io_errl, i_actions) \
    if(i_actions) {} \
    errlCommit(io_errl, PRDF_COMP_ID)

/**
 * @brief Collect component trace
 */
#define PRDF_COLLECT_TRACE(io_errl, i_max) \
    io_errl->collectTrace(PRDF_COMP_NAME, i_max)

/**
 * @brief Add a procedure ( software ) callout
 */
#define PRDF_ADD_PROCEDURE_CALLOUT(io_errl, i_priority, i_procedure) \
    io_errl->addProcedureCallout((const HWAS::epubProcedureID)i_procedure, \
                                 (const HWAS::callOutPriority)i_priority)

/**
 * @brief Adds a software section to the log
 * mostly used as a stack call indicator
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl hasn't added this in yet so make it a no-op for now
#define PRDF_ADD_SW_ERR(io_errl, i_rc, i_fileId, i_codeloc)

/**
 * @brief Set the platform Log Id
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_SET_PLID(io_errl, i_plid)

/**
 * @brief Get the platform Log Id
 */
#define PRDF_GET_PLID(io_errl, o_plid) \
    o_plid = io_errl->plid()

/**
 * @brief Set 32 bit user defined return code
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_SET_RC(io_errl, i_rc)

/**
 * @brief Get 32 bit user defined return code
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_GET_RC(io_errl, o_rc)

/**
 * @brief Get reason code
 */
#define PRDF_GET_REASONCODE(io_errl, o_reasonCode) \
    o_reasonCode = io_errl->reasonCode()

/**
 * @brief get previously stored SRC
 *        A special index ( 0 ) is used to a
 *        ccess the primary src.
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_GET_SRC(io_errl, o_src, i_idx)

/**
 * @brief Determine if the src is terminating
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_GET_TERM_SRC(io_errl, o_termSRC)

/**
 * @brief write SRC termination flag
 */
// FIXME:RTC: 65609 will address this issue.
// hberrl doesn't have this setter method so make it a no-op for now
#define PRDF_SRC_WRITE_TERM_STATE_ON(io_errl, i_flags)

// end Singleton macros

/*--------------------------------------------------------------------*/
/*  HW Deconfig Errl macros for Hostboot                              */
/*--------------------------------------------------------------------*/

// FIXME:RTC: 65609 will address this issue.
// defines for enums that are not available in hostboot
// these ERRL sevs are currently not supported in HB
#define ERRL_SEV_PREDICTIVE          ERRL_SEV_UNRECOVERABLE
#define ERRL_SEV_RECOVERED           ERRL_SEV_INFORMATIONAL

/**
 * @brief function to create an error log.
 */
#define  PRDF_HW_CREATE_ERRL(io_errl,      \
                             i_sev,        \
                             i_etype,      \
                             i_type,       \
                             i_srcAttr,    \
                             i_mid,        \
                             i_refCode,    \
                             i_reasonCode, \
                             i_userData1,  \
                             i_userData2,  \
                             i_userData3,  \
                             i_userData4,  \
                             i_termFlag,   \
                             i_pldCheck)   \
  PRDF_CREATE_ERRL(io_errl, i_sev, i_etype, i_type,            \
                   i_srcAttr, i_mid, i_refCode, i_reasonCode,  \
                   i_userData1, i_userData2, i_userData3, i_userData4)

/**
 * @brief Add a procedure callout to an existing error log
 */
#define PRDF_HW_ADD_PROC_CALLOUT(i_procedure,   \
                                 i_priority,    \
                                 io_errl,       \
                                 i_severity)    \
  PRDF_ADD_PROCEDURE_CALLOUT(io_errl, i_priority, i_procedure)

/**
 * @brief Error log interface to add a HW callout to an existing error log.
 * @note  convert immediate deconfig to delayed deconfig in HB.
 */
#define PRDF_HW_ADD_CALLOUT(i_target, i_priority,         \
                            i_deconfigState, i_gardState,             \
                            io_errl, i_writeVpd,                      \
                            i_gardErrType, i_severity, i_hcdb_update) \
  io_errl->addHwCallout(i_target,                                    \
                        (const HWAS::callOutPriority)i_priority,     \
                        (i_deconfigState == HWAS::DECONFIG ?         \
                        HWAS::DELAYED_DECONFIG : i_deconfigState),   \
                        (const HWAS::GARD_ErrorType)i_gardErrType);  \
  (void)(i_hcdb_update)

/**
 * @brief Process's pending deconfig and GARD service actions
 *        and thencommits and deletes the error log.
 */
#define PRDF_HW_COMMIT_ERRL(io_sysTerm, io_errl, i_deferDeconfig, \
                            i_action, i_continue)                 \
  io_sysTerm = false;  \
  PRDF_COMMIT_ERRL(io_errl, i_action);

/**
 * @brief  indicate whether an abort is active or not
 */
// no-op in Hostboot
#define PRDF_ABORTING(o_abort) \
  o_abort = false;

/**
 * @brief Interface to request a Hardware Unit dump collection
 */
// FIXME:RTC: 65609 will address this issue.
// need to implement in Hostboot
#define PRDF_HWUDUMP( i_errl, i_content, i_huid ) \
  SUCCESS

#endif // __prdfErrlUtil_H
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//
//  Original author of this file is Nick Hebner (hebnern@gmail.com).
//

#include "AudioDecoderThread.h"

#include "../base/Logger.h"
#include "../base/TimeSource.h"
#include "../base/ScopeTimer.h"

#if AVUTIL_VERSION_INT > AV_VERSION_INT(52, 0, 0)
#include <libavutil/samplefmt.h>
#endif

using namespace std;

namespace avg {

AudioDecoderThread::AudioDecoderThread(CQueue& cmdQ, AudioMsgQueue& msgQ,
        VideoMsgQueue& packetQ, AVStream* pStream, const AudioParams& ap)
    : WorkerThread<AudioDecoderThread>(string("AudioDecoderThread"), cmdQ),
      m_MsgQ(msgQ),
      m_PacketQ(packetQ),
      m_AP(ap),
      m_pStream(pStream),
      m_pResampleContext(0),
      m_State(DECODING)
{
    m_LastFrameTime = 0;
    m_AudioStartTimestamp = 0;

    if (m_pStream->start_time != (long long)AV_NOPTS_VALUE) {
        m_AudioStartTimestamp = float(av_q2d(m_pStream->time_base)*m_pStream->start_time);
    }
    m_InputSampleRate = (int)(m_pStream->codec->sample_rate);
    m_InputSampleFormat = m_pStream->codec->sample_fmt;
}

AudioDecoderThread::~AudioDecoderThread()
{
    if (m_pResampleContext) {
        audio_resample_close(m_pResampleContext);
        m_pResampleContext = 0;
    }
}

static ProfilingZoneID DecoderProfilingZone("Audio Decoder Thread", true);
static ProfilingZoneID PacketWaitProfilingZone("Audio Wait for packet", true);

bool AudioDecoderThread::work()
{
    ScopeTimer timer(DecoderProfilingZone);
    VideoMsgPtr pMsg;
    {
        ScopeTimer timer(PacketWaitProfilingZone);
        pMsg = m_PacketQ.pop(true);
    }
    switch (pMsg->getType()) {
        case VideoMsg::PACKET: {
            AVPacket* pPacket = pMsg->getPacket();
            switch(m_State) {
                case DECODING:
                    decodePacket(pPacket);
                    break;
                case SEEK_DONE:
                    handleSeekDone(pPacket);
                    break;
                case DISCARDING:
                    discardPacket(pPacket);
                    break;
                default:
                    AVG_ASSERT(false);
            }
            av_free_packet(pPacket);
            delete pPacket;
            break;
        }
        case VideoMsg::SEEK_DONE:
            m_State = SEEK_DONE;
            m_SeekSeqNum = pMsg->getSeekSeqNum();
            m_SeekTime = pMsg->getSeekTime();
            break;
        case VideoMsg::END_OF_FILE:
            pushEOF();
            break;
        case VideoMsg::CLOSED:
            m_MsgQ.clear();
            stop();
            break;
        default:
            pMsg->dump();
            AVG_ASSERT(false);
    }
    ThreadProfiler::get()->reset();
    return true;
}

void AudioDecoderThread::decodePacket(AVPacket* pPacket)
{
    char* pDecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE +
            FF_INPUT_BUFFER_PADDING_SIZE);
    AVPacket* pTempPacket = new AVPacket;
    av_init_packet(pTempPacket);
    pTempPacket->data = pPacket->data;
    pTempPacket->size = pPacket->size;
    while (pTempPacket->size > 0) {
        int bytesDecoded = AVCODEC_MAX_AUDIO_FRAME_SIZE;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 31, 0)
        int bytesConsumed = avcodec_decode_audio3(m_pStream->codec, (short*)pDecodedData,
                &bytesDecoded, pTempPacket);
#else
        int bytesConsumed = avcodec_decode_audio2(m_pStream->codec, (short*)pDecodedData,
                &bytesDecoded, pTempPacket->data, pTempPacket->size);
#endif
        AVG_ASSERT(bytesConsumed != 0);
        if (bytesConsumed < 0) {
            // Error decoding -> throw away current packet.
            bytesDecoded = 0;
            pTempPacket->size = 0;
        } else {
            pTempPacket->data += bytesConsumed;
            pTempPacket->size -= bytesConsumed;
        }
        if (bytesDecoded > 0) {
            int framesDecoded = bytesDecoded/(m_pStream->codec->channels*
                    getBytesPerSample(m_InputSampleFormat));
            AudioBufferPtr pBuffer;
            bool bNeedsResample = (m_InputSampleRate != m_AP.m_SampleRate ||
                    m_InputSampleFormat != SAMPLE_FMT_S16 ||
                    m_pStream->codec->channels != m_AP.m_Channels);
            if (bNeedsResample) {
                pBuffer = resampleAudio(pDecodedData, framesDecoded);
            } else {
                pBuffer = AudioBufferPtr(new AudioBuffer(framesDecoded, m_AP));
                memcpy(pBuffer->getData(), pDecodedData, bytesDecoded);
            }
            m_LastFrameTime += float(pBuffer->getNumFrames())/m_AP.m_SampleRate;
            pushAudioMsg(pBuffer, m_LastFrameTime);
        }
    }
    av_free(pDecodedData);
    delete pTempPacket;
}

void AudioDecoderThread::handleSeekDone(AVPacket* pPacket)
{
    m_MsgQ.clear();
    m_LastFrameTime = float(pPacket->dts*av_q2d(m_pStream->time_base))
            - m_AudioStartTimestamp;

   if (fabs(m_LastFrameTime - m_SeekTime) < 0.01) {
        pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
        decodePacket(pPacket);
        m_State = DECODING;
    } else {
        if (m_LastFrameTime-0.01f < m_SeekTime) {
            // Received frame that's earlier than the destination, so throw away frames
            // until the time is correct.
            m_State = DISCARDING;
        } else {
            // Received frame that's too late, so insert a buffer of silence to
            // compensate.
            insertSilence(m_LastFrameTime - m_SeekTime);
            m_LastFrameTime = m_SeekTime;
            pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
            decodePacket(pPacket);
            m_State = DECODING;
        }
    }
}

void AudioDecoderThread::discardPacket(AVPacket* pPacket)
{
    m_LastFrameTime = float(pPacket->dts*av_q2d(m_pStream->time_base))
            - m_AudioStartTimestamp;
    if (m_LastFrameTime-0.01f > m_SeekTime) {
        pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
        m_State = DECODING;
    }
}

AudioBufferPtr AudioDecoderThread::resampleAudio(char* pDecodedData, int framesDecoded)
{
    if (!m_pResampleContext) {
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52, 24, 0)
        m_pResampleContext = av_audio_resample_init(m_AP.m_Channels,
                m_pStream->codec->channels, m_AP.m_SampleRate, m_InputSampleRate,
                SAMPLE_FMT_S16, (SampleFormat)m_InputSampleFormat, 16, 10, 0, 0.8);
#else
        m_pResampleContext = audio_resample_init(m_AP.m_Channels,
                m_pStream->codec->channels, m_AP.m_SampleRate, m_InputSampleRate);
#endif
        AVG_ASSERT(m_pResampleContext);
    }

    short pResampledData[AVCODEC_MAX_AUDIO_FRAME_SIZE/2];
    int framesResampled = audio_resample(m_pResampleContext, pResampledData,
            (short*)pDecodedData, framesDecoded);
    AudioBufferPtr pBuffer(new AudioBuffer(framesResampled, m_AP));
    memcpy(pBuffer->getData(), pResampledData,
            framesResampled*m_AP.m_Channels*sizeof(short));
    return pBuffer;
}

void AudioDecoderThread::insertSilence(float duration)
{
    int numDelaySamples = int(duration*m_AP.m_SampleRate);
    AudioBufferPtr pBuffer(new AudioBuffer(numDelaySamples, m_AP));
    pBuffer->clear();
    pushAudioMsg(pBuffer, m_LastFrameTime);
}

void AudioDecoderThread::pushAudioMsg(AudioBufferPtr pBuffer, float time)
{
    VideoMsgPtr pMsg(new VideoMsg());
    pMsg->setAudio(pBuffer, time);
    m_MsgQ.push(pMsg);
}

void AudioDecoderThread::pushSeekDone(float time, int seqNum)
{
    VideoMsgPtr pMsg(new VideoMsg());
    pMsg->setSeekDone(seqNum, time);
    m_MsgQ.push(pMsg);
}

void AudioDecoderThread::pushEOF()
{
    VideoMsgPtr pMsg(new VideoMsg());
    pMsg->setEOF();
    m_MsgQ.push(pMsg);
}

int AudioDecoderThread::getBytesPerSample(int sampleFormat)
{
    switch (sampleFormat) {
        case SAMPLE_FMT_U8:
            return 1;
        case SAMPLE_FMT_S16:
            return 2;
        case SAMPLE_FMT_S16P:
            return 2;
        case SAMPLE_FMT_S32:
            return 4;
        case SAMPLE_FMT_FLT:
            return 4;
        case SAMPLE_FMT_DBL:
            return 8;
        default:
            AVG_LOG_ERROR("Unknown SampleFormat: " << sampleFormat << "\n");
            AVG_ASSERT(false);
            return 0;
    }
}

}
<commit_msg>Build fix for older ffmpeg.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//
//  Original author of this file is Nick Hebner (hebnern@gmail.com).
//

#include "AudioDecoderThread.h"

#include "../base/Logger.h"
#include "../base/TimeSource.h"
#include "../base/ScopeTimer.h"

#if AVUTIL_VERSION_INT > AV_VERSION_INT(52, 0, 0)
#include <libavutil/samplefmt.h>
#endif

using namespace std;

namespace avg {

AudioDecoderThread::AudioDecoderThread(CQueue& cmdQ, AudioMsgQueue& msgQ,
        VideoMsgQueue& packetQ, AVStream* pStream, const AudioParams& ap)
    : WorkerThread<AudioDecoderThread>(string("AudioDecoderThread"), cmdQ),
      m_MsgQ(msgQ),
      m_PacketQ(packetQ),
      m_AP(ap),
      m_pStream(pStream),
      m_pResampleContext(0),
      m_State(DECODING)
{
    m_LastFrameTime = 0;
    m_AudioStartTimestamp = 0;

    if (m_pStream->start_time != (long long)AV_NOPTS_VALUE) {
        m_AudioStartTimestamp = float(av_q2d(m_pStream->time_base)*m_pStream->start_time);
    }
    m_InputSampleRate = (int)(m_pStream->codec->sample_rate);
    m_InputSampleFormat = m_pStream->codec->sample_fmt;
}

AudioDecoderThread::~AudioDecoderThread()
{
    if (m_pResampleContext) {
        audio_resample_close(m_pResampleContext);
        m_pResampleContext = 0;
    }
}

static ProfilingZoneID DecoderProfilingZone("Audio Decoder Thread", true);
static ProfilingZoneID PacketWaitProfilingZone("Audio Wait for packet", true);

bool AudioDecoderThread::work()
{
    ScopeTimer timer(DecoderProfilingZone);
    VideoMsgPtr pMsg;
    {
        ScopeTimer timer(PacketWaitProfilingZone);
        pMsg = m_PacketQ.pop(true);
    }
    switch (pMsg->getType()) {
        case VideoMsg::PACKET: {
            AVPacket* pPacket = pMsg->getPacket();
            switch(m_State) {
                case DECODING:
                    decodePacket(pPacket);
                    break;
                case SEEK_DONE:
                    handleSeekDone(pPacket);
                    break;
                case DISCARDING:
                    discardPacket(pPacket);
                    break;
                default:
                    AVG_ASSERT(false);
            }
            av_free_packet(pPacket);
            delete pPacket;
            break;
        }
        case VideoMsg::SEEK_DONE:
            m_State = SEEK_DONE;
            m_SeekSeqNum = pMsg->getSeekSeqNum();
            m_SeekTime = pMsg->getSeekTime();
            break;
        case VideoMsg::END_OF_FILE:
            pushEOF();
            break;
        case VideoMsg::CLOSED:
            m_MsgQ.clear();
            stop();
            break;
        default:
            pMsg->dump();
            AVG_ASSERT(false);
    }
    ThreadProfiler::get()->reset();
    return true;
}

void AudioDecoderThread::decodePacket(AVPacket* pPacket)
{
    char* pDecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE +
            FF_INPUT_BUFFER_PADDING_SIZE);
    AVPacket* pTempPacket = new AVPacket;
    av_init_packet(pTempPacket);
    pTempPacket->data = pPacket->data;
    pTempPacket->size = pPacket->size;
    while (pTempPacket->size > 0) {
        int bytesDecoded = AVCODEC_MAX_AUDIO_FRAME_SIZE;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 31, 0)
        int bytesConsumed = avcodec_decode_audio3(m_pStream->codec, (short*)pDecodedData,
                &bytesDecoded, pTempPacket);
#else
        int bytesConsumed = avcodec_decode_audio2(m_pStream->codec, (short*)pDecodedData,
                &bytesDecoded, pTempPacket->data, pTempPacket->size);
#endif
        AVG_ASSERT(bytesConsumed != 0);
        if (bytesConsumed < 0) {
            // Error decoding -> throw away current packet.
            bytesDecoded = 0;
            pTempPacket->size = 0;
        } else {
            pTempPacket->data += bytesConsumed;
            pTempPacket->size -= bytesConsumed;
        }
        if (bytesDecoded > 0) {
            int framesDecoded = bytesDecoded/(m_pStream->codec->channels*
                    getBytesPerSample(m_InputSampleFormat));
            AudioBufferPtr pBuffer;
            bool bNeedsResample = (m_InputSampleRate != m_AP.m_SampleRate ||
                    m_InputSampleFormat != SAMPLE_FMT_S16 ||
                    m_pStream->codec->channels != m_AP.m_Channels);
            if (bNeedsResample) {
                pBuffer = resampleAudio(pDecodedData, framesDecoded);
            } else {
                pBuffer = AudioBufferPtr(new AudioBuffer(framesDecoded, m_AP));
                memcpy(pBuffer->getData(), pDecodedData, bytesDecoded);
            }
            m_LastFrameTime += float(pBuffer->getNumFrames())/m_AP.m_SampleRate;
            pushAudioMsg(pBuffer, m_LastFrameTime);
        }
    }
    av_free(pDecodedData);
    delete pTempPacket;
}

void AudioDecoderThread::handleSeekDone(AVPacket* pPacket)
{
    m_MsgQ.clear();
    m_LastFrameTime = float(pPacket->dts*av_q2d(m_pStream->time_base))
            - m_AudioStartTimestamp;

   if (fabs(m_LastFrameTime - m_SeekTime) < 0.01) {
        pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
        decodePacket(pPacket);
        m_State = DECODING;
    } else {
        if (m_LastFrameTime-0.01f < m_SeekTime) {
            // Received frame that's earlier than the destination, so throw away frames
            // until the time is correct.
            m_State = DISCARDING;
        } else {
            // Received frame that's too late, so insert a buffer of silence to
            // compensate.
            insertSilence(m_LastFrameTime - m_SeekTime);
            m_LastFrameTime = m_SeekTime;
            pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
            decodePacket(pPacket);
            m_State = DECODING;
        }
    }
}

void AudioDecoderThread::discardPacket(AVPacket* pPacket)
{
    m_LastFrameTime = float(pPacket->dts*av_q2d(m_pStream->time_base))
            - m_AudioStartTimestamp;
    if (m_LastFrameTime-0.01f > m_SeekTime) {
        pushSeekDone(m_LastFrameTime, m_SeekSeqNum);
        m_State = DECODING;
    }
}

AudioBufferPtr AudioDecoderThread::resampleAudio(char* pDecodedData, int framesDecoded)
{
    if (!m_pResampleContext) {
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52, 24, 0)
        m_pResampleContext = av_audio_resample_init(m_AP.m_Channels,
                m_pStream->codec->channels, m_AP.m_SampleRate, m_InputSampleRate,
                SAMPLE_FMT_S16, (SampleFormat)m_InputSampleFormat, 16, 10, 0, 0.8);
#else
        m_pResampleContext = audio_resample_init(m_AP.m_Channels,
                m_pStream->codec->channels, m_AP.m_SampleRate, m_InputSampleRate);
#endif
        AVG_ASSERT(m_pResampleContext);
    }

    short pResampledData[AVCODEC_MAX_AUDIO_FRAME_SIZE/2];
    int framesResampled = audio_resample(m_pResampleContext, pResampledData,
            (short*)pDecodedData, framesDecoded);
    AudioBufferPtr pBuffer(new AudioBuffer(framesResampled, m_AP));
    memcpy(pBuffer->getData(), pResampledData,
            framesResampled*m_AP.m_Channels*sizeof(short));
    return pBuffer;
}

void AudioDecoderThread::insertSilence(float duration)
{
    int numDelaySamples = int(duration*m_AP.m_SampleRate);
    AudioBufferPtr pBuffer(new AudioBuffer(numDelaySamples, m_AP));
    pBuffer->clear();
    pushAudioMsg(pBuffer, m_LastFrameTime);
}

void AudioDecoderThread::pushAudioMsg(AudioBufferPtr pBuffer, float time)
{
    VideoMsgPtr pMsg(new VideoMsg());
    pMsg->setAudio(pBuffer, time);
    m_MsgQ.push(pMsg);
}

void AudioDecoderThread::pushSeekDone(float time, int seqNum)
{
    VideoMsgPtr pMsg(new VideoMsg());
    pMsg->setSeekDone(seqNum, time);
    m_MsgQ.push(pMsg);
}

void AudioDecoderThread::pushEOF()
{
    VideoMsgPtr pMsg(new VideoMsg());
    pMsg->setEOF();
    m_MsgQ.push(pMsg);
}

int AudioDecoderThread::getBytesPerSample(int sampleFormat)
{
    switch (sampleFormat) {
        case SAMPLE_FMT_U8:
            return 1;
        case SAMPLE_FMT_S16:
            return 2;
#ifdef SAMPLE_FMT_S16P
        case SAMPLE_FMT_S16P:
            return 2;
#endif
        case SAMPLE_FMT_S32:
            return 4;
        case SAMPLE_FMT_FLT:
            return 4;
        case SAMPLE_FMT_DBL:
            return 8;
        default:
            AVG_LOG_ERROR("Unknown SampleFormat: " << sampleFormat << "\n");
            AVG_ASSERT(false);
            return 0;
    }
}

}
<|endoftext|>