<commit_before>//===--- ToolChain.cpp - Collections of tools for one platform ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/ToolChain.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang::driver;
using namespace clang;

ToolChain::ToolChain(const Driver &D, const llvm::Triple &T)
  : D(D), Triple(T) {
}

ToolChain::~ToolChain() {
}

const Driver &ToolChain::getDriver() const {
 return D;
}

std::string ToolChain::getDefaultUniversalArchName() const {
  // In universal driver terms, the arch name accepted by -arch isn't exactly
  // the same as the ones that appear in the triple. Roughly speaking, this is
  // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the
  // only interesting special case is powerpc.
  switch (Triple.getArch()) {
  case llvm::Triple::ppc:
    return "ppc";
  case llvm::Triple::ppc64:
    return "ppc64";
  default:
    return Triple.getArchName();
  }
}

bool ToolChain::IsUnwindTablesDefault() const {
  return false;
}

std::string ToolChain::GetFilePath(const char *Name) const {
  return D.GetFilePath(Name, *this);

}

std::string ToolChain::GetProgramPath(const char *Name) const {
  return D.GetProgramPath(Name, *this);
}

types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
  return types::lookupTypeForExtension(Ext);
}

bool ToolChain::HasNativeLLVMSupport() const {
  return false;
}

ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
  return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
                     VersionTuple());
}

/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
//
// FIXME: tblgen this.
static const char *getARMTargetCPU(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  // For Darwin targets, the -arch option (which is translated to a
  // corresponding -march option) should determine the architecture
  // (and the Mach-O slice) regardless of any -mcpu options.
  if (!Triple.isOSDarwin()) {
    // FIXME: Warn on inconsistent use of -mcpu and -march.
    // If we have -mcpu=, use that.
    if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
      return A->getValue();
  }

  StringRef MArch;
  if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
    // Otherwise, if we have -march= choose the base CPU for that arch.
    MArch = A->getValue();
  } else {
    // Otherwise, use the Arch from the triple.
    MArch = Triple.getArchName();
  }

  return llvm::StringSwitch<const char *>(MArch)
    .Cases("armv2", "armv2a","arm2")
    .Case("armv3", "arm6")
    .Case("armv3m", "arm7m")
    .Cases("armv4", "armv4t", "arm7tdmi")
    .Cases("armv5", "armv5t", "arm10tdmi")
    .Cases("armv5e", "armv5te", "arm1026ejs")
    .Case("armv5tej", "arm926ej-s")
    .Cases("armv6", "armv6k", "arm1136jf-s")
    .Case("armv6j", "arm1136j-s")
    .Cases("armv6z", "armv6zk", "arm1176jzf-s")
    .Case("armv6t2", "arm1156t2-s")
    .Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
    .Cases("armv7f", "armv7-f", "cortex-a9-mp")
    .Cases("armv7s", "armv7-s", "swift")
    .Cases("armv7r", "armv7-r", "cortex-r4", "cortex-r5")
    .Cases("armv7m", "armv7-m", "cortex-m3")
    .Case("ep9312", "ep9312")
    .Case("iwmmxt", "iwmmxt")
    .Case("xscale", "xscale")
    .Cases("armv6m", "armv6-m", "cortex-m0")
    // If all else failed, return the most base CPU LLVM supports.
    .Default("arm7tdmi");
}

/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
/// CPU.
//
// FIXME: This is redundant with -mcpu, why does LLVM use this.
// FIXME: tblgen this, or kill it!
static const char *getLLVMArchSuffixForARM(StringRef CPU) {
  return llvm::StringSwitch<const char *>(CPU)
    .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
    .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
    .Cases("arm920", "arm920t", "arm922t", "v4t")
    .Cases("arm940t", "ep9312","v4t")
    .Cases("arm10tdmi",  "arm1020t", "v5")
    .Cases("arm9e",  "arm926ej-s",  "arm946e-s", "v5e")
    .Cases("arm966e-s",  "arm968e-s",  "arm10e", "v5e")
    .Cases("arm1020e",  "arm1022e",  "xscale", "iwmmxt", "v5e")
    .Cases("arm1136j-s",  "arm1136jf-s",  "arm1176jz-s", "v6")
    .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")
    .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")
    .Cases("cortex-a8", "cortex-a9", "cortex-a15", "v7")
    .Case("cortex-m3", "v7m")
    .Case("cortex-m4", "v7m")
    .Case("cortex-m0", "v6m")
    .Case("cortex-a9-mp", "v7f")
    .Case("swift", "v7s")
    .Default("");
}

std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
                                         types::ID InputType) const {
  switch (getTriple().getArch()) {
  default:
    return getTripleString();

  case llvm::Triple::arm:
  case llvm::Triple::thumb: {
    // FIXME: Factor into subclasses.
    llvm::Triple Triple = getTriple();

    // Thumb2 is the default for V7 on Darwin.
    //
    // FIXME: Thumb should just be another -target-feaure, not in the triple.
    StringRef Suffix =
      getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
    bool ThumbDefault = (Suffix.startswith("v7") && getTriple().isOSDarwin());
    std::string ArchName = "arm";

    // Assembly files should start in ARM mode.
    if (InputType != types::TY_PP_Asm &&
        Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
      ArchName = "thumb";
    Triple.setArchName(ArchName + Suffix.str());

    return Triple.getTriple();
  }
  }
}

std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
                                                   types::ID InputType) const {
  // Diagnose use of Darwin OS deployment target arguments on non-Darwin.
  if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
                               options::OPT_miphoneos_version_min_EQ,
                               options::OPT_mios_simulator_version_min_EQ))
    getDriver().Diag(diag::err_drv_clang_unsupported)
      << A->getAsString(Args);

  return ComputeLLVMTriple(Args, InputType);
}

void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                          ArgStringList &CC1Args) const {
  // Each toolchain should provide the appropriate include flags.
}

void ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
                                      ArgStringList &CC1Args) const {
}

ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
  const ArgList &Args) const
{
  if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "compiler-rt")
      return ToolChain::RLT_CompilerRT;
    if (Value == "libgcc")
      return ToolChain::RLT_Libgcc;
    getDriver().Diag(diag::err_drv_invalid_rtlib_name)
      << A->getAsString(Args);
  }

  return GetDefaultRuntimeLibType();
}

ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "libc++")
      return ToolChain::CST_Libcxx;
    if (Value == "libstdc++")
      return ToolChain::CST_Libstdcxx;
    getDriver().Diag(diag::err_drv_invalid_stdlib_name)
      << A->getAsString(Args);
  }

  return ToolChain::CST_Libstdcxx;
}

/// \brief Utility function to add a system include directory to CC1 arguments.
/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
                                            ArgStringList &CC1Args,
                                            const Twine &Path) {
  CC1Args.push_back("-internal-isystem");
  CC1Args.push_back(DriverArgs.MakeArgString(Path));
}

/// \brief Utility function to add a system include directory with extern "C"
/// semantics to CC1 arguments.
///
/// Note that this should be used rarely, and only for directories that
/// historically and for legacy reasons are treated as having implicit extern
/// "C" semantics. These semantics are *ignored* by and large today, but its
/// important to preserve the preprocessor changes resulting from the
/// classification.
/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
                                                   ArgStringList &CC1Args,
                                                   const Twine &Path) {
  CC1Args.push_back("-internal-externc-isystem");
  CC1Args.push_back(DriverArgs.MakeArgString(Path));
}

/// \brief Utility function to add a list of system include directories to CC1.
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
                                             ArgStringList &CC1Args,
                                             ArrayRef<StringRef> Paths) {
  for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end();
       I != E; ++I) {
    CC1Args.push_back("-internal-isystem");
    CC1Args.push_back(DriverArgs.MakeArgString(*I));
  }
}

void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
                                             ArgStringList &CC1Args) const {
  // Header search paths should be handled by each of the subclasses.
  // Historically, they have not been, and instead have been handled inside of
  // the CC1-layer frontend. As the logic is hoisted out, this generic function
  // will slowly stop being called.
  //
  // While it is being called, replicate a bit of a hack to propagate the
  // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
  // header search paths with it. Once all systems are overriding this
  // function, the CC1 flag and this line can be removed.
  DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
}

void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
                                    ArgStringList &CmdArgs) const {
  CXXStdlibType Type = GetCXXStdlibType(Args);

  switch (Type) {
  case ToolChain::CST_Libcxx:
    CmdArgs.push_back("-lc++");
    break;

  case ToolChain::CST_Libstdcxx:
    CmdArgs.push_back("-lstdc++");
    break;
  }
}

void ToolChain::AddCCKextLibArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-lcc_kext");
}

bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
                                              ArgStringList &CmdArgs) const {
  // Check if -ffast-math or -funsafe-math is enabled.
  Arg *A = Args.getLastArg(options::OPT_ffast_math,
                           options::OPT_fno_fast_math,
                           options::OPT_funsafe_math_optimizations,
                           options::OPT_fno_unsafe_math_optimizations);

  if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
      A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
    return false;

  // If crtfastmath.o exists add it to the arguments.
  std::string Path = GetFilePath("crtfastmath.o");
  if (Path == "crtfastmath.o") // Not found.
    return false;

  CmdArgs.push_back(Args.MakeArgString(Path));
  return true;
}
<commit_msg>Adding armv7l default to cortex-a8<commit_after>//===--- ToolChain.cpp - Collections of tools for one platform ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/ToolChain.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang::driver;
using namespace clang;

ToolChain::ToolChain(const Driver &D, const llvm::Triple &T)
  : D(D), Triple(T) {
}

ToolChain::~ToolChain() {
}

const Driver &ToolChain::getDriver() const {
 return D;
}

std::string ToolChain::getDefaultUniversalArchName() const {
  // In universal driver terms, the arch name accepted by -arch isn't exactly
  // the same as the ones that appear in the triple. Roughly speaking, this is
  // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the
  // only interesting special case is powerpc.
  switch (Triple.getArch()) {
  case llvm::Triple::ppc:
    return "ppc";
  case llvm::Triple::ppc64:
    return "ppc64";
  default:
    return Triple.getArchName();
  }
}

bool ToolChain::IsUnwindTablesDefault() const {
  return false;
}

std::string ToolChain::GetFilePath(const char *Name) const {
  return D.GetFilePath(Name, *this);

}

std::string ToolChain::GetProgramPath(const char *Name) const {
  return D.GetProgramPath(Name, *this);
}

types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
  return types::lookupTypeForExtension(Ext);
}

bool ToolChain::HasNativeLLVMSupport() const {
  return false;
}

ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
  return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
                     VersionTuple());
}

/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
//
// FIXME: tblgen this.
static const char *getARMTargetCPU(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  // For Darwin targets, the -arch option (which is translated to a
  // corresponding -march option) should determine the architecture
  // (and the Mach-O slice) regardless of any -mcpu options.
  if (!Triple.isOSDarwin()) {
    // FIXME: Warn on inconsistent use of -mcpu and -march.
    // If we have -mcpu=, use that.
    if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
      return A->getValue();
  }

  StringRef MArch;
  if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
    // Otherwise, if we have -march= choose the base CPU for that arch.
    MArch = A->getValue();
  } else {
    // Otherwise, use the Arch from the triple.
    MArch = Triple.getArchName();
  }

  return llvm::StringSwitch<const char *>(MArch)
    .Cases("armv2", "armv2a","arm2")
    .Case("armv3", "arm6")
    .Case("armv3m", "arm7m")
    .Cases("armv4", "armv4t", "arm7tdmi")
    .Cases("armv5", "armv5t", "arm10tdmi")
    .Cases("armv5e", "armv5te", "arm1026ejs")
    .Case("armv5tej", "arm926ej-s")
    .Cases("armv6", "armv6k", "arm1136jf-s")
    .Case("armv6j", "arm1136j-s")
    .Cases("armv6z", "armv6zk", "arm1176jzf-s")
    .Case("armv6t2", "arm1156t2-s")
    .Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
    .Cases("armv7l", "armv7-l", "cortex-a8")
    .Cases("armv7f", "armv7-f", "cortex-a9-mp")
    .Cases("armv7s", "armv7-s", "swift")
    .Cases("armv7r", "armv7-r", "cortex-r4", "cortex-r5")
    .Cases("armv7m", "armv7-m", "cortex-m3")
    .Case("ep9312", "ep9312")
    .Case("iwmmxt", "iwmmxt")
    .Case("xscale", "xscale")
    .Cases("armv6m", "armv6-m", "cortex-m0")
    // If all else failed, return the most base CPU LLVM supports.
    .Default("arm7tdmi");
}

/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
/// CPU.
//
// FIXME: This is redundant with -mcpu, why does LLVM use this.
// FIXME: tblgen this, or kill it!
static const char *getLLVMArchSuffixForARM(StringRef CPU) {
  return llvm::StringSwitch<const char *>(CPU)
    .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
    .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
    .Cases("arm920", "arm920t", "arm922t", "v4t")
    .Cases("arm940t", "ep9312","v4t")
    .Cases("arm10tdmi",  "arm1020t", "v5")
    .Cases("arm9e",  "arm926ej-s",  "arm946e-s", "v5e")
    .Cases("arm966e-s",  "arm968e-s",  "arm10e", "v5e")
    .Cases("arm1020e",  "arm1022e",  "xscale", "iwmmxt", "v5e")
    .Cases("arm1136j-s",  "arm1136jf-s",  "arm1176jz-s", "v6")
    .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")
    .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")
    .Cases("cortex-a8", "cortex-a9", "cortex-a15", "v7")
    .Case("cortex-m3", "v7m")
    .Case("cortex-m4", "v7m")
    .Case("cortex-m0", "v6m")
    .Case("cortex-a9-mp", "v7f")
    .Case("swift", "v7s")
    .Default("");
}

std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
                                         types::ID InputType) const {
  switch (getTriple().getArch()) {
  default:
    return getTripleString();

  case llvm::Triple::arm:
  case llvm::Triple::thumb: {
    // FIXME: Factor into subclasses.
    llvm::Triple Triple = getTriple();

    // Thumb2 is the default for V7 on Darwin.
    //
    // FIXME: Thumb should just be another -target-feaure, not in the triple.
    StringRef Suffix =
      getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
    bool ThumbDefault = (Suffix.startswith("v7") && getTriple().isOSDarwin());
    std::string ArchName = "arm";

    // Assembly files should start in ARM mode.
    if (InputType != types::TY_PP_Asm &&
        Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
      ArchName = "thumb";
    Triple.setArchName(ArchName + Suffix.str());

    return Triple.getTriple();
  }
  }
}

std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
                                                   types::ID InputType) const {
  // Diagnose use of Darwin OS deployment target arguments on non-Darwin.
  if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
                               options::OPT_miphoneos_version_min_EQ,
                               options::OPT_mios_simulator_version_min_EQ))
    getDriver().Diag(diag::err_drv_clang_unsupported)
      << A->getAsString(Args);

  return ComputeLLVMTriple(Args, InputType);
}

void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                          ArgStringList &CC1Args) const {
  // Each toolchain should provide the appropriate include flags.
}

void ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
                                      ArgStringList &CC1Args) const {
}

ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
  const ArgList &Args) const
{
  if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "compiler-rt")
      return ToolChain::RLT_CompilerRT;
    if (Value == "libgcc")
      return ToolChain::RLT_Libgcc;
    getDriver().Diag(diag::err_drv_invalid_rtlib_name)
      << A->getAsString(Args);
  }

  return GetDefaultRuntimeLibType();
}

ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "libc++")
      return ToolChain::CST_Libcxx;
    if (Value == "libstdc++")
      return ToolChain::CST_Libstdcxx;
    getDriver().Diag(diag::err_drv_invalid_stdlib_name)
      << A->getAsString(Args);
  }

  return ToolChain::CST_Libstdcxx;
}

/// \brief Utility function to add a system include directory to CC1 arguments.
/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
                                            ArgStringList &CC1Args,
                                            const Twine &Path) {
  CC1Args.push_back("-internal-isystem");
  CC1Args.push_back(DriverArgs.MakeArgString(Path));
}

/// \brief Utility function to add a system include directory with extern "C"
/// semantics to CC1 arguments.
///
/// Note that this should be used rarely, and only for directories that
/// historically and for legacy reasons are treated as having implicit extern
/// "C" semantics. These semantics are *ignored* by and large today, but its
/// important to preserve the preprocessor changes resulting from the
/// classification.
/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
                                                   ArgStringList &CC1Args,
                                                   const Twine &Path) {
  CC1Args.push_back("-internal-externc-isystem");
  CC1Args.push_back(DriverArgs.MakeArgString(Path));
}

/// \brief Utility function to add a list of system include directories to CC1.
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
                                             ArgStringList &CC1Args,
                                             ArrayRef<StringRef> Paths) {
  for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end();
       I != E; ++I) {
    CC1Args.push_back("-internal-isystem");
    CC1Args.push_back(DriverArgs.MakeArgString(*I));
  }
}

void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
                                             ArgStringList &CC1Args) const {
  // Header search paths should be handled by each of the subclasses.
  // Historically, they have not been, and instead have been handled inside of
  // the CC1-layer frontend. As the logic is hoisted out, this generic function
  // will slowly stop being called.
  //
  // While it is being called, replicate a bit of a hack to propagate the
  // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
  // header search paths with it. Once all systems are overriding this
  // function, the CC1 flag and this line can be removed.
  DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
}

void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
                                    ArgStringList &CmdArgs) const {
  CXXStdlibType Type = GetCXXStdlibType(Args);

  switch (Type) {
  case ToolChain::CST_Libcxx:
    CmdArgs.push_back("-lc++");
    break;

  case ToolChain::CST_Libstdcxx:
    CmdArgs.push_back("-lstdc++");
    break;
  }
}

void ToolChain::AddCCKextLibArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-lcc_kext");
}

bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
                                              ArgStringList &CmdArgs) const {
  // Check if -ffast-math or -funsafe-math is enabled.
  Arg *A = Args.getLastArg(options::OPT_ffast_math,
                           options::OPT_fno_fast_math,
                           options::OPT_funsafe_math_optimizations,
                           options::OPT_fno_unsafe_math_optimizations);

  if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
      A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
    return false;

  // If crtfastmath.o exists add it to the arguments.
  std::string Path = GetFilePath("crtfastmath.o");
  if (Path == "crtfastmath.o") // Not found.
    return false;

  CmdArgs.push_back(Args.MakeArgString(Path));
  return true;
}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (C) 2010 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gameobjectprivate.h"

using namespace GluonEngine;

GameObjectPrivate::GameObjectPrivate()
    : enabled( true )
    , position( QVector3D() )
    , scale( QVector3D( 1, 1, 1 ) )
    , orientation( QQuaternion( 0, 0, 0, 1 ) )
    , transform( QMatrix4x4() )
    , transformInvalidated( true )
    , parentGameObject( 0 )
{
}

GameObjectPrivate::GameObjectPrivate( const GameObjectPrivate& other )
    : description( other.description )
    , enabled( other.enabled )
    , position( other.position )
    , scale( other.scale )
    , orientation( other.orientation )
    , transform( QMatrix4x4() )
    , transformInvalidated( true )
    , parentGameObject( other.parentGameObject )
{
}

GameObjectPrivate::~GameObjectPrivate()
{
}
<commit_msg>A wrong initialization value of orientation caused a 180 degrees rotation of the scene sometimes.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (c) 2010 Arjen Hiemstra <ahiemstra@heimr.nl>
 * Copyright (C) 2010 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gameobjectprivate.h"

using namespace GluonEngine;

GameObjectPrivate::GameObjectPrivate()
    : enabled( true )
    , position( QVector3D() )
    , scale( QVector3D( 1, 1, 1 ) )
    , orientation( QQuaternion( 1, 0, 0, 0 ) )
    , transform( QMatrix4x4() )
    , transformInvalidated( true )
    , parentGameObject( 0 )
{
}

GameObjectPrivate::GameObjectPrivate( const GameObjectPrivate& other )
    : description( other.description )
    , enabled( other.enabled )
    , position( other.position )
    , scale( other.scale )
    , orientation( other.orientation )
    , transform( QMatrix4x4() )
    , transformInvalidated( true )
    , parentGameObject( other.parentGameObject )
{
}

GameObjectPrivate::~GameObjectPrivate()
{
}
<|endoftext|>


<commit_before>/**
 * @file state_map.hpp
 * @brief Purpose: Contain a class to states method's management.
 *
 * MIT License
 * Copyright (c) 2017 MindScape
 *
 * https://github.com/TecProg2017-2/mindscape/blob/master/LICENSE.md
 */

#ifndef STATE_MAP_H
#define STATE_MAP_H

#include <string>
#include <unordered_map>

namespace engine {

	/**
	 * @brief A StateMap class.
	 *
	 * Define a state of the game or of the characters.
	 */

  	class StateMap {
    	private:
      		std::unordered_map<std::string, std::string> states;

    	public:
     		StateMap(std::unordered_map<std::string, std::string> p_states =
     		{{}}
     		):states(p_states){
     		};

      		~StateMap(){
      		};

      		void set_state (std::string, std::string);

      		std::string get_state (std::string);
  	};
}

#endif
<commit_msg>[INITIALIZATION] Applies initialization in state_map.hpp variables<commit_after>/**
 * @file state_map.hpp
 * @brief Purpose: Contain a class to states method's management.
 *
 * MIT License
 * Copyright (c) 2017 MindScape
 *
 * https://github.com/TecProg2017-2/mindscape/blob/master/LICENSE.md
 */

#ifndef STATE_MAP_H
#define STATE_MAP_H

#include <string>
#include <unordered_map>

namespace engine {

	/**
	 * @brief A StateMap class.
	 *
	 * Define a state of the game or of the characters.
	 */

  	class StateMap {
    	private:
      		std::unordered_map<std::string, std::string> states = {{}};

    	public:
     		StateMap(std::unordered_map<std::string, std::string> p_states =
     		{{}}
     		):states(p_states){
     		};

      		~StateMap(){
      		};

      		void set_state (std::string, std::string);

      		std::string get_state (std::string);
  	};
}

#endif
<|endoftext|>


<commit_before>/*
* Block Cipher Lookup
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/def_eng.h>
#include <botan/scan_name.h>
#include <botan/algo_factory.h>

#if defined(BOTAN_HAS_AES)
  #include <botan/aes.h>
#endif

#if defined(BOTAN_HAS_BLOWFISH)
  #include <botan/blowfish.h>
#endif

#if defined(BOTAN_HAS_CAST)
  #include <botan/cast128.h>
  #include <botan/cast256.h>
#endif

#if defined(BOTAN_HAS_DES)
  #include <botan/des.h>
  #include <botan/desx.h>
#endif

#if defined(BOTAN_HAS_GOST_28147_89)
  #include <botan/gost_28147.h>
#endif

#if defined(BOTAN_HAS_IDEA)
  #include <botan/idea.h>
#endif

#if defined(BOTAN_HAS_KASUMI)
  #include <botan/kasumi.h>
#endif

#if defined(BOTAN_HAS_LION)
  #include <botan/lion.h>
#endif

#if defined(BOTAN_HAS_LUBY_RACKOFF)
  #include <botan/lubyrack.h>
#endif

#if defined(BOTAN_HAS_MARS)
  #include <botan/mars.h>
#endif

#if defined(BOTAN_HAS_MISTY1)
  #include <botan/misty1.h>
#endif

#if defined(BOTAN_HAS_NOEKEON)
  #include <botan/noekeon.h>
#endif

#if defined(BOTAN_HAS_RC2)
  #include <botan/rc2.h>
#endif

#if defined(BOTAN_HAS_RC5)
  #include <botan/rc5.h>
#endif

#if defined(BOTAN_HAS_RC6)
  #include <botan/rc6.h>
#endif

#if defined(BOTAN_HAS_SAFER)
  #include <botan/safer_sk.h>
#endif

#if defined(BOTAN_HAS_SEED)
  #include <botan/seed.h>
#endif

#if defined(BOTAN_HAS_SERPENT)
  #include <botan/serpent.h>
#endif

#if defined(BOTAN_HAS_SKIPJACK)
  #include <botan/skipjack.h>
#endif

#if defined(BOTAN_HAS_SQUARE)
  #include <botan/square.h>
#endif

#if defined(BOTAN_HAS_TEA)
  #include <botan/tea.h>
#endif

#if defined(BOTAN_HAS_TWOFISH)
  #include <botan/twofish.h>
#endif

#if defined(BOTAN_HAS_XTEA)
  #include <botan/xtea.h>
#endif

namespace Botan {

/*
* Look for an algorithm with this name
*/
BlockCipher*
Default_Engine::find_block_cipher(const SCAN_Name& request,
                                  Algorithm_Factory& af) const
   {

#if defined(BOTAN_HAS_AES)
   if(request.algo_name() == "AES")
      return new AES;
   if(request.algo_name() == "AES-128")
      return new AES_128;
   if(request.algo_name() == "AES-192")
      return new AES_192;
   if(request.algo_name() == "AES-256")
      return new AES_256;
#endif

#if defined(BOTAN_HAS_BLOWFISH)
   if(request.algo_name() == "Blowfish")
      return new Blowfish;
#endif

#if defined(BOTAN_HAS_CAST)
   if(request.algo_name() == "CAST-128")
      return new CAST_128;
   if(request.algo_name() == "CAST-256")
      return new CAST_256;
#endif

#if defined(BOTAN_HAS_DES)
   if(request.algo_name() == "DES")
      return new DES;
   if(request.algo_name() == "DESX")
      return new DESX;
   if(request.algo_name() == "TripleDES")
      return new TripleDES;
#endif

#if defined(BOTAN_HAS_GOST_28147_89)
   if(request.algo_name() == "GOST-28147-89")
      return new GOST_28147_89;
#endif

#if defined(BOTAN_HAS_IDEA)
   if(request.algo_name() == "IDEA")
      return new IDEA;
#endif

#if defined(BOTAN_HAS_KASUMI)
   if(request.algo_name() == "KASUMI")
      return new KASUMI;
#endif

#if defined(BOTAN_HAS_MARS)
   if(request.algo_name() == "MARS")
      return new MARS;
#endif

#if defined(BOTAN_HAS_MISTY1)
   if(request.algo_name() == "MISTY1")
      return new MISTY1(request.arg_as_u32bit(0, 8));
#endif

#if defined(BOTAN_HAS_NOEKEON)
   if(request.algo_name() == "Noekeon")
      return new Noekeon;
#endif

#if defined(BOTAN_HAS_RC2)
   if(request.algo_name() == "RC2")
      return new RC2;
#endif

#if defined(BOTAN_HAS_RC5)
   if(request.algo_name() == "RC5")
      return new RC5(request.arg_as_u32bit(0, 12));
#endif

#if defined(BOTAN_HAS_RC6)
   if(request.algo_name() == "RC6")
      return new RC6;
#endif

#if defined(BOTAN_HAS_SAFER)
   if(request.algo_name() == "SAFER-SK")
      return new SAFER_SK(request.arg_as_u32bit(0, 10));
#endif

#if defined(BOTAN_HAS_SEED)
   if(request.algo_name() == "SEED")
      return new SEED;
#endif

#if defined(BOTAN_HAS_SERPENT)
   if(request.algo_name() == "Serpent")
      return new Serpent;
#endif

#if defined(BOTAN_HAS_SKIPJACK)
   if(request.algo_name() == "Skipjack")
      return new Skipjack;
#endif

#if defined(BOTAN_HAS_SQUARE)
   if(request.algo_name() == "Square")
      return new Square;
#endif

#if defined(BOTAN_HAS_TEA)
   if(request.algo_name() == "TEA")
      return new TEA;
#endif

#if defined(BOTAN_HAS_TWOFISH)
   if(request.algo_name() == "Twofish")
      return new Twofish;
#endif

#if defined(BOTAN_HAS_XTEA)
   if(request.algo_name() == "XTEA")
      return new XTEA;
#endif

#if defined(BOTAN_HAS_LUBY_RACKOFF)
   if(request.algo_name() == "Luby-Rackoff" && request.arg_count() == 1)
      {
      const HashFunction* hash = af.prototype_hash_function(request.arg(0));

      if(hash)
         return new LubyRackoff(hash->clone());
      }
#endif

#if defined(BOTAN_HAS_LION)
   if(request.algo_name() == "Lion" && request.arg_count_between(2, 3))
      {
      const u32bit block_size = request.arg_as_u32bit(2, 1024);

      const HashFunction* hash =
         af.prototype_hash_function(request.arg(0));

      const StreamCipher* stream_cipher =
         af.prototype_stream_cipher(request.arg(1));

      if(!hash || !stream_cipher)
         return 0;

      return new Lion(hash->clone(), stream_cipher->clone(), block_size);
      }
#endif

   return 0;
   }

}
<commit_msg>Support different GOST paramters in the lookup interface.<commit_after>/*
* Block Cipher Lookup
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/def_eng.h>
#include <botan/scan_name.h>
#include <botan/algo_factory.h>

#if defined(BOTAN_HAS_AES)
  #include <botan/aes.h>
#endif

#if defined(BOTAN_HAS_BLOWFISH)
  #include <botan/blowfish.h>
#endif

#if defined(BOTAN_HAS_CAST)
  #include <botan/cast128.h>
  #include <botan/cast256.h>
#endif

#if defined(BOTAN_HAS_DES)
  #include <botan/des.h>
  #include <botan/desx.h>
#endif

#if defined(BOTAN_HAS_GOST_28147_89)
  #include <botan/gost_28147.h>
#endif

#if defined(BOTAN_HAS_IDEA)
  #include <botan/idea.h>
#endif

#if defined(BOTAN_HAS_KASUMI)
  #include <botan/kasumi.h>
#endif

#if defined(BOTAN_HAS_LION)
  #include <botan/lion.h>
#endif

#if defined(BOTAN_HAS_LUBY_RACKOFF)
  #include <botan/lubyrack.h>
#endif

#if defined(BOTAN_HAS_MARS)
  #include <botan/mars.h>
#endif

#if defined(BOTAN_HAS_MISTY1)
  #include <botan/misty1.h>
#endif

#if defined(BOTAN_HAS_NOEKEON)
  #include <botan/noekeon.h>
#endif

#if defined(BOTAN_HAS_RC2)
  #include <botan/rc2.h>
#endif

#if defined(BOTAN_HAS_RC5)
  #include <botan/rc5.h>
#endif

#if defined(BOTAN_HAS_RC6)
  #include <botan/rc6.h>
#endif

#if defined(BOTAN_HAS_SAFER)
  #include <botan/safer_sk.h>
#endif

#if defined(BOTAN_HAS_SEED)
  #include <botan/seed.h>
#endif

#if defined(BOTAN_HAS_SERPENT)
  #include <botan/serpent.h>
#endif

#if defined(BOTAN_HAS_SKIPJACK)
  #include <botan/skipjack.h>
#endif

#if defined(BOTAN_HAS_SQUARE)
  #include <botan/square.h>
#endif

#if defined(BOTAN_HAS_TEA)
  #include <botan/tea.h>
#endif

#if defined(BOTAN_HAS_TWOFISH)
  #include <botan/twofish.h>
#endif

#if defined(BOTAN_HAS_XTEA)
  #include <botan/xtea.h>
#endif

namespace Botan {

/*
* Look for an algorithm with this name
*/
BlockCipher*
Default_Engine::find_block_cipher(const SCAN_Name& request,
                                  Algorithm_Factory& af) const
   {

#if defined(BOTAN_HAS_AES)
   if(request.algo_name() == "AES")
      return new AES;
   if(request.algo_name() == "AES-128")
      return new AES_128;
   if(request.algo_name() == "AES-192")
      return new AES_192;
   if(request.algo_name() == "AES-256")
      return new AES_256;
#endif

#if defined(BOTAN_HAS_BLOWFISH)
   if(request.algo_name() == "Blowfish")
      return new Blowfish;
#endif

#if defined(BOTAN_HAS_CAST)
   if(request.algo_name() == "CAST-128")
      return new CAST_128;
   if(request.algo_name() == "CAST-256")
      return new CAST_256;
#endif

#if defined(BOTAN_HAS_DES)
   if(request.algo_name() == "DES")
      return new DES;
   if(request.algo_name() == "DESX")
      return new DESX;
   if(request.algo_name() == "TripleDES")
      return new TripleDES;
#endif

#if defined(BOTAN_HAS_GOST_28147_89)
   if(request.algo_name() == "GOST-28147-89")
      return new GOST_28147_89(request.arg(0, "R3411_94_TestParam"));
#endif

#if defined(BOTAN_HAS_IDEA)
   if(request.algo_name() == "IDEA")
      return new IDEA;
#endif

#if defined(BOTAN_HAS_KASUMI)
   if(request.algo_name() == "KASUMI")
      return new KASUMI;
#endif

#if defined(BOTAN_HAS_MARS)
   if(request.algo_name() == "MARS")
      return new MARS;
#endif

#if defined(BOTAN_HAS_MISTY1)
   if(request.algo_name() == "MISTY1")
      return new MISTY1(request.arg_as_u32bit(0, 8));
#endif

#if defined(BOTAN_HAS_NOEKEON)
   if(request.algo_name() == "Noekeon")
      return new Noekeon;
#endif

#if defined(BOTAN_HAS_RC2)
   if(request.algo_name() == "RC2")
      return new RC2;
#endif

#if defined(BOTAN_HAS_RC5)
   if(request.algo_name() == "RC5")
      return new RC5(request.arg_as_u32bit(0, 12));
#endif

#if defined(BOTAN_HAS_RC6)
   if(request.algo_name() == "RC6")
      return new RC6;
#endif

#if defined(BOTAN_HAS_SAFER)
   if(request.algo_name() == "SAFER-SK")
      return new SAFER_SK(request.arg_as_u32bit(0, 10));
#endif

#if defined(BOTAN_HAS_SEED)
   if(request.algo_name() == "SEED")
      return new SEED;
#endif

#if defined(BOTAN_HAS_SERPENT)
   if(request.algo_name() == "Serpent")
      return new Serpent;
#endif

#if defined(BOTAN_HAS_SKIPJACK)
   if(request.algo_name() == "Skipjack")
      return new Skipjack;
#endif

#if defined(BOTAN_HAS_SQUARE)
   if(request.algo_name() == "Square")
      return new Square;
#endif

#if defined(BOTAN_HAS_TEA)
   if(request.algo_name() == "TEA")
      return new TEA;
#endif

#if defined(BOTAN_HAS_TWOFISH)
   if(request.algo_name() == "Twofish")
      return new Twofish;
#endif

#if defined(BOTAN_HAS_XTEA)
   if(request.algo_name() == "XTEA")
      return new XTEA;
#endif

#if defined(BOTAN_HAS_LUBY_RACKOFF)
   if(request.algo_name() == "Luby-Rackoff" && request.arg_count() == 1)
      {
      const HashFunction* hash = af.prototype_hash_function(request.arg(0));

      if(hash)
         return new LubyRackoff(hash->clone());
      }
#endif

#if defined(BOTAN_HAS_LION)
   if(request.algo_name() == "Lion" && request.arg_count_between(2, 3))
      {
      const u32bit block_size = request.arg_as_u32bit(2, 1024);

      const HashFunction* hash =
         af.prototype_hash_function(request.arg(0));

      const StreamCipher* stream_cipher =
         af.prototype_stream_cipher(request.arg(1));

      if(!hash || !stream_cipher)
         return 0;

      return new Lion(hash->clone(), stream_cipher->clone(), block_size);
      }
#endif

   return 0;
   }

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006-2016  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia 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 (FSF), either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include <iostream>
#include <essentia/algorithmfactory.h>
#include <essentia/streaming/algorithms/poolstorage.h>
#include <essentia/scheduler/network.h>
#include "credit_libav.h"

using namespace std;
using namespace essentia;
using namespace essentia::streaming;
using namespace essentia::scheduler;

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

  if (argc != 3) {
    cout << "Error: incorrect number of arguments." << endl;
    cout << "Usage: " << argv[0] << " audio_input json_output" << endl;
    cout << "Computes spectrogram and mel-band log-energies spectrogram for the input audiofile." << endl;
    creditLibAV();
    exit(1);
  }

  string audioFilename = argv[1];
  string outputFilename = argv[2];

  essentia::init();

  Pool pool;

  // TODO this should be configurable
  Real sampleRate = 44100.0;
  int frameSize = 2048;
  int hopSize = 1024;
  std::string format ("json");

  AlgorithmFactory& factory = streaming::AlgorithmFactory::instance();

  Algorithm* audio = factory.create("MonoLoader",
                                    "filename", audioFilename,
                                    "sampleRate", sampleRate);

  Algorithm* fc    = factory.create("FrameCutter",
                                    "frameSize", frameSize,
                                    "hopSize", hopSize,
                                    "silentFrames", "noise");

  Algorithm* w     = factory.create("Windowing",
                                    "type", "blackmanharris62");

  Algorithm* spec  = factory.create("Spectrum");
  Algorithm* mfcc  = factory.create("MFCC", "numberBands", 40,
                                    "numberCoefficients", 20);
  Algorithm* melbands96 = factory.create("MelBands",
                                         "numberBands", 96,
                                         "log", true);

  // Audio -> FrameCutter -> Windowing -> Spectrum
  audio->output("audio") >> fc->input("signal");
  fc->output("frame") >> w->input("frame");
  w->output("frame") >> spec->input("frame");

  // Spectrum -> MFCC -> Pool
  spec->output("spectrum") >> mfcc->input("spectrum");
  spec->output("spectrum") >> melbands96->input("spectrum");

  mfcc->output("bands") >> NOWHERE; // only store high-res mel bands
  mfcc->output("mfcc") >> PC(pool, "lowlevel.mfcc");
  melbands96->output("bands") >> PC(pool, "lowlevel.melbands96");

  cout << "Analyzing " << audioFilename << endl;;

  Network n(audio);
  n.run();

  // write results to file
  cout << "Writing results to file " << outputFilename << endl;

  standard::Algorithm* output = standard::AlgorithmFactory::create("YamlOutput",
                                                                   "filename", outputFilename,
                                                                   "format", format);
  output->input("pool").set(pool);
  output->compute();

  n.clear();

  delete output;
  essentia::shutdown();

  return 0;
}
<commit_msg>Output binary spectrogram in spectrogram extractor<commit_after>/*
 * Copyright (C) 2006-2016  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia 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 (FSF), either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include <iostream>
#include <essentia/algorithmfactory.h>
#include <essentia/streaming/algorithms/poolstorage.h>
#include <essentia/streaming/algorithms/fileoutput.h>
#include <essentia/scheduler/network.h>
#include "credit_libav.h"

using namespace std;
using namespace essentia;
using namespace essentia::streaming;
using namespace essentia::scheduler;

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

  if (argc != 3) {
    cout << "Error: incorrect number of arguments." << endl;
    cout << "Usage: " << argv[0] << " audio_input json_output" << endl;
    cout << "Computes spectrogram and mel-band log-energies spectrogram for the input audiofile." << endl;
    creditLibAV();
    exit(1);
  }

  string audioFile = argv[1];
  string outputFile = argv[2];
  string outputSpecFile = outputFile + ".spec";

  essentia::init();

  Pool pool;

  // TODO this should be configurable
  Real sampleRate = 44100.0;
  int frameSize = 2048;
  int hopSize = 1024;
  std::string format ("json");

  AlgorithmFactory& factory = streaming::AlgorithmFactory::instance();

  Algorithm* audio = factory.create("MonoLoader",
                                    "filename", audioFile,
                                    "sampleRate", sampleRate);

  Algorithm* fc    = factory.create("FrameCutter",
                                    "frameSize", frameSize,
                                    "hopSize", hopSize,
                                    "silentFrames", "noise");

  Algorithm* w     = factory.create("Windowing",
                                    "type", "blackmanharris62");

  Algorithm* spec  = factory.create("Spectrum");
  Algorithm* mfcc  = factory.create("MFCC", "numberBands", 40,
                                    "numberCoefficients", 20);
  Algorithm* melbands96 = factory.create("MelBands",
                                         "numberBands", 96,
                                         "log", true);

  Algorithm* file = new FileOutput<vector<Real> >();
  file->configure("filename", outputSpecFile, "mode", "binary");

  // Audio -> FrameCutter -> Windowing -> Spectrum
  audio->output("audio") >> fc->input("signal");
  fc->output("frame") >> w->input("frame");
  w->output("frame") >> spec->input("frame");

  // Spectrum -> MFCC -> Pool
  spec->output("spectrum") >> mfcc->input("spectrum");
  spec->output("spectrum") >> melbands96->input("spectrum");
  spec->output("spectrum") >> file->input("data");

  mfcc->output("bands") >> NOWHERE; // only store high-res mel bands
  mfcc->output("mfcc") >> PC(pool, "lowlevel.mfcc");
  melbands96->output("bands") >> PC(pool, "lowlevel.melbands96");

  cout << "Analyzing " << audioFile << endl;;

  Network n(audio);
  n.run();

  // write results to file
  cout << "Writing results to json file " << outputFile << endl;
  cout << "Writing spectrogram to binary file " << outputSpecFile << endl;

  standard::Algorithm* output = standard::AlgorithmFactory::create("YamlOutput",
                                                                   "filename", outputFile,
                                                                   "format", format);

  output->input("pool").set(pool);
  output->compute();

  n.clear();

  delete output;
  essentia::shutdown();

  return 0;
}
<|endoftext|>


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

#include "src/js/mse/media_element.h"

#include <cmath>

#include "src/core/js_manager_impl.h"
#include "src/js/dom/document.h"
#include "src/js/js_error.h"
#include "src/js/mse/media_source.h"
#include "src/js/mse/time_ranges.h"
#include "src/media/media_utils.h"
#include "src/util/macros.h"
#include "src/util/utils.h"

namespace shaka {
namespace js {
namespace mse {

#define NOT_ATTACHED_ERROR                 \
  JsError::DOMException(InvalidStateError, \
                        "The video has been detached from the MediaPlayer")
#define CHECK_ATTACHED() \
  if (player_)           \
    ;                    \
  else                   \
    return NOT_ATTACHED_ERROR

HTMLMediaElement::HTMLMediaElement(RefPtr<dom::Document> document,
                                   const std::string& name,
                                   media::MediaPlayer* player)
    : dom::Element(document, name, nullopt, nullopt),
      autoplay(false),
      loop(false),
      default_muted(false),
      audio_tracks(new AudioTrackList(player)),
      video_tracks(new VideoTrackList(player)),
      text_tracks(new TextTrackList(player)),
      player_(player),
      clock_(&util::Clock::Instance) {
  AddListenerField(EventType::Encrypted, &on_encrypted);
  AddListenerField(EventType::WaitingForKey, &on_waiting_for_key);
  player_->AddClient(this);
}

// \cond Doxygen_Skip
HTMLMediaElement::~HTMLMediaElement() {
  if (player_)
    Detach();
}
// \endcond Doxygen_Skip

void HTMLMediaElement::Trace(memory::HeapTracer* tracer) const {
  dom::Element::Trace(tracer);
  tracer->Trace(&error);
  tracer->Trace(&media_source_);
  tracer->Trace(&audio_tracks);
  tracer->Trace(&video_tracks);
  tracer->Trace(&text_tracks);
}

void HTMLMediaElement::Detach() {
  player_->RemoveClient(this);
  player_ = nullptr;

  audio_tracks->Detach();
  video_tracks->Detach();
  text_tracks->Detach();
}

Promise HTMLMediaElement::SetMediaKeys(RefPtr<eme::MediaKeys> media_keys) {
  if (!player_)
    return Promise::Rejected(NOT_ATTACHED_ERROR);
  if (!media_keys && !media_source_)
    return Promise::Resolved();

  eme::Implementation* cdm = media_keys ? media_keys->GetCdm() : nullptr;
  std::string key_system = media_keys ? media_keys->key_system : "";
  player_->SetEmeImplementation(key_system, cdm);
  this->media_keys = media_keys;
  return Promise::Resolved();
}

ExceptionOr<void> HTMLMediaElement::Load() {
  CHECK_ATTACHED();
  error = nullptr;

  if (media_source_) {
    player_->Detach();
    media_source_->CloseMediaSource();
    media_source_.reset();
  } else if (!src_.empty()) {
    player_->Detach();
    src_ = "";
  }

  SetMuted(default_muted);
  return {};
}

CanPlayTypeEnum HTMLMediaElement::CanPlayType(const std::string& type) {
  auto info =
      ConvertMimeToDecodingConfiguration(type, media::MediaDecodingType::File);

  auto support = player_->DecodingInfo(info);
  if (!support.supported)
    return CanPlayTypeEnum::EMPTY;
  else if (!support.smooth)
    return CanPlayTypeEnum::MAYBE;
  return CanPlayTypeEnum::PROBABLY;
}

media::VideoReadyState HTMLMediaElement::GetReadyState() const {
  if (!player_)
    return media::VideoReadyState::HaveNothing;

  auto ret = player_->ReadyState();
  if (ret == media::VideoReadyState::NotAttached)
    ret = media::VideoReadyState::HaveNothing;
  return ret;
}

RefPtr<TimeRanges> HTMLMediaElement::Buffered() const {
  return new TimeRanges(player_ ? player_->GetBuffered()
                                : std::vector<media::BufferedRange>{});
}

RefPtr<TimeRanges> HTMLMediaElement::Seekable() const {
  const double duration = Duration();
  media::BufferedRanges ranges;
  if (std::isfinite(duration))
    ranges.emplace_back(0, duration);
  return new TimeRanges(ranges);
}

std::string HTMLMediaElement::Source() const {
  return media_source_ ? media_source_->url : src_;
}

ExceptionOr<void> HTMLMediaElement::SetSource(const std::string& src) {
  // Unload any previous MediaSource objects.
  RETURN_IF_ERROR(Load());

  DCHECK(!media_source_);
  if (src.empty())
    return {};

  media_source_ = MediaSource::FindMediaSource(src);
  if (media_source_) {
    if (!player_->AttachMse()) {
      return JsError::DOMException(NotSupportedError,
                                   "Error attaching to MediaPlayer");
    }
    media_source_->OpenMediaSource(this, player_);

    if (autoplay)
      player_->Play();
  } else {
    if (!player_->AttachSource(src)) {
      return JsError::DOMException(NotSupportedError,
                                   "Given src= URL is unsupported");
    }
    src_ = src;
  }
  return {};
}

double HTMLMediaElement::CurrentTime() const {
  return player_ ? player_->CurrentTime() : 0;
}

ExceptionOr<void> HTMLMediaElement::SetCurrentTime(double time) {
  CHECK_ATTACHED();
  player_->SetCurrentTime(time);
  return {};
}

double HTMLMediaElement::Duration() const {
  return player_ ? player_->Duration() : 0;
}

double HTMLMediaElement::PlaybackRate() const {
  return player_ ? player_->PlaybackRate() : 0;
}

ExceptionOr<void> HTMLMediaElement::SetPlaybackRate(double rate) {
  CHECK_ATTACHED();
  player_->SetPlaybackRate(rate);
  return {};
}

bool HTMLMediaElement::Muted() const {
  return player_ && player_->Muted();
}

ExceptionOr<void> HTMLMediaElement::SetMuted(bool muted) {
  CHECK_ATTACHED();
  player_->SetMuted(muted);
  return {};
}

double HTMLMediaElement::Volume() const {
  return player_ ? player_->Volume() : 0;
}

ExceptionOr<void> HTMLMediaElement::SetVolume(double volume) {
  CHECK_ATTACHED();
  if (volume < 0 || volume > 1) {
    return JsError::DOMException(
        IndexSizeError,
        util::StringPrintf(
            "The volume provided (%f) is outside the range [0, 1].", volume));
  }

  player_->SetVolume(volume);
  return {};
}

bool HTMLMediaElement::Paused() const {
  if (!player_)
    return false;

  auto state = player_->PlaybackState();
  return state == media::VideoPlaybackState::Initializing ||
         state == media::VideoPlaybackState::Paused ||
         state == media::VideoPlaybackState::Ended;
}

bool HTMLMediaElement::Seeking() const {
  return player_ &&
         player_->PlaybackState() == media::VideoPlaybackState::Seeking;
}

bool HTMLMediaElement::Ended() const {
  return player_ &&
         player_->PlaybackState() == media::VideoPlaybackState::Ended;
}

ExceptionOr<void> HTMLMediaElement::Play() {
  CHECK_ATTACHED();
  player_->Play();
  return {};
}

ExceptionOr<void> HTMLMediaElement::Pause() {
  CHECK_ATTACHED();
  player_->Pause();
  return {};
}

ExceptionOr<RefPtr<TextTrack>> HTMLMediaElement::AddTextTrack(
    media::TextTrackKind kind, optional<std::string> label,
    optional<std::string> language) {
  CHECK_ATTACHED();

  auto track =
      player_->AddTextTrack(kind, label.value_or(""), language.value_or(""));
  if (!track) {
    return JsError::DOMException(UnknownError, "Error creating TextTrack");
  }

  // The TextTrackList should already have gotten an event callback for the new
  // track, so the JS object should be in the list.
  RefPtr<TextTrack> ret = text_tracks->GetTrack(track);
  DCHECK(ret);
  return ret;
}

void HTMLMediaElement::OnReadyStateChanged(media::VideoReadyState old_state,
                                           media::VideoReadyState new_state) {
  if (old_state < media::VideoReadyState::HaveMetadata &&
      new_state >= media::VideoReadyState::HaveMetadata) {
    ScheduleEvent<events::Event>(EventType::LoadedMetaData);
  }
  if (old_state < media::VideoReadyState::HaveCurrentData &&
      new_state >= media::VideoReadyState::HaveCurrentData) {
    ScheduleEvent<events::Event>(EventType::LoadedData);
  }
  if (old_state < media::VideoReadyState::HaveFutureData &&
      new_state >= media::VideoReadyState::HaveFutureData) {
    ScheduleEvent<events::Event>(EventType::CanPlay);
  }
  if (old_state < media::VideoReadyState::HaveEnoughData &&
      new_state >= media::VideoReadyState::HaveEnoughData) {
    ScheduleEvent<events::Event>(EventType::CanPlayThrough);
  }

  if (old_state >= media::VideoReadyState::HaveFutureData &&
      new_state < media::VideoReadyState::HaveFutureData &&
      new_state > media::VideoReadyState::HaveNothing) {
    ScheduleEvent<events::Event>(EventType::Waiting);
  }

  ScheduleEvent<events::Event>(EventType::ReadyStateChange);
}

void HTMLMediaElement::OnPlaybackStateChanged(
    media::VideoPlaybackState old_state, media::VideoPlaybackState new_state) {
  switch (new_state) {
    case media::VideoPlaybackState::Detached:
      ScheduleEvent<events::Event>(EventType::Emptied);
      break;
    case media::VideoPlaybackState::Paused:
      ScheduleEvent<events::Event>(EventType::Pause);
      break;
    case media::VideoPlaybackState::Buffering:
      ScheduleEvent<events::Event>(EventType::Waiting);
      break;
    case media::VideoPlaybackState::Playing:
      ScheduleEvent<events::Event>(EventType::Playing);
      break;
    case media::VideoPlaybackState::Ended:
      ScheduleEvent<events::Event>(EventType::Ended);
      break;

    case media::VideoPlaybackState::Initializing:
    case media::VideoPlaybackState::Errored:
      break;
    case media::VideoPlaybackState::Seeking:
      // We also get an OnSeeking callback, so raise event there.
      break;
    case media::VideoPlaybackState::WaitingForKey:
      // This happens multiple times, raise the event in the OnWaitingForKey.
      break;
  }
  if (old_state == media::VideoPlaybackState::Seeking)
    ScheduleEvent<events::Event>(EventType::Seeked);
}

void HTMLMediaElement::OnError(const std::string& error) {
  if (!this->error) {
    if (error.empty())
      this->error = new MediaError(MEDIA_ERR_DECODE, "Unknown media error");
    else
      this->error = new MediaError(MEDIA_ERR_DECODE, error);
  }
  ScheduleEvent<events::Event>(EventType::Error);
}

void HTMLMediaElement::OnPlay() {
  ScheduleEvent<events::Event>(EventType::Play);
}

void HTMLMediaElement::OnSeeking() {
  ScheduleEvent<events::Event>(EventType::Seeking);
}

void HTMLMediaElement::OnWaitingForKey() {
  ScheduleEvent<events::Event>(EventType::WaitingForKey);
}

HTMLMediaElementFactory::HTMLMediaElementFactory() {
  AddConstant("HAVE_NOTHING", media::VideoReadyState::HaveNothing);
  AddConstant("HAVE_METADATA", media::VideoReadyState::HaveMetadata);
  AddConstant("HAVE_CURRENT_DATA", media::VideoReadyState::HaveCurrentData);
  AddConstant("HAVE_FUTURE_DATA", media::VideoReadyState::HaveFutureData);
  AddConstant("HAVE_ENOUGH_DATA", media::VideoReadyState::HaveEnoughData);

  AddListenerField(EventType::Encrypted, &HTMLMediaElement::on_encrypted);
  AddListenerField(EventType::WaitingForKey,
                   &HTMLMediaElement::on_waiting_for_key);

  AddReadWriteProperty("autoplay", &HTMLMediaElement::autoplay);
  AddReadWriteProperty("loop", &HTMLMediaElement::loop);
  AddReadWriteProperty("defaultMuted", &HTMLMediaElement::default_muted);
  AddReadOnlyProperty("mediaKeys", &HTMLMediaElement::media_keys);
  AddReadOnlyProperty("error", &HTMLMediaElement::error);
  AddReadOnlyProperty("audioTracks", &HTMLMediaElement::audio_tracks);
  AddReadOnlyProperty("videoTracks", &HTMLMediaElement::video_tracks);
  AddReadOnlyProperty("textTracks", &HTMLMediaElement::text_tracks);

  AddGenericProperty("readyState", &HTMLMediaElement::GetReadyState);
  AddGenericProperty("paused", &HTMLMediaElement::Paused);
  AddGenericProperty("seeking", &HTMLMediaElement::Seeking);
  AddGenericProperty("ended", &HTMLMediaElement::Ended);
  AddGenericProperty("buffered", &HTMLMediaElement::Buffered);
  AddGenericProperty("seekable", &HTMLMediaElement::Seekable);
  AddGenericProperty("src", &HTMLMediaElement::Source,
                     &HTMLMediaElement::SetSource);
  AddGenericProperty("currentSrc", &HTMLMediaElement::Source);
  AddGenericProperty("currentTime", &HTMLMediaElement::CurrentTime,
                     &HTMLMediaElement::SetCurrentTime);
  AddGenericProperty("duration", &HTMLMediaElement::Duration);
  AddGenericProperty("playbackRate", &HTMLMediaElement::PlaybackRate,
                     &HTMLMediaElement::SetPlaybackRate);
  AddGenericProperty("volume", &HTMLMediaElement::Volume,
                     &HTMLMediaElement::SetVolume);
  AddGenericProperty("muted", &HTMLMediaElement::Muted,
                     &HTMLMediaElement::SetMuted);

  AddMemberFunction("load", &HTMLMediaElement::Load);
  AddMemberFunction("play", &HTMLMediaElement::Play);
  AddMemberFunction("pause", &HTMLMediaElement::Pause);
  AddMemberFunction("setMediaKeys", &HTMLMediaElement::SetMediaKeys);
  AddMemberFunction("addTextTrack", &HTMLMediaElement::AddTextTrack);
  AddMemberFunction("canPlayType", &HTMLMediaElement::CanPlayType);

  NotImplemented("crossOrigin");
  NotImplemented("networkState");
  NotImplemented("preload");
  NotImplemented("getStartDate");
  NotImplemented("defaultPlaybackRate");
  NotImplemented("playable");
  NotImplemented("mediaGroup");
  NotImplemented("controller");
  NotImplemented("controls");
}

}  // namespace mse
}  // namespace js
}  // namespace shaka
<commit_msg>Propagate errors attaching MediaKeys.<commit_after>// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/js/mse/media_element.h"

#include <cmath>

#include "src/core/js_manager_impl.h"
#include "src/js/dom/document.h"
#include "src/js/js_error.h"
#include "src/js/mse/media_source.h"
#include "src/js/mse/time_ranges.h"
#include "src/media/media_utils.h"
#include "src/util/macros.h"
#include "src/util/utils.h"

namespace shaka {
namespace js {
namespace mse {

#define NOT_ATTACHED_ERROR                 \
  JsError::DOMException(InvalidStateError, \
                        "The video has been detached from the MediaPlayer")
#define CHECK_ATTACHED() \
  if (player_)           \
    ;                    \
  else                   \
    return NOT_ATTACHED_ERROR

HTMLMediaElement::HTMLMediaElement(RefPtr<dom::Document> document,
                                   const std::string& name,
                                   media::MediaPlayer* player)
    : dom::Element(document, name, nullopt, nullopt),
      autoplay(false),
      loop(false),
      default_muted(false),
      audio_tracks(new AudioTrackList(player)),
      video_tracks(new VideoTrackList(player)),
      text_tracks(new TextTrackList(player)),
      player_(player),
      clock_(&util::Clock::Instance) {
  AddListenerField(EventType::Encrypted, &on_encrypted);
  AddListenerField(EventType::WaitingForKey, &on_waiting_for_key);
  player_->AddClient(this);
}

// \cond Doxygen_Skip
HTMLMediaElement::~HTMLMediaElement() {
  if (player_)
    Detach();
}
// \endcond Doxygen_Skip

void HTMLMediaElement::Trace(memory::HeapTracer* tracer) const {
  dom::Element::Trace(tracer);
  tracer->Trace(&error);
  tracer->Trace(&media_source_);
  tracer->Trace(&audio_tracks);
  tracer->Trace(&video_tracks);
  tracer->Trace(&text_tracks);
}

void HTMLMediaElement::Detach() {
  player_->RemoveClient(this);
  player_ = nullptr;

  audio_tracks->Detach();
  video_tracks->Detach();
  text_tracks->Detach();
}

Promise HTMLMediaElement::SetMediaKeys(RefPtr<eme::MediaKeys> media_keys) {
  if (!player_)
    return Promise::Rejected(NOT_ATTACHED_ERROR);
  if (!media_keys && !media_source_)
    return Promise::Resolved();

  eme::Implementation* cdm = media_keys ? media_keys->GetCdm() : nullptr;
  const std::string key_system = media_keys ? media_keys->key_system : "";
  if (!player_->SetEmeImplementation(key_system, cdm)) {
    return Promise::Rejected(
        JsError::TypeError("Error changing MediaKeys on the MediaPlayer"));
  }

  this->media_keys = media_keys;
  return Promise::Resolved();
}

ExceptionOr<void> HTMLMediaElement::Load() {
  CHECK_ATTACHED();
  error = nullptr;

  if (media_source_) {
    player_->Detach();
    media_source_->CloseMediaSource();
    media_source_.reset();
  } else if (!src_.empty()) {
    player_->Detach();
    src_ = "";
  }

  SetMuted(default_muted);
  return {};
}

CanPlayTypeEnum HTMLMediaElement::CanPlayType(const std::string& type) {
  auto info =
      ConvertMimeToDecodingConfiguration(type, media::MediaDecodingType::File);

  auto support = player_->DecodingInfo(info);
  if (!support.supported)
    return CanPlayTypeEnum::EMPTY;
  else if (!support.smooth)
    return CanPlayTypeEnum::MAYBE;
  return CanPlayTypeEnum::PROBABLY;
}

media::VideoReadyState HTMLMediaElement::GetReadyState() const {
  if (!player_)
    return media::VideoReadyState::HaveNothing;

  auto ret = player_->ReadyState();
  if (ret == media::VideoReadyState::NotAttached)
    ret = media::VideoReadyState::HaveNothing;
  return ret;
}

RefPtr<TimeRanges> HTMLMediaElement::Buffered() const {
  return new TimeRanges(player_ ? player_->GetBuffered()
                                : std::vector<media::BufferedRange>{});
}

RefPtr<TimeRanges> HTMLMediaElement::Seekable() const {
  const double duration = Duration();
  media::BufferedRanges ranges;
  if (std::isfinite(duration))
    ranges.emplace_back(0, duration);
  return new TimeRanges(ranges);
}

std::string HTMLMediaElement::Source() const {
  return media_source_ ? media_source_->url : src_;
}

ExceptionOr<void> HTMLMediaElement::SetSource(const std::string& src) {
  // Unload any previous MediaSource objects.
  RETURN_IF_ERROR(Load());

  DCHECK(!media_source_);
  if (src.empty())
    return {};

  media_source_ = MediaSource::FindMediaSource(src);
  if (media_source_) {
    if (!player_->AttachMse()) {
      return JsError::DOMException(NotSupportedError,
                                   "Error attaching to MediaPlayer");
    }
    media_source_->OpenMediaSource(this, player_);

    if (autoplay)
      player_->Play();
  } else {
    if (!player_->AttachSource(src)) {
      return JsError::DOMException(NotSupportedError,
                                   "Given src= URL is unsupported");
    }
    src_ = src;
  }
  return {};
}

double HTMLMediaElement::CurrentTime() const {
  return player_ ? player_->CurrentTime() : 0;
}

ExceptionOr<void> HTMLMediaElement::SetCurrentTime(double time) {
  CHECK_ATTACHED();
  player_->SetCurrentTime(time);
  return {};
}

double HTMLMediaElement::Duration() const {
  return player_ ? player_->Duration() : 0;
}

double HTMLMediaElement::PlaybackRate() const {
  return player_ ? player_->PlaybackRate() : 0;
}

ExceptionOr<void> HTMLMediaElement::SetPlaybackRate(double rate) {
  CHECK_ATTACHED();
  player_->SetPlaybackRate(rate);
  return {};
}

bool HTMLMediaElement::Muted() const {
  return player_ && player_->Muted();
}

ExceptionOr<void> HTMLMediaElement::SetMuted(bool muted) {
  CHECK_ATTACHED();
  player_->SetMuted(muted);
  return {};
}

double HTMLMediaElement::Volume() const {
  return player_ ? player_->Volume() : 0;
}

ExceptionOr<void> HTMLMediaElement::SetVolume(double volume) {
  CHECK_ATTACHED();
  if (volume < 0 || volume > 1) {
    return JsError::DOMException(
        IndexSizeError,
        util::StringPrintf(
            "The volume provided (%f) is outside the range [0, 1].", volume));
  }

  player_->SetVolume(volume);
  return {};
}

bool HTMLMediaElement::Paused() const {
  if (!player_)
    return false;

  auto state = player_->PlaybackState();
  return state == media::VideoPlaybackState::Initializing ||
         state == media::VideoPlaybackState::Paused ||
         state == media::VideoPlaybackState::Ended;
}

bool HTMLMediaElement::Seeking() const {
  return player_ &&
         player_->PlaybackState() == media::VideoPlaybackState::Seeking;
}

bool HTMLMediaElement::Ended() const {
  return player_ &&
         player_->PlaybackState() == media::VideoPlaybackState::Ended;
}

ExceptionOr<void> HTMLMediaElement::Play() {
  CHECK_ATTACHED();
  player_->Play();
  return {};
}

ExceptionOr<void> HTMLMediaElement::Pause() {
  CHECK_ATTACHED();
  player_->Pause();
  return {};
}

ExceptionOr<RefPtr<TextTrack>> HTMLMediaElement::AddTextTrack(
    media::TextTrackKind kind, optional<std::string> label,
    optional<std::string> language) {
  CHECK_ATTACHED();

  auto track =
      player_->AddTextTrack(kind, label.value_or(""), language.value_or(""));
  if (!track) {
    return JsError::DOMException(UnknownError, "Error creating TextTrack");
  }

  // The TextTrackList should already have gotten an event callback for the new
  // track, so the JS object should be in the list.
  RefPtr<TextTrack> ret = text_tracks->GetTrack(track);
  DCHECK(ret);
  return ret;
}

void HTMLMediaElement::OnReadyStateChanged(media::VideoReadyState old_state,
                                           media::VideoReadyState new_state) {
  if (old_state < media::VideoReadyState::HaveMetadata &&
      new_state >= media::VideoReadyState::HaveMetadata) {
    ScheduleEvent<events::Event>(EventType::LoadedMetaData);
  }
  if (old_state < media::VideoReadyState::HaveCurrentData &&
      new_state >= media::VideoReadyState::HaveCurrentData) {
    ScheduleEvent<events::Event>(EventType::LoadedData);
  }
  if (old_state < media::VideoReadyState::HaveFutureData &&
      new_state >= media::VideoReadyState::HaveFutureData) {
    ScheduleEvent<events::Event>(EventType::CanPlay);
  }
  if (old_state < media::VideoReadyState::HaveEnoughData &&
      new_state >= media::VideoReadyState::HaveEnoughData) {
    ScheduleEvent<events::Event>(EventType::CanPlayThrough);
  }

  if (old_state >= media::VideoReadyState::HaveFutureData &&
      new_state < media::VideoReadyState::HaveFutureData &&
      new_state > media::VideoReadyState::HaveNothing) {
    ScheduleEvent<events::Event>(EventType::Waiting);
  }

  ScheduleEvent<events::Event>(EventType::ReadyStateChange);
}

void HTMLMediaElement::OnPlaybackStateChanged(
    media::VideoPlaybackState old_state, media::VideoPlaybackState new_state) {
  switch (new_state) {
    case media::VideoPlaybackState::Detached:
      ScheduleEvent<events::Event>(EventType::Emptied);
      break;
    case media::VideoPlaybackState::Paused:
      ScheduleEvent<events::Event>(EventType::Pause);
      break;
    case media::VideoPlaybackState::Buffering:
      ScheduleEvent<events::Event>(EventType::Waiting);
      break;
    case media::VideoPlaybackState::Playing:
      ScheduleEvent<events::Event>(EventType::Playing);
      break;
    case media::VideoPlaybackState::Ended:
      ScheduleEvent<events::Event>(EventType::Ended);
      break;

    case media::VideoPlaybackState::Initializing:
    case media::VideoPlaybackState::Errored:
      break;
    case media::VideoPlaybackState::Seeking:
      // We also get an OnSeeking callback, so raise event there.
      break;
    case media::VideoPlaybackState::WaitingForKey:
      // This happens multiple times, raise the event in the OnWaitingForKey.
      break;
  }
  if (old_state == media::VideoPlaybackState::Seeking)
    ScheduleEvent<events::Event>(EventType::Seeked);
}

void HTMLMediaElement::OnError(const std::string& error) {
  if (!this->error) {
    if (error.empty())
      this->error = new MediaError(MEDIA_ERR_DECODE, "Unknown media error");
    else
      this->error = new MediaError(MEDIA_ERR_DECODE, error);
  }
  ScheduleEvent<events::Event>(EventType::Error);
}

void HTMLMediaElement::OnPlay() {
  ScheduleEvent<events::Event>(EventType::Play);
}

void HTMLMediaElement::OnSeeking() {
  ScheduleEvent<events::Event>(EventType::Seeking);
}

void HTMLMediaElement::OnWaitingForKey() {
  ScheduleEvent<events::Event>(EventType::WaitingForKey);
}

HTMLMediaElementFactory::HTMLMediaElementFactory() {
  AddConstant("HAVE_NOTHING", media::VideoReadyState::HaveNothing);
  AddConstant("HAVE_METADATA", media::VideoReadyState::HaveMetadata);
  AddConstant("HAVE_CURRENT_DATA", media::VideoReadyState::HaveCurrentData);
  AddConstant("HAVE_FUTURE_DATA", media::VideoReadyState::HaveFutureData);
  AddConstant("HAVE_ENOUGH_DATA", media::VideoReadyState::HaveEnoughData);

  AddListenerField(EventType::Encrypted, &HTMLMediaElement::on_encrypted);
  AddListenerField(EventType::WaitingForKey,
                   &HTMLMediaElement::on_waiting_for_key);

  AddReadWriteProperty("autoplay", &HTMLMediaElement::autoplay);
  AddReadWriteProperty("loop", &HTMLMediaElement::loop);
  AddReadWriteProperty("defaultMuted", &HTMLMediaElement::default_muted);
  AddReadOnlyProperty("mediaKeys", &HTMLMediaElement::media_keys);
  AddReadOnlyProperty("error", &HTMLMediaElement::error);
  AddReadOnlyProperty("audioTracks", &HTMLMediaElement::audio_tracks);
  AddReadOnlyProperty("videoTracks", &HTMLMediaElement::video_tracks);
  AddReadOnlyProperty("textTracks", &HTMLMediaElement::text_tracks);

  AddGenericProperty("readyState", &HTMLMediaElement::GetReadyState);
  AddGenericProperty("paused", &HTMLMediaElement::Paused);
  AddGenericProperty("seeking", &HTMLMediaElement::Seeking);
  AddGenericProperty("ended", &HTMLMediaElement::Ended);
  AddGenericProperty("buffered", &HTMLMediaElement::Buffered);
  AddGenericProperty("seekable", &HTMLMediaElement::Seekable);
  AddGenericProperty("src", &HTMLMediaElement::Source,
                     &HTMLMediaElement::SetSource);
  AddGenericProperty("currentSrc", &HTMLMediaElement::Source);
  AddGenericProperty("currentTime", &HTMLMediaElement::CurrentTime,
                     &HTMLMediaElement::SetCurrentTime);
  AddGenericProperty("duration", &HTMLMediaElement::Duration);
  AddGenericProperty("playbackRate", &HTMLMediaElement::PlaybackRate,
                     &HTMLMediaElement::SetPlaybackRate);
  AddGenericProperty("volume", &HTMLMediaElement::Volume,
                     &HTMLMediaElement::SetVolume);
  AddGenericProperty("muted", &HTMLMediaElement::Muted,
                     &HTMLMediaElement::SetMuted);

  AddMemberFunction("load", &HTMLMediaElement::Load);
  AddMemberFunction("play", &HTMLMediaElement::Play);
  AddMemberFunction("pause", &HTMLMediaElement::Pause);
  AddMemberFunction("setMediaKeys", &HTMLMediaElement::SetMediaKeys);
  AddMemberFunction("addTextTrack", &HTMLMediaElement::AddTextTrack);
  AddMemberFunction("canPlayType", &HTMLMediaElement::CanPlayType);

  NotImplemented("crossOrigin");
  NotImplemented("networkState");
  NotImplemented("preload");
  NotImplemented("getStartDate");
  NotImplemented("defaultPlaybackRate");
  NotImplemented("playable");
  NotImplemented("mediaGroup");
  NotImplemented("controller");
  NotImplemented("controls");
}

}  // namespace mse
}  // namespace js
}  // namespace shaka
<|endoftext|>